diff options
Diffstat (limited to 'filters/kword/oowriter/ExportFilter.cc')
-rw-r--r-- | filters/kword/oowriter/ExportFilter.cc | 2229 |
1 files changed, 0 insertions, 2229 deletions
diff --git a/filters/kword/oowriter/ExportFilter.cc b/filters/kword/oowriter/ExportFilter.cc deleted file mode 100644 index 216ace492..000000000 --- a/filters/kword/oowriter/ExportFilter.cc +++ /dev/null @@ -1,2229 +0,0 @@ -/* This file is part of the KDE project - Copyright (C) 2001, 2002, 2003, 2004 Nicolas GOUTTE <goutte@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 file is based on the old file: - /home/kde/koffice/filters/kword/ascii/asciiexport.cc - - The old file was copyrighted by - 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> - - The old file was licensed under the terms of the GNU Library General Public - License version 2. -*/ - -#include <tqmap.h> -#include <tqiodevice.h> -#include <tqbuffer.h> -#include <tqtextstream.h> -#include <tqdom.h> - -#include <kdebug.h> -#include <tdelocale.h> -#include <kzip.h> - -#include <KoPageLayout.h> -#include <KoPictureKey.h> -#include <KoPicture.h> - -#include <KWEFStructures.h> -#include <KWEFUtil.h> -#include <KWEFBaseWorker.h> -#include <KWEFKWordLeader.h> - -#include "ExportFilter.h" - -OOWriterWorker::OOWriterWorker(void) : m_streamOut(NULL), - m_paperBorderTop(0.0),m_paperBorderLeft(0.0), - m_paperBorderBottom(0.0),m_paperBorderRight(0.0), m_zip(NULL), m_pictureNumber(0), - m_automaticParagraphStyleNumber(0), m_automaticTextStyleNumber(0), - m_footnoteNumber(0), m_tableNumber(0), m_textBoxNumber( 0 ), - m_columnspacing( 36.0 ), m_columns( 1 ) -{ -} - -TQString OOWriterWorker::escapeOOText(const TQString& strText) const -{ - // Escape quotes (needed in attributes) - // Escape apostrophs (allowed by XML) - return KWEFUtil::EscapeSgmlText(NULL,strText,true,true); -} - -TQString OOWriterWorker::escapeOOSpan(const TQString& strText) const -// We need not only to escape the classical XML stuff but also to take care of spaces and tabs. -{ - TQString strReturn; - TQChar ch; - int spaceNumber = 0; // How many spaces should be written - - for (uint i=0; i<strText.length(); i++) - { - ch=strText[i]; - - if (ch!=' ') - { - // The next character is not a space (anymore) - if ( spaceNumber > 0 ) - { - strReturn += ' '; - --spaceNumber; - if ( spaceNumber > 0 ) - { - strReturn += "<text:s text:c=\""; - strReturn += TQString::number( spaceNumber ); - strReturn += "\"/>"; - } - spaceNumber = 0; - } - } - - // ### TODO: would be switch/case or if/elseif the best? - switch (ch.unicode()) - { - case 9: // Tab - { - strReturn+="<text:tab-stop/>"; - break; - } - case 10: // Line-feed - { - strReturn+="<text:line-break/>"; - break; - } - case 32: // Space - { - if ( spaceNumber > 0 ) - { - ++spaceNumber; - } - else - { - spaceNumber = 1; - } - break; - } - case 38: // & - { - strReturn+="&"; - break; - } - case 60: // < - { - strReturn+="<"; - break; - } - case 62: // > - { - strReturn+=">"; - break; - } - case 34: // " - { - strReturn+="""; - break; - } - case 39: // ' - { - strReturn+="'"; - break; - } - case 1: // (Non-XML-compatible) replacement character from KWord 0.8 - { - strReturn += '#'; //use KWord 1.[123] replacement character instead - break; - } - // Following characters are not allowed in XML (but some files from KWord 0.8 have some of them.) - case 0: - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - case 11: - case 12: - case 14: - case 15: - case 16: - case 17: - case 18: - case 19: - case 20: - case 21: - case 22: - case 23: - case 24: - case 25: - case 26: - case 27: - case 28: - case 29: - case 30: - case 31: - { - kdWarning(30518) << "Not allowed XML character: " << ch.unicode() << endl; - strReturn += '?'; - break; - } - case 13: // ### TODO: what to do with it? - default: - { - strReturn+=ch; - break; - } - } - } - - if ( spaceNumber > 0 ) - { - // The last characters were spaces - strReturn += ' '; - --spaceNumber; - if ( spaceNumber > 0 ) - { - strReturn += "<text:s text:c=\""; - strReturn += TQString::number( spaceNumber ); - strReturn += "\"/>"; - } - spaceNumber = 0; - } - - return strReturn; -} - -bool OOWriterWorker::doOpenFile(const TQString& filenameOut, const TQString& ) -{ - kdDebug(30518) << "Opening file: " << filenameOut - << " (in OOWriterWorker::doOpenFile)" << endl; - - m_zip=new KZip(filenameOut); // How to check failure? - - if (!m_zip->open(IO_WriteOnly)) - { - kdError(30518) << "Could not open ZIP file for writing! Aborting!" << endl; - delete m_zip; - m_zip=NULL; - return false; - } - - m_zip->setCompression( KZip::NoCompression ); - m_zip->setExtraField( KZip::NoExtraField ); - - const TQCString appId( "application/vnd.sun.xml.writer" ); - - m_zip->writeFile( "mimetype", TQString(), TQString(), appId.length(), appId.data() ); - - m_zip->setCompression( KZip::DeflateCompression ); - - m_streamOut=new TQTextStream(m_contentBody, IO_WriteOnly); - - m_streamOut->setEncoding( TQTextStream::UnicodeUTF8 ); - - return true; -} - -bool OOWriterWorker::zipPrepareWriting(const TQString& name) -{ - if (!m_zip) - return false; - m_size=0; - return m_zip->prepareWriting(name, TQString(), TQString(), 0); -} - -bool OOWriterWorker::zipDoneWriting(void) -{ - if (!m_zip) - return false; - return m_zip->doneWriting(m_size); -} - -bool OOWriterWorker::zipWriteData(const char* str) -{ - if (!m_zip) - return false; - const uint size=strlen(str); - m_size+=size; - return m_zip->writeData(str,size); -} - -bool OOWriterWorker::zipWriteData(const TQByteArray& array) -{ - if (!m_zip) - return false; - const uint size=array.size(); - m_size+=size; - return m_zip->writeData(array.data(),size); -} - -bool OOWriterWorker::zipWriteData(const TQCString& cstr) -{ - if (!m_zip) - return false; - const uint size=cstr.length(); - m_size+=size; - return m_zip->writeData(cstr.data(),size); -} - -bool OOWriterWorker::zipWriteData(const TQString& str) -{ - return zipWriteData(str.utf8()); -} - -void OOWriterWorker::writeStartOfFile(const TQString& type) -{ - const bool noType=type.isEmpty(); - zipWriteData("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); - - zipWriteData("<!DOCTYPE office:document"); - if (!noType) - { - // No type might happen for raw XML documents (which this filter does not support yet.) - zipWriteData("-"); - zipWriteData(type); - } - zipWriteData(" PUBLIC \"-//OpenOffice.org//DTD OfficeDocument 1.0//EN\""); - zipWriteData(" \"office.dtd\""); - zipWriteData(">\n"); - - zipWriteData("<office:document"); - if (!noType) - { - zipWriteData("-"); - zipWriteData(type); - } - - // The name spaces used by OOWriter (those not used by this filter are commented out) - - // General namespaces - zipWriteData(" xmlns:office=\"http://openoffice.org/2000/office\""); - zipWriteData(" xmlns:xlink=\"http://www.w3.org/1999/xlink\""); - - // Namespaces for context.xml and style.xml - if ( type == "content" || type == "styles" || type.isEmpty() ) - { - zipWriteData(" xmlns:style=\"http://openoffice.org/2000/style\""); - zipWriteData(" xmlns:text=\"http://openoffice.org/2000/text\""); - zipWriteData(" xmlns:table=\"http://openoffice.org/2000/table\""); - zipWriteData(" xmlns:draw=\"http://openoffice.org/2000/drawing\""); - zipWriteData(" xmlns:fo=\"http://www.w3.org/1999/XSL/Format\""); - - //zipWriteData(" xmlns:number=\"http://openoffice.org/2000/datastyle\""); - zipWriteData(" xmlns:svg=\"http://www.w3.org/2000/svg\""); - //zipWriteData(" xmlns:chart=\"http://openoffice.org/2000/chart\""); - //zipWriteData(" xmlns:dr3d=\"http://openoffice.org/2000/dr3d\""); - //zipWriteData(" xmlns:math=\"http://www.w3.org/1998/Math/MathML""); - //zipWriteData(" xmlns:form=\"http://openoffice.org/2000/form\""); - //zipWriteData(" xmlns:script=\"http://openoffice.org/2000/script\""); - } - - // Namespaces For meta.xml - if ( type == "meta" || type.isEmpty() ) - { - zipWriteData(" xmlns:dc=\"http://purl.org/dc/elements/1.1/\""); - zipWriteData(" xmlns:meta=\"http://openoffice.org/2000/meta\""); - } - - zipWriteData(" office:class=\"text\""); - - -#ifdef STRICT_OOWRITER_VERSION_1 - zipWriteData(" office:version=\"1.0\""); -#else - // We are using an (rejected draft OASIS) extension compared to version 1.0, so we cannot write the version string. - // (We do not even write it for context.xml and meta.xml, as OOWriter 1.0.1 does not like it in this case.) -#endif - - zipWriteData(">\n"); -} - -void OOWriterWorker::writeFontDeclaration(void) -{ - zipWriteData( " <office:font-decls>\n"); - TQMap<TQString,TQString>::ConstIterator end(m_fontNames.end()); - for (TQMap<TQString,TQString>::ConstIterator it=m_fontNames.begin(); it!=end; ++it) - { - const bool space=(it.key().find(' ')>=0); // Does the font has at least a space in its name - const TQString fontName(escapeOOText(it.key())); - zipWriteData(" <style:font-decl style:name=\""); - zipWriteData(fontName); - zipWriteData("\" fo:font-family=\""); - if (space) - { // It has a space, so (simple) quote it - zipWriteData("'"); - zipWriteData(fontName); - zipWriteData("'"); - } - else - { // The font has no space in its name, so it can be written normally. - zipWriteData(fontName); - } - zipWriteData("\" "); - zipWriteData(it.data()); // already in XML, so do not escape - zipWriteData(" />\n"); - } - zipWriteData(" </office:font-decls>\n"); -} - -void OOWriterWorker::writeStylesXml(void) -{ - if (!m_zip) - return; - - zipPrepareWriting("styles.xml"); - - writeStartOfFile("styles"); - - writeFontDeclaration(); - - zipWriteData(m_styles); - - zipWriteData(" <office:automatic-styles>\n"); - zipWriteData(" <style:page-master style:name=\"pm1\">\n"); // ### TODO: verify if style name is unique - - zipWriteData(" <style:properties "); - zipWriteData( " style:page-usage=\"all\"" ); // ### TODO: check - - zipWriteData(" fo:page-width=\""); - zipWriteData(TQString::number(m_paperWidth)); - zipWriteData("pt\" fo:page-height=\""); - zipWriteData(TQString::number(m_paperHeight)); - zipWriteData("pt\" "); - - zipWriteData("style:print-orientation=\""); - if (1==m_paperOrientation) - { - zipWriteData("landscape"); - } - else - { - zipWriteData("portrait"); - } - - zipWriteData("\" fo:margin-top=\""); - zipWriteData(TQString::number(m_paperBorderTop)); - zipWriteData("pt\" fo:margin-bottom=\""); - zipWriteData(TQString::number(m_paperBorderBottom)); - zipWriteData("pt\" fo:margin-left=\""); - zipWriteData(TQString::number(m_paperBorderLeft)); - zipWriteData("pt\" fo:margin-right=\""); - zipWriteData(TQString::number(m_paperBorderRight)); - zipWriteData("pt\" style:first-page-number=\""); - zipWriteData(TQString::number(m_varSet.startingPageNumber)); - zipWriteData( "\">\n" ); - - if ( m_columns > 1 ) - { - zipWriteData( " <style:columns" ); - zipWriteData( " fo:column-count=\"" ); - zipWriteData( TQString::number( m_columns ) ); - zipWriteData( "\" fo:column-gap=\"" ); - zipWriteData( TQString::number( m_columnspacing ) ); - zipWriteData( "pt\">\n" ); - - for (int i=0; i < m_columns; ++i) - { - zipWriteData( " <style:column style:rel-width=\"1*\" fo:margin-left=\"0cm\" fo:margin-right=\"0cm\"/>\n" ); - } - - zipWriteData( " </style:columns>\n" ); - } - - zipWriteData(" </style:properties>\n"); - - zipWriteData(" </style:page-master>\n"); - zipWriteData(" </office:automatic-styles>\n"); - - zipWriteData(" <office:master-styles>\n"); - zipWriteData(" <style:master-page style:name=\"Standard\" style:page-master-name=\"pm1\" />\n"); - zipWriteData(" </office:master-styles>\n"); - - zipWriteData( "</office:document-styles>\n" ); - - zipDoneWriting(); -} - -void OOWriterWorker::writeContentXml(void) -{ - if (!m_zip) - return; - - zipPrepareWriting("content.xml"); - - writeStartOfFile("content"); - - writeFontDeclaration(); - - zipWriteData(" <office:automatic-styles>\n"); - zipWriteData(m_contentAutomaticStyles); - m_contentAutomaticStyles = TQString(); // Release memory - - zipWriteData(" </office:automatic-styles>\n"); - - zipWriteData(m_contentBody); - m_contentBody.resize( 0 ); // Release memory - - zipWriteData( "</office:document-content>\n" ); - - zipDoneWriting(); -} - -void OOWriterWorker::writeMetaXml(void) -{ - if (!m_zip) - return; - - zipPrepareWriting("meta.xml"); - - writeStartOfFile("meta"); - - zipWriteData(" <office:meta>\n"); - - // Tell who we are in case that we have a bug in our filter output! - zipWriteData(" <meta:generator>KWord's OOWriter Export Filter"); - zipWriteData(TQString("$Revision: 515673 $").mid(10).remove('$')); // has a leading and a trailing space. - - zipWriteData("</meta:generator>\n"); - - if (!m_docInfo.title.isEmpty()) - { - zipWriteData(" <dc:title>"); - zipWriteData(escapeOOText(m_docInfo.title)); - zipWriteData("</dc:title>\n"); - } - if (!m_docInfo.abstract.isEmpty()) - { - zipWriteData(" <dc:description>"); - zipWriteData(escapeOOText(m_docInfo.abstract)); - zipWriteData("</dc:description>\n"); - } - - if (m_varSet.creationTime.isValid()) - { - zipWriteData(" <meta:creation-date>"); - zipWriteData(escapeOOText(m_varSet.creationTime.toString(Qt::ISODate))); - zipWriteData("</meta:creation-date>\n"); - } - - if (m_varSet.modificationTime.isValid()) - { - zipWriteData(" <dc:date>"); - zipWriteData(escapeOOText(m_varSet.modificationTime.toString(Qt::ISODate))); - zipWriteData("</dc:date>\n"); - } - - if (m_varSet.printTime.isValid()) - { - zipWriteData(" <meta:print-date>"); - zipWriteData(escapeOOText(m_varSet.printTime.toString(Qt::ISODate))); - zipWriteData("</meta:print-date>\n"); - } - - zipWriteData( " <meta:document-statistic" ); - - // KWord files coming from import filters mostly do not have no page count - if ( m_numPages > 0 ) - { - zipWriteData( " meta:page-count=\"" ); - zipWriteData( TQString::number ( m_numPages ) ); - zipWriteData( "\"" ); - } - - zipWriteData( " meta:image-count=\"" ); // This is not specified in the OO specification section 2.1.19 - zipWriteData( TQString::number ( m_pictureNumber ) ); - zipWriteData( "\"" ); - - zipWriteData( " meta:table-count=\"" ); - zipWriteData( TQString::number ( m_tableNumber ) ); - zipWriteData( "\"" ); - - zipWriteData( "/>\n" ); // meta:document-statistic - - zipWriteData(" </office:meta>\n"); - zipWriteData("</office:document-meta>\n"); - - zipDoneWriting(); -} - -bool OOWriterWorker::doCloseFile(void) -{ - kdDebug(30518)<< "OOWriterWorker::doCloseFile" << endl; - if (m_zip) - { - writeContentXml(); - writeMetaXml(); - writeStylesXml(); - m_zip->close(); - } - - delete m_zip; - m_zip=NULL; - return true; -} - -bool OOWriterWorker::doOpenDocument(void) -{ - kdDebug(30518)<< "OOWriterWorker::doOpenDocument" << endl; - - *m_streamOut << " <office:body>\n"; - - return true; -} - -bool OOWriterWorker::doCloseDocument(void) -{ - *m_streamOut << " </office:body>\n"; - return true; -} - -bool OOWriterWorker::doOpenBody(void) -{ - TQValueList<FrameAnchor>::Iterator it; - - // We have to process all non-inline pictures - kdDebug(30518) << "=== Processing non-inlined pictures ===" << endl; - for ( it = m_nonInlinedPictureAnchors.begin(); it != m_nonInlinedPictureAnchors.end(); ++it ) - { - *m_streamOut << " "; - makePicture( *it, AnchorNonInlined ); - *m_streamOut << "\n"; - } - kdDebug(30518) << "=== Non-inlined pictures processed ===" << endl; - - // We have to process all non-inline tables - kdDebug(30518) << "=== Processing non-inlined tables ===" << endl; - for ( it = m_nonInlinedTableAnchors.begin(); it != m_nonInlinedTableAnchors.end(); ++it ) - { - *m_streamOut << " "; - makeTable( *it, AnchorNonInlined ); - *m_streamOut << "\n"; - } - kdDebug(30518) << "=== Non-inlined tables processed ===" << endl; - - return true; -} - -TQString OOWriterWorker::textFormatToStyle(const TextFormatting& formatOrigin, - const TextFormatting& formatData, const bool force, TQString& key) -{ - // TODO: rename variable formatData - TQString strElement; // TODO: rename this variable - - // Font name - TQString fontName = formatData.fontName; - declareFont(fontName); - if ( !fontName.isEmpty() - && (force || (formatOrigin.fontName!=formatData.fontName))) - { - strElement+="style:font-name=\""; - strElement+= escapeOOText(fontName); - strElement+="\" "; - key += fontName; - } - - key += ","; - - if (force || (formatOrigin.italic!=formatData.italic)) - { - // Font style - strElement+="fo:font-style=\""; - if ( formatData.italic ) - { - strElement+="italic"; - key+='I'; - } - else - { - strElement+="normal"; - key+='N'; - } - strElement+="\" "; - } - - key += ","; - - if (force || ((formatOrigin.weight>=75)!=(formatData.weight>=75))) - { - strElement+="fo:font-weight=\""; - if ( formatData.weight >= 75 ) - { - strElement+="bold"; - key+='B'; - } - else - { - strElement+="normal"; - key+='N'; - } - strElement+="\" "; - } - - key += ","; - - if (force || (formatOrigin.fontSize!=formatData.fontSize)) - { - const int size=formatData.fontSize; - if (size>0) - { - strElement+="fo:font-size=\""; - strElement+=TQString::number(size,10); - strElement+="pt\" "; - key+=TQString::number(size,10); - } - } - - key += ","; - - if (force || (formatOrigin.fgColor!=formatData.fgColor)) - { - if ( formatData.fgColor.isValid() ) - { - strElement+="fo:color=\""; - strElement+=formatData.fgColor.name(); - strElement+="\" "; - key+=formatData.fgColor.name(); - } - } - - key += ","; - - if (force || (formatOrigin.bgColor!=formatData.bgColor)) - { - if ( formatData.bgColor.isValid() ) - { - strElement+="style:text-background-color=\""; // ### what is fo:background-color ? - strElement+=formatData.bgColor.name(); - strElement+="\" "; - key+=formatData.bgColor.name(); - } - } - - key += ';'; // Another separator - - if ( force || ( formatOrigin.underline != formatData.underline ) - || ( formatOrigin.underlineColor != formatData.underlineColor ) - || ( formatOrigin.underlineValue != formatData.underlineValue ) - || ( formatOrigin.underlineStyle != formatData.underlineStyle ) ) - { - strElement+="style:text-underline=\""; - if ( formatData.underline ) - { - TQString underlineValue ( formatData.underlineValue ); - TQString underlineStyle ( formatData.underlineStyle ); - - if ( underlineStyle.isEmpty() ) - underlineStyle = "solid"; - if ( underlineValue == "1" ) - underlineValue = "single"; - - if ( underlineValue == "single" ) - { - if ( underlineStyle == "dash" ) - { - strElement += "dash"; - key += "DA"; - } - else if ( underlineStyle == "dot" ) - { - strElement += "dotted"; - key += "DO"; - } - else if ( underlineStyle == "dashdot" ) - { - strElement += "dot-dash"; - key += "DDA"; - } - else if ( underlineStyle == "dashdotdot" ) - { - strElement += "dot-dot-dash"; - key += "DDDA"; - } - else - { - strElement += "single"; - key += "1"; - } - } - else if ( underlineValue == "double" ) - { - strElement += "double"; - key += "2"; - } - else if ( underlineValue == "single-bold" ) - { - strElement += "bold"; - key += "BL"; - } - else if ( underlineValue == "wave" ) - { - strElement += "wave"; - key += "WV"; - } - else - { - strElement += "single"; - key += "?"; - } - } - else - { - strElement+="none"; - key += 'N'; - } - strElement += "\" "; - - if ( formatData.underline && formatData.underlineColor.isValid() ) - { - const TQString colorName( formatData.underlineColor.name() ); - strElement += "style:text-underline-color=\""; - strElement += colorName; - strElement += "\" "; - key += colorName; - } - - } - - key += ','; - - if ( force - || (formatOrigin.strikeout != formatData.strikeout ) - || (formatOrigin.strikeoutType != formatData.strikeoutType ) ) - { - // OOWriter can only do single, double, thick (and slash and X that KWord cannot do.) - // So no dash, dot and friends. - - strElement+="style:text-crossing-out=\""; - if ( ( formatData.strikeoutType == "single" ) || ( formatData.strikeoutType == "1" ) ) - { - strElement+="single-line"; - key += "1"; - } - else if ( formatData.strikeoutType == "double" ) - { - strElement+="double-line"; - key += "2"; - } - else if ( formatData.strikeoutType == "single-bold" ) - { - strElement+="thick"; - key += "T"; - } - else - { - strElement+="none"; - key += 'N'; - } - strElement+="\" "; - } - - key += ','; - - // It seems that OOWriter 1.1 does have problems with word-by-word (OO Issue #11873, #25187) - // It is supposed to be fixed in development versions of OO - if (force || ( formatOrigin.underlineWord != formatData.underlineWord ) - || (formatOrigin.strikeoutWord != formatData.strikeoutWord ) ) - { - // Strikeout and underline can only have one word-by-word behaviour in OO - // (OO Issue #????? ; will not be changed.) - strElement+="fo:score-spaces=\""; // Are space processed? - if ( formatData.underlineWord || formatData.strikeoutWord ) - { - strElement += "false"; - key += 'W'; - } - else - { - strElement += "true"; - key += 'N'; - } - strElement += "\" "; - } - - key += ','; - - if ( force || ( formatOrigin.language != formatData.language ) ) - { - const TQString lang ( formatData.language ); - if ( ! lang.isEmpty() ) - { - const int res = lang.find( '_' ); - - if ( res >= 0 ) - { - kdDebug(30518) << "Language: " << lang << " => " << lang.left( res ) << " - " << lang.mid( res + 1 ) << endl; - strElement += "fo:language=\""; - strElement += lang.left( res ); - strElement += "\" "; - strElement += "fo:country=\""; - strElement += lang.mid( res + 1 ); - strElement += "\" "; - } - else - { - kdDebug(30518) << "Language without country: " << lang << endl; - strElement += "fo:language=\""; - strElement += lang; - strElement += "\" "; - } - - key+=formatData.language; - } - } - - key += ","; - - if ( force || ( formatOrigin.fontAttribute != formatData.fontAttribute ) ) - { - // Note: OOWriter does not like when both fo:text-transform and fo:font-variant exist (except if both are none/normal) - // (It is documented so, see sections 3.10.1 and 3.10.2) - if ( formatData.fontAttribute == "uppercase" ) - { - strElement += "fo:text-transform=\"uppercase\" "; - key += 'U'; - } - else if ( formatData.fontAttribute == "lowercase" ) - { - strElement += "fo:text-transform=\"lowercase\" "; - key += 'L'; - } - else if ( formatData.fontAttribute == "smallcaps" ) - { - strElement += "fo:font-variant=\"small-caps\" "; - key += 'S'; - } - else - { - strElement += "fo:text-transform=\"none\" "; - strElement += "fo:font-variant=\"normal\" "; - key += 'N'; - } - } - - key += ","; - - if ( force || ( formatOrigin.verticalAlignment != formatData.verticalAlignment ) ) - { - if ( 1 == formatData.verticalAlignment ) - { - //Subscript - strElement += "style:text-position=\"sub\" "; - key += 'B'; - } - else if ( 2 == formatData.verticalAlignment ) - { - //Superscript - strElement += "style:text-position=\"super\" "; - key += 'P'; - } - // ### TODO: how to reset it? "0pt" ? - } - - return strElement.stripWhiteSpace(); // Remove especially trailing spaces -} - -#define ALLOW_TABLE - -TQString OOWriterWorker::cellToProperties( const TableCell& cell, TQString& key) const -{ -#ifdef ALLOW_TABLE - const FrameData& frame = cell.frame; - TQString properties; - - key += "!L"; // left border - key += frame.lColor.name(); - key += ","; - key += TQString::number( frame.lWidth ); - properties += " fo:border-left=\""; - if ( frame.lColor.isValid() && frame.lWidth > 0.0 ) - { - properties += TQString::number( frame.lWidth ); - properties += "pt"; - properties += " solid "; // ### TODO - properties += frame.lColor.name(); - } - else - { - properties += "0pt none #000000"; - } - properties += "\""; - - key += "!R"; // right border - key += frame.rColor.name(); - key += ","; - key += TQString::number( frame.rWidth ); - properties += " fo:border-right=\""; - if ( frame.rColor.isValid() && frame.rWidth > 0.0 ) - { - properties += TQString::number( frame.rWidth ); - properties += "pt"; - properties += " solid "; // ### TODO - properties += frame.rColor.name(); - } - else - { - properties += "0pt none #000000"; - } - properties += "\""; - - key += "!T"; // top border - key += frame.tColor.name(); - key += ","; - key += TQString::number( frame.tWidth ); - properties += " fo:border-top=\""; - if ( frame.tColor.isValid() && frame.tWidth > 0.0 ) - { - properties += TQString::number( frame.tWidth ); - properties += "pt"; - properties += " solid "; // ### TODO - properties += frame.tColor.name(); - } - else - { - properties += "0pt none #000000"; - } - properties += "\""; - - key += "!B"; // bottom border - key += frame.bColor.name(); - key += ","; - key += TQString::number( frame.bWidth ); - properties += " fo:border-bottom=\""; - if ( frame.bColor.isValid() && frame.bWidth > 0.0 ) - { - properties += TQString::number( frame.bWidth ); - properties += "pt"; - properties += " solid "; // ### TODO - properties += frame.bColor.name(); - } - else - { - properties += "0pt none #000000"; - } - properties += "\""; - - return properties; -#else - return TQString(); -#endif -} - -bool OOWriterWorker::makeTableRows( const TQString& tableName, const Table& table, int firstRowNumber ) -{ -#ifdef ALLOW_TABLE - // ### TODO: rows - // ### TODO: be careful that covered-cell can be due vertical spanning. - // ### TODO: One way to find is the difference between the row variables (or against the last known column) - // ### TODO: be careful that fully-covered rows might exist. - - *m_streamOut << "<table:table-row>\n"; - int rowCurrent = firstRowNumber; - - ulong cellNumber = 0L; - - TQMap<TQString,TQString> mapCellStyleKeys; - - for ( TQValueList<TableCell>::ConstIterator itCell ( table.cellList.begin() ); - itCell != table.cellList.end(); ++itCell) - { - if ( rowCurrent != (*itCell).row ) - { - rowCurrent = (*itCell).row; - *m_streamOut << "</table:table-row>\n"; - *m_streamOut << "<table:table-row>\n"; - } - - TQString key; - const TQString props ( cellToProperties( (*itCell), key ) ); - - TQString automaticCellStyle; - TQMap<TQString,TQString>::ConstIterator it ( mapCellStyleKeys.find( key ) ); - if ( it == mapCellStyleKeys.end() ) - { - automaticCellStyle = makeAutomaticStyleName( tableName + ".Cell", cellNumber ); - mapCellStyleKeys [ key ] = automaticCellStyle; - kdDebug(30518) << "Creating automatic cell style: " << automaticCellStyle << " key: " << key << endl; - m_contentAutomaticStyles += " <style:style"; - m_contentAutomaticStyles += " style:name=\"" + escapeOOText( automaticCellStyle ) + "\""; - m_contentAutomaticStyles += " style:family=\"table-cell\""; - m_contentAutomaticStyles += ">\n"; - m_contentAutomaticStyles += " <style:properties "; - m_contentAutomaticStyles += props; - m_contentAutomaticStyles += "/>\n"; - m_contentAutomaticStyles += " </style:style>\n"; - } - else - { - automaticCellStyle = it.data(); - kdDebug(30518) << "Using automatic cell style: " << automaticCellStyle << " key: " << key << endl; - } - - *m_streamOut << "<table:table-cell table:value-type=\"string\" table:style-name=\"" - << escapeOOText( automaticCellStyle) - << "\""; - - // More than one column width? - { - *m_streamOut << " table:number-columns-spanned=\"" << (*itCell).m_cols << "\""; - } - - *m_streamOut << ">\n"; - - if (!doFullAllParagraphs(*(*itCell).paraList)) - { - return false; - } - - *m_streamOut << "</table:table-cell>\n"; - - if ( (*itCell).m_cols > 1 ) - { - // We need to add some placeholder for the "covered" cells - for (int i = 1; i < (*itCell).m_cols; ++i) - { - *m_streamOut << "<table:covered-table-cell/>"; - } - } - } - - *m_streamOut << "</table:table-row>\n"; - return true; -#else - return false; -#endif -} - -#ifdef ALLOW_TABLE -static uint getColumnWidths( const Table& table, TQMemArray<double>& widthArray, int firstRowNumber ) -{ - bool uniqueColumns = true; // We have not found any horizontally spanned cells yet. - uint currentColumn = 0; - int tryingRow = firstRowNumber; // We are trying the first row - TQValueList<TableCell>::ConstIterator itCell; - - for ( itCell = table.cellList.begin(); - itCell != table.cellList.end(); ++itCell ) - { - kdDebug(30518) << "Column: " << (*itCell).col << " (Row: " << (*itCell).row << ")" << endl; - - if ( (*itCell).row != tryingRow ) - { - if ( uniqueColumns ) - { - // We had a full row without any horizontally spanned cell, so we have the needed data - return currentColumn; - } - else - { - // No luck in the previous row, so now try this new one - tryingRow = (*itCell).row; - uniqueColumns = true; - currentColumn = 0; - } - } - - if ( (*itCell).m_cols > 1 ) - { - // We have a horizontally spanned cell - uniqueColumns = false; - // Do not waste the time to calculate the width - continue; - } - - const double width = ( (*itCell).frame.right - (*itCell).frame.left ); - - if ( currentColumn >= widthArray.size() ) - widthArray.resize( currentColumn + 4, TQGArray::SpeedOptim); - - widthArray.at( currentColumn ) = width; - ++currentColumn; - } - - // If we are here, it can be: - // - the table is either empty or there is not any row without horizontally spanned cells - // - we have needed the last row for getting something usable - - return uniqueColumns ? currentColumn : 0; -} -#endif - -#ifdef ALLOW_TABLE -static uint getFirstRowColumnWidths( const Table& table, TQMemArray<double>& widthArray, int firstRowNumber ) -// Get the column widths only by the first row. -// This is used when all table rows have horizontally spanned cells. -{ - uint currentColumn = 0; - TQValueList<TableCell>::ConstIterator itCell; - - for ( itCell = table.cellList.begin(); - itCell != table.cellList.end(); ++itCell ) - { - kdDebug(30518) << "Column: " << (*itCell).col << " (Row: " << (*itCell).row << ")" << endl; - if ( (*itCell).row != firstRowNumber ) - break; // We have finished the first row - - int cols = (*itCell).m_cols; - if ( cols < 1) - cols = 1; - - // ### FIXME: the columns behind a larger cell do not need to be symmetrical - const double width = ( (*itCell).frame.right - (*itCell).frame.left ) / cols; - - if ( currentColumn + cols > widthArray.size() ) - widthArray.resize( currentColumn + 4, TQGArray::SpeedOptim); - - for ( int i = 0; i < cols; ++i ) - { - widthArray.at( currentColumn ) = width; - ++currentColumn; - } - } - return currentColumn; -} -#endif - -bool OOWriterWorker::makeTable( const FrameAnchor& anchor, const AnchorType anchorType ) -{ -#ifdef ALLOW_TABLE - - // Be careful that while being similar the following 5 strings have different purposes - const TQString automaticTableStyle ( makeAutomaticStyleName( "Table", m_tableNumber ) ); // It also increases m_tableNumber - const TQString tableName( TQString( "Table" ) + TQString::number( m_tableNumber ) ); // m_tableNumber was already increased - const TQString translatedName( i18n( "Object name", "Table %1").arg( m_tableNumber ) ); - const TQString automaticFrameStyle ( makeAutomaticStyleName( "TableFrame", m_textBoxNumber ) ); // It also increases m_textBoxNumber - const TQString translatedFrameName( i18n( "Object name", "Table Frame %1").arg( m_textBoxNumber ) ); - - kdDebug(30518) << "Processing table " << anchor.key.toString() << " => " << tableName << endl; - - const TQValueList<TableCell>::ConstIterator firstCell ( anchor.table.cellList.begin() ); - - if ( firstCell == anchor.table.cellList.end() ) - { - kdError(30518) << "Table has not any cell!" << endl; - return false; - } - - const int firstRowNumber = (*firstCell).row; - kdDebug(30518) << "First row: " << firstRowNumber << endl; - - TQMemArray<double> widthArray(4); - - uint numberColumns = getColumnWidths( anchor.table, widthArray, firstRowNumber ); - - if ( numberColumns <= 0 ) - { - kdDebug(30518) << "Could not get correct column widths, so approximating" << endl; - // There was a problem, the width array cannot be trusted, so try to do a column width array with the first row - numberColumns = getFirstRowColumnWidths( anchor.table, widthArray, firstRowNumber ); - if ( numberColumns <= 0 ) - { - // Still not right? Then it is an error! - kdError(30518) << "Cannot get column widths of table " << anchor.key.toString() << endl; - return false; - } - } - - kdDebug(30518) << "Number of columns: " << numberColumns << endl; - - - double tableWidth = 0.0; // total width of table - uint i; // We need the loop variable 2 times - for ( i=0; i < numberColumns; ++i ) - { - tableWidth += widthArray.at( i ); - } - kdDebug(30518) << "Table width: " << tableWidth << endl; - - // An inlined table, is an "as-char" text-box - *m_streamOut << "<draw:text-box"; - *m_streamOut << " style:name=\"" << escapeOOText( automaticFrameStyle ) << "\""; - *m_streamOut << " draw:name=\"" << escapeOOText( translatedFrameName ) << "\""; - if ( anchorType == AnchorNonInlined ) - { - // ### TODO: correctly set a OOWriter frame positioned on the page - *m_streamOut << " text:anchor-type=\"paragraph\""; - } - else - { - *m_streamOut << " text:anchor-type=\"as-char\""; - } - *m_streamOut << " svg:width=\"" << tableWidth << "pt\""; // ### TODO: any supplement to the width? - //*m_streamOut << " fo:min-height=\"1pt\"";// ### TODO: a better height (can be calulated from the KWord table frames) - *m_streamOut << ">\n"; - - *m_streamOut << "<table:table table:name=\"" - << escapeOOText( translatedName ) - << "\" table:style-name=\"" - << escapeOOText( automaticTableStyle ) - << "\" >\n"; - - - // Now we have enough information to generate the style for the table and its frame - - kdDebug(30518) << "Creating automatic frame style: " << automaticFrameStyle /* << " key: " << styleKey */ << endl; - m_contentAutomaticStyles += " <style:style"; // for frame - m_contentAutomaticStyles += " style:name=\"" + escapeOOText( automaticFrameStyle ) + "\""; - m_contentAutomaticStyles += " style:family=\"graphics\""; - m_contentAutomaticStyles += " style:parent-style-name=\"Frame\""; // ### TODO: parent style needs to be correctly defined - m_contentAutomaticStyles += ">\n"; - m_contentAutomaticStyles += " <style:properties "; // ### TODO - m_contentAutomaticStyles += " text:anchor-type=\"as-char\""; // ### TODO: needed? - m_contentAutomaticStyles += " fo:padding=\"0pt\" fo:border=\"none\""; - m_contentAutomaticStyles += " fo:margin-left=\"0pt\""; - m_contentAutomaticStyles += " fo:margin-top=\"0pt\""; - m_contentAutomaticStyles += " fo:margin-bottom=\"0pt\""; - m_contentAutomaticStyles += " fo:margin-right=\"0pt\""; - m_contentAutomaticStyles += "/>\n"; - m_contentAutomaticStyles += " </style:style>\n"; - - kdDebug(30518) << "Creating automatic table style: " << automaticTableStyle /* << " key: " << styleKey */ << endl; - m_contentAutomaticStyles += " <style:style"; // for table - m_contentAutomaticStyles += " style:name=\"" + escapeOOText( automaticTableStyle ) + "\""; - m_contentAutomaticStyles += " style:family=\"table\""; - m_contentAutomaticStyles += ">\n"; - m_contentAutomaticStyles += " <style:properties "; - m_contentAutomaticStyles += " style:width=\"" + TQString::number( tableWidth ) + "pt\" "; - m_contentAutomaticStyles += "/>\n"; - m_contentAutomaticStyles += " </style:style>\n"; - - TQValueList<TableCell>::ConstIterator itCell; - - ulong columnNumber = 0L; - - for ( i=0; i < numberColumns; ++i ) - { - const TQString automaticColumnStyle ( makeAutomaticStyleName( tableName + ".Column", columnNumber ) ); - kdDebug(30518) << "Creating automatic column style: " << automaticColumnStyle /* << " key: " << styleKey */ << endl; - - m_contentAutomaticStyles += " <style:style"; - m_contentAutomaticStyles += " style:name=\"" + escapeOOText( automaticColumnStyle ) + "\""; - m_contentAutomaticStyles += " style:family=\"table-column\""; - m_contentAutomaticStyles += ">\n"; - m_contentAutomaticStyles += " <style:properties "; - // Despite that some OO specification examples use fo:width, OO specification section 4.19 tells to use style:column-width - // and/or the relative variant: style:rel-column-width - m_contentAutomaticStyles += " style:column-width=\"" + TQString::number( widthArray.at( i ) ) + "pt\" "; - m_contentAutomaticStyles += "/>\n"; - m_contentAutomaticStyles += " </style:style>\n"; - - // ### TODO: find a way how to use table:number-columns-repeated for more that one cell's column(s) - *m_streamOut << "<table:table-column table:style-name=\"" - << escapeOOText( automaticColumnStyle ) - << "\" table:number-columns-repeated=\"1\"/>\n"; - } - - makeTableRows( tableName, anchor.table, firstRowNumber ); - - *m_streamOut << "</table:table>\n"; - - *m_streamOut << "</draw:text-box>"; // End of inline - -#endif - return true; -} - -bool OOWriterWorker::makePicture( const FrameAnchor& anchor, const AnchorType anchorType ) -{ - kdDebug(30518) << "New picture: " << anchor.picture.koStoreName - << " , " << anchor.picture.key.toString() << endl; - - const TQString koStoreName(anchor.picture.koStoreName); - - TQByteArray image; - - TQString strExtension(koStoreName.lower()); - const int result=koStoreName.findRev("."); - if (result>=0) - { - strExtension=koStoreName.mid(result+1); - } - - bool isImageLoaded=false; - - if (strExtension=="png") - { - isImageLoaded=loadSubFile(koStoreName,image); - } - else if ((strExtension=="jpg") || (strExtension=="jpeg")) - { - isImageLoaded=loadSubFile(koStoreName,image); - strExtension="jpg"; // ### TODO: verify - } - else if ((strExtension=="tif") || (strExtension=="tiff")) - { - isImageLoaded=loadSubFile(koStoreName,image); - strExtension="tif"; // ### TODO: verify - } - else if ((strExtension=="gif") || (strExtension=="wmf")) - // ### TODO: Which other image formats does OOWriter support directly? - { - isImageLoaded=loadSubFile(koStoreName,image); - } - else - { - // All other picture types must be converted to PNG - isImageLoaded=loadAndConvertToImage(koStoreName,strExtension,"PNG",image); - strExtension="png"; - } - - if (!isImageLoaded) - { - kdWarning(30518) << "Unable to load picture: " << koStoreName << endl; - return true; - } - - kdDebug(30518) << "Picture loaded: " << koStoreName << endl; - - double height = 0.0; - double width = 0.0; - - if ( anchorType == AnchorTextImage ) - { - // Text image have no frameset, so the only size information is in the picture itself. - TQBuffer buffer( image.copy() ); // Be more safe than sorry and do not allow shallow copy - KoPicture pic; - buffer.open( IO_ReadOnly ); - if ( pic.load( TQT_TQIODEVICE(&buffer), strExtension ) ) - { - const TQSize size ( pic.getOriginalSize() ); - height = size.height(); - width = size.width(); - } - else - { - kdWarning(30518) << "Could not load KoPicture: " << koStoreName << endl; - } - buffer.close(); - } - else - { - // Use frame size - height=anchor.frame.bottom - anchor.frame.top; - width =anchor.frame.right - anchor.frame.left; - } - - if ( height < 1.0 ) - { - kdWarning(30518) << "Silly height for " << koStoreName << " : " << height << endl; - height = 72.0; - } - if ( width < 1.0 ) - { - kdWarning(30518) << "Silly width for " << koStoreName << " : " << width << endl; - width = 72.0; - } - - // We need a 32 digit hex value of the picture number - // Please note: it is an exact 32 digit value, truncated if the value is more than 512 bits wide. :-) - TQString number; - number.fill('0',32); - number += TQString::number(++m_pictureNumber,16); // in hex - - TQString ooName("Pictures/"); - ooName += number.right(32); - ooName += '.'; - ooName += strExtension; - - kdDebug(30518) << "Picture " << koStoreName << " => " << ooName << endl; - - // TODO: we are only using the filename, not the rest of the key - // TODO: (bad if there are two images of the same name, but of a different key) - *m_streamOut << "<draw:image draw:name=\"" << anchor.picture.key.filename() << "\""; - *m_streamOut << " draw:style-name=\"Graphics\""; // ### TODO: should be an automatic "graphic" style name instead - if ( anchorType == AnchorNonInlined ) - { - // ### TODO: correctly set a OOWriter frame positioned on the page - *m_streamOut << " text:anchor-type=\"paragraph\""; - } - else - { - *m_streamOut << " text:anchor-type=\"as-char\""; - } - *m_streamOut << " svg:height=\"" << height << "pt\" svg:width=\"" << width << "pt\""; - *m_streamOut << " draw:z-index=\"0\" xlink:href=\"#" << ooName << "\""; - *m_streamOut << " xlink:type=\"simple\" xlink:show=\"embed\" xlink:actuate=\"onLoad\""; - *m_streamOut << "/>"; // NO end of line! - - if (m_zip) - { -#if 0 - // ### FIXME Why is the following line not working (at least with KDE 3.1)? (It makes unzip having problems with meta.xml) - m_zip->writeFile(ooName,TQString(), TQString(), image.size(), image.data()); -#else - zipPrepareWriting(ooName); - zipWriteData( image ); - zipDoneWriting(); -#endif - } - - return true; -} - -void OOWriterWorker::processNormalText ( const TQString ¶Text, - const TextFormatting& formatLayout, - const FormatData& formatData) -{ - // Retrieve text and escape it (and necessary space, tabs and line-break tags) - const TQString partialText( escapeOOSpan( paraText.mid( formatData.pos, formatData.len ) ) ); - - if (formatData.text.missing) - { - // It's just normal text, so we do not need a <text:span> element! - *m_streamOut << partialText; - } - else - { // Text with properties, so use a <text:span> element! - *m_streamOut << "<text:span"; - - TQString styleKey; - const TQString props ( textFormatToStyle(formatLayout,formatData.text,false,styleKey) ); - - TQMap<TQString,TQString>::ConstIterator it ( m_mapTextStyleKeys.find(styleKey) ); - kdDebug(30518) << "Searching text key: " << styleKey << endl; - - TQString automaticStyle; - if (it==m_mapTextStyleKeys.end()) - { - // We have not any match, so we need a new automatic text style - automaticStyle=makeAutomaticStyleName("T", m_automaticTextStyleNumber); - kdDebug(30518) << "Creating automatic text style: " << automaticStyle << " key: " << styleKey << endl; - m_mapTextStyleKeys[styleKey]=automaticStyle; - - m_contentAutomaticStyles += " <style:style"; - m_contentAutomaticStyles += " style:name=\"" + escapeOOText(automaticStyle) + "\""; - m_contentAutomaticStyles += " style:family=\"text\""; - m_contentAutomaticStyles += ">\n"; - m_contentAutomaticStyles += " <style:properties "; - m_contentAutomaticStyles += props; - m_contentAutomaticStyles += "/>\n"; - m_contentAutomaticStyles += " </style:style>\n"; - } - else - { - // We have a match, so use the already defined automatic text style - automaticStyle=it.data(); - kdDebug(30518) << "Using automatic text style: " << automaticStyle << " key: " << styleKey << endl; - } - - *m_streamOut << " text:style-name=\"" << escapeOOText(automaticStyle) << "\" "; - - *m_streamOut << ">" << partialText << "</text:span>"; - } -} - -void OOWriterWorker::processFootnote( const VariableData& variable ) -{ - // Footnote - const TQValueList<ParaData> *paraList = variable.getFootnotePara(); - if( paraList ) - { - const TQString value ( variable.getFootnoteValue() ); - //const bool automatic = formatData.variable.getFootnoteAuto(); - const bool flag = variable.getFootnoteType(); - - if ( flag ) - { - *m_streamOut << "<text:footnote text:id=\"ft"; - *m_streamOut << (++m_footnoteNumber); - *m_streamOut << "\">"; - *m_streamOut << "<text:footnote-citation>" << escapeOOText( value ) << "</text:footnote-citation>"; - *m_streamOut << "<text:footnote-body>\n"; - - doFullAllParagraphs( *paraList ); - - *m_streamOut << "\n</text:footnote-body>"; - *m_streamOut << "</text:footnote>"; - } - else - { - *m_streamOut << "<text:endnote text:id=\"ft"; - *m_streamOut << (++m_footnoteNumber); - *m_streamOut << "\">"; - *m_streamOut << "<text:endnote-citation>" << escapeOOText( value ) << "</text:endnote-citation>"; - *m_streamOut << "<text:endnote-body>\n"; - - doFullAllParagraphs( *paraList ); - - *m_streamOut << "\n</text:endnote-body>"; - *m_streamOut << "</text:endnote>"; - } - } -} - -void OOWriterWorker::processNote( const VariableData& variable ) -{ - // KWord 1.3's annotations are anonymous and undated, - // however the OO specification tells that author and date are mandatory (even if OOWriter 1.1 consider them optional) - - *m_streamOut << "<office:annotation office:create-date=\""; - - // We use the document creation date as creation date for the annotation - // (OOWriter uses only the date part, there is no time part) - if ( m_varSet.creationTime.isValid() ) - *m_streamOut << escapeOOText( m_varSet.creationTime.date().toString( Qt::ISODate ) ); - else - *m_streamOut << "1970-01-01"; - - *m_streamOut << "\" office:author=\""; - - // We try to use the document author's name as annotation author - if ( m_docInfo.fullName.isEmpty() ) - *m_streamOut << escapeOOText( i18n( "Pseudo-author for annotations", "KWord 1.3" ) ); - else - *m_streamOut << escapeOOText( m_docInfo.fullName ); - - *m_streamOut << "\">\n"; - *m_streamOut << "<text:p>" - << escapeOOSpan( variable.getGenericData( "note" ) ) - << "</text:p>\n" - << "</office:annotation>"; -} - -void OOWriterWorker::processVariable ( const TQString&, - const TextFormatting& /*formatLayout*/, - const FormatData& formatData) -{ - if (0==formatData.variable.m_type) - { - *m_streamOut << "<text:date/>"; // ### TODO: parameters - } - else if (2==formatData.variable.m_type) - { - *m_streamOut << "<text:time/>"; // ### TODO: parameters - } - else if (4==formatData.variable.m_type) - { - // ### TODO: the other under-types, other parameters - if (formatData.variable.isPageNumber()) - { - *m_streamOut << "<text:page-number text:select-page=\"current\"/>"; - } - else if (formatData.variable.isPageCount()) - { - *m_streamOut << "<text:page-count/>"; - } - else - { - // Unknown subtype, therefore write out the result - *m_streamOut << formatData.variable.m_text; - } - } - else if (9==formatData.variable.m_type) - { - // A link - *m_streamOut << "<text:a xlink:href=\"" - << escapeOOText(formatData.variable.getHrefName()) - << "\" xlink:type=\"simple\">" - << escapeOOText(formatData.variable.getLinkName()) - << "</text:a>"; - } - else if ( 10 == formatData.variable.m_type ) - { // Note (OOWriter: annotation) - processNote ( formatData.variable ); - } - else if (11==formatData.variable.m_type) - { - // Footnote - processFootnote ( formatData.variable ); - } - else - { - // Generic variable - *m_streamOut << formatData.variable.m_text; - } -} - -void OOWriterWorker::processAnchor ( const TQString&, - const TextFormatting& /*formatLayout*/, //TODO - const FormatData& formatData) -{ - // We have a picture or a table - if ( (2==formatData.frameAnchor.type) // <IMAGE> or <PICTURE> - || (5==formatData.frameAnchor.type) ) // <CLIPART> - { - makePicture( formatData.frameAnchor, AnchorInlined ); - } - else if (6==formatData.frameAnchor.type) - { - makeTable( formatData.frameAnchor, AnchorInlined ); - } - else - { - kdWarning(30518) << "Unsupported anchor type: " - << formatData.frameAnchor.type << endl; - } -} - -void OOWriterWorker::processTextImage ( const TQString&, - const TextFormatting& /*formatLayout*/, - const FormatData& formatData) -{ - kdDebug(30518) << "Text Image: " << formatData.frameAnchor.key.toString() << endl; - makePicture( formatData.frameAnchor, AnchorTextImage ); -} - -void OOWriterWorker::processParagraphData ( const TQString ¶Text, - const TextFormatting& formatLayout, - const ValueListFormatData ¶FormatDataList) -{ - if ( paraText.length () > 0 ) - { - ValueListFormatData::ConstIterator paraFormatDataIt; - - for ( paraFormatDataIt = paraFormatDataList.begin (); - paraFormatDataIt != paraFormatDataList.end (); - paraFormatDataIt++ ) - { - if (1==(*paraFormatDataIt).id) - { - processNormalText(paraText, formatLayout, (*paraFormatDataIt)); - } - else if (2==(*paraFormatDataIt).id) - { - processTextImage(paraText, formatLayout, (*paraFormatDataIt)); - } - else if ( 3 == (*paraFormatDataIt).id ) - { - // Just a (KWord 0.8) tab stop, nothing else to do! - *m_streamOut << "<text:tab-stop/>"; - } - else if (4==(*paraFormatDataIt).id) - { - processVariable(paraText, formatLayout, (*paraFormatDataIt)); - } - else if (6==(*paraFormatDataIt).id) - { - processAnchor(paraText, formatLayout, (*paraFormatDataIt)); - } - else if ( 1001 == (*paraFormatDataIt).id ) // Start of bookmark - { - *m_streamOut << "<text:bookmark-start text:name=\"" - << escapeOOText( (*paraFormatDataIt).variable.m_text ) - <<"\"/>"; - } - else if ( 1002 == (*paraFormatDataIt).id ) // End of bookmark - { - *m_streamOut << "<text:bookmark-end text:name=\"" - << escapeOOText( (*paraFormatDataIt).variable.m_text ) - <<"\"/>"; - } - } - } -} - -TQString OOWriterWorker::layoutToParagraphStyle(const LayoutData& layoutOrigin, - const LayoutData& layout, const bool force, TQString& styleKey) -{ - TQString props; // Props has to remain empty, if there is no difference. - - styleKey += layout.styleName; - styleKey += ','; - - if (force || (layoutOrigin.alignment!=layout.alignment)) - { - // NOTE: OO 1.0.x uses start and end like left and right (section 3.11.4) - // Unfortunately in XSL-FO's text-align, they are really supposed to be the start and the end. - if (layout.alignment == "left") - { - props += "fo:text-align=\"start\" "; - styleKey += 'L'; - } - else if (layout.alignment == "right") - { - props += "fo:text-align=\"end\" "; - styleKey += 'R'; - } - else if (layout.alignment == "center") - { - props += "fo:text-align=\"center\" "; - styleKey += 'C'; - } - else if (layout.alignment == "justify") - { - props += "fo:text-align=\"justify\" "; - styleKey += 'J'; - } - else if (layout.alignment == "auto") - { - props += "fo:text-align=\"start\" "; -#ifndef STRICT_OOWRITER_VERSION_1 - props += "style:text-auto-align=\"true\" "; // rejected draft OASIS extension -#endif - styleKey += 'A'; - } - else - { - kdWarning(30518) << "Unknown alignment: " << layout.alignment << endl; - } - } - - styleKey += ','; - - if ((layout.indentLeft>=0.0) - && (force || (layoutOrigin.indentLeft!=layout.indentLeft))) - { - props += TQString("fo:margin-left=\"%1pt\" ").arg(layout.indentLeft); - styleKey += TQString::number(layout.indentLeft); - } - - styleKey += ','; - - if ((layout.indentRight>=0.0) - && (force || (layoutOrigin.indentRight!=layout.indentRight))) - { - props += TQString("fo:margin-right=\"%1pt\" ").arg(layout.indentRight); - styleKey += TQString::number(layout.indentRight); - } - - styleKey += ','; - - if (force || (layoutOrigin.indentLeft!=layout.indentLeft)) - { - props += "fo:text-indent=\""; - props += TQString::number(layout.indentFirst); - props += "\" "; - styleKey += TQString::number(layout.indentFirst); - } - - styleKey += ','; - - if ((layout.marginBottom>=0.0) - && ( force || ( layoutOrigin.marginBottom != layout.marginBottom ) ) ) - { - props += TQString("fo:margin-bottom=\"%1pt\" ").arg(layout.marginBottom); - styleKey += TQString::number(layout.marginBottom); - } - - styleKey += ','; - - if ((layout.marginTop>=0.0) - && ( force || ( layoutOrigin.marginTop != layout.marginTop ) ) ) - { - props += TQString("fo:margin-top=\"%1pt\" ").arg(layout.marginTop); - styleKey += TQString::number(layout.marginTop); - } - - styleKey += ','; - - if (force - || ( layoutOrigin.lineSpacingType != layout.lineSpacingType ) - || ( layoutOrigin.lineSpacing != layout.lineSpacing ) ) - { - switch ( layout.lineSpacingType ) - { - case LayoutData::LS_CUSTOM: - { - // We have a custom line spacing (in points) - const TQString height ( TQString::number(layout.lineSpacing) ); // ### TODO: rounding? - props += "style:line-spacing=\""; - props += height; - props += "pt\" "; - styleKey += height; - styleKey += 'C'; - break; - } - case LayoutData::LS_SINGLE: - { - props += "fo:line-height=\"normal\" "; // One - styleKey += "100%"; // One - break; - } - case LayoutData::LS_ONEANDHALF: - { - props += "fo:line-height=\"150%\" "; // One-and-half - styleKey += "150%"; - break; - } - case LayoutData::LS_DOUBLE: - { - props += "fo:line-height=\"200%\" "; // Two - styleKey += "200%"; - break; - } - case LayoutData::LS_MULTIPLE: - { - // OOWriter 1.1 only allows up to 200% - const TQString mult ( TQString::number( tqRound( layout.lineSpacing * 100 ) ) ); - props += "fo:line-height=\""; - props += mult; - props += "%\" "; - styleKey += mult; - styleKey += "%"; - break; - } - case LayoutData::LS_FIXED: - { - // We have a fixed line height (in points) - const TQString height ( TQString::number(layout.lineSpacing) ); // ### TODO: rounding? - props += "fo:line-height=\""; - props += height; - props += "pt\" "; - styleKey += height; - styleKey += 'F'; - break; - } - case LayoutData::LS_ATLEAST: - { - // We have a at-least line height (in points) - const TQString height ( TQString::number(layout.lineSpacing) ); // ### TODO: rounding? - props += "style:line-height-at-least=\""; - props += height; - props += "pt\" "; - styleKey += height; - styleKey += 'A'; - break; - } - default: - { - kdWarning(30518) << "Unsupported lineSpacingType: " << layout.lineSpacingType << " (Ignoring!)" << endl; - break; - } - } - } - - styleKey += ','; - - if ( layout.pageBreakBefore ) - { - // We have a page break before the paragraph - props += "fo:page-break-before=\"page\" "; - styleKey += 'B'; - } - - styleKey += ','; - - if ( layout.pageBreakAfter ) - { - // We have a page break after the paragraph - props += "fo:page-break-after=\"page\" "; - styleKey += 'A'; - } - - styleKey += '@'; // A more visible seperator - - props += textFormatToStyle(layoutOrigin.formatData.text,layout.formatData.text,force,styleKey); - - props += ">"; - - styleKey += '@'; // A more visible seperator - - // ### TODO/FIXME: what if all tabulators must be erased? - if (!layout.tabulatorList.isEmpty() - && (force || (layoutOrigin.tabulatorList!=layout.tabulatorList) )) - { - props += "\n <style:tab-stops>\n"; - TabulatorList::ConstIterator it; - TabulatorList::ConstIterator end(layout.tabulatorList.end()); - for (it=layout.tabulatorList.begin();it!=end;++it) - { - props+=" <style:tab-stop style:position=\""; - props += TQString::number((*it).m_ptpos); - props += "pt\""; - styleKey += TQString::number((*it).m_ptpos); - switch ((*it).m_type) - { - case 0: props += " style:type=\"left\""; styleKey += "L"; break; - case 1: props += " style:type=\"center\""; styleKey += "C"; break; - case 2: props += " style:type=\"right\""; styleKey += "R"; break; - case 3: props += " style:type=\"char\" style:char=\".\""; styleKey += "D"; break; // decimal - default: props += " style:type=\"left\""; styleKey += "L"; break; - } - switch ((*it).m_filling) // ### TODO: check if the characters are right - { - case TabulatorData::TF_NONE: break; - case TabulatorData::TF_DOT: props += " style:leader-char=\".\""; break; - case TabulatorData::TF_LINE: props += " style:leader-char=\"_\""; break; - - case TabulatorData::TF_DASH: - case TabulatorData::TF_DASHDOT: - case TabulatorData::TF_DASHDOTDOT: props += " style:leader-char=\"-\""; break; - - default: break; - } - props += "/>\n"; - styleKey +='/'; - } - props += " </style:tab-stops>\n "; - } - - return props; -} - -bool OOWriterWorker::doFullParagraph(const TQString& paraText, const LayoutData& layout, - const ValueListFormatData& paraFormatDataList) -{ - const bool header = ( (layout.counter.numbering == CounterData::NUM_CHAPTER) - && (layout.counter.depth<10) ); // ### TODO: Does OOWriter really limits to 10? - - if (header) - { - *m_streamOut << " <text:h text:level=\""; - *m_streamOut << TQString::number(layout.counter.depth+1,10); - *m_streamOut << "\" "; - } - else - *m_streamOut << " <text:p "; - - const LayoutData& styleLayout=m_styleMap[layout.styleName]; - - TQString styleKey; - const TQString props(layoutToParagraphStyle(styleLayout,layout,false,styleKey)); - - TQString actualStyle(layout.styleName); - if (!props.isEmpty()) - { - TQMap<TQString,TQString>::ConstIterator it ( m_mapParaStyleKeys.find(styleKey) ); - kdDebug(30518) << "Searching paragraph key: " << styleKey << endl; - - TQString automaticStyle; - - if (it==m_mapParaStyleKeys.end()) - { - // We have additional properties, so we need an automatic style for the paragraph - automaticStyle = makeAutomaticStyleName("P", m_automaticParagraphStyleNumber); - kdDebug(30518) << "Creating automatic paragraph style: " << automaticStyle << " key: " << styleKey << endl; - m_mapParaStyleKeys[styleKey]=automaticStyle; - - m_contentAutomaticStyles += " <style:style"; - m_contentAutomaticStyles += " style:name=\"" + escapeOOText(automaticStyle) + "\""; - m_contentAutomaticStyles += " style:parent-style-name=\"" + escapeOOText(layout.styleName) + "\""; - m_contentAutomaticStyles += " style:family=\"paragraph\" style:class=\"text\""; - m_contentAutomaticStyles += ">\n"; - m_contentAutomaticStyles += " <style:properties "; - m_contentAutomaticStyles += props; - m_contentAutomaticStyles += "</style:properties>\n"; - m_contentAutomaticStyles += " </style:style>\n"; - } - else - { - // We have a match, so use the already defined automatic paragraph style - automaticStyle=it.data(); - kdDebug(30518) << "Using automatic paragraph style: " << automaticStyle << " key: " << styleKey << endl; - } - - actualStyle=automaticStyle; - } - - if (!actualStyle.isEmpty()) - { - *m_streamOut << "text:style-name=\"" << escapeOOText(actualStyle) << "\" "; - } - else - { // SHould not happen - kdWarning(30518) << "No style for a paragraph!" << endl; - } - - *m_streamOut << ">"; - - processParagraphData(paraText, layout.formatData.text, paraFormatDataList); - - if (header) - *m_streamOut << "</text:h>\n"; - else - *m_streamOut << "</text:p>\n"; - - return true; -} - -bool OOWriterWorker::doOpenStyles(void) -{ - m_styles += " <office:styles>\n"; - m_styles += " <style:style style:name=\"Graphics\" style:family=\"graphics\">\n"; // ### TODO: what if Graphics is a normal style - m_styles += " <style:properties text:anchor-type=\"paragraph\" style:wrap=\"none\"/>\n"; - m_styles += " </style:style>\n"; - m_styles += " <style:style style:name=\"Frame\" style:family=\"graphics\">\n"; // ### TODO: what if Frame is a normal style - m_styles += " <style:properties text:anchor-type=\"paragraph\" style:wrap=\"none\"/>\n"; - m_styles += " </style:style>\n"; - return true; -} - -bool OOWriterWorker::doFullDefineStyle(LayoutData& layout) -{ - //Register style in the style map - m_styleMap[layout.styleName]=layout; - - m_styles += " <style:style"; - - m_styles += " style:name=\"" + escapeOOText( layout.styleName ) + "\""; - m_styles += " style:next-style-name=\"" + escapeOOText( layout.styleFollowing ) + "\""; - m_styles += " style:family=\"paragraph\" style:class=\"text\""; - m_styles += ">\n"; - m_styles += " <style:properties "; - - TQString debugKey; // Not needed - m_styles += layoutToParagraphStyle(layout,layout,true,debugKey); - kdDebug(30518) << "Defining style: " << debugKey << endl; - - m_styles += "</style:properties>\n"; - m_styles += " </style:style>\n"; - - return true; -} - -bool OOWriterWorker::doCloseStyles(void) -{ - m_styles += " </office:styles>\n"; - return true; -} - -bool OOWriterWorker::doFullPaperFormat(const int format, - const double width, const double height, const int orientation) -{ - if ( ( format < 0 ) // Be careful that 0 is ISO A3 - || ( width < 1.0 ) - || ( height < 1.0 ) ) - { - kdWarning(30518) << "Page size problem: format: " << format << " width: " << width << " height: " << height << endl; - // Something is wrong with the page size - KoFormat newFormat = KoFormat ( format ); - if ( ( format < 0 ) || ( format > PG_LAST_FORMAT ) ) - { - // Bad or unknown format, so assume ISO A4 - newFormat = PG_DIN_A4; - } - m_paperWidth = KoPageFormat::width ( newFormat, KoOrientation( orientation ) ) * 72.0 / 25.4 ; - m_paperHeight = KoPageFormat::height ( newFormat, KoOrientation( orientation ) ) * 72.0 / 25.4 ; - m_paperFormat = newFormat; - } - else - { - m_paperFormat=format; - m_paperWidth=width; - m_paperHeight=height; - } - m_paperOrientation=orientation; // ### TODO: check if OOWriter needs the orignal size (without landscape) or the real size - return true; -} - -bool OOWriterWorker::doFullPaperBorders (const double top, const double left, - const double bottom, const double right) -{ - m_paperBorderTop=top; - m_paperBorderLeft=left; - m_paperBorderBottom=bottom; - m_paperBorderRight=right; - return true; -} - -bool OOWriterWorker::doFullPaperFormatOther ( const int columns, const double columnspacing, const int numPages ) -{ - m_columns = columns; - m_columnspacing = columnspacing; - m_numPages = numPages; - return true; -} - -bool OOWriterWorker::doFullDocumentInfo(const KWEFDocumentInfo& docInfo) -{ - m_docInfo=docInfo; - - return true; -} - -bool OOWriterWorker::doVariableSettings(const VariableSettingsData& vs) -{ - m_varSet=vs; - - return true; -} - -bool OOWriterWorker::doDeclareNonInlinedFramesets( TQValueList<FrameAnchor>& pictureAnchors, TQValueList<FrameAnchor>& tableAnchors ) -{ - m_nonInlinedPictureAnchors = pictureAnchors; - m_nonInlinedTableAnchors = tableAnchors; - return true; -} - -void OOWriterWorker::declareFont(const TQString& fontName) -{ - if (fontName.isEmpty()) - return; - - if (m_fontNames.find(fontName)==m_fontNames.end()) - { - TQString props; - - // Disabled, as TQFontInfo::styleHint() cannot guess -#if 0 - TQFont font(fontName); - TQFontInfo info(font); - props+="style:font-family-generic=\"" - switch (info.styleHint()) - { - case TQFont::SansSerif: - default: - { - props += "swiss"; - break; - } - case TQFont::Serif: - { - props += "roman"; - break; - } - case TQFont::Courier: - { - props += "modern"; - break; - } - case TQFont::OldEnglish: - { - props += "decorative"; - break; - } - } - props +="\" "; -#endif - - props +="style:font-pitch=\"variable\""; // ### TODO: check if font is variable or fixed - // New font, so register it - m_fontNames[fontName]=props; - } -} - -TQString OOWriterWorker::makeAutomaticStyleName(const TQString& prefix, ulong& counter) const -{ - const TQString str (prefix + TQString::number(++counter,10)); - - // Checks if the automatic style has not the same name as a user one. - // If it is the case, change it! - - if (m_styleMap.find(str)==m_styleMap.end()) - return str; // Unique, so let's go! - - TQString str2(str+"_bis"); - if (m_styleMap.find(str2)==m_styleMap.end()) - return str2; - - str2 = str+"_ter"; - if (m_styleMap.find(str2)==m_styleMap.end()) - return str2; - - // If it is still not unique, try a time stamp. - const TQDateTime dt(TQDateTime::currentDateTime(Qt::UTC)); - - str2 = str + "_" + TQString::number(dt.toTime_t(),16); - if (m_styleMap.find(str2)==m_styleMap.end()) - return str2; - - kdWarning(30518) << "Could not make an unique style name: " << str2 << endl; - return str2; // Still return, as we have nothing better -} - |