summaryrefslogtreecommitdiffstats
path: root/filters/kword/ascii/asciiexport.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'filters/kword/ascii/asciiexport.cpp')
-rw-r--r--filters/kword/ascii/asciiexport.cpp545
1 files changed, 545 insertions, 0 deletions
diff --git a/filters/kword/ascii/asciiexport.cpp b/filters/kword/ascii/asciiexport.cpp
new file mode 100644
index 000000000..1bea9a269
--- /dev/null
+++ b/filters/kword/ascii/asciiexport.cpp
@@ -0,0 +1,545 @@
+/* This file is part of the KDE project
+ Copyright (C) 1998, 1999 Reginald Stadlbauer <reggie@kde.org>
+ Copyright (c) 2000 ID-PRO Deutschland GmbH. All rights reserved.
+ Contact: Wolf-Michael Bolle <Bolle@ID-PRO.de>
+ Copyright (C) 2001, 2002, 2004 Nicolas GOUTTE <goutte@kde.org>
+ Copyright (C) 2003 Clarence Dang <dang@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 <limits.h>
+
+#include <tqcstring.h>
+#include <tqfile.h>
+#include <tqiodevice.h>
+#include <tqstring.h>
+#include <tqtextcodec.h>
+#include <tqtextstream.h>
+
+#include <kdebug.h>
+#include <kgenericfactory.h>
+
+#include <KoFilterChain.h>
+#include <KoFilterManager.h>
+#include <KoStore.h>
+
+#include <KWEFStructures.h>
+#include <KWEFBaseWorker.h>
+#include <KWEFKWordLeader.h>
+
+#include <ExportDialog.h>
+#include <asciiexport.h>
+
+
+class ASCIIExportFactory : KGenericFactory<ASCIIExport, KoFilter>
+{
+public:
+ ASCIIExportFactory() : KGenericFactory<ASCIIExport, KoFilter>("kwordasciiexport")
+ {
+ }
+
+protected:
+ virtual void setupTranslations(void)
+ {
+ TDEGlobal::locale()->insertCatalogue("kofficefilters");
+ }
+};
+
+K_EXPORT_COMPONENT_FACTORY(libasciiexport, ASCIIExportFactory())
+
+
+class ASCIIWorker : public KWEFBaseWorker
+{
+public:
+ ASCIIWorker() : m_ioDevice(NULL), m_streamOut(NULL), m_eol("\n")/*,
+ m_inList(false)*/
+ {
+ }
+
+ virtual ~ASCIIWorker()
+ {
+ delete m_streamOut; delete m_ioDevice;
+ }
+
+public:
+ virtual bool doOpenFile(const TQString& filenameOut, const TQString& to);
+ virtual bool doCloseFile(void); // Close file in normal conditions
+
+ virtual bool doOpenDocument(void);
+ virtual bool doCloseDocument(void);
+
+ virtual bool doFullParagraphList(const TQValueList<ParaData>& paraList);
+ virtual bool doFullParagraph(const ParaData& para);
+ virtual bool doFullParagraph(const TQString& paraText,
+ const LayoutData& layout,
+ const ValueListFormatData& paraFormatDataList);
+
+public:
+ TQString getEndOfLine(void) const { return m_eol; }
+ void setEndOfLine(const TQString& str) { m_eol = str; }
+
+ TQTextCodec* getCodec(void) const { return m_codec; }
+ void setCodec(TQTextCodec* codec) { m_codec = codec; }
+
+private:
+ virtual bool ProcessTable(const Table& table);
+ virtual bool ProcessParagraphData (const TQString& paraText,
+ const ValueListFormatData& paraFormatDataList);
+
+private:
+ TQIODevice* m_ioDevice;
+ TQTextStream* m_streamOut;
+
+ TQTextCodec* m_codec; // TQTextCodec in which the file will be written
+ TQString m_eol; // End of line character(s)
+ TQStringList m_automaticNotes; // Automatic foot-/endnotes
+ TQString m_manualNotes; // Manual foot-/endnotes
+
+#if 0
+ CounterData::Style m_typeList; // What is the style of the current list (undefined, if we are not in a list)
+ bool m_inList; // Are we currently in a list?
+ bool m_orderedList; // Is the current list ordered or not (undefined, if we are not in a list)
+ int m_counterList; // Counter for te lists
+#endif
+};
+
+bool ASCIIWorker::doOpenFile(const TQString& filenameOut, const TQString& /*to*/)
+{
+ m_ioDevice = TQT_TQIODEVICE(new TQFile(filenameOut));
+
+ if (!m_ioDevice)
+ {
+ kdError(30502) << "No output file! Aborting!" << endl;
+ return false;
+ }
+
+ if (!m_ioDevice->open(IO_WriteOnly))
+ {
+ kdError(30502) << "Unable to open output file!" << endl;
+ return false;
+ }
+
+ m_streamOut = new TQTextStream(m_ioDevice);
+ if (!m_streamOut)
+ {
+ kdError(30502) << "Could not create output stream! Aborting!" << endl;
+ m_ioDevice->close();
+ return false;
+ }
+
+ kdDebug(30502) << "Charset used: " << getCodec()->name() << endl;
+
+ if (!getCodec())
+ {
+ kdError(30502) << "Could not create TQTextCodec! Aborting" << endl;
+ return false;
+ }
+
+ m_streamOut->setCodec(getCodec());
+
+ return true;
+}
+
+bool ASCIIWorker::doCloseFile(void)
+{
+ delete m_streamOut;
+ m_streamOut=NULL;
+ if (m_ioDevice)
+ m_ioDevice->close();
+ return (m_ioDevice);
+}
+
+bool ASCIIWorker::doOpenDocument(void)
+{
+ // We have nothing to do, but to give our OK to continue
+ return true;
+}
+
+bool ASCIIWorker::doCloseDocument(void)
+{
+ // Add foot-/endnotes
+ if (!m_automaticNotes.empty())
+ {
+ *m_streamOut << m_eol;
+ int noteNumber = 1;
+ for (TQStringList::Iterator it = m_automaticNotes.begin(); it != m_automaticNotes.end(); ++it)
+ {
+ *m_streamOut << "[" << noteNumber << "] " << *it;
+ noteNumber++;
+ }
+ }
+
+ if (!m_manualNotes.isEmpty())
+ *m_streamOut << m_eol << m_manualNotes;
+
+ return true;
+}
+
+bool ASCIIWorker::doFullParagraphList(const TQValueList<ParaData>& paraList)
+{
+ for (TQValueList<ParaData>::ConstIterator it = paraList.begin();
+ it != paraList.end();
+ it++)
+ {
+ if (!doFullParagraph(*it)) return false;
+ }
+
+ return true;
+}
+
+bool ASCIIWorker::doFullParagraph(const ParaData& para)
+{
+ return doFullParagraph(para.text, para.layout, para.formattingList);
+}
+
+bool ASCIIWorker::doFullParagraph(const TQString& paraText, const LayoutData& layout,
+ const ValueListFormatData& paraFormatDataList)
+{
+ kdDebug(30502) << "Entering ASCIIWorker::doFullParagraph" << endl;
+
+#if 0
+ // As KWord has only one depth of lists, we can process lists very simply.
+ // --
+ // Not anymore - Clarence
+ if ( layout.counter.numbering == CounterData::NUM_LIST )
+ {
+ // Are we still in a list of the right type?
+ if (!m_inList || (layout.counter.style!=m_typeList))
+ {
+ // We are not yet part of a list
+ m_inList=true;
+ m_counterList=1; // Start numbering
+ m_typeList=layout.counter.style;
+ }
+
+ switch (m_typeList)
+ // TODO: when we would be able to save to UTF-8,
+ // use correct symbols
+ {
+ case CounterData::STYLE_CUSTOMBULLET: // We cannot keep the custom type/style
+ default:
+ {
+ m_orderedList=false;
+ *m_streamOut << "- ";
+ break;
+ }
+ case CounterData::STYLE_NONE:
+ {
+ m_orderedList=false;
+ break;
+ }
+ case CounterData::STYLE_CIRCLEBULLET:
+ {
+ m_orderedList=false;
+ *m_streamOut << "o ";
+ break;
+ }
+ case CounterData::STYLE_SQUAREBULLET:
+ {
+ m_orderedList=false;
+ *m_streamOut << "~ "; // Not much a square
+ break;
+ }
+ case CounterData::STYLE_DISCBULLET:
+ {
+ m_orderedList=false;
+ *m_streamOut << "* "; // Not much a disc
+ break;
+ }
+ case CounterData::STYLE_NUM:
+ case CounterData::STYLE_CUSTOM:
+ {
+ m_orderedList=true;
+ *m_streamOut << TQString::number(m_counterList,10);
+ break;
+ }
+ case CounterData::STYLE_ALPHAB_L:
+ {
+ m_orderedList=true;
+ TQString strTemp;
+ for (int i=m_counterList;i>0;i/=26)
+ strTemp=TQChar(0x40+i%26)+strTemp; // Lower alpha
+ *m_streamOut << strTemp;
+ break;
+ }
+ case CounterData::STYLE_ALPHAB_U:
+ {
+ m_orderedList=true;
+ TQString strTemp;
+ for (int i=m_counterList;i>0;i/=26)
+ strTemp=TQChar(0x40+i%26)+strTemp; // Lower alpha
+ *m_streamOut << strTemp;
+ break;
+ }
+ case CounterData::STYLE_ROM_NUM_L:
+ {
+ // For now, we do not support lower-case Roman numbering (TODO)
+ m_orderedList=true;
+ *m_streamOut << TQString::number(m_counterList,10);
+ break;
+ }
+ case CounterData::STYLE_ROM_NUM_U:
+ {
+ // For now, we do not support upper-case Roman numbering (TODO)
+ m_orderedList=true;
+ *m_streamOut << TQString::number(m_counterList,10);
+ break;
+ }
+ }
+ ProcessParagraphData ( paraText, paraFormatDataList);
+ m_counterList++; // Increment the list counter
+ }
+ else
+ {
+ m_inList=false; // Close an eventual list
+ if ( layout.counter.numbering == CounterData::NUM_CHAPTER )
+ {
+ if (!layout.counter.depth)
+ { // HEAD 1
+ *m_streamOut << "###################################" << m_eol;
+ *m_streamOut << "# ";
+ ProcessParagraphData ( paraText, paraFormatDataList);
+ *m_streamOut << "###################################" << m_eol;
+ }
+ else if (layout.counter.depth==1)
+ { // HEAD 2
+ *m_streamOut << "#### ";
+ ProcessParagraphData ( paraText, paraFormatDataList);
+ }
+ else if (layout.counter.depth==2)
+ { // HEAD 3
+ *m_streamOut << "## ";
+ ProcessParagraphData ( paraText, paraFormatDataList);
+ }
+ else if (layout.counter.depth==3)
+ { // HEAD 4
+ *m_streamOut << "# ";
+ ProcessParagraphData ( paraText, paraFormatDataList);
+ }
+ else
+ {
+ ProcessParagraphData ( paraText, paraFormatDataList);
+ }
+ }
+ else
+ {
+ ProcessParagraphData ( paraText, paraFormatDataList);
+ }
+ }
+#else
+ if (!layout.counter.text.isEmpty())
+ *m_streamOut << layout.counter.text << " ";
+
+ if (!ProcessParagraphData(paraText, paraFormatDataList)) return false;
+#endif
+
+ kdDebug(30502) << "Exiting ASCIIWorker::doFullParagraph" << endl;
+ return true;
+}
+
+
+bool ASCIIWorker::ProcessTable(const Table& table)
+{
+ kdDebug(30502) << "processTable CALLED!" << endl;
+
+ // just dump the table out (no layout for now)
+ for (TQValueList<TableCell>::ConstIterator it = table.cellList.begin();
+ it != table.cellList.end();
+ it++)
+ {
+ if (!doFullParagraphList(*(*it).paraList)) return false;
+ }
+
+ return true;
+}
+
+// ProcessParagraphData () mangles the pure text through the
+// formatting information stored in the FormatData list and prints it
+// out to the export file.
+bool ASCIIWorker::ProcessParagraphData(const TQString& paraText,
+ const ValueListFormatData& paraFormatDataList)
+{
+ bool lastSegmentWasText = true;
+
+ if (!paraText.isEmpty())
+ {
+ ValueListFormatData::ConstIterator paraFormatDataIt;
+
+ for (paraFormatDataIt = paraFormatDataList.begin ();
+ paraFormatDataIt != paraFormatDataList.end ();
+ paraFormatDataIt++)
+ {
+ lastSegmentWasText = true;
+
+ switch ((*paraFormatDataIt).id)
+ {
+ case 1: // Normal text
+ {
+ TQString strText(paraText.mid((*paraFormatDataIt).pos,(*paraFormatDataIt).len));
+ strText = strText.replace(TQChar(10), m_eol, true);
+ *m_streamOut << strText;
+ break;
+ }
+ case 4: // Variable
+ {
+ if (11==(*paraFormatDataIt).variable.m_type)
+ {
+ // Footnote
+ TQString value = (*paraFormatDataIt).variable.getFootnoteValue();
+ bool automatic = (*paraFormatDataIt).variable.getFootnoteAuto();
+ TQValueList<ParaData> *paraList = (*paraFormatDataIt).variable.getFootnotePara();
+ if (paraList)
+ {
+ TQString notestr;
+ TQValueList<ParaData>::ConstIterator it;
+ TQValueList<ParaData>::ConstIterator end(paraList->end());
+ for (it=paraList->begin();it!=end;++it)
+ notestr += (*it).text.stripWhiteSpace().replace(TQChar(10), m_eol, true) + m_eol;
+
+ *m_streamOut << "[";
+ if (automatic) {
+ // Automatic footnote
+ *m_streamOut << m_automaticNotes.count() + 1;
+ m_automaticNotes.append(notestr);
+ }
+ else
+ {
+ // Manual footnote
+ *m_streamOut << value;
+ m_manualNotes += "[" + value + "] " + notestr;
+ }
+ *m_streamOut << "]";
+ }
+ }
+ else
+ {
+ // Generic variable
+ *m_streamOut << (*paraFormatDataIt).variable.m_text;
+ }
+ break;
+ }
+ case 6: // Frame Anchor
+ {
+ if ((*paraFormatDataIt).frameAnchor.type == 6) // Table
+ {
+ if ((*paraFormatDataIt).pos)
+ *m_streamOut << m_eol;
+
+ if (!ProcessTable((*paraFormatDataIt).frameAnchor.table))
+ return false;
+ }
+ else
+ {
+ kdWarning(30502) << "Unsupported frame anchor type: "
+ << (*paraFormatDataIt).frameAnchor.type << endl;
+ }
+
+ lastSegmentWasText = false;
+ break;
+ }
+ default:
+ {
+ kdWarning(30502) << "Not supported paragraph type: "
+ << (*paraFormatDataIt).id << endl;
+ break;
+ }
+ }
+ }
+ }
+
+ if (lastSegmentWasText)
+ *m_streamOut << m_eol; // Write end of line
+
+ return true;
+}
+
+
+ASCIIExport::ASCIIExport(KoFilter*, const char*, const TQStringList&)
+ : KoFilter()
+{
+}
+
+KoFilter::ConversionStatus ASCIIExport::convert(const TQCString& from, const TQCString& to)
+{
+ if (to != "text/plain" || from != "application/x-kword")
+ {
+ return KoFilter::NotImplemented;
+ }
+ AsciiExportDialog* dialog = 0;
+ if (!m_chain->manager()->getBatchMode())
+ {
+ dialog = new AsciiExportDialog();
+ if (!dialog)
+ {
+ kdError(30502) << "Dialog has not been created! Aborting!" << endl;
+ return KoFilter::StupidError;
+ }
+
+ if (!dialog->exec())
+ {
+ kdError(30502) << "Dialog was aborted! Aborting filter!" << endl;
+ return KoFilter::UserCancelled;
+ }
+ }
+ ASCIIWorker* worker = new ASCIIWorker();
+
+ if (!worker)
+ {
+ kdError(30502) << "Cannot create Worker! Aborting!" << endl;
+ delete dialog;
+ return KoFilter::StupidError;
+ }
+ TQTextCodec* codec;
+ if (dialog)
+ codec = dialog->getCodec();
+ else
+ codec = TQTextCodec::codecForName("UTF-8");
+
+ if ( !codec )
+ {
+ kdError(30502) << "No codec!" << endl;
+ delete dialog;
+ return KoFilter::StupidError;
+ }
+
+ worker->setCodec( codec );
+ if (dialog)
+ worker->setEndOfLine(dialog->getEndOfLine());
+ else
+ worker->setEndOfLine("\n");
+
+ delete dialog;
+
+ KWEFKWordLeader* leader = new KWEFKWordLeader(worker);
+
+ if (!leader)
+ {
+ kdError(30502) << "Cannot create Worker! Aborting!" << endl;
+ delete worker;
+ return KoFilter::StupidError;
+ }
+
+ KoFilter::ConversionStatus result = leader->convert(m_chain,from,to);
+
+ delete leader;
+ delete worker;
+
+ return result;
+}
+
+#include <asciiexport.moc>