diff options
| author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
|---|---|---|
| committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-01-20 01:29:50 +0000 |
| commit | 8362bf63dea22bbf6736609b0f49c152f975eb63 (patch) | |
| tree | 0eea3928e39e50fae91d4e68b21b1e6cbae25604 /filters/olefilters | |
| download | koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.tar.gz koffice-8362bf63dea22bbf6736609b0f49c152f975eb63.zip | |
Added old abandoned KDE3 version of koffice
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/koffice@1077364 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'filters/olefilters')
23 files changed, 4579 insertions, 0 deletions
diff --git a/filters/olefilters/Makefile.am b/filters/olefilters/Makefile.am new file mode 100644 index 000000000..e7bd753ac --- /dev/null +++ b/filters/olefilters/Makefile.am @@ -0,0 +1,22 @@ + +INCLUDES = -I$(srcdir) -I$(srcdir)/lib \ +-I$(srcdir)/powerpoint97 $(KOFFICE_INCLUDES) \ +$(all_includes) + +libolefilter_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +libolefilter_la_LIBADD = ./lib/libfilterbase.la ./lib/libklaola.la \ +./powerpoint97/libpowerpoint97.la \ +$(LIB_KOFFICECORE) + +####### Files + +SUBDIRS = lib powerpoint97 + +kde_module_LTLIBRARIES = libolefilter.la + +libolefilter_la_SOURCES = olefilter.cc + +noinst_HEADERS = olefilter.h + +libolefilter_la_METASOURCES = AUTO + diff --git a/filters/olefilters/lib/Makefile.am b/filters/olefilters/lib/Makefile.am new file mode 100644 index 000000000..9e902fd25 --- /dev/null +++ b/filters/olefilters/lib/Makefile.am @@ -0,0 +1,16 @@ +####### General stuff + +INCLUDES = -I$(srcdir) $(KOFFICE_INCLUDES) $(all_includes) + +####### Files + +noinst_LTLIBRARIES = libfilterbase.la libklaola.la + +libfilterbase_la_SOURCES = filterbase.cc +libfilterbase_la_METASOURCES = filterbase.moc +libfilterbase_la_LDFLAGS = $(all_libraries) + +libklaola_la_SOURCES = klaola.cc +libklaola_la_LDFLAGS = $(all_libraries) + +noinst_HEADERS = filterbase.h klaola.h diff --git a/filters/olefilters/lib/filterbase.cc b/filters/olefilters/lib/filterbase.cc new file mode 100644 index 000000000..b1ec9c32b --- /dev/null +++ b/filters/olefilters/lib/filterbase.cc @@ -0,0 +1,91 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <trobin@kde.org> + + 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. +*/ + +#include <filterbase.h> + +FilterBase::FilterBase() : QObject() { + m_success=true; + m_ready=false; +} + +FilterBase::FilterBase(QStringList &oleStreams) : QObject() { + FilterBase(); + m_oleStreams = oleStreams; +} + +bool FilterBase::filter() { + QString newstr; + + // Page sizes, margins etc. all in points. + + const unsigned height = 841; // Height. + const unsigned width = 595; // Width. + const unsigned hMargin = 28; // Horizontal margin. + const unsigned vMargin = 42; // Vertical margin. + + newstr = QString("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE DOC >\n" + "<DOC author=\"Reginald Stadlbauer and Torben Weis\" email=\"reggie@kde.org and weis@kde.org\" editor=\"KWord\" mime=\"application/x-kword\">\n" + " <PAPER format=\"1\" ptWidth=\"595\" ptHeight=\"841\" mmWidth =\"210\" mmHeight=\"297\" inchWidth =\"8.26772\" inchHeight=\"11.6929\" orientation=\"0\" columns=\"1\" ptColumnspc=\"2\" mmColumnspc=\"1\" inchColumnspc=\"0.0393701\" hType=\"0\" fType=\"0\" ptHeadBody=\"9\" ptFootBody=\"9\" mmHeadBody=\"3.5\" mmFootBody=\"3.5\" inchHeadBody=\"0.137795\" inchFootBody=\"0.137795\">\n" + " <PAPERBORDERS mmLeft=\"10\" mmTop=\"15\" mmRight=\"10\" mmBottom=\"15\" ptLeft=\""); + newstr.append(QString::number(hMargin)); + newstr.append("\" ptTop=\""); + newstr.append(QString::number(vMargin)); + newstr.append("\" ptRight=\""); + newstr.append(QString::number(hMargin)); + newstr.append("\" ptBottom=\""); + newstr.append(QString::number(vMargin)); + newstr.append("\" inchLeft=\"0.393701\" inchTop=\"0.590551\" inchRight=\"0.393701\" inchBottom=\"0.590551\"/>\n" + " </PAPER>\n" + " <ATTRIBUTES processing=\"0\" standardpage=\"1\" hasHeader=\"0\" hasFooter=\"0\" unit=\"mm\"/>\n" + " <FOOTNOTEMGR>\n" + " <START value=\"1\"/>\n" + " <FORMAT superscript=\"1\" type=\"1\"/>\n" + " <FIRSTPARAG ref=\"(null)\"/>\n" + " </FOOTNOTEMGR>\n" + " <FRAMESETS>\n"); + newstr.append( + " <FRAMESET frameType=\"1\" frameInfo=\"0\" removeable=\"0\" visible=\"1\">\n" + " <FRAME left=\""); + newstr.append(QString::number(hMargin)); + newstr.append("\" top=\""); + newstr.append(QString::number(vMargin)); + newstr.append("\" right=\""); + newstr.append(QString::number(width - hMargin)); + newstr.append("\" bottom=\""); + newstr.append(QString::number(height - vMargin)); + newstr.append("\" runaround=\"1\" runaGapPT=\"2\" runaGapMM=\"1\" runaGapINCH=\"0.0393701\" lWidth=\"1\" lRed=\"255\" lGreen=\"255\" lBlue=\"255\" lStyle=\"0\" rWidth=\"1\" rRed=\"255\" rGreen=\"255\" rBlue=\"255\" rStyle=\"0\" tWidth=\"1\" tRed=\"255\" tGreen=\"255\" tBlue=\"255\" tStyle=\"0\" bWidth=\"1\" bRed=\"255\" bGreen=\"255\" bBlue=\"255\" bStyle=\"0\" bkRed=\"255\" bkGreen=\"255\" bkBlue=\"255\" bleftpt=\"0\" bleftmm=\"0\" bleftinch=\"0\" brightpt=\"0\" brightmm=\"0\" brightinch=\"0\" btoppt=\"0\" btopmm=\"0\" btopinch=\"0\" bbottompt=\"0\" bbottommm=\"0\" bbottominch=\"0"); + newstr.append("\" autoCreateNewFrame=\"1\" newFrameBehaviour=\"0\"/>\n" + " <PARAGRAPH>\n" + " <TEXT>"); + newstr.append("Cannot import OLE streams of type: "); + newstr.append(m_oleStreams.join(",")); + newstr.append("</TEXT>\n" + " </PARAGRAPH>\n" + " </FRAMESET>\n"); + newstr.append( + " </FRAMESETS>\n" + "</DOC>\n"); + m_part=QDomDocument("doc"); + m_part.setContent(newstr); + m_success=true; + m_ready=true; + return m_success; +} + +#include <filterbase.moc> diff --git a/filters/olefilters/lib/filterbase.h b/filters/olefilters/lib/filterbase.h new file mode 100644 index 000000000..942c3836f --- /dev/null +++ b/filters/olefilters/lib/filterbase.h @@ -0,0 +1,109 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <trobin@kde.org> + + 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 class is the base class for all the filters (excel97, powerpoint97, +// winword97) +// If you want to write a filter you'll have to derive your class from +// this one. + +#ifndef FILTERBASE_H +#define FILTERBASE_H + +#include <qobject.h> +#include <qdom.h> +#include <qstringlist.h> + +class myFile; +class QCString; + +// Attention: The nameOUT Strings are allocated with new[] in the +// slots. Therefore you have to delete [] them! +// If you call slotGetStream you have to delete [] the +// stream.data prt after use! +class FilterBase : public QObject { + + Q_OBJECT + +public: + + // Default constructor used by subclasses. + FilterBase(); + // This filter only ever gets used in error cases, when we could not find a + // real filter. So, pass in the names of the OLE streams making up the item + // item that could not be converted. + FilterBase(QStringList &oleStreams); + virtual ~FilterBase() {} + + // Manages the filtering process + virtual bool filter(); + + // override this to return true if you want to return a plain QCString + virtual bool plainString() const { return false; } + // okay -- let's get the QDomDocument + virtual const QDomDocument *const part() { return &m_part; } + // or get the plain QCString ;) + virtual QCString CString() const { return QCString(); } + +signals: + // See olefilter.h for information + void signalSaveDocumentInformation( + const QString &fullName, + const QString &title, + const QString &company, + const QString &email, + const QString &telephone, + const QString &fax, + const QString &postalCode, + const QString &country, + const QString &city, + const QString &street, + const QString &docTitle, + const QString &docAbstract); + void signalSavePic( + const QString &nameIN, + QString &storageId, + const QString &extension, + unsigned int length, + const char *data); + void signalSavePart( + const QString &nameIN, + QString &storageId, + QString &mimeType, + const QString &extension, + unsigned int length, + const char *data); + void signalPart(const QString& nameIN, QString &storageId, QString &mimeType); + void signalGetStream(const int &handle, myFile &stream); + // Note: might return wrong stream as names are NOT unique!!! + // (searching only in current dir) + void signalGetStream(const QString &name, myFile &stream); + void sigProgress(int value); + +protected: + bool m_success; // ok, the filtering process was successful + bool m_ready; // filtering took place, you may fetch the file now + QDomDocument m_part; // this represents the part (document) + +private: + // Don't copy or assign me... + FilterBase(const FilterBase &); + const FilterBase &operator=(const FilterBase &); + QStringList m_oleStreams; +}; +#endif // FILTERBASE_H diff --git a/filters/olefilters/lib/klaola.cc b/filters/olefilters/lib/klaola.cc new file mode 100644 index 000000000..69d5284eb --- /dev/null +++ b/filters/olefilters/lib/klaola.cc @@ -0,0 +1,579 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <trobin@kde.org> + + 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. +*/ + +#include <klaola.h> +#include <kdebug.h> + +const int KLaola::s_area = 30510; + +KLaola::KLaola(const myFile &file) { + + smallBlockDepot=0L; + bigBlockDepot=0L; + smallBlockFile=0L; + bbd_list=0L; + ok=true; + m_nodeList.setAutoDelete(true); + //m_currentPath.setAutoDelete(true); + + if( (file.length % 0x200) != 0 ) { + kdError(s_area) << "KLaola::KLaola(): Invalid file size!" << endl; + ok=false; + } + if(ok) { + m_file=file; + maxblock = file.length / 0x200 - 2; + maxSblock=0; // will be set in readSmallBlockDepot + + if(!parseHeader()) + ok=false; + if(ok) { + readBigBlockDepot(); + readSmallBlockDepot(); + readSmallBlockFile(); + readRootList(); + } + } + m_currentPath.clear(); + testIt(); + + // current path=root dirHandle + m_currentPath.clear(); + if ( !m_nodeTree.isEmpty() ) + m_currentPath.append(m_nodeTree.getFirst()->getFirst()->node); +} + +KLaola::~KLaola() { + + delete [] bigBlockDepot; + bigBlockDepot=0L; + delete [] smallBlockDepot; + smallBlockDepot=0L; + delete [] smallBlockFile; + smallBlockFile=0L; + delete [] bbd_list; + bbd_list=0L; +} + +// Comvert the given list of nodes into a tree. +void KLaola::createTree(const int handle, const short index) { + + Node *node = dynamic_cast<Node *>(m_nodeList.at(handle)); + SubTree *subtree; + + TreeNode *tree=new TreeNode; + tree->node=node; + tree->subtree=-1; + + //QString nix="### entering create tree: handle="; + //nix+=QString::number(handle); + //nix+=" index="; + //nix+=QString::number(index); + //kdDebug(s_area) << nix << endl; + + if(node->prevHandle!=-1) { + //kdDebug(s_area) << "create tree: prevHandle" << endl; + createTree(node->prevHandle, index); + } + if(node->dirHandle!=-1) { + subtree=new SubTree; + subtree->setAutoDelete(true); + m_nodeTree.append(subtree); + tree->subtree=m_nodeTree.at(); + //kdDebug(s_area) << "create tree: dirHandle" << endl; + createTree(node->dirHandle, tree->subtree); + } + subtree=m_nodeTree.at(index); + //kdDebug(s_area) << "create tree: APPEND " << handle << " tree node " << tree << endl; + subtree->append(tree); + if(node->nextHandle!=-1) { + //kdDebug(s_area) << "create tree: nextHandle" << endl; + createTree(node->nextHandle, index); + } +} + +const KLaola::NodeList KLaola::currentPath() const { + return m_currentPath; +} + +bool KLaola::enterDir(const OLENode *dirHandle) { + + NodeList nodes; + Node *node; + + if(ok) { + nodes = parseCurrentDir(); + for (node = dynamic_cast<Node *>(nodes.first()); node; node = dynamic_cast<Node *>(nodes.next())) + { + if(node->m_handle==dirHandle->handle() && node->isDirectory() && !node->deadDir) { + m_currentPath.append(node); + return true; + } + } + } + return false; +} + +const KLaola::NodeList KLaola::find(const QString &name, bool onlyCurrentDir) { + + OLENode *node; + NodeList ret; + int i=0; + + if(ok) { + if(!onlyCurrentDir) { + for(node=m_nodeList.first(); node; node=m_nodeList.next()) { + if(node->name()==name) { + ret.append(node); + ++i; + } + } + } + else { + NodeList list=parseCurrentDir(); + + for(node=list.first(); node; node=list.next()) { + if(node->name()==name) { + ret.append(node); + ++i; + } + } + } + } + return ret; +} + +bool KLaola::leaveDir() { + + if (ok) { + return m_currentPath.removeLast(); + } + return false; +} + +int KLaola::nextBigBlock(int pos) const +{ + + int x=pos*4; + return ( (bigBlockDepot[x+3] << 24) + (bigBlockDepot[x+2] << 16) + + (bigBlockDepot[x+1] << 8) + bigBlockDepot[x] ); +} + +int KLaola::nextSmallBlock(int pos) const +{ + + if(smallBlockDepot) { + int x=pos*4; + return ( (smallBlockDepot[x+3] << 24) + (smallBlockDepot[x+2] << 16) + + (smallBlockDepot[x+1] << 8) + smallBlockDepot[x] ); + } + else + return -2; // Emergency Break :) +} + +bool KLaola::parseHeader() { + + if(qstrncmp((const char*)m_file.data,"\xd0\xcf\x11\xe0\xa1\xb1\x1a\xe1",8 )!=0) { + kdError(s_area) << "KLaola::parseHeader(): Invalid file format (unexpected id in header)!" << endl; + return false; + } + + num_of_bbd_blocks=read32(0x2c); + root_startblock=read32(0x30); + sbd_startblock=read32(0x3c); + + if (num_of_bbd_blocks >= 0x800000) { + kdError(s_area) << "KLaola::parseHeader(): Too many bbd blocks found in header!" << endl; + return false; + } + bbd_list=new unsigned int[num_of_bbd_blocks]; + + unsigned int i, j; + for(i=0, j=0; i<num_of_bbd_blocks; ++i, j=j+4) { + bbd_list[i]=read32(0x4c+j); + if (bbd_list[i] >= (0x800000 - 1)) { + kdError(s_area) << "KLaola::parseHeader(): bbd " << i << " offset (" << bbd_list[i] << ") too large" << endl; + return false; + } + } + return true; +} + +KLaola::NodeList KLaola::parseCurrentDir() { + + Node *node; + SubTree *subtree; + NodeList nodeList; + TreeNode *treeNode; + unsigned int i; + bool found; + + if(ok) { + for(i=0, subtree=m_nodeTree.first(); i<m_currentPath.count(); ++i) { + treeNode=subtree->first(); + found=false; + do { + if(treeNode==0) { + kdError(s_area) << "KLaola::parseCurrentDir(): path seems to be corrupted!" << endl; + ok=false; + } + else if(treeNode->node->handle()==m_currentPath.at(i)->handle() && treeNode->subtree!=-1) { + found=true; + } + else + treeNode=subtree->next(); + } while(!found && ok); + subtree=m_nodeTree.at(treeNode->subtree); + } + } + if(ok) { + for(treeNode=subtree->first(); treeNode!=0; treeNode=subtree->next()) { + node=new Node(*treeNode->node); + node->deadDir = (node->dirHandle==-1 && node->isDirectory()); + // this is a strange situation :) + if (node->deadDir) + kdDebug(s_area) << "ignoring: " << node->describe() << " is empty" << endl; + else + nodeList.append(node); + } + } + return nodeList; +} + +KLaola::NodeList KLaola::parseRootDir() { + + NodeList tmpNodeList; + NodeList tmp; + + if(ok) { + tmp=m_currentPath; + m_currentPath.clear(); // current path=root dirHandle + m_currentPath.append(m_nodeTree.getFirst()->getFirst()->node); + tmpNodeList=parseCurrentDir(); + m_currentPath=tmp; + } + return tmpNodeList; +} + +unsigned char KLaola::read8(int i) const +{ + return m_file.data[i]; +} + +unsigned short KLaola::read16(int i) const +{ + return ( (m_file.data[i+1] << 8) + m_file.data[i] ); +} + +unsigned int KLaola::read32(int i) const +{ + return ( (read16(i+2) << 16) + read16(i) ); +} + +const unsigned char *KLaola::readBBStream(int start, bool setmaxSblock) +{ + + int i=0, tmp; + unsigned char *p=0; + + tmp=start; + /* 0x10000 chosen as arbitrary "too many blocks" limit to not loop forver */ + while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=static_cast<int>(maxblock)) { + ++i; + tmp=nextBigBlock(tmp); + } + if(i!=0) { + p=new unsigned char[i*0x200]; + if(setmaxSblock) + maxSblock=i*8-1; + i=0; + tmp=start; + while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=static_cast<int>(maxblock)) { + memcpy(&p[i*0x200], &m_file.data[(tmp+1)*0x200], 0x200); + tmp=nextBigBlock(tmp); + ++i; + } + } + return p; +} + +const unsigned char *KLaola::readSBStream(int start) const { + + int i=0, tmp; + unsigned char *p=0; + + tmp=start; + /* 0x10000 chosen as arbitrary "too many blocks" limit to not loop forver */ + while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=static_cast<int>(maxSblock)) { + ++i; + tmp=nextSmallBlock(tmp); + } + if(i!=0) { + p=new unsigned char[i*0x40]; + i=0; + tmp=start; + while(tmp!=-2 && tmp>=0 && i<0x10000 && tmp<=static_cast<int>(maxSblock)) { + memcpy(&p[i*0x40], &smallBlockFile[tmp*0x40], 0x40); + tmp=nextSmallBlock(tmp); + ++i; + } + } + return p; +} + +void KLaola::readBigBlockDepot() { + if (num_of_bbd_blocks >= 0x800000) + return; + + bigBlockDepot=new unsigned char[0x200*num_of_bbd_blocks]; + for(unsigned int i=0; i<num_of_bbd_blocks; ++i) { + unsigned int offset = (bbd_list[i]+1)*0x200; + if (offset > m_file.length - 0x200) { + /* attempting to read past end of file */ + memset(&bigBlockDepot[i*0x200], 0, 0x200); + } + else { + memcpy(&bigBlockDepot[i*0x200], &m_file.data[offset], 0x200); + } + } +} + +void KLaola::readSmallBlockDepot() { + smallBlockDepot=const_cast<unsigned char*>(readBBStream(sbd_startblock)); +} + +void KLaola::readSmallBlockFile() { + smallBlockFile=const_cast<unsigned char*>(readBBStream( read32( (root_startblock+1)*0x200 + 0x74), true)); +} + +void KLaola::readRootList() { + + int pos=root_startblock; + int handle=0; + + while(pos!=-2 && pos>=0 && pos<=static_cast<int>(maxblock)) { + for(int i=0; i<4; ++i, ++handle) + readPPSEntry((pos+1)*0x200+0x80*i, handle); + pos=nextBigBlock(pos); + } + SubTree *subtree=new SubTree; + subtree->setAutoDelete(true); + m_nodeTree.append(subtree); + + createTree(0, 0); // build the tree with a recursive method :) +} + +// Add the given OLE node to the list of nodes. +void KLaola::readPPSEntry(int pos, const int handle) { + + int nameSize = read16(pos + 0x40); + + // Does the PPS Entry seem to be valid? + + if (nameSize) + { + int i; + Node *node = new Node(this); + + // The first character of the name can be a prefix. + node->m_prefix = static_cast<Prefix>(read16(pos)); + if (node->m_prefix <= RESERVED_LAST) + { + i = 1; + } + else + { + node->m_prefix = NONE; + i = 0; + } + + // Get the rest of the name. + for (; i < (nameSize / 2) - 1; ++i) + { + QChar tmp; + + tmp = read16(pos + 2 * i); + node->m_name += tmp; + } + node->m_handle = handle; + node->type = static_cast<NodeType>(read8(pos + 0x42)); + node->prevHandle = static_cast<int>(read32(pos + 0x44)); + node->nextHandle = static_cast<int>(read32(pos + 0x48)); + node->dirHandle = static_cast<int>(read32(pos + 0x4C)); + node->ts1s = static_cast<int>(read32(pos + 0x64)); + node->ts1d = static_cast<int>(read32(pos + 0x68)); + node->ts2s = static_cast<int>(read32(pos + 0x6C)); + node->ts2d = static_cast<int>(read32(pos + 0x70)); + node->sb = read32(pos + 0x74); + node->size = read32(pos + 0x78); + node->deadDir = false; + m_nodeList.append(node); + } +} + +myFile KLaola::stream(const OLENode *node) { + + const Node *realNode = dynamic_cast<const Node *>(node); + const unsigned char *temp; + myFile ret; + + if(ok) { + if(realNode->size>=0x1000) + temp = readBBStream(realNode->sb); + else + temp = readSBStream(realNode->sb); + ret.setRawData(temp, realNode->size); + } + return ret; +} + +myFile KLaola::stream(unsigned handle) { + + OLENode *node; + + node = m_nodeList.at(handle); + return stream(node); +} + +void KLaola::testIt(QString prefix) +{ + + NodeList nodes; + OLENode *node; + + nodes = parseCurrentDir(); + for (node = nodes.first(); node; node = nodes.next()) + { + kdDebug(s_area) << prefix + node->describe() << endl; + if (node->isDirectory()) + { + enterDir(node); + testIt(prefix + " "); + } + } +} + +// Return a human-readable description of a stream. +QString KLaola::Node::describe() const +{ + QString description; + myFile file; + unsigned i; + + description = QString::number(m_handle) + " " + + m_name + "(" + + QString::number(sb) + " " + + QString::number(size) + " bytes)"; + if (isDirectory()) + description += ", directory"; + switch (m_prefix) + { + case OLE_MANAGED_0: + description += ", OLE_0"; + break; + case CLSID: + description += ", CLSID="; + description += readClassStream(); + file = m_laola->stream(this); + description += ", "; + for (i = 16; i < file.length; i++) + { + description += QString::number((file.data[i] >> 4) & 0xf, 16); + description += QString::number(file.data[i] & 0xf, 16); + } + description += ", "; + for (i = 16; i < file.length; i++) + { + QChar tmp = file.data[i]; + + if (tmp.isPrint()) + description += tmp; + else + description += '.'; + } + break; + case OLE_MANAGED_2: + description += ", OLE_2"; + break; + case PARENT_MANAGED: + description += ", parent managed"; + break; + case STRUCTURED_STORAGE: + description += ", reserved 0x" + QString::number(m_prefix, 16); + break; + case NONE: + break; + default: + description += ", reserved 0x" + QString::number(m_prefix, 16); + break; + } + return description; +} + +QString KLaola::Node::name() const +{ + return m_name; +} + +// See "Associating Code with Storage" in Inside OLE. +QString KLaola::Node::readClassStream() const +{ + if (isDirectory()) + return QString::null; + if (m_prefix == CLSID) + { + myFile file; + unsigned i; + QString clsid; + + // CLSID format is: 00020900-0000-0000-C000-000000000046 + file = m_laola->stream(this); + for (i = 0; i < 4; i++) + { + clsid += QString::number((file.data[i] >> 4) & 0xf, 16); + clsid += QString::number(file.data[i] & 0xf, 16); + } + clsid += '-'; + for (; i < 6; i++) + { + clsid += QString::number((file.data[i] >> 4) & 0xf, 16); + clsid += QString::number(file.data[i] & 0xf, 16); + } + clsid += '-'; + for (; i < 8; i++) + { + clsid += QString::number((file.data[i] >> 4) & 0xf, 16); + clsid += QString::number(file.data[i] & 0xf, 16); + } + clsid += '-'; + for (; i < 10; i++) + { + clsid += QString::number((file.data[i] >> 4) & 0xf, 16); + clsid += QString::number(file.data[i] & 0xf, 16); + } + clsid += '-'; + for (; i < 16; i++) + { + clsid += QString::number((file.data[i] >> 4) & 0xf, 16); + clsid += QString::number(file.data[i] & 0xf, 16); + } + return clsid; + } + return QString::null; +} diff --git a/filters/olefilters/lib/klaola.h b/filters/olefilters/lib/klaola.h new file mode 100644 index 000000000..816a76667 --- /dev/null +++ b/filters/olefilters/lib/klaola.h @@ -0,0 +1,193 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <trobin@kde.org> + + 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. + +DESCRIPTION + + This class is used to decode OLE 2 streams. When instantiated, it + constructs an internal "filesystem" that corresponds to the OLE storage + tree. This tree can be navigated, and the individual OLE streams + returned as a linear memory buffer. +*/ + +#ifndef KLAOLA_H +#define KLAOLA_H + +#include <myfile.h> +#include <qstring.h> +#include <qptrlist.h> + +class KLaola { + +public: + KLaola(const myFile &file); // see myfile.h! + ~KLaola(); + + bool isOk() {return ok;} + + // A class representing an abstracted node in the OLE filesystem. + + class OLENode { + public: + virtual ~OLENode() {}; + virtual unsigned handle() const = 0; + virtual QString name() const = 0; + + // Does the node represent a stream datum, or a storage container + // of data? + virtual bool isDirectory() const = 0; + + // If isDirectory() is true, return the CLSID associated with + // any child CompObj node. If the Node is a CompObj, return + // its CLSID. Otherwise return QString::null. + // + // The CLSID is returned in the form: + // + // 00020900-0000-0000-C000-000000000046 + // + virtual QString readClassStream() const = 0; + + // Return a human-readable description of a stream. + virtual QString describe() const = 0; + protected: + OLENode() {} + }; + + // Wade through the "file system" + + typedef QPtrList<OLENode> NodeList; + NodeList parseRootDir(); + NodeList parseCurrentDir(); + const NodeList currentPath() const; + const NodeList find(const QString &name, bool onlyCurrentDir=false); + bool enterDir(const OLENode *node); + bool leaveDir(); + + // Return the stream for a given node. + // + // Note: data - 512 byte blocks, but length is set correctly :) + myFile stream(const OLENode *node); + myFile stream(unsigned handle); + +private: + KLaola(const KLaola &); + const KLaola &operator=(const KLaola &); + static const int s_area; + + unsigned char read8(int i) const; + unsigned short read16(int i) const; + unsigned int read32(int i) const; + + // Parsing functions. + bool parseHeader(); + void readBigBlockDepot(); + void readSmallBlockDepot(); + void readSmallBlockFile(); + void readRootList(); + void readPPSEntry(int pos, const int handle); + void createTree(const int handle, const short index); + const unsigned char *readBBStream(int start, bool setmaxSblock=false); + const unsigned char *readSBStream(int start) const; + int nextBigBlock(int pos) const; + int nextSmallBlock(int pos) const; + + // Dump the parsed structure info (similar to "lls" + // of the LAOLA-project). + void testIt(QString prefix = ""); + +public: + typedef enum + { + DIRECTORY = 1, + FILE = 2, + ROOT_ENTRY = 5 + } NodeType; + + // If the first part of an on-disk name is less than 32, it is a prefix. + typedef enum + { + OLE_MANAGED_0, + CLSID, + OLE_MANAGED_2, + PARENT_MANAGED, // Marks an element as owned by the code that + // manages the parent storage of that element. + STRUCTURED_STORAGE, // For the exclusive use of the Structured Storage + // implementation. + RESERVED_FIRST, + RESERVED_LAST = 31, + NONE = 32 + } Prefix; + + class Node: public OLENode { + public: + Node(KLaola *laola) { m_laola = laola; } + ~Node() {} + unsigned handle() const { return m_handle; } + QString name() const; + bool isDirectory() const { return (type == DIRECTORY) || (type == ROOT_ENTRY); } + QString readClassStream() const; + QString describe() const; + + KLaola *m_laola; + unsigned m_handle; // PPS entry number + Prefix m_prefix; + QString m_name; + NodeType type; + int prevHandle; // Last pps + int nextHandle; // Next pps + int dirHandle; // Dir pps + int ts1s; // Timestamp 1, seconds + int ts1d; // Timestamp 1, days + int ts2s; // Timestamp 2, seconds + int ts2d; // Timestamp 2, days + unsigned sb; // Starting block + unsigned size; // Size of property + bool deadDir; // true, if the dir is a "dead end" + }; + +private: + // Lists of nodes. + + NodeList m_nodeList; + NodeList m_currentPath; + + // The OLE storage is represented as a tree. Each node in the tree may + // refer to a subtree. Each subtree is stored as a list of nodes. + + struct TreeNode + { + Node *node; + short subtree; + }; + typedef QPtrList<TreeNode> SubTree; + QPtrList<SubTree> m_nodeTree; + + bool ok; // is the file OK? + + myFile m_file; + unsigned char *bigBlockDepot; + unsigned char *smallBlockDepot; + unsigned char *smallBlockFile; + + unsigned int maxblock; // maximum number of big-blocks + unsigned int maxSblock; // small-blocks + unsigned int num_of_bbd_blocks; // number of big block depot blocks + unsigned int root_startblock; // Root chain's first big block + unsigned int sbd_startblock; // small block depot's first big block + unsigned int *bbd_list; //array of num_of_bbd_blocks big block numbers +}; +#endif // KLAOLA_H diff --git a/filters/olefilters/lib/myfile.h b/filters/olefilters/lib/myfile.h new file mode 100644 index 000000000..7be578b35 --- /dev/null +++ b/filters/olefilters/lib/myfile.h @@ -0,0 +1,49 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <trobin@kde.org> + + 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. + +DESCRIPTION + + A data-structure to hold the file data for an OLE stream. Shared storage is + used to implement reference counting and storage reclamation. +*/ + +#ifndef MYFILE_H +#define MYFILE_H + +#include <qcstring.h> + +class myFile: public QByteArray +{ +public: + myFile() { data = 0L; length = 0; } + + // NOTE: this implementation may look completely ugly, but its features are + // mostly for backwards compatibility. If you feel like cleaning up, be my + // guest! + + const unsigned char *data; + unsigned int length; + + void setRawData(const unsigned char *data, unsigned length) + { + this->data = data; + this->length = length; + QByteArray::setRawData((const char *)data, length); + } +}; +#endif // MYFILE_H diff --git a/filters/olefilters/olefilter.cc b/filters/olefilters/olefilter.cc new file mode 100644 index 000000000..3d671ecbf --- /dev/null +++ b/filters/olefilters/olefilter.cc @@ -0,0 +1,525 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <trobin@kde.org> + + 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. + +DESCRIPTION + + When reading, the point of this module is toperform a depth-first traversal + of an OLE file. This ensures that a parent object is processed only after + its child objects have been processed. +*/ + +#include <olefilter.h> + +#include <qfile.h> +#include <ktempfile.h> +#include <kgenericfactory.h> +#include <kmimetype.h> +#include <KoFilterChain.h> +#include <KoDocumentInfo.h> + +//#include <excelfilter.h> +#include <powerpointfilter.h> +//#include <wordfilter.h> +//#include <hancomwordfilter.h> + +#include <myfile.h> + +const int OLEFilter::s_area = 30510; + +class OLEFilterFactory : KGenericFactory<OLEFilter, KoFilter> +{ +public: + OLEFilterFactory(void) : KGenericFactory<OLEFilter, KoFilter> ("olefilter") + {} +protected: + virtual void setupTranslations( void ) + { + KGlobal::locale()->insertCatalogue( "kofficefilters" ); + } +}; + +K_EXPORT_COMPONENT_FACTORY( libolefilter, OLEFilterFactory() ) + +OLEFilter::OLEFilter(KoFilter *, const char *, const QStringList&) : + KoEmbeddingFilter(), numPic( 0 ), + docfile( 0 ), m_embeddeeData( 0 ), + m_embeddeeLength( 0 ), success( true ) +{ + olefile.data=0L; +} + +OLEFilter::~OLEFilter() +{ + delete [] olefile.data; + delete docfile; +} + +KoFilter::ConversionStatus OLEFilter::convert( const QCString& from, const QCString& to ) +{ + if(to!="application/x-kword" && + to!="application/x-kspread" && + to!="application/x-kpresenter") + return KoFilter::NotImplemented; + if(from!="application/vnd.ms-word" && + from!="application/vnd.ms-excel" && + from!="application/msword" && + from!="application/msexcel" && + from!="application/mspowerpoint" && + from!="application/x-hancomword") + return KoFilter::NotImplemented; + + QFile in(m_chain->inputFile()); + if(!in.open(IO_ReadOnly)) { + kdError(s_area) << "OLEFilter::filter(): Unable to open input" << endl; + in.close(); + return KoFilter::FileNotFound; + } + + // Open the OLE 2 file. [TODO] Is it really the best way to + // read all the stuff without buffer? + olefile.length=in.size(); + olefile.data=new unsigned char[olefile.length]; + in.readBlock((char*)olefile.data, olefile.length); + in.close(); + + docfile=new KLaola(olefile); + if(!docfile->isOk()) { + kdError(s_area) << "OLEFilter::filter(): Unable to read input file correctly!" << endl; + delete [] olefile.data; + olefile.data=0L; + return KoFilter::StupidError; + } + + // Recursively convert the file + convert( "" ); + if ( success ) + return KoFilter::OK; + else + return KoFilter::StupidError; +} + +void OLEFilter::commSlotDelayStream( const char* delay ) +{ + emit internalCommDelayStream( delay ); +} + +void OLEFilter::commSlotShapeID( unsigned int& shapeID ) +{ + emit internalCommShapeID( shapeID ); +} + +void OLEFilter::slotSavePart( + const QString &nameIN, + QString &storageId, + QString &mimeType, + const QString &extension, + unsigned int length, + const char *data) +{ + if(nameIN.isEmpty()) + return; + + int id = internalPartReference( nameIN ); + + if (id != -1) + { + // The part is already there, this is a lookup operation + // -> return the part id. + storageId = QString::number( id ); + mimeType = internalPartMimeType( nameIN ); + } + else + { + // Set up the variables for the template method callback + m_embeddeeData = data; + m_embeddeeLength = length; + + QString srcMime( KoEmbeddingFilter::mimeTypeByExtension( extension ) ); + if ( srcMime == KMimeType::defaultMimeType() ) + kdWarning( s_area ) << "Couldn't determine the mimetype from the extension" << endl; + + KoFilter::ConversionStatus status; + QCString destMime( mimeType.latin1() ); + storageId = QString::number( embedPart( srcMime.latin1(), destMime, status, nameIN ) ); + + // copy back what the method returned + mimeType = destMime; + + // Reset the variables to be on the safe side + m_embeddeeData = 0; + m_embeddeeLength = 0; + + if ( status != KoFilter::OK ) + kdDebug(s_area) << "Huh??? Couldn't convert that file" << endl; + } +} + +void OLEFilter::slotSaveDocumentInformation( + const QString &fullName, + const QString &title, + const QString &company, + const QString &email, + const QString &telephone, + const QString &fax, + const QString &postalCode, + const QString &country, + const QString &city, + const QString &street, + const QString &docTitle, + const QString &docAbstract) +{ + KoDocumentInfo *info = new KoDocumentInfo(); + KoDocumentInfoAuthor *author = static_cast<KoDocumentInfoAuthor *>(info->page("author")); + KoDocumentInfoAbout *about = static_cast<KoDocumentInfoAbout *>(info->page("about")); + author->setFullName(fullName); + author->setTitle(title); + author->setCompany(company); + author->setEmail(email); + author->setTelephoneHome(telephone); + author->setFax(fax); + author->setCountry(postalCode); + author->setPostalCode(country); + author->setCity(city); + author->setStreet(street); + about->setTitle(docTitle); + about->setTitle(docAbstract); + + KoStoreDevice* docInfo = m_chain->storageFile( "documentinfo.xml", KoStore::Write ); + + if(!docInfo) + { + kdError(s_area) << "OLEFilter::slotSaveDocumentInformation(): Could not open documentinfo.xml!" << endl; + return; + } + + QCString data = info->save().toCString(); + // Important: don't use data.length() here. It's slow, and dangerous (in case of a '\0' somewhere) + // The -1 is because we don't want to write the final \0. + Q_LONG length = data.size()-1; + + if(docInfo->writeBlock(data, length) != length) + kdError(s_area) << "OLEFilter::slotSaveDocumentInformation(): Could not write to KoStore!" << endl; +} + +void OLEFilter::slotSavePic( + const QString &nameIN, + QString &storageId, + const QString &extension, + unsigned int length, + const char *data) +{ + if(nameIN.isEmpty()) + return; + + QMap<QString, QString>::ConstIterator it = imageMap.find(nameIN); + + if (it != imageMap.end()) + // The key is already here - return the part id. + storageId = it.data(); + else + { + // It's not here, so let's generate one. + storageId = QString( "pictures/picture%1.%2" ).arg( numPic++ ).arg( extension ); + imageMap.insert(nameIN, storageId); + KoStoreDevice* pic = m_chain->storageFile( storageId, KoStore::Write ); + if(!pic) + { + success = false; + kdError(s_area) << "OLEFilter::slotSavePic(): Could not open KoStore!" << endl; + return; + } + // Write it to the gzipped tar file + // Let's hope we never have to save images bigger than 2GB :-) + bool ret = pic->writeBlock(data, length) == static_cast<int>( length ); + if (!ret) + kdError(s_area) << "OLEFilter::slotSavePic(): Could not write to KoStore!" << endl; + } +} + +// ##### Only used for lookup now! +void OLEFilter::slotPart( + const QString& nameIN, + QString &storageId, + QString &mimeType) +{ + if (nameIN.isEmpty()) + return; + + int id = internalPartReference( nameIN ); + + if (id != -1) + { + // The key is already here - return the part id. + storageId = QString::number( id ); + mimeType = internalPartMimeType( nameIN ); + } + else + kdWarning( s_area ) << "slotPart() can be used for lookup operations only" << endl; +} + +// Don't forget the delete [] the stream.data ptr! +void OLEFilter::slotGetStream(const int &handle, myFile &stream) { + stream=docfile->stream(handle); +} + +// I can't guarantee that you get the right stream as the names +// in a OLE 2 file are not unique! (searching only the current dir!) +// Don't forget the delete [] the stream.data ptr! +void OLEFilter::slotGetStream(const QString &name, myFile &stream) { + + KLaola::NodeList handle; + + handle=docfile->find(name, true); // search only in current dir! + + if (handle.count()==1) + stream=docfile->stream(handle.at(0)); + else { + stream.data=0L; + stream.length=0; + } +} + +void OLEFilter::savePartContents( QIODevice* file ) +{ + if ( m_embeddeeData != 0 && m_embeddeeLength != 0 ) + file->writeBlock( m_embeddeeData, m_embeddeeLength ); +} + +// The recursive method to do all the work +void OLEFilter::convert( const QCString& mimeTypeHint ) +{ + KLaola::NodeList list=docfile->parseCurrentDir(); + KLaola::OLENode *node; + bool onlyDirs=true; + + // Search for the directories + for(node=list.first(); node!=0; node=list.next()) { + if(node->isDirectory()) { // It's a dir! + if(docfile->enterDir(node)) { + // Go one level deeper, but don't increase the depth + // for ObjectPools. + if (node->name() == "ObjectPool") + convert( "" ); + else { + // Get the storage name of the part (dirname==key), and associate the + // mimeType with it for later use. + QCString mimeHint( mimeTypeHelper() ); + if ( mimeHint.isEmpty() ) + mimeHint = "application/x-kword"; // will be converted to a dummy KWord part + startInternalEmbedding( node->name(), mimeHint ); + convert( mimeHint ); + endInternalEmbedding(); + } + docfile->leaveDir(); + } + } + else + onlyDirs=false; // To prevent useless looping in the next loop + } + + if(!onlyDirs) { + QStringList nodeNames; + QCString mimeType; + if ( !mimeTypeHint.isEmpty() ) + mimeType = mimeTypeHint; + else + mimeType = mimeTypeHelper(); + + FilterBase *myFilter=0L; + + #if 0 + if ( mimeType == "application/x-kword" ) { + // WinWord (or dummy). + + myFile main; + KLaola::NodeList tmp; + tmp=docfile->find("WordDocument", true); + + if(tmp.count()==1) { + // okay, not a dummy + main=docfile->stream(tmp.at(0)); + + myFile table0, table1, data; + tmp=docfile->find("0Table", true); + if(tmp.count()==1) + table0=docfile->stream(tmp.at(0)); + + tmp=docfile->find("1Table", true); + if(tmp.count()==1) + table1=docfile->stream(tmp.at(0)); + + tmp=docfile->find("Data", true); + if(tmp.count()==1) + data=docfile->stream(tmp.at(0)); + + myFilter=new WordFilter(main, table0, table1, data); + + // forward the internal communication calls + connect( this, SIGNAL( internalCommShapeID( unsigned int& ) ), myFilter, SIGNAL( internalCommShapeID( unsigned int& ) ) ); + connect( this, SIGNAL( internalCommDelayStream( const char* ) ), myFilter, SIGNAL( internalCommDelayStream( const char* ) ) ); + } + } + else if ( mimeType == "application/x-kspread" ) { + // Excel. + + myFile workbook; + KLaola::NodeList tmp; + + tmp = docfile->find( "Workbook", true ); + if ( tmp.count() == 1 ) + workbook = docfile->stream( tmp.at( 0 ) ); + else { + tmp = docfile->find( "Book", true ); + if ( tmp.count() == 1 ) + workbook = docfile->stream( tmp.at( 0 ) ); + } + myFilter=new ExcelFilter(workbook); + } + else + #endif + if ( mimeType == "application/x-kpresenter" ) { + // Powerpoint. + + myFile main, currentUser, pictures, summary, documentSummary; + KLaola::NodeList tmp; + + tmp=docfile->find("PowerPoint Document", true); + if(tmp.count()==1) + main=docfile->stream(tmp.at(0)); + + tmp=docfile->find("Current User", true); + if(tmp.count()==1) + currentUser=docfile->stream(tmp.at(0)); + + tmp=docfile->find("Pictures", true); + if(tmp.count()==1) + pictures=docfile->stream(tmp.at(0)); + + tmp=docfile->find("SummaryInformation", true); + if(tmp.count()==1) + summary=docfile->stream(tmp.at(0)); + + tmp=docfile->find("DocumentSummaryInformation", true); + if(tmp.count()==1) + documentSummary=docfile->stream(tmp.at(0)); + + myFilter=new PowerPointFilter(main, currentUser, pictures); + } + #if 0 + else if ( mimeType == "application/x-hancomword" ) { + // HancomWord 6 + myFile prvText; + KLaola::NodeList tmp; + + tmp = docfile->find( "PrvText", true ); + if( tmp.count() == 1 ) prvText = docfile->stream( tmp.at( 0 ) ); + + myFilter = new HancomWordFilter( prvText ); + } + #endif + + if(!myFilter) { + // Unknown type. We turn it into a dummy kword document... + node = list.first(); + do { + nodeNames.prepend(node->name()); + node = list.next(); + } while ( node ); + + kdWarning(s_area) << "cannot convert \"" << nodeNames.join(",") << "\"" << endl; + myFilter=new FilterBase(nodeNames); + } + + // connect SIGNALs&SLOTs + connectCommon(&myFilter); + + // Launch the filtering process... + success=myFilter->filter(); + // ...and fetch the file + QCString file; + if(!myFilter->plainString()) { + const QDomDocument * const part=myFilter->part(); + file=part->toCString(); + } + else + file=myFilter->CString(); + + KoStoreDevice* dev = m_chain->storageFile( "root", KoStore::Write ); + if(!dev) { + success=false; + kdError(s_area) << "OLEFilter::convert(): Could not open KoStore!" << endl; + return; + } + + // Write it to the gzipped tar file + bool ret = dev->writeBlock(file.data(), file.size()-1) == static_cast<Q_LONG>( file.size() - 1 ); + if (!ret) + kdError(s_area) << "OLEFilter::slotSavePic(): Could not write to KoStore!" << endl; + delete myFilter; + } +} + +void OLEFilter::connectCommon(FilterBase **myFilter) { + QObject::connect( + *myFilter, + SIGNAL(signalSaveDocumentInformation(const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &)), + this, + SLOT(slotSaveDocumentInformation(const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &, const QString &))); + + QObject::connect( + *myFilter, + SIGNAL(signalSavePic(const QString &, QString &, const QString &, unsigned int, const char *)), + this, + SLOT(slotSavePic(const QString &, QString &, const QString &, unsigned int, const char *))); + QObject::connect( + *myFilter, + SIGNAL(signalSavePart(const QString &, QString &, QString &, const QString &, unsigned int, const char *)), + this, + SLOT(slotSavePart(const QString &, QString &, QString &, const QString &, unsigned int, const char *))); + QObject::connect(*myFilter, SIGNAL(signalPart(const QString&, QString &, QString &)), + this, SLOT(slotPart(const QString&, QString &, QString &))); + QObject::connect(*myFilter, SIGNAL(signalGetStream(const int &, myFile &)), this, + SLOT(slotGetStream(const int &, myFile &))); + QObject::connect(*myFilter, SIGNAL(signalGetStream(const QString &, myFile &)), this, + SLOT(slotGetStream(const QString &, myFile &))); + QObject::connect(*myFilter, SIGNAL(sigProgress(int)), this, SIGNAL(sigProgress(int))); +} + +QCString OLEFilter::mimeTypeHelper() +{ + KLaola::NodeList list = docfile->parseCurrentDir(); + KLaola::OLENode* node = list.first(); + + // ###### FIXME: Shaheed, please add additional mimetypes here + while ( node ) { + if ( node->name() == "WordDocument" ) + return "application/x-kword"; + else if ( node->name() == "Workbook" || node->name() == "Book" ) + return "application/x-kspread"; + else if ( node->name() == "PowerPoint Document" ) + return "application/x-kpresenter"; + else if ( node->name() == "PrvText" || node->name() == "BodyText" ) + return "application/x-hancomword"; + else + node = list.next(); + } + kdWarning( s_area ) << "No known mimetype detected" << endl; + return ""; +} + +#include <olefilter.moc> diff --git a/filters/olefilters/olefilter.h b/filters/olefilters/olefilter.h new file mode 100644 index 000000000..a1509973f --- /dev/null +++ b/filters/olefilters/olefilter.h @@ -0,0 +1,131 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <trobin@kde.org> + + 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. +*/ + +// The OLEFilter class is the main filtering class. It manages the +// correct handling of the input and output file and provides the +// OLE 2 streams for the real filters (excel97, powerpoint97, winword97) + +#ifndef OLEFILTER_H +#define OLEFILTER_H + +#include <filterbase.h> +#include <KoFilter.h> +#include <klaola.h> + +class KoStore; + +class OLEFilter : public KoEmbeddingFilter { + + Q_OBJECT + +public: + OLEFilter(KoFilter *parent, const char *name, const QStringList&); + virtual ~OLEFilter(); + + virtual KoFilter::ConversionStatus convert( const QCString& from, const QCString& to ); + +public slots: + void commSlotDelayStream( const char* delay ); + void commSlotShapeID( unsigned int& shapeID ); + +protected slots: + // This slot saves the document informations to the KOffice tar storage. + void slotSaveDocumentInformation( + const QString &fullName, + const QString &title, + const QString &company, + const QString &email, + const QString &telephone, + const QString &fax, + const QString &postalCode, + const QString &country, + const QString &city, + const QString &street, + const QString &docTitle, + const QString &docAbstract); + + // This slot saves an embedded Picture to the KOffice tar storage. + void slotSavePic( + const QString &nameIN, + QString &storageId, + const QString &extension, + unsigned int length, + const char *data); + + // This slot saves an embedded object to the KOffice tar storage. Note that + // this only applies to objects within an OLE stream (like embedded WMFs) + // that we want to handle as parts rather than using slotSavePic() since OLE + // objects are handled by us, and a filter need only call slotPart(). + void slotSavePart( + const QString &nameIN, + QString &storageId, + QString &mimeType, + const QString &extension, + unsigned int length, + const char *data); + + // Generate a name for a new part to store it in the KOffice tar storage, + // or find the name and type of an existing one. + void slotPart( + const QString &nameIN, + QString &storageId, + QString &mimeType); + + // Get another OLE 2 stream for your filter. + // Attention: You'll have to delete [] the stream.data ptr! + void slotGetStream(const int &handle, myFile &stream); + + // Like above. Note: This method might return the wrong stream + // as the stream names are NOT unique in the OLE 2 file!!! + // (Therefore it's searching only in the current dir) + // Attention: You'll have to delete [] the stream.data ptr! + void slotGetStream(const QString &name, myFile &stream); + +signals: + // Forwarding signals for inter-filter communication + void internalCommShapeID( unsigned int& shapeID ); + void internalCommDelayStream( const char* delay ); + +private: + // Don't copy or assign me >:) + OLEFilter(const OLEFilter &); + const OLEFilter &operator=(const OLEFilter &); + + // Template method, triggered by embedPart calls + virtual void savePartContents( QIODevice* file ); + + void convert( const QCString& mimeTypeHint ); + void connectCommon(FilterBase **myFilter); + QCString mimeTypeHelper(); + + QMap<QString, QString> imageMap; + + myFile olefile; + int numPic; // for the "unique name generation" + KLaola *docfile; // used to split up the OLE 2 file + + // Needed for the template method callback savePartContents + const char* m_embeddeeData; + unsigned int m_embeddeeLength; + + bool success; + static const int s_area; +}; + +#endif // OLEFILTER_H diff --git a/filters/olefilters/powerpoint97/Makefile.am b/filters/olefilters/powerpoint97/Makefile.am new file mode 100644 index 000000000..d0c3fc2ba --- /dev/null +++ b/filters/olefilters/powerpoint97/Makefile.am @@ -0,0 +1,17 @@ +####### General stuff + +INCLUDES= -I$(srcdir) -I$(srcdir)/../lib $(KOFFICE_INCLUDES) $(all_includes) + +####### Files + +noinst_LTLIBRARIES = libpowerpoint97.la + +libpowerpoint97_la_SOURCES = powerpointfilter.cc powerpoint.cc pptdoc.cc pptxml.cc pptSlide.cpp +libpowerpoint97_la_LDFLAGS = $(all_libraries) + +noinst_HEADERS = powerpointfilter.h powerpoint.h pptdoc.h pptxml.h pptSlide.h + +METASOURCES = AUTO + +service_DATA = ole_powerpoint97_import.desktop +servicedir = $(kde_servicesdir) diff --git a/filters/olefilters/powerpoint97/README b/filters/olefilters/powerpoint97/README new file mode 100644 index 000000000..9a667e75c --- /dev/null +++ b/filters/olefilters/powerpoint97/README @@ -0,0 +1,47 @@ +The Powerpoint filter design has these components: + +powerpointfilter.h +powerpoint.h +pptdoc.h +pptxml.h + +These are described in turn below. + +powerpointfilter.h +================== + +This is the interface to the KOffice filter architecture. It is invoked from +olefilter when an OLE file is detected to have a Powerpoint document in it. + +powerpoint.h +============ + +This is the actual parser. It is designed to walk the Powerpoint file and is +not intended to have much embedded knowledge beyond that required to invoke +a series of virtual functions when it recognises low level objects. See also +pptdoc.h. + +In principle, each record in the Powerpoint file is modelled as a structure +defined in powerpoint.h, as well as a virtual function callback to output it. +In practice, this is true only of records that contain data. Records that are +simply containers for other records don't have an associated structure, but +instead have two callbacks, one each marking entry to and exit from the +container. + +pptdoc.h +======== + +The purpose of pptdoc.h is to take the output from powerpoint.h and create a +high level interface to the Powerpoint file contents. The idea is that it can +take the low output from powerpoint.h and aggregate it into objects at a more +useful level of abstraction. + +The output of this is again via a series of virtual function callbacks. +Subclasses of pptdoc.h can simply override the callbacks for the objects of +interest. + +pptxml.h +======== + +This is a subclass of pptdoc.h that produces kpresenter-compatible XML which +is delivered to kpresenter via powerpointfilter.h. diff --git a/filters/olefilters/powerpoint97/ole_powerpoint97_import.desktop b/filters/olefilters/powerpoint97/ole_powerpoint97_import.desktop new file mode 100644 index 000000000..f89271205 --- /dev/null +++ b/filters/olefilters/powerpoint97/ole_powerpoint97_import.desktop @@ -0,0 +1,67 @@ +[Desktop Entry] +Type=Service +Name=KPresenter PowerPoint 97 Filter +Name[af]=Kpresenter Powerpoint 97 Filter +Name[az]=KPresenter PowerPoint 97 Süzgəci +Name[bg]=Филтър за експортиране от KPresenter в PowerPoint 97 +Name[br]=Sil PowerPoint 97 KPresenter +Name[ca]=Filtre d'exportació PowerPoint 97 per a KPresenter +Name[cy]=Hidlen PowerPoint 97 KPresenter +Name[de]=KPresenter PowerPoint97-Filter +Name[el]=Φίλτρο εξαγωγής PowerPoint 97 του KPresenter +Name[eo]=KPresenter PowerPoint-97-filtrilo +Name[es]=Filtro de PowerPoint 97 para KPresenter +Name[et]=KPresenteri PowerPoint 97 filter +Name[eu]=KPresenter-en PowerPoint 97 iragazkia +Name[fa]=پالایۀ KPresenter PowerPoint 97 +Name[fr]=Filtre d'exportation PowerPoint 97 de KPresenter +Name[fy]=PowerPoint 97-filter foar KPresenter +Name[ga]=Scagaire PowerPoint 97 le haghaidh KPresenter +Name[gl]=Filtro de PowerPoint 97 para KPresenter +Name[hi]=के-प्रेज़ेन्टर पावरपाइंट 97 छननी +Name[hr]=KPresenter PowerPoint 97 filtar +Name[hu]=KPresenter PowerPoint 97 importszűrő +Name[id]=Filter PowerPoint 97 KPresenter +Name[is]=PowerPoint 97 sÃa f. KPresenter +Name[it]=Filtro PowerPoint 97 per KPresenter +Name[ja]=KPresenter PowerPoint 97 エクスポートフィルタ +Name[km]=តម្រង KPresenter PowerPoint 97 +Name[lo]=ຕົວຕອງ PowerPoint 97 ຂອງການນຳສະເໝK +Name[lt]=KPresenter PowerPoint 97 filtras +Name[lv]=KPresenter PowerPoint 97 filtrs +Name[mk]=KPresenter PowerPoint 97 филтер +Name[ms]=Penapis KPresenter PowerPoint 97 +Name[mt]=Filtru PowerPoint 97 għal KPresenter +Name[nb]=PowerPoint 97-filter for KPresenter +Name[nds]=PowerPoint97-Filter för KPresenter +Name[ne]=केडीई प्रस्तुतकर्ता पावरपोइन्ट ९७ फिल्टर +Name[nl]=PowerPoint 97-filter voor KPresenter +Name[nn]=PowerPoint 97-filter for KPresenter +Name[pl]=Filtr PowerPoint 97 dla KPresenter +Name[pt]=Filtro de PowerPoint 97 para o KPresenter +Name[pt_BR]=Filtro de PowerPoint 97 para o KPresenter +Name[ro]=Filtru KPresenter pentru PowerPoint 97 +Name[ru]=Фильтр импорта презентаций PowerPoint 97 в KPresenter +Name[se]=KPresenter:a PowerPoint 97 silli +Name[sk]=PowerPoint 97 Filter pre KPresenter +Name[sl]=Filter za PowerPoint 97 v KPresenteru +Name[sr]=KPresenter-ов филтер за PowerPoint 97 +Name[sr@Latn]=KPresenter-ov filter za PowerPoint 97 +Name[sv]=Kpresenter PowerPoint 97-filter +Name[ta]=KPresenter PowerPoint 97 வடிகட்டி +Name[tg]=Филтри KPresenter PowerPoint 97 +Name[th]=ตัวกรอง PowerPoint 97 ของการนำเสนอ K +Name[tr]=KPresenter PowerPoint 97 Filtresi +Name[uk]=Фільтр PowerPoint 97 для KPresenter +Name[uz]=KPresenter PowerPoint 97 filteri +Name[uz@cyrillic]=KPresenter PowerPoint 97 филтери +Name[ven]=Mulanguli wa K fhethu ha maanda 97 filithara +Name[wa]=Passete PowerPoint 97 po KPresenter +Name[xh]=Isihluzi se KPresenter PowerPoint 97 +Name[zh_TW]=KPresenter PowerPoint 97 過濾程式 +Name[zu]=KPresenter PowerPoint 97 Icebo lokuhlaziya ifayela +X-KDE-Export=application/x-kpresenter +X-KDE-Import=application/mspowerpoint +X-KDE-Weight=1 +X-KDE-Library=libolefilter +ServiceTypes=KOfficeFilter diff --git a/filters/olefilters/powerpoint97/powerpoint.cc b/filters/olefilters/powerpoint97/powerpoint.cc new file mode 100644 index 000000000..f01c71c78 --- /dev/null +++ b/filters/olefilters/powerpoint97/powerpoint.cc @@ -0,0 +1,1303 @@ +/* + Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>. + This file is part of the KDE project + + 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. + +DESCRIPTION +*/ + +#include <kdebug.h> +#include <myfile.h> +#include <powerpoint.h> + +const int Powerpoint::s_area = 30512; + +Powerpoint::Powerpoint() +{ + mEditOffset = 0; + m_pptSlide = 0; +} + +Powerpoint::~Powerpoint() +{ + m_persistentReferences.clear(); + //m_slides.clear(); +} + +void Powerpoint::invokeHandler( + Header &op, + Q_UINT32 bytes, + QDataStream &operands) +{ + typedef void (Powerpoint::*method)(Header &op, Q_UINT32 bytes, QDataStream &operands); + + typedef struct + { + const char *name; + Q_UINT16 opcode; + method handler; + } opcodeEntry; + + static const opcodeEntry funcTab[] = + { + { "ANIMATIONINFO", 4116, 0 /* &Powerpoint::opAnimationInfo */ }, + { "ANIMATIONINFOATOM", 4081, 0 /* &Powerpoint::opAnimationInfoAtom */ }, + { "ARRAYELEMENTATOM", 2030, 0 /* &Powerpoint::opArrayElementAtom */ }, + { "BASETEXTPROPATOM", 4002, 0 /* &Powerpoint::opBaseTextPropAtom */ }, + { "BINARYTAGDATA", 5003, 0 /* &Powerpoint::opBinaryTagData */ }, + { "BOOKMARKCOLLECTION", 2019, 0 /* &Powerpoint::opBookmarkCollection */ }, + { "BOOKMARKENTITYATOM", 4048, 0 /* &Powerpoint::opBookmarkEntityAtom */ }, + { "BOOKMARKSEEDATOM", 2025, 0 /* &Powerpoint::opBookmarkSeedAtom */ }, + { "CHARFORMATATOM", 4066, 0 /* &Powerpoint::opCharFormatAtom */ }, + { "CLIENTSIGNAL1", 6, 0 /* &Powerpoint::opClientSignal1 */ }, + { "CLIENTSIGNAL2", 7, 0 /* &Powerpoint::opClientSignal2 */ }, + { "COLORSCHEMEATOM", 2032, &Powerpoint::opColorSchemeAtom }, + { "COREPICT", 4037, 0 /* &Powerpoint::opCorePict */ }, + { "COREPICTATOM", 4038, 0 /* &Powerpoint::opCorePictAtom */ }, + { "CSTRING", 4026, &Powerpoint::opCString }, + { "CURRENTUSERATOM", 4086, &Powerpoint::opCurrentUserAtom }, + { "DATETIMEMCATOM", 4087, 0 /* &Powerpoint::opDateTimeMCAtom */ }, + { "DEFAULTRULERATOM", 4011, 0 /* &Powerpoint::opDefaultRulerAtom */ }, + { "DOCROUTINGSLIP", 1030, 0 /* &Powerpoint::opDocRoutingSlip */ }, + { "DOCUMENT", 1000, &Powerpoint::opDocument }, + { "DOCUMENTATOM", 1001, &Powerpoint::opDocumentAtom }, + { "DOCVIEWINFO", 1014, 0 /* &Powerpoint::opDocViewInfo */ }, + { "EMFORMATATOM", 4065, 0 /* &Powerpoint::opEmFormatAtom */ }, + { "ENDDOCUMENT", 1002, &Powerpoint::opEndDocument }, + { "ENVIRONMENT", 1010, &Powerpoint::opEnvironment }, + { "EXAVIMOVIE", 4102, 0 /* &Powerpoint::opExAviMovie */ }, + { "EXCDAUDIO", 4110, 0 /* &Powerpoint::opExCDAudio */ }, + { "EXCDAUDIOATOM", 4114, 0 /* &Powerpoint::opExCDAudioAtom */ }, + { "EXCONTROL", 4078, 0 /* &Powerpoint::opExControl */ }, + { "EXCONTROLATOM", 4091, 0 /* &Powerpoint::opExControlAtom */ }, + { "EXEMBED", 4044, &Powerpoint::opExEmbed }, + { "EXEMBEDATOM", 4045, &Powerpoint::opExEmbedAtom }, + { "EXHYPERLINK", 4055, 0 /* &Powerpoint::opExHyperlink */ }, + { "EXHYPERLINKATOM", 4051, 0 /* &Powerpoint::opExHyperlinkAtom */ }, + { "EXLINK", 4046, 0 /* &Powerpoint::opExLink */ }, + { "EXLINKATOM", 4049, 0 /* &Powerpoint::opExLinkAtom */ }, + { "EXLINKATOM_OLD", 4047, 0 /* &Powerpoint::opExLinkAtom_old */ }, + { "EXMCIMOVIE", 4103, 0 /* &Powerpoint::opExMCIMovie */ }, + { "EXMEDIAATOM", 4100, 0 /* &Powerpoint::opExMediaAtom */ }, + { "EXMIDIAUDIO", 4109, 0 /* &Powerpoint::opExMIDIAudio */ }, + { "EXOBJLIST", 1033, &Powerpoint::opExObjList }, + { "EXOBJLISTATOM", 1034, &Powerpoint::opExObjListAtom }, + { "EXOBJREFATOM", 3009, &Powerpoint::opExObjRefAtom }, + { "EXOLEOBJ", 4034, &Powerpoint::opExOleObj }, + { "EXOLEOBJATOM", 4035, &Powerpoint::opExOleObjAtom }, + { "EXOLEOBJSTG", 4113, &Powerpoint::opExOleObjStg }, + { "EXPLAIN", 4053, 0 /* &Powerpoint::opExPlain */ }, + { "EXPLAINATOM", 4039, 0 /* &Powerpoint::opExPlainAtom */ }, + { "EXPLAINLINK", 4054, 0 /* &Powerpoint::opExPlainLink */ }, + { "EXPLAINLINKATOM", 4036, 0 /* &Powerpoint::opExPlainLinkAtom */ }, + { "EXQUICKTIME", 4073, 0 /* &Powerpoint::opExQuickTime */ }, + { "EXQUICKTIMEMOVIE", 4074, 0 /* &Powerpoint::opExQuickTimeMovie */ }, + { "EXQUICKTIMEMOVIEDATA", 4075, 0 /* &Powerpoint::opExQuickTimeMovieData */ }, + { "EXSUBSCRIPTION", 4076, 0 /* &Powerpoint::opExSubscription */ }, + { "EXSUBSCRIPTIONSECTION", 4077, 0 /* &Powerpoint::opExSubscriptionSection */ }, + { "EXTERNALOBJECT", 4027, 0 /* &Powerpoint::opExternalObject */ }, + { "EXVIDEO", 4101, 0 /* &Powerpoint::opExVideo */ }, + { "EXWAVAUDIOEMBEDDED", 4111, 0 /* &Powerpoint::opExWAVAudioEmbedded */ }, + { "EXWAVAUDIOEMBEDDEDATOM", 4115, 0 /* &Powerpoint::opExWAVAudioEmbeddedAtom */ }, + { "EXWAVAUDIOLINK", 4112, 0 /* &Powerpoint::opExWAVAudioLink */ }, + { "FONTCOLLECTION", 2005, &Powerpoint::opFontCollection }, + { "FONTEMBEDDATA", 4024, 0 /* &Powerpoint::opFontEmbedData */ }, + { "FONTENTITYATOM", 4023, &Powerpoint::opFontEntityAtom }, + { "FOOTERMCATOM", 4090, 0 /* &Powerpoint::opFooterMCAtom */ }, + { "GENERICDATEMCATOM", 4088, 0 /* &Powerpoint::opGenericDateMCAtom */ }, + { "GLINEATOM", 10004, 0 /* &Powerpoint::opGlineAtom */ }, + { "GLPOINTATOM", 10003, 0 /* &Powerpoint::opGLPointAtom */ }, + { "GPOINTATOM", 3034, 0 /* &Powerpoint::opGpointAtom */ }, + { "GRATIOATOM", 3031, 0 /* &Powerpoint::opGratioAtom */ }, + { "GRCOLOR", 3020, 0 /* &Powerpoint::opGrColor */ }, + { "GRCOLORATOM", 10002, 0 /* &Powerpoint::opGrColorAtom */ }, + { "GRECTATOM", 3025, 0 /* &Powerpoint::opGrectAtom */ }, + { "GSCALING", 3032, 0 /* &Powerpoint::opGscaling */ }, + { "GSCALINGATOM", 10001, 0 /* &Powerpoint::opGscalingAtom */ }, + { "GUIDEATOM", 1019, 0 /* &Powerpoint::opGuideAtom */ }, + { "GUIDELIST", 2026, 0 /* &Powerpoint::opGuideList */ }, + { "HANDOUT", 4041, 0 /* &Powerpoint::opHandout */ }, + { "HEADERMCATOM", 4089, 0 /* &Powerpoint::opHeaderMCAtom */ }, + { "HEADERSFOOTERS", 4057, &Powerpoint::opHeadersFooters }, + { "HEADERSFOOTERSATOM", 4058, &Powerpoint::opHeadersFootersAtom }, + { "INT4ARRAYATOM", 2031, 0 /* &Powerpoint::opInt4ArrayAtom */ }, + { "INTERACTIVEINFO", 4082, 0 /* &Powerpoint::opInteractiveInfo */ }, + { "INTERACTIVEINFOATOM", 4083, 0 /* &Powerpoint::opInteractiveInfoAtom */ }, + { "IRRATOM", 2, 0 /* &Powerpoint::opIRRAtom */ }, + { "LIST", 2000, &Powerpoint::opList }, + { "LISTPLACEHOLDER", 2017, 0 /* &Powerpoint::opListPlaceholder */ }, + { "MAINMASTER", 1016, &Powerpoint::opMainMaster }, + { "MASTERTEXT", 4068, 0 /* &Powerpoint::opMasterText */ }, + { "METAFILE", 4033, 0 /* &Powerpoint::opMetaFile */ }, + { "NAMEDSHOW", 1041, 0 /* &Powerpoint::opNamedShow */ }, + { "NAMEDSHOWS", 1040, 0 /* &Powerpoint::opNamedShows */ }, + { "NAMEDSHOWSLIDES", 1042, 0 /* &Powerpoint::opNamedShowSlides */ }, + { "NOTES", 1008, &Powerpoint::opNotes }, + { "NOTESATOM", 1009, &Powerpoint::opNotesAtom }, + { "OEPLACEHOLDERATOM", 3011, 0 /* &Powerpoint::opOEPlaceholderAtom */ }, + { "OESHAPE", 3008, 0 /* &Powerpoint::opOEShape */ }, + { "OESHAPEATOM", 3035, 0 /* &Powerpoint::opOEShapeAtom */ }, + { "OUTLINETEXTREFATOM", 3998, 0 /* &Powerpoint::opOutlineTextRefAtom */ }, + { "OUTLINEVIEWINFO", 1031, &Powerpoint::opOutlineViewInfo }, + { "PARAFORMATATOM", 4067, 0 /* &Powerpoint::opParaFormatAtom */ }, + { "PERSISTPTRFULLBLOCK", 6001, 0 /* &Powerpoint::opPersistPtrFullBlock */ }, + { "PERSISTPTRINCREMENTALBLOCK", 6002, &Powerpoint::opPersistPtrIncrementalBlock }, + { "POWERPOINTSTATEINFOATOM", 10, 0 /* &Powerpoint::opPowerPointStateInfoAtom */ }, + { "PPDRAWING", 1036, &Powerpoint::opPPDrawing }, + { "PPDRAWINGGROUP", 1035, &Powerpoint::opPPDrawingGroup }, + { "PRINTOPTIONS", 6000, 0 /* &Powerpoint::opPrintOptions */ }, + { "PROGBINARYTAG", 5002, 0 /* &Powerpoint::opProgBinaryTag */ }, + { "PROGSTRINGTAG", 5001, 0 /* &Powerpoint::opProgStringTag */ }, + { "PROGTAGS", 5000, 0 /* &Powerpoint::opProgTags */ }, + { "PSS", 3, 0 /* &Powerpoint::opPSS */ }, + { "RECOLORENTRYATOM", 4062, 0 /* &Powerpoint::opRecolorEntryAtom */ }, + { "RECOLORINFOATOM", 4071, 0 /* &Powerpoint::opRecolorInfoAtom */ }, + { "RTFDATETIMEMCATOM", 4117, 0 /* &Powerpoint::opRTFDateTimeMCAtom */ }, + { "RULERINDENTATOM", 10000, 0 /* &Powerpoint::opRulerIndentAtom */ }, + { "RUNARRAY", 2028, 0 /* &Powerpoint::opRunArray */ }, + { "RUNARRAYATOM", 2029, 0 /* &Powerpoint::opRunArrayAtom */ }, + { "SCHEME", 1012, 0 /* &Powerpoint::opScheme */ }, + { "SCHEMEATOM", 1013, 0 /* &Powerpoint::opSchemeAtom */ }, + { "SLIDE", 1006, &Powerpoint::opSlide }, + { "SLIDEATOM", 1007, &Powerpoint::opSlideAtom }, + { "SLIDEBASE", 1004, 0 /* &Powerpoint::opSlideBase */ }, + { "SLIDEBASEATOM", 1005, 0 /* &Powerpoint::opSlideBaseAtom */ }, + { "SLIDELIST", 4084, 0 /* &Powerpoint::opSlideList */ }, + { "SLIDELISTWITHTEXT", 4080, &Powerpoint::opSlideListWithText }, + { "SLIDENUMBERMCATOM", 4056, 0 /* &Powerpoint::opSlideNumberMCAtom */ }, + { "SLIDEPERSIST", 1003, 0 /* &Powerpoint::opSlidePersist */ }, + { "SLIDEPERSISTATOM", 1011, &Powerpoint::opSlidePersistAtom }, + { "SLIDEVIEWINFO", 1018, &Powerpoint::opSlideViewInfo }, + { "SLIDEVIEWINFOATOM", 1022, 0 /* &Powerpoint::opSlideViewInfoAtom */ }, + { "SORTERVIEWINFO", 1032, 0 /* &Powerpoint::opSorterViewInfo */ }, + { "SOUND", 2022, 0 /* &Powerpoint::opSound */ }, + { "SOUNDCOLLATOM", 2021, 0 /* &Powerpoint::opSoundCollAtom */ }, + { "SOUNDCOLLECTION", 2020, 0 /* &Powerpoint::opSoundCollection */ }, + { "SOUNDDATA", 2023, 0 /* &Powerpoint::opSoundData */ }, + { "SRKINSOKU", 4040, &Powerpoint::opSrKinsoku }, + { "SRKINSOKUATOM", 4050, 0 /* &Powerpoint::opSrKinsokuAtom */ }, + { "SSDOCINFOATOM", 1025, &Powerpoint::opSSDocInfoAtom }, + { "SSLIDELAYOUTATOM", 1015, &Powerpoint::opSSSlideLayoutAtom }, + { "SSSLIDEINFOATOM", 1017, 0 /* &Powerpoint::opSSSlideInfoAtom */ }, + { "STYLETEXTPROPATOM", 4001, &Powerpoint::opStyleTextPropAtom }, + { "SUBCONTAINERCOMPLETED", 1, 0 /* &Powerpoint::opSubContainerCompleted */ }, + { "SUBCONTAINEREXCEPTION", 4, 0 /* &Powerpoint::opSubContainerException */ }, + { "SUMMARY", 1026, 0 /* &Powerpoint::opSummary */ }, + { "TEXTBOOKMARKATOM", 4007, 0 /* &Powerpoint::opTextBookmarkAtom */ }, + { "TEXTBYTESATOM", 4008, &Powerpoint::opTextBytesAtom }, + { "TEXTCHARSATOM", 4000, &Powerpoint::opTextCharsAtom }, + { "TEXTHEADERATOM", 3999, &Powerpoint::opTextHeaderAtom }, + { "TEXTRULERATOM", 4006, 0 /* &Powerpoint::opTextRulerAtom */ }, + { "TEXTSPECINFOATOM", 4010, &Powerpoint::opTextSpecInfoAtom }, + { "TEXTURE", 1027, 0 /* &Powerpoint::opTexture */ }, + { "TXCFSTYLEATOM", 4004, 0 /* &Powerpoint::opTxCFStyleAtom */ }, + { "TXINTERACTIVEINFOATOM", 4063, 0 /* &Powerpoint::opTxInteractiveInfoAtom */ }, + { "TXMASTERSTYLEATOM", 4003, &Powerpoint::opTxMasterStyleAtom }, + { "TXPFSTYLEATOM", 4005, 0 /* &Powerpoint::opTxPFStyleAtom */ }, + { "TXSISTYLEATOM", 4009, &Powerpoint::opTxSIStyleAtom }, + { "TYPEFACE", 4025, 0 /* &Powerpoint::opTypeFace */ }, + { "USEREDITATOM", 4085, &Powerpoint::opUserEditAtom }, + { "VBAINFO", 1023, &Powerpoint::opVBAInfo }, + { "VBAINFOATOM", 1024, 0 /* &Powerpoint::opVBAInfoAtom */ }, + { "VBASLIDEINFO", 1028, 0 /* &Powerpoint::opVBASlideInfo */ }, + { "VBASLIDEINFOATOM", 1029, 0 /* &Powerpoint::opVBASlideInfoAtom */ }, + { "VIEWINFO", 1020, 0 /* &Powerpoint::opViewInfo */ }, + { "VIEWINFOATOM", 1021, 0 /* &Powerpoint::opViewInfoAtom */ }, + { NULL, 0, 0 }, + { "MSOD", 0, &Powerpoint::opMsod } + }; + unsigned i; + method result; + + // Scan lookup table for operation. + + for (i = 0; funcTab[i].name; i++) + { + if (funcTab[i].opcode == op.type) + { + break; + } + } + + // Invoke handler. + + result = funcTab[i].handler; + if (!result && (op.type >= 0xF000) && (0xFFFF >= op.type)) + result = funcTab[++i].handler; + if (!result) + { + if (funcTab[i].name) + kdWarning(s_area) << "invokeHandler: unsupported opcode: " << + funcTab[i].name << + " operands: " << bytes << endl; + else + kdWarning(s_area) << "invokeHandler: unsupported opcode: " << + op.type << + " operands: " << bytes << endl; + + // Skip data we cannot use. + skip(bytes, operands); + } + else + { + kdDebug(s_area) << "invokeHandler: opcode: " << funcTab[i].name << + " operands: " << bytes << endl; + + // We don't invoke the handler directly on the incoming operands, but + // via a temporary datastream. This adds overhead, but eliminates the + // need for the individual handlers to read *exactly* the right amount + // of data (thus speeding development, and possibly adding some + // future-proofing). + + if (bytes) + { + QByteArray *record = new QByteArray(bytes); + QDataStream *body; + + operands.readRawBytes(record->data(), bytes); + body = new QDataStream(*record, IO_ReadOnly); + body->setByteOrder(QDataStream::LittleEndian); + (this->*result)(op, bytes, *body); + delete body; + delete record; + } + else + { + QDataStream *body = new QDataStream(); + + (this->*result)(op, bytes, *body); + delete body; + } + } +} + +bool Powerpoint::parse( + myFile &mainStream, + myFile ¤tUser, + myFile &pictures) +{ + unsigned i; + + m_mainStream = mainStream; + m_pictures = pictures; + m_documentRef = 0; + m_documentRefFound = false; + m_persistentReferences.clear(); + m_slideList.clear(); + m_editDepth = 0; + + // Find the slide references. + + m_pass = PASS_GET_SLIDE_REFERENCES; + kdError(s_area) << "parseing step 1 walkRecord..." << endl; + walkRecord(currentUser.length, currentUser.data);//get curren user information + + kdError(s_area) << "parseing step 2 walkReference..." << endl; + //for(i = 0; i <= 2; i++)//walk the 2 slide atoms + //{ + // kdError(s_area) << "ref == :" << i <<endl; + //walkReference(i); + //} + kdError(s_area) << "walking slide list!!!!.." << endl; + if(mEditOffset != 0) walk(mEditOffset); + else walkDocument(); + // We should have a complete list of slide persistent references. + m_pass = PASS_GET_SLIDE_CONTENTS; + kdError(s_area) << "TOTAL SLIDES XXxx: " << m_slideList.count() << endl; + + for (i = 0; i < m_slideList.count(); i++) + { + m_pptSlide = m_slideList.at(i); + walkReference(i); + gotSlide(*m_pptSlide); + } + + return true; +} + +void Powerpoint::opColorSchemeAtom( + Header & /* op */, + Q_UINT32, + QDataStream &operands) +{ + struct + { + Q_UINT32 background; + Q_UINT32 textAndLines; + Q_UINT32 shadows; + Q_UINT32 titleText; + Q_UINT32 fills; + Q_UINT32 accent; + Q_UINT32 accentAndHyperlink; + Q_UINT32 accentAndFollowedHyperlink; + } data; + + operands >> data.background >> data.textAndLines >> data.shadows >> + data.titleText >> data.fills >> data.accent >> data.accentAndHyperlink >> + data.accentAndFollowedHyperlink; +} + +// +// A Unicode String. +// +void Powerpoint::opCString( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + QString value; + unsigned i; + + for (i = 0; i < bytes / 2; i++) + { + Q_UINT16 tmp; + + operands >> tmp; + value += tmp; + } + kdDebug(s_area) << "value: " << value << endl; +} + +void Powerpoint::opCurrentUserAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &operands) +{ + + const Q_UINT32 MAGIC_NUMBER = (Q_UINT32)(-476987297); + //unsigned i; + + operands >> mCurrentUserAtom.size >> mCurrentUserAtom.magic >> mCurrentUserAtom.offsetToCurrentEdit >> + mCurrentUserAtom.lenUserName >> mCurrentUserAtom.docFileVersion >> mCurrentUserAtom.majorVersion >> + mCurrentUserAtom.minorVersion; + + kdDebug(s_area) << "\nPSR_CurrentUserAtom:" << + "\n\tsize: " << mCurrentUserAtom.size << + "\n\tmagic: " << mCurrentUserAtom.magic << + "\n\toffsetToCurrentEdit: " << mCurrentUserAtom.offsetToCurrentEdit << + "\n\tlenUserName: " << mCurrentUserAtom.lenUserName << + "\n\tdocFileVersion: " << mCurrentUserAtom.docFileVersion << + "\n\tmajorVersion: " << mCurrentUserAtom.majorVersion << + "\n\tminorVersion: " << mCurrentUserAtom.minorVersion << endl; + + switch (m_pass) + { + case PASS_GET_SLIDE_REFERENCES: + if (mCurrentUserAtom.size != 20) + { + kdError(s_area) << "invalid size: " << mCurrentUserAtom.size << endl; + } + if (mCurrentUserAtom.magic != MAGIC_NUMBER) + { + kdError(s_area) << "invalid magic number: " << mCurrentUserAtom.magic << endl; + } + if ((mCurrentUserAtom.docFileVersion != 1012) || + (mCurrentUserAtom.majorVersion != 3) || + (mCurrentUserAtom.minorVersion != 0))// || + // (data.release < 8) || + // (data.release > 10)) + { + kdError(s_area) << "invalid version: " << mCurrentUserAtom.docFileVersion << + "." << mCurrentUserAtom.majorVersion << + "." << mCurrentUserAtom.minorVersion << + endl; + //"." << data.release << endl; + } + + // Now walk main stream starting at current edit point. + + walkRecord(mCurrentUserAtom.offsetToCurrentEdit); + break; + case PASS_GET_SLIDE_CONTENTS: + break; + }; +} + +void Powerpoint::opDocument( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opDocumentAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ +} + +void Powerpoint::opEndDocument( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opEnvironment( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +// +// Contains an ExEmbedAtom and 3 CStrings (the menu name, the program id which +// unqiuely identifies the type of object, and the "paste special" name). +// +void Powerpoint::opExEmbed( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +// +// Information about an embedded object. +// +void Powerpoint::opExEmbedAtom( + Header & /* op */, + Q_UINT32, + QDataStream &operands) +{ + struct + { + Q_INT32 followColorScheme; + Q_UINT8 cantLockServerB; + Q_UINT8 noSizeToServerB; + Q_UINT8 isTable; + } data; + + operands >> data.followColorScheme; + operands >> data.cantLockServerB; + operands >> data.noSizeToServerB; + operands >> data.isTable; +} + +void Powerpoint::opFontCollection( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opFontEntityAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ +} + +void Powerpoint::opHeadersFooters( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opHeadersFootersAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ +} + +void Powerpoint::opList( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opMainMaster( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opMsod( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + char *data; + + switch (m_pass) + { + case PASS_GET_SLIDE_REFERENCES: + break; + case PASS_GET_SLIDE_CONTENTS: + data = new char[bytes]; + operands.readRawBytes((char *)data, bytes); +kdError() <<" drgid: "<< m_pptSlide->getPsrReference() << endl; + gotDrawing(m_pptSlide->getPsrReference(), "msod", bytes, data); + delete [] data; + break; + }; +} + +void Powerpoint::opNotes( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opNotesAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &operands) +{ + struct + { + Q_INT32 slideId; // Id for the corresponding slide. + Q_UINT16 flags; + } data; + + operands >> data.slideId >> data.flags; +} + +// +// Contains an ExObjListAtom and a list of all objects in a document. +// +void Powerpoint::opExObjList( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +// +// Get the next unique identifier for OLE objects. +// +void Powerpoint::opExObjListAtom( + Header & /* op */, + Q_UINT32, + QDataStream &operands) +{ + Q_UINT32 objectSeedId; + + operands >> objectSeedId; + kdDebug(s_area) << "next OLE obj id: " << objectSeedId << endl; +} + +void Powerpoint::opExObjRefAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ +} + +void Powerpoint::opExOleObj( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ +} + +void Powerpoint::opExOleObjAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &operands) +{ + struct + { + Q_UINT32 drawAspect; + Q_INT32 type; + Q_INT32 objID; + Q_INT32 subType; + Q_INT8 isBlank; + } data; + + operands >> data.drawAspect; + operands >> data.type; + operands >> data.objID; + operands >> data.subType; + operands >> data.isBlank; + kdDebug(s_area) << ((data.type == 0) ? "embedded " : "linked ") << + "OLE obj id: " << data.objID << endl; +} + +void Powerpoint::opExOleObjStg( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ +} + +void Powerpoint::opOutlineViewInfo( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opPersistPtrIncrementalBlock2( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ + //PSR_UserEditAtom userEdit; + //Q_INT16 offsetToEdit = mCurrentUserAtom.offsetToCurrentEdit; + + /* huh? + while(0 < offsetToEdit) + { + + }*/ + +// mpLastUserEditAtom; + +} + +void Powerpoint::opPersistPtrIncrementalBlock( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + struct + { + union + { + Q_UINT32 info; + struct + { + Q_UINT32 offsetNumber: 20; + Q_UINT32 offsetCount: 12; + } fields; + } header; + Q_UINT32 offset; + } data; + Q_UINT32 length = 0; + + while (length < bytes) + { + unsigned i; + + // Walk references numbered between: + // + // offsetNumber..offsetNumber + offsetCount - 1 + // + operands >> data.header.info; + length += sizeof(data.header.info); + kdDebug(s_area) << "length1: " << length << endl; + kdDebug(s_area) << "m_pass: " << m_pass << endl; + //kdDebug(s_area) << "PASS_GET_SLIDE_REFERENCES: " << PASS_GET_SLIDE_REFERENCES << endl; + kdDebug(s_area) << "data.header.fields.offsetCount: " << data.header.fields.offsetCount << endl; + + for (i = 0; i < data.header.fields.offsetCount; i++) + { + unsigned reference = data.header.fields.offsetNumber + i; + + operands >> data.offset; + length += sizeof(data.offset); + //kdDebug(s_area) << "length2: " << length << endl; + switch (m_pass) + { + case PASS_GET_SLIDE_REFERENCES: + + // Create a record of this persistent reference. + + if (m_persistentReferences.end() == m_persistentReferences.find(reference)) + { + if(reference < 5) + { + kdDebug(s_area) << "persistent reference: " << reference << + ": " << data.offset << endl; + } + m_persistentReferences.insert(reference, data.offset); + } + else + { + // This reference has already been seen! Since the parse proceeds + // backwards in time form the most recent edit, I assume this means + // that this is an older version of this slide...so just ignore it. + // kdDebug(s_area) << "superseded reference: " << reference << + // ": " << data.offset << endl; + } + break; + case PASS_GET_SLIDE_CONTENTS: + break; + }; + } + kdDebug(s_area) << "LEAVING persistant block -- " << endl; + } + +} + +void Powerpoint::opPPDrawing( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opPPDrawingGroup( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opSlide( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opSlideAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &operands) +{ + struct + { + Q_UINT8 layout[12]; // Slide layout descriptor. + Q_INT32 masterId; // Id of the master of the slide. Zero for a master slide. + Q_INT32 notesId; // Id for the corresponding notes slide. Zero if slide has no notes. + Q_UINT16 flags; + } data; + + Header tmp; + tmp.type = 1015; + tmp.length = sizeof(data.layout); + invokeHandler(tmp, tmp.length, operands); + operands >> data.masterId >> data.notesId >> data.flags; + + kdDebug(s_area) << "\nSlideAtom:" << + "\n\tmasterId: " << data.masterId << + "\n\tnotesId: " << data.notesId << + "\n\tflags: " << data.flags << endl; + + //invokeHandler(tmp, tmp.length, operands); + +} + +void Powerpoint::opSlideListWithText( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opSlidePersistAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &operands) +{ + struct + { + Q_UINT32 psrReference; // Logical reference to the slide persist object. + Q_UINT32 flags; // If bit 3 set then slide contains shapes other than placeholders. + Q_INT32 numberTexts; // Number of placeholder texts stored with the persist object. + Q_INT32 slideId; // Unique slide identifier, used for OLE link monikers for example. + Q_UINT32 reserved; + } data; + + operands >> data.psrReference >> data.flags >> data.numberTexts >> + data.slideId >> data.reserved; + + kdDebug(s_area) << "\nopSlidePersistAtom: " << + "\n\tpsrReference: " << data.psrReference << + "\n\tflags: " << data.flags << + "\n\tnumberTexts: " << data.numberTexts << + "\n\tslideId: " << data.slideId << + "\n\treserved: " << data.reserved << endl; + + switch (m_pass) + { + case PASS_GET_SLIDE_REFERENCES: + if(data.slideId > 0)//if not master slide.. is there another way to tell??? + { + m_pptSlide = new PptSlide; + m_pptSlide->setPsrReference(data.psrReference); + m_slideList.append(m_pptSlide); + + kdDebug(s_area) << "XXXXXXXXXslide: " << data.psrReference << + " has texts: " << data.numberTexts << endl; + } + break; + case PASS_GET_SLIDE_CONTENTS: + break; + }; +} + +void Powerpoint::opSlideViewInfo( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opSrKinsoku( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::opSSDocInfoAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ +} + +void Powerpoint::opSSSlideLayoutAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &operands) +{ + + PSR_SSlideLayoutAtom data; + unsigned i; + + operands >> data.geom; + for (i = 0; i < sizeof(data.placeholderId); i++) + { + operands >> data.placeholderId[i]; + } + + kdDebug(s_area) << "\nPSR_SSlideLayoutAtom:" << + "\n\tgeom: " << data.geom << + "\n\tplaceholderId[0]: " << data.placeholderId[0] << + "\n\tplaceholderId[1]: " << data.placeholderId[1] << + "\n\tplaceholderId[2]: " << data.placeholderId[2] << + "\n\tplaceholderId[3]: " << data.placeholderId[3] << + "\n\tplaceholderId[4]: " << data.placeholderId[4] << + "\n\tplaceholderId[5]: " << data.placeholderId[5] << + "\n\tplaceholderId[6]: " << data.placeholderId[6] << + "\n\tplaceholderId[7]: " << data.placeholderId[7] << endl; + +} +//this is where we set bold/italic/etc and paragraph styles +void Powerpoint::opStyleTextPropAtom( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + + Q_UINT16 totalLength = 0; + Q_UINT16 length = 0; + Q_UINT32 style1 = 0; + Q_UINT32 style2 = 0; + Q_UINT16 style3 = 0; + Q_UINT32 BOLD = 0x00010000; + Q_UINT32 ITALIC = 0x00020000; + Q_UINT32 UNDERLINE = 0x00040000; + + //--get the paragraph style? + operands >> length >> style1 >> style2; + totalLength += 10; + + kdDebug(s_area) << "\nopStyleTextPropAtom1:" << + "\n\tlength: " << length << + "\n\tstyle1: " << style1 << + "\n\tstyle2: " << style2 << endl; + //-- + + //--get the char styles + while(bytes > totalLength) + { + length = 0; + style1 = 0; + style2 = 0; + style3 = 0; + + operands >> length >> style1; + totalLength += 6; + if(style1 == 0) + { + operands >> style3; + totalLength += 2; + } + else + { + operands >> style2; + totalLength += 4; + } + + kdDebug(s_area) << "\nopStyleTextPropAtom2:" << + "\n\tlength: " << length << + "\n\tstyle1: " << style1 << + "\n\tstyle2: " << style2 << + "\n\tstyle3: " << style3 << endl; + if(style1 & BOLD) + kdDebug(s_area) << "BOLD here" << endl; + if(style1 & ITALIC) + kdDebug(s_area) << "ITALIC here" << endl; + if(style1 & UNDERLINE) + kdDebug(s_area) << "UNDERLINE here" << endl; + } + //-- +} + +void Powerpoint::opTextBytesAtom( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + QString data; + unsigned i; + + for (i = 0; i < bytes; i++) + { + Q_UINT8 tmp; + + operands >> tmp; + data += tmp; + } + kdDebug(s_area) << "\nopTextBytesAtom: " << + "\n\tdata: " << data << endl; + + //SlideText *text; + switch (m_pass) + { + case PASS_GET_SLIDE_REFERENCES: + //text = new SlideText; + //text->type = m_textType; + //text->data = data; + //m_slide->text.append(text); + if(m_pptSlide) + { + m_pptSlide->addText(data, m_textType); + kdDebug(s_area) << "Text Added: " << data << " type: " << m_textType << endl; + } + else + kdDebug(s_area) << "WEVE GOTS US AN ERROR!!!" << endl; + + break; + case PASS_GET_SLIDE_CONTENTS: + break; + }; +} + +void Powerpoint::opTextCharsAtom( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + QString data; + unsigned i; + + for (i = 0; i < bytes / 2; i++) + { + Q_UINT16 tmp; + + operands >> tmp; + data += tmp; + } + + //SlideText *text; + switch (m_pass) + { + case PASS_GET_SLIDE_REFERENCES: + //text = new SlideText; + //text->type = m_textType; + //text->data = data; + //m_slide->text.append(text); + if(m_pptSlide) + { + m_pptSlide->addText(data, m_textType); + kdDebug(s_area) << "Text Added: " << data << " type: " << m_textType << endl; + } + else + kdDebug(s_area) << "WEVE GOTS US AN ERROR!!!" << endl; + + break; + case PASS_GET_SLIDE_CONTENTS: + break; + }; +} + +void Powerpoint::opTextHeaderAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &operands) +{ + struct + { + Q_UINT32 txType; // Type of text: + // + // 0 Title + // 1 Body + // 2 Notes + // 3 Not Used + // 4 Other (Text in a shape) + // 5 Center body (subtitle in title slide) + // 6 Center title (title in title slide) + // 7 Half body (body in two-column slide) + // 8 Quarter body (body in four-body slide) + } data; + + operands >> data.txType; + + kdDebug(s_area) << "\nopTextHeaderAtom:" << + "\n\ttxType: " << data.txType << endl; + + switch (m_pass) + { + case PASS_GET_SLIDE_REFERENCES: + m_textType = data.txType; + break; + case PASS_GET_SLIDE_CONTENTS: + break; + }; +} + +void Powerpoint::opTextSpecInfoAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ +} + +void Powerpoint::opTxMasterStyleAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ +} + +void Powerpoint::opTxSIStyleAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &/*operands*/) +{ +} + +// +// This routine is where the parse actually gets going. It should be the first +// structure encoutered in the main OLE stream. +// +void Powerpoint::opUserEditAtom( + Header & /* op */, + Q_UINT32 /*bytes*/, + QDataStream &operands) +{ + + operands >> mUserEditAtom.lastSlideID >> mUserEditAtom.version >> mUserEditAtom.offsetLastEdit >> + mUserEditAtom.offsetPersistDirectory >> mUserEditAtom.documentRef >> + mUserEditAtom.maxPersistWritten >> mUserEditAtom.lastViewType; + + if(mEditOffset == 0)mEditOffset = mUserEditAtom.offsetLastEdit; + + kdDebug(s_area) << "\nPSR_UserEditAtom:" << + "\n\tlastSlideID: " << mUserEditAtom.lastSlideID << + "\n\tversion: " << mUserEditAtom.version << + "\n\toffsetLastEdit: " << mUserEditAtom.offsetLastEdit << + "\n\toffsetPersistDirectory: " << mUserEditAtom.offsetPersistDirectory << + "\n\tdocumentRef: " << mUserEditAtom.documentRef << + "\n\tmaxPersistWritten: " << mUserEditAtom.maxPersistWritten << + "\n\tlastViewType: " << mUserEditAtom.lastViewType << endl; + + if (!m_documentRefFound) + { + m_documentRef = mUserEditAtom.documentRef; + m_documentRefFound = true; + } + switch (m_pass) + { + case PASS_GET_SLIDE_REFERENCES: + + // Gather the persistent references. That should fill the list of + // references which we then use to look up our document. + + walkRecord(mUserEditAtom.offsetPersistDirectory); + + // Now recursively walk the main OLE stream parsing previous edits. + + if (mUserEditAtom.offsetLastEdit) + { + m_editDepth++; + walkRecord(mUserEditAtom.offsetLastEdit); + m_editDepth--; + } + break; + case PASS_GET_SLIDE_CONTENTS: + break; + }; +} + +void Powerpoint::opVBAInfo( + Header & /* op */, + Q_UINT32 bytes, + QDataStream &operands) +{ + walk(bytes, operands); +} + +void Powerpoint::skip(Q_UINT32 bytes, QDataStream &operands) +{ + if ((int)bytes < 0) + { + kdError(s_area) << "skip: " << (int)bytes << endl; + return; + } + if (bytes) + { + Q_UINT32 i; + Q_UINT8 discard; + + kdDebug(s_area) << "skip: " << bytes << endl; + for (i = 0; i < bytes; i++) + { + operands >> discard; + } + } +} + +// +// Handle a container record. +// +void Powerpoint::walk(Q_UINT32 bytes, QDataStream &operands) +{ + Header op; + Q_UINT32 length = 0; + + // Stop parsing when there are no more records. Note that we stop as soon + // as we cannot get a complete header. + while (length + 8 <= bytes) + { + operands >> op.opcode.info >> op.type >> op.length; + + // If we get some duff data, protect ourselves. + if (length + op.length + 8 > bytes) + { + op.length = bytes - length - 8; + } + length += op.length + 8; + + // Package the arguments... + + invokeHandler(op, op.length, operands); + } + + // Eat unexpected data that the caller may expect us to consume. + skip(bytes - length, operands); +} + +void Powerpoint::walk(Q_UINT32 mainStreamOffset) +{ + Q_UINT32 length = m_mainStream.length - mainStreamOffset; + QByteArray a; + + a.setRawData((const char *)m_mainStream.data + mainStreamOffset, length); + QDataStream stream(a, IO_ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + walk(length, stream); + a.resetRawData((const char *)m_mainStream.data + mainStreamOffset, length); +} +void Powerpoint::walkDocument() +{ + QByteArray a; + Q_UINT32 mainStreamOffset = 0; + Q_UINT32 bytes = m_mainStream.length - mainStreamOffset; + + a.setRawData((const char *)m_mainStream.data + mainStreamOffset, bytes); + QDataStream stream(a, IO_ReadOnly); + stream.setByteOrder(QDataStream::LittleEndian); + //--get tho the slide list + Header op; + Q_UINT32 length = 0; + + // Stop parsing when there are no more records. Note that we stop as soon + // as we cannot get a complete header. + while (length + 8 <= bytes && op.type != 1000)//document + { + stream >> op.opcode.info >> op.type >> op.length; + + // If we get some duff data, protect ourselves. + if (length + op.length + 8 > bytes) + { + op.length = bytes - length - 8; + } + length += op.length + 8; + } + + //-- + invokeHandler(op, op.length, stream); + a.resetRawData((const char *)m_mainStream.data + mainStreamOffset, bytes); + +} + +void Powerpoint::walkRecord(Q_UINT32 bytes, const unsigned char *operands) +{ + // First read what should be the next header using one stream. + + kdError(s_area) << "WalkRecord - bytes: " << bytes << endl; + + Q_UINT32 length = sizeof(Header); + QByteArray a; + Header op; + + a.setRawData((const char *)operands, bytes); + QDataStream stream1(a, IO_ReadOnly); + stream1.setByteOrder(QDataStream::LittleEndian); + stream1 >> op.opcode.info >> op.type >> op.length; + a.resetRawData((const char *)operands, bytes); + + // Armed with the length, parse in the usual way using a second stream. + + length += op.length; + a.setRawData((const char *)operands, length); + QDataStream stream2(a, IO_ReadOnly); + stream2.setByteOrder(QDataStream::LittleEndian); + walk(length, stream2); + a.resetRawData((const char *)operands, length); +} + +void Powerpoint::walkRecord(Q_UINT32 mainStreamOffset) +{ + walkRecord(sizeof(Header), m_mainStream.data + mainStreamOffset); +} + +void Powerpoint::walkReference(Q_UINT32 reference) +{ + if (m_persistentReferences.end() == m_persistentReferences.find(reference)) + { + kdError(s_area) << "cannot find reference: " << reference << endl; + } + else + { + unsigned offset = m_persistentReferences[reference]; + kdDebug(s_area) << "found reference: " << reference << + " offset: " << offset << endl; + walkRecord(offset); + kdDebug(s_area) << "****************************" << endl; + + } +} diff --git a/filters/olefilters/powerpoint97/powerpoint.h b/filters/olefilters/powerpoint97/powerpoint.h new file mode 100644 index 000000000..5c7a91958 --- /dev/null +++ b/filters/olefilters/powerpoint97/powerpoint.h @@ -0,0 +1,355 @@ +/* + Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>. + This file is part of the KDE project + + 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. + +DESCRIPTION + + This is a generic parser for Microsoft Powerpoint documents. The output is + a series of callbacks (a.k.a. virtual functions) which the caller can + override as required. +*/ + +#ifndef POWERPOINT_H +#define POWERPOINT_H + + +#include <myfile.h> +#include <qdatastream.h> +#include <qptrlist.h> +#include <qmap.h> +#include <pptSlide.h> + +typedef Q_INT32 sint4; // signed 4-byte integral value +typedef Q_INT16 sint2; // signed 4-byte integral value +typedef Q_UINT32 uint4; // unsigned 4-byte integral value +typedef Q_UINT16 uint2; // 2-byte +typedef Q_INT8 bool1; // 1-byte boolean +typedef Q_UINT8 ubyte1; // unsigned byte value +typedef uint2 psrType; +typedef uint4 psrSize; // each record is preceded by +// pssTypeType and pssSizeType. +typedef uint2 psrInstance; +typedef uint2 psrVersion; +typedef uint4 psrReference; // Saved object reference +//typedef QList<PptSlide> PptSlideList; + +class Powerpoint +{ +public: + + // Construction. + + Powerpoint(); + virtual ~Powerpoint(); + + // Called to parse the given file. + + bool parse( + myFile &mainStream, + myFile ¤tUser, + myFile &pictures); + + typedef struct + { + unsigned type; + QString data; + } SlideText; + + typedef struct + { + unsigned persistentReference; + QPtrList<SlideText> text; + } Slide; + +protected: + + virtual void gotDrawing( + unsigned id, + QString type, + unsigned length, + const char *data) = 0; + virtual void gotSlide( + PptSlide &slide) = 0; + +private: + Powerpoint(const Powerpoint &); + const Powerpoint &operator=(const Powerpoint &); + + // Debug support. + +public: + static const int s_area; + +private: + myFile m_mainStream; + myFile m_pictures; + unsigned m_documentRef; + bool m_documentRefFound; + QMap<unsigned, unsigned> m_persistentReferences; + unsigned m_editDepth; + enum + { + PASS_GET_SLIDE_REFERENCES, + PASS_GET_SLIDE_CONTENTS + } m_pass; + unsigned m_textType; + + QPtrList<PptSlide> m_slideList; + PptSlide* m_pptSlide; + +struct PSR_CurrentUserAtom +{ + uint4 size; + uint4 magic; // Magic number to ensure this is a PowerPoint file. + uint4 offsetToCurrentEdit; // Offset in main stream to current edit field. + uint2 lenUserName; + uint2 docFileVersion; + ubyte1 majorVersion; + ubyte1 minorVersion; +}; + +struct PSR_UserEditAtom +{ + sint4 lastSlideID; // slideID + uint4 version; // This is major/minor/build which did the edit + uint4 offsetLastEdit; // File offset of last edit + uint4 offsetPersistDirectory; // Offset to PersistPtrs for + // this file version. + uint4 documentRef; + uint4 maxPersistWritten; // Addr of last persist ref written to the file (max seen so far). + sint2 lastViewType; // enum view type +}; + +struct PSR_SSlideLayoutAtom +{ + sint4 geom; + ubyte1 placeholderId[8]; +}; + + PSR_CurrentUserAtom mCurrentUserAtom; + PSR_UserEditAtom mUserEditAtom; + PSR_UserEditAtom* mpLastUserEditAtom; + Q_UINT32 mEditOffset; + + // Common Header. + + typedef struct + { + union + { + Q_UINT16 info; + struct + { + Q_UINT16 version: 4; + Q_UINT16 instance: 12; + } fields; + } opcode; + Q_UINT16 type; + Q_UINT32 length; + } Header; + + // Opcode handling and painter methods. + + void walk( + Q_UINT32 bytes, + QDataStream &operands); + void walk( + Q_UINT32 mainStreamOffset); + void walkRecord( + Q_UINT32 bytes, + const unsigned char *operands); + void walkRecord( + Q_UINT32 mainStreamOffset); + void walkReference( + Q_UINT32 reference); + void skip( + Q_UINT32 bytes, + QDataStream &operands); + void invokeHandler( + Header &op, + Q_UINT32 bytes, + QDataStream &operands); + void walkDocument(); + + void opAnimationInfo(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opAnimationInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opArrayElementAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opBaseTextPropAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opBinaryTagData(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opBookmarkCollection(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opBookmarkEntityAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opBookmarkSeedAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opCharFormatAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opClientSignal1(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opClientSignal2(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opColorSchemeAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opCorePict(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opCorePictAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opCString(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opCurrentUserAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opDateTimeMCAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opDefaultRulerAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opDocRoutingSlip(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opDocument(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opDocumentAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opDocViewInfo(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opEmFormatAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opEndDocument(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opEnvironment(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExAviMovie(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExCDAudio(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExCDAudioAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExControl(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExControlAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExEmbed(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExEmbedAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExHyperlink(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExHyperlinkAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExLink(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExLinkAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExLinkAtom_old(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExMCIMovie(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExMediaAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExMIDIAudio(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExObjList(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExObjListAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExObjRefAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExOleObj(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExOleObjAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExOleObjStg(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExPlain(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExPlainAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExPlainLink(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExPlainLinkAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExQuickTime(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExQuickTimeMovie(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExQuickTimeMovieData(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExSubscription(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExSubscriptionSection(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExternalObject(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExVideo(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExWAVAudioEmbedded(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExWAVAudioEmbeddedAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opExWAVAudioLink(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opFontCollection(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opFontEmbedData(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opFontEntityAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opFooterMCAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGenericDateMCAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGlineAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGLPointAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGpointAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGratioAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGrColor(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGrColorAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGrectAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGscaling(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGscalingAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGuideAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opGuideList(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opHandout(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opHeaderMCAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opHeadersFooters(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opHeadersFootersAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opInt4ArrayAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opInteractiveInfo(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opInteractiveInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opIRRAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opList(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opListPlaceholder(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opMainMaster(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opMasterText(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opMetaFile(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opMsod(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opNamedShow(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opNamedShows(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opNamedShowSlides(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opNotes(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opNotesAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opOEPlaceholderAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opOEShape(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opOEShapeAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opOutlineTextRefAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opOutlineViewInfo(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opParaFormatAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opPersistPtrFullBlock(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opPersistPtrIncrementalBlock(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opPersistPtrIncrementalBlock2(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opPowerPointStateInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opPPDrawing(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opPPDrawingGroup(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opPrintOptions(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opProgBinaryTag(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opProgStringTag(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opProgTags(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opPSS(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opRecolorEntryAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opRecolorInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opRTFDateTimeMCAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opRulerIndentAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opRunArray(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opRunArrayAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opScheme(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSchemeAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlide(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlideAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlideBase(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlideBaseAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlideList(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlideListWithText(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlideNumberMCAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlidePersist(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlidePersistAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlideViewInfo(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSlideViewInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSorterViewInfo(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSound(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSoundCollAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSoundCollection(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSoundData(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSrKinsoku(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSrKinsokuAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSSDocInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSSSlideLayoutAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSSSlideInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opStyleTextPropAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSubContainerCompleted(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSubContainerException(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opSummary(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTextBookmarkAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTextBytesAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTextCharsAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTextHeaderAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTextRulerAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTextSpecInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTexture(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTxCFStyleAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTxInteractiveInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTxMasterStyleAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTxPFStyleAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTxSIStyleAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opTypeFace(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opUserEditAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opVBAInfo(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opVBAInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opVBASlideInfo(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opVBASlideInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opViewInfo(Header &op, Q_UINT32 bytes, QDataStream &operands); + void opViewInfoAtom(Header &op, Q_UINT32 bytes, QDataStream &operands); +}; +#endif diff --git a/filters/olefilters/powerpoint97/powerpointfilter.cc b/filters/olefilters/powerpoint97/powerpointfilter.cc new file mode 100644 index 000000000..e0ea629a5 --- /dev/null +++ b/filters/olefilters/powerpoint97/powerpointfilter.cc @@ -0,0 +1,73 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <trobin@kde.org> + + 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. +*/ + +#include <pptxml.h> +#include <powerpointfilter.h> + +PowerPointFilter::PowerPointFilter( + const myFile &mainStream, + const myFile ¤tUser, + const myFile &pictures): + FilterBase() +{ + m_tree = new PptXml(mainStream, currentUser, pictures); + + // Hook up the embedded object support. + + connect( + m_tree, + SIGNAL(signalPart(const QString&, QString &, QString &)), + this, + SIGNAL(signalPart(const QString&, QString &, QString &))); + + // Hook up the embedded picture support. + + connect( + m_tree, + SIGNAL(signalSavePic(const QString &, QString &, const QString &, unsigned int, const char *)), + this, + SIGNAL(signalSavePic(const QString &, QString &, const QString &, unsigned int, const char *))); + + // Hook up the embedded part support. + + connect( + m_tree, + SIGNAL(signalSavePart(const QString &, QString &, QString &, const QString &, unsigned int, const char *)), + this, + SIGNAL(signalSavePart(const QString &, QString &, QString &, const QString &, unsigned int, const char *))); +} + +PowerPointFilter::~PowerPointFilter() +{ + delete m_tree; +} + +bool PowerPointFilter::filter() +{ + return m_tree->convert(); +} + +const QDomDocument * const PowerPointFilter::part() +{ + m_part = QDomDocument("DOC"); + m_part.setContent(m_tree->getXml()); + return &m_part; +} + +#include <powerpointfilter.moc> diff --git a/filters/olefilters/powerpoint97/powerpointfilter.h b/filters/olefilters/powerpoint97/powerpointfilter.h new file mode 100644 index 000000000..173d1ebb1 --- /dev/null +++ b/filters/olefilters/powerpoint97/powerpointfilter.h @@ -0,0 +1,47 @@ +/* This file is part of the KDE project + Copyright (C) 1999 Werner Trobin <trobin@kde.org> + + 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 POWERPOINTFILTER_H +#define POWERPOINTFILTER_H + +#include <filterbase.h> +#include <pptxml.h> + +class PowerPointFilter: + public FilterBase +{ + Q_OBJECT + +public: + PowerPointFilter( + const myFile &mainStream, + const myFile ¤tUser, + const myFile &pictures); + virtual ~PowerPointFilter(); + virtual bool filter(); + virtual const QDomDocument * const part(); + +private: + PowerPointFilter(const PowerPointFilter &); + const PowerPointFilter &operator=(const PowerPointFilter &); + + PptXml *m_tree; +}; +#endif + diff --git a/filters/olefilters/powerpoint97/pptSlide.cpp b/filters/olefilters/powerpoint97/pptSlide.cpp new file mode 100644 index 000000000..b86418c9a --- /dev/null +++ b/filters/olefilters/powerpoint97/pptSlide.cpp @@ -0,0 +1,111 @@ +/* + Copyright (C) 2002, M.Marcucio <michaelmarcucio@hotmail.com>. + This file is part of the KDE project + + 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. + +DESCRIPTION + +*/ + +#include <pptSlide.h> + +static const int s_area = 30512; + +PptSlide::PptSlide() +{ + m_slideLayout = 0; //type of slide + m_numberOfPholders = 0; //number of placeholder on the slide + m_psrReference = 0; //logical reference +} + +//PptSlide::~PptSlide() +//{ +//} + +QStringList PptSlide::getPlaceholderText(void) +{ + return m_currentPholder->paragraphs; +} + +//styleRun PptSlide::getPlaceholderStyleRun(void) +//{ +// return m_currentPholder->styleRun; +//} + +Q_UINT16 PptSlide::getPlaceholderType(void) +{ + return m_currentPholder->type; +} + +Q_UINT16 PptSlide::gotoPlaceholder(Q_UINT16 pholderNumber) +{ + m_currentPholder = m_placeholderList.at(pholderNumber); + return 0; +} + +Q_INT32 PptSlide::getPsrReference(void) +{ + return m_psrReference; +} + +void PptSlide::setPsrReference(Q_INT32 psr) +{ + m_psrReference = psr; +} + +Q_UINT16 PptSlide::getNumberOfPholders() +{ + return m_numberOfPholders; +} + +void PptSlide::addText(QString text, Q_UINT16 type) +{ + unsigned j; + m_currentPholder = new placeholder; + m_placeholderList.append(m_currentPholder); + m_numberOfPholders++; + m_currentPholder->type = type; + kdError(s_area) << "adding to slide now!!!!!!!!!!!! m_numberOfPholders: " << m_numberOfPholders << endl; + + switch (type) + { + case TITLE_TEXT: + case CENTER_TITLE_TEXT: + m_currentPholder->paragraphs.append(text); + //m_titleText.append("\n"); + break; + case NOTES_TEXT: + m_currentPholder->paragraphs.append(text); + m_currentPholder->paragraphs.append("\n"); + //m_notesText.append("\n"); + break; + case BODY_TEXT: + case OTHER_TEXT: + case CENTER_BODY_TEXT: + case HALF_BODY_TEXT: + case QUARTER_BODY_TEXT: + QStringList data(QStringList::split(QChar('\r'), text, true)); + for (j = 0; j < data.count(); j++) + { + m_currentPholder->paragraphs.append(data[j]); + //m_body.paragraphs.append(data[j]); + } + //m_body.type = type; + break; + } +}//addtext + diff --git a/filters/olefilters/powerpoint97/pptSlide.h b/filters/olefilters/powerpoint97/pptSlide.h new file mode 100644 index 000000000..16d53f8b0 --- /dev/null +++ b/filters/olefilters/powerpoint97/pptSlide.h @@ -0,0 +1,93 @@ +/* + Copyright (C) 2002, M.Marcucio <michaelmarcucio@hotmail.com>. + This file is part of the KDE project + + 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. + +DESCRIPTION + +*/ + +//#ifndef PPTSLIDE_H +//#define PPTSLIDE_H + +#include <kdebug.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qptrlist.h> + +//--text types +#define TITLE_TEXT 0 //title +#define BODY_TEXT 1 //body +#define NOTES_TEXT 2 //notes +#define NOTUSED_TEXT 3 //not used +#define OTHER_TEXT 4 //other(test in shape) +#define CENTER_BODY_TEXT 5 //center body(subtitle in title slide) +#define CENTER_TITLE_TEXT 6 //center title(title in title slide) +#define HALF_BODY_TEXT 7 //half body(body in two-column slide) +#define QUARTER_BODY_TEXT 8 //quarter body(body in four-body slide) +//-- + +//--char style types +enum +{ + BOLD_STYLE = 1, + ITALIC_STYLE = 2, + UNDERLINE_STYLE = 3 +}; +//-- + +class PptSlide +{ +public: + typedef struct + { + Q_UINT16 style; //the style of the text run + Q_UINT16 length; //length of the style run + }styleRunType; + + typedef QPtrList<styleRunType> styleRun; + + PptSlide(); + QStringList getPlaceholderText(void); //gets the list of paragraphs from the placeholder + //styleRun getPlaceholderStyleRun(void); //gets the list of placeholder style runs + Q_UINT16 getPlaceholderType(void); //gets the type of the placeholder + Q_UINT16 gotoPlaceholder(Q_UINT16 pholderNumber); //goto the n'th placeholder + Q_UINT16 getNumberOfPholders(); //gets the number of placeholders on slide + + Q_INT32 getPsrReference(void); + void setPsrReference(Q_INT32 psr); + + void addText(QString text, Q_UINT16 type); //adds text of the given type + void addToStyleRun(Q_UINT16 style, Q_UINT16 length); //adds to the current style run + +private: + typedef struct + { + QStringList paragraphs; //text of the placeholder + Q_UINT16 type; //what is the text type + styleRun style; //char style info + }placeholder; + + Q_INT16 m_slideLayout; //type of slide + Q_INT16 m_numberOfPholders; //number of placeholder on the slide + Q_INT32 m_psrReference; //logical reference + QPtrList<placeholder> m_placeholderList; //list of all the placeholders on the slide + placeholder* m_currentPholder; //pointer to current placeholder + +}; + +//#endif diff --git a/filters/olefilters/powerpoint97/pptdoc.cc b/filters/olefilters/powerpoint97/pptdoc.cc new file mode 100644 index 000000000..0e40293f4 --- /dev/null +++ b/filters/olefilters/powerpoint97/pptdoc.cc @@ -0,0 +1,87 @@ +/* + Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>. + This file is part of the KDE project + + 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. + +DESCRIPTION + + This file implements a simplified abstraction of Microsoft Powerpoint documents. +*/ + +#include <kdebug.h> +#include <pptdoc.h> +#include <qptrlist.h> + +const int PptDoc::s_area = 30512; + +PptDoc::PptDoc( + const myFile &mainStream, + const myFile ¤tUser, + const myFile &pictures) : + Powerpoint() +{ + m_mainStream = mainStream; + m_currentUser = currentUser; + m_pictures = pictures; +} + +PptDoc::~PptDoc() +{ +} +/* +void PptDoc::gotSlide( + PptSlide &slide) +{ + Slide ourSlide; + unsigned i; + + for (i = 0; i < slide.text.count(); i++) + { + SlideText *text = slide.text.at(i); + QStringList data(QStringList::split(QChar('\r'), text->data, true)); + unsigned j; + + switch (text->type) + { + case TITLE_TEXT: + case CENTER_TITLE_TEXT: + ourSlide.title = data.join("\n"); + break; + case NOTES_TEXT: + ourSlide.notes = data.join("\n"); + break; + case BODY_TEXT: + case OTHER_TEXT: + case CENTER_BODY_TEXT: + case HALF_BODY_TEXT: + case QUARTER_BODY_TEXT: + for (j = 0; j < data.count(); j++) + { + ourSlide.body.append(data[j]); + } + break; + } + } + + gotSlide(slide); +} +*/ + +bool PptDoc::parse() +{ + return Powerpoint::parse(m_mainStream, m_currentUser, m_pictures); +} diff --git a/filters/olefilters/powerpoint97/pptdoc.h b/filters/olefilters/powerpoint97/pptdoc.h new file mode 100644 index 000000000..f7008ad92 --- /dev/null +++ b/filters/olefilters/powerpoint97/pptdoc.h @@ -0,0 +1,82 @@ +/* + Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>. + This file is part of the KDE project + + 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. + +DESCRIPTION + + This file implements a simplified abstraction of Microsoft Powerpoint documents. +*/ + +#ifndef PPTDOC_H +#define PPTDOC_H + +#include <kdebug.h> +#include <myfile.h> +#include <powerpoint.h> +#include <qstring.h> +#include <qstringlist.h> + +class myFile; + +class PptDoc: + protected Powerpoint +{ +protected: + + // Construction. Invoke with the OLE streams that comprise the Powerpoint document. + + PptDoc( + const myFile &mainStream, + const myFile ¤tUser, + const myFile &pictures); + virtual ~PptDoc(); + + // Metadata. + + QString getAuthor(void) const; + + // Call the parse() function to process the document. The callbacks return + // the text along with any relevant attributes. + + bool parse(); + + virtual void gotDrawing( + unsigned id, + QString type, + unsigned length, + const char *data) = 0; + virtual void gotSlide(PptSlide &slide) = 0; + +private: + PptDoc(const PptDoc &); + const PptDoc &operator=(const PptDoc &); + + // Error handling and reporting support. + + static const int s_area; + + myFile m_mainStream; + myFile m_currentUser; + myFile m_pictures; + + // Override the base class functions. + + //void gotSlide( + // PptSlide &slide); +}; +#endif diff --git a/filters/olefilters/powerpoint97/pptxml.cc b/filters/olefilters/powerpoint97/pptxml.cc new file mode 100644 index 000000000..1202edcce --- /dev/null +++ b/filters/olefilters/powerpoint97/pptxml.cc @@ -0,0 +1,317 @@ +/* + Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>. + This file is part of the KDE project + + 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. + +DESCRIPTION +*/ + +#include <pptdoc.h> +#include <pptxml.h> +#include <qobject.h> +#include <KoGlobal.h> + +const int PptXml::s_area = 30512; + +PptXml::PptXml( + const myFile &mainStream, + const myFile ¤tUser, + const myFile &pictures): + PptDoc( + mainStream, + currentUser, + pictures) +{ + m_isConverted = false; + m_success = false; + m_half = false; + m_y = 0; +} + +PptXml::~PptXml() +{ +} + +bool PptXml::convert() +{ + if (!m_isConverted) + { + // m_y = 30; + m_success = parse(); + m_isConverted = true; + } + return m_success; +} + +void PptXml::encode(QString &text) +{ + // When encoding the stored form of text to its run-time form, + // be sure to do the conversion for "&" to "&" first to avoid + // accidentally converting user text into one of the other escape + // sequences. + + text.replace('&', "&"); + text.replace('<', "<"); + text.replace('>', ">"); // Needed to avoid ]]> + + // Strictly, there is no need to encode " or ', but we do so to allow + // them to co-exist! + + text.replace('"', """); + text.replace('\'', "'"); +} + +const QString PptXml::getXml() const +{ + QString body = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><!DOCTYPE DOC>\n" + "<DOC mime=\"application/x-kpresenter\" email=\"reggie@kde.org\" syntaxVersion=\"2\" author=\"Reginald Stadlbauer\" editor=\"Powerpoint import filter\">\n" + " <PAPER ptWidth=\"680\" unit=\"0\" format=\"5\" orientation=\"0\" ptHeight=\"510\">\n" + " <PAPERBORDERS ptRight=\"0\" ptBottom=\"0\" ptLeft=\"0\" ptTop=\"0\"/>\n" + " </PAPER>\n" + " <BACKGROUND rastX=\"10\" rastY=\"10\" color=\"#ffffff\">\n"; + body += m_pages; + body += " </BACKGROUND>\n" + " <HEADER show=\"0\">\n" + " <ORIG x=\"0\" y=\"0\"/>\n" + " <SIZE width=\"680\" height=\"20\"/>\n" + " <PEN width=\"1\" style=\"0\" color=\"#000000\"/>\n" + " <TEXTOBJ>\n" + " <P/>\n" + " </TEXTOBJ>\n" + " </HEADER>\n" + " <FOOTER show=\"0\">\n" + " <ORIG x=\"0\" y=\"430\"/>\n" + " <SIZE width=\"680\" height=\"20\"/>\n" + " <PEN width=\"1\" style=\"0\" color=\"#000000\"/>\n" + " <TEXTOBJ>\n" + " <P/>\n" + " </TEXTOBJ>\n" + " </FOOTER>\n" + " <PAGETITLES>\n"; + body += m_titles; + body += " </PAGETITLES>\n" + " <PAGENOTES>\n"; + body += m_notes; + body += " </PAGENOTES>\n" + " <OBJECTS>\n"; + body += m_text; + body += " </OBJECTS>\n" + " <INFINITLOOP value=\"0\"/>\n" + " <MANUALSWITCH value=\"1\"/>\n" + " <PRESSPEED value=\"1\"/>\n" + " <PRESSLIDES value=\"0\"/>\n" + " <SELSLIDES>\n" + " <SLIDE nr=\"0\" show=\"1\"/>\n" + " </SELSLIDES>\n" + " <PIXMAPS>\n" + " </PIXMAPS>\n" + " <CLIPARTS>\n" + " </CLIPARTS>\n"; + body += m_embedded; + body += "</DOC>\n"; + //kdDebug(s_area) << body << endl; + return body; +} + +void PptXml::gotDrawing( + unsigned id, + QString type, + unsigned length, + const char *data) +{ + QString ourKey; + QString uid; + QString mimeType; + QString filterArgs; + + // Send the picture to the outside world and get back the UID. + + ourKey = "vectorGraphic" + QString::number(id) + "." + type; + if (type == "msod") + { + filterArgs = "shape-id="; + filterArgs += QString::number(id); + filterArgs += ";delay-stream="; + filterArgs += QString::number(0); + } + emit signalSavePart( + ourKey, + uid, + mimeType, + type, + length, + data); + + // Add an entry to the list of embedded objects too. TBD: fix + // RECT and FRAME settings. +if (mimeType != "application/x-kontour") +{ + m_embedded += " <EMBEDDED>\n" + "<OBJECT url=\"" + + uid + + "\" mime=\"" + + mimeType + + "\">\n<RECT x=\"30\" y=\"190\" w=\"120\" h=\"80\"/>\n" + "</OBJECT>\n" + "<SETTINGS>\n" + "<EFFECTS effect=\"0\" effect2=\"0\"/>\n" + "<PEN red=\"0\" green=\"0\" blue=\"0\" width=\"1\" style=\"0\"/>\n" + "<BRUSH red=\"0\" green=\"0\" blue=\"0\" style=\"0\"/>\n" + "<PRESNUM value=\"0\"/>\n" + "<ANGLE value=\"0\"/>\n" + "<FILLTYPE value=\"0\"/>\n" + "<GRADIENT red1=\"255\" green1=\"0\" blue1=\"0\" red2=\"0\" green2=\"255\" blue2=\"0\" type=\"1\" unbalanced=\"0\" xfactor=\"100\" yfactor=\"100\"/>\n" + "<DISAPPEAR effect=\"0\" doit=\"0\" num=\"1\"/>\n" + "</SETTINGS>\n" + " </EMBEDDED>\n"; +} +} + +void PptXml::gotSlide(PptSlide &slide) +{ + static const unsigned pageHeight = 510; + Q_UINT16 numbOfPholders = 0; + m_pages += " <PAGE/>\n"; + numbOfPholders = slide.getNumberOfPholders(); + for(Q_UINT16 i = 0; i < numbOfPholders; i++) + { + slide.gotoPlaceholder(i); + setPlaceholder(slide); + } + m_y += pageHeight; +} + +void PptXml::setPlaceholder(PptSlide &slide) +{ + QString xml_friendly; + unsigned i = 0; + bool bulletedList = false; //is this a bulleted list? + Q_UINT16 type; //type of text + QString x; //x of placeholder + QString align; //align of text + QString height ; //height of placeholder + QString width ; //width of placeholder + QString pointSize; //font size + + xml_friendly = *slide.getPlaceholderText().at(i); + encode(xml_friendly); + + type = slide.getPlaceholderType(); + Q_UINT16 y = 0; + + switch (type) + { + case TITLE_TEXT: + y = 30; + height = QString::number(55); + x = QString::number(30); + width = QString::number(610); + align = QString::number(ALIGN_CENTER); + pointSize = QString::number(44); + bulletedList = false; + m_titles += " <Title title=\"" + xml_friendly + "\" />\n"; + break; + case CENTER_TITLE_TEXT: + y = 130; + x = QString::number(45); + height = QString::number(55); + width = QString::number(610); + align = QString::number(ALIGN_CENTER); + pointSize = QString::number(44); + bulletedList = false; + m_titles += " <Title title=\"" + xml_friendly + "\" />\n"; + break; + case CENTER_BODY_TEXT: + y = 200; + x = QString::number(35); + height = QString::number(37); + width = QString::number(610); + align = QString::number(ALIGN_CENTER); + pointSize = QString::number(32); + bulletedList = false; + break; + case NOTES_TEXT: + m_notes += " <Note note=\"\" />\n"; + break; + case BODY_TEXT: + y = 130; + x = QString::number(35); + height = QString::number(268); + width = QString::number(610); + align = QString::number(ALIGN_LEFT); + pointSize = QString::number(28); + bulletedList = true; + break; + case OTHER_TEXT: + case HALF_BODY_TEXT: + case QUARTER_BODY_TEXT: + y = 130; + if(m_half) + { + x = QString::number(335); + width = QString::number(300); + m_half = false; + } + else + { + x = QString::number(30); + width = QString::number(300); + m_half = true; + } + height = QString::number(268); + align = QString::number(ALIGN_LEFT); + pointSize = QString::number(28); + bulletedList = true; + break; + default: + return; + break; + } + + m_text += "<OBJECT type=\"4\">\n" + " <ORIG x=\""+x+"\" y=\""+QString::number(y + m_y)+"\"/>\n" + " <SIZE width=\""+width+"\" height=\""+ height +"\"/>\n" + " <PEN width=\"1\" style=\"0\" color=\"#000000\"/>\n" + " <TEXTOBJ>\n" + " <P align=\""+align+"\">\n"; + if(bulletedList) + m_text += " <COUNTER numberingtype=\"0\" type=\"10\" depth=\"0\" />\n"; + m_text += " <TEXT family=\"utopia\" pointSize=\""+pointSize+"\" color=\"#000000\">"; + + for (i = 0; i < slide.getPlaceholderText().count(); i++) + { + xml_friendly = *slide.getPlaceholderText().at(i); + encode(xml_friendly); + m_text += xml_friendly; + if (i < slide.getPlaceholderText().count() - 1) + { + m_text += "</TEXT>\n" + " </P>\n" + " <P align=\"1\">\n"; + if(bulletedList) + m_text += " <COUNTER numberingtype=\"0\" type=\"10\" depth=\"0\" />\n"; + m_text += " <TEXT family=\"utopia\" pointSize=\""+pointSize+"\" color=\"#000000\">"; + } + } + m_text += "</TEXT>\n" + " </P>\n" + " </TEXTOBJ>\n" + "</OBJECT>"; + +} + +#include "pptxml.moc" diff --git a/filters/olefilters/powerpoint97/pptxml.h b/filters/olefilters/powerpoint97/pptxml.h new file mode 100644 index 000000000..b57338cb6 --- /dev/null +++ b/filters/olefilters/powerpoint97/pptxml.h @@ -0,0 +1,109 @@ +/* + Copyright (C) 2000, S.R.Haque <shaheedhaque@hotmail.com>. + This file is part of the KDE project + + 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. + +DESCRIPTION +*/ + +#ifndef PPTXML_H +#define PPTXML_H + +#include <pptdoc.h> +#include <qobject.h> +#include <qstring.h> + +#define ALIGN_LEFT 1 +#define ALIGN_RIGHT 2 +#define ALIGN_CENTER 4 +#define ALIGN_JUSTIFY 8 + +class myFile; +class QDomDocument; + +class PptXml: + public QObject, + private PptDoc +{ + + Q_OBJECT + +public: + PptXml( + const myFile &mainStream, + const myFile ¤tUser, + const myFile &pictures); + ~PptXml(); + + bool convert(); + + const QString getXml() const; + +signals: + // See olefilter.h for information + void signalSavePic( + const QString &nameIN, + QString &storageId, + const QString &extension, + unsigned int length, + const char *data); + + void signalSavePart( + const QString &nameIN, + QString &storageId, + QString &mimeType, + const QString &extension, + unsigned int length, + const char *data); + + void signalPart( + const QString& nameIN, + QString &storageId, + QString &mimeType); + +private: + PptXml(const PptXml &); + const PptXml &operator=(const PptXml &); + + // Error handling and reporting support. + + static const int s_area; + + // The conversion is done exactly once. Has it already happened? + + bool m_isConverted; + bool m_success; + bool m_half; + unsigned m_y; + QString m_embedded; + QString m_pages; + QString m_titles; + QString m_notes; + QString m_text; + void encode(QString &text); + + // Override the base class functions. + + void gotDrawing( + unsigned id, + QString type, + unsigned length, + const char *data); + void gotSlide(PptSlide &slide); + void setPlaceholder(PptSlide &slide); +}; +#endif diff --git a/filters/olefilters/powerpoint97/status.html b/filters/olefilters/powerpoint97/status.html new file mode 100644 index 000000000..5db4ed524 --- /dev/null +++ b/filters/olefilters/powerpoint97/status.html @@ -0,0 +1,156 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<html> +<head> + <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> + <title>KOffice filters status: POWERPOINT FILTER</title> +</head> +<body text="#000000" bgcolor="#FFFFFF" link="#000099" vlink="#666666" alink="#666666"> +<A NAME="START"> </A> + +<BR> +<center> + <h1> + KOffice filters status: <i>PowerPoint97 FILTER</i> + </h1> +</center> + +<hr NOSHADE SIZE=2 WIDTH="70%"> + +<font size="-1"><b> + <A HREF="#import">Import</A> | + <A HREF="#export">Export</A> +</b></font> + +<BR><BR><BR> +<center><a NAME="import"></a></center> + +<A HREF="#START"><font size="-1"><b>Up</b></font></A> +<center> +<table BORDER=0 CELLSPACING=0 BGCOLOR="#000000" WIDTH="100%"> + <tr> + <td> + <table BORDER=0 CELLPADDING=2 BGCOLOR="#FFFFFF" WIDTH="100%"> + + <tr BGCOLOR="#DDFFDD"> + <td COLSPAN="2"> + <center><b><i><font size="+1"> + <BR> + Import PowerPoint97 for kpresenter<BR> + <BR> + </font></i></b></center> + </td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP WIDTH="1%" NOWRAP><b><font size="+1">Last update</font></b></td> + <td>27 March 2002</td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">Features</font></b></td> + <td>Imports text from Powerpoint97/XP documents.</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Todo</font></b></td> + <td>- Everything!</td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">History</font></b></td> + <td>---</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Authors</font></b></td> + <td> + <A HREF="mailto:srhaque@iee.org">Shaheed Haque</A> + </td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">Links</font></b></td> + <td>Check your local copy of the MSDN Library</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Progress report </font></b></td> + <td>---</td> + </tr> + </table> + </td> + </tr> +</table> +</center> +<A HREF="#START"><font size="-1"><b>Up</b></font></A> + +<br><br><br> + +<hr NOSHADE SIZE=1> +<br><br><br> + + +<center> + <a NAME="export"></a> +</center> + +<A HREF="#START"><font size="-1"><b>Up</b></font></A> +<center> +<table BORDER=0 CELLSPACING=0 BGCOLOR="#000000" WIDTH="100%"> + <tr> + <td> + <table BORDER=0 CELLPADDING=2 BGCOLOR="#FFFFFF" WIDTH="100%"> + <tr BGCOLOR="#FFDDDD"> + <td COLSPAN="2"> + <center><b><i><font size="+1"> + <BR>Export kpresenter to PowerPoint97<BR><BR> + </font></i></b></center> + </td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP WIDTH="1%" NOWRAP><b><font size="+1">Last update</font></b></td> + <td>-</td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">Features</font></b></td> + <td>None</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Todo</font></b></td> + <td>Everything</td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">History</font></b></td> + <td>-</td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Authors</font></b></td> + <td><!a href="mailto:null@kde.org">-</a></td> + </tr> + + <tr BGCOLOR="#CCCCFF"> + <td VALIGN=TOP><b><font size="+1">Links</font></b></td> + <td><!a href="http://www.koffice.org">-</a></td> + </tr> + + <tr BGCOLOR="#EEEEFF"> + <td VALIGN=TOP><b><font size="+1">Progress report </font></b></td> + <td>---</td> + </tr> + + + + </table> + </td> + </tr> +</table> +</center> +<A HREF="#START"><font size="-1"><b>Up</b></font></A> + +</body> +</html> |
