You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
546 lines
16 KiB
546 lines
16 KiB
/* 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)
|
|
{
|
|
KGlobal::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& tqlayout,
|
|
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.tqlayout, para.formattingList);
|
|
}
|
|
|
|
bool ASCIIWorker::doFullParagraph(const TQString& paraText, const LayoutData& tqlayout,
|
|
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 ( tqlayout.counter.numbering == CounterData::NUM_LIST )
|
|
{
|
|
// Are we still in a list of the right type?
|
|
if (!m_inList || (tqlayout.counter.style!=m_typeList))
|
|
{
|
|
// We are not yet part of a list
|
|
m_inList=true;
|
|
m_counterList=1; // Start numbering
|
|
m_typeList=tqlayout.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 ( tqlayout.counter.numbering == CounterData::NUM_CHAPTER )
|
|
{
|
|
if (!tqlayout.counter.depth)
|
|
{ // HEAD 1
|
|
*m_streamOut << "###################################" << m_eol;
|
|
*m_streamOut << "# ";
|
|
ProcessParagraphData ( paraText, paraFormatDataList);
|
|
*m_streamOut << "###################################" << m_eol;
|
|
}
|
|
else if (tqlayout.counter.depth==1)
|
|
{ // HEAD 2
|
|
*m_streamOut << "#### ";
|
|
ProcessParagraphData ( paraText, paraFormatDataList);
|
|
}
|
|
else if (tqlayout.counter.depth==2)
|
|
{ // HEAD 3
|
|
*m_streamOut << "## ";
|
|
ProcessParagraphData ( paraText, paraFormatDataList);
|
|
}
|
|
else if (tqlayout.counter.depth==3)
|
|
{ // HEAD 4
|
|
*m_streamOut << "# ";
|
|
ProcessParagraphData ( paraText, paraFormatDataList);
|
|
}
|
|
else
|
|
{
|
|
ProcessParagraphData ( paraText, paraFormatDataList);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ProcessParagraphData ( paraText, paraFormatDataList);
|
|
}
|
|
}
|
|
#else
|
|
if (!tqlayout.counter.text.isEmpty())
|
|
*m_streamOut << tqlayout.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 tqlayout 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.tqreplace(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().tqreplace(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::ConversiontqStatus 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::ConversiontqStatus result = leader->convert(m_chain,from,to);
|
|
|
|
delete leader;
|
|
delete worker;
|
|
|
|
return result;
|
|
}
|
|
|
|
#include <asciiexport.moc>
|