diff options
Diffstat (limited to 'filters/kword/starwriter/starwriterimport.cpp')
-rw-r--r-- | filters/kword/starwriter/starwriterimport.cpp | 425 |
1 files changed, 425 insertions, 0 deletions
diff --git a/filters/kword/starwriter/starwriterimport.cpp b/filters/kword/starwriter/starwriterimport.cpp new file mode 100644 index 000000000..43dc1b623 --- /dev/null +++ b/filters/kword/starwriter/starwriterimport.cpp @@ -0,0 +1,425 @@ +/* + This file is part of the KDE project + Copyright (C) 2002 Marco Zanon <info@marcozanon.com> + and Ariya Hidayat <ariya@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 <starwriterimport.h> + +#include <tqdatastream.h> +#include <tqiodevice.h> +#include <tqstring.h> + +#include <KoFilterChain.h> +#include <kgenericfactory.h> + +#include "pole.h" + +typedef KGenericFactory<StarWriterImport, KoFilter> StarWriterImportFactory; +K_EXPORT_COMPONENT_FACTORY(libstarwriterimport, StarWriterImportFactory("kofficefilters")) + +// Get unsigned 24-bits integer at given offset +static inline TQ_UINT32 readU24(TQByteArray array, TQ_UINT32 p) +{ + TQ_UINT8* ptr = (TQ_UINT8*) array.data(); + return (TQ_UINT32) (ptr[p] + (ptr[p+1] << 8) + (ptr[p+2] << 16)); +} + +// Get unsigned 16-bits integer at given offset +static inline TQ_UINT16 readU16(TQByteArray array, TQ_UINT32 p) +{ + TQ_UINT8* ptr = (TQ_UINT8*) array.data(); + return (TQ_UINT16) (ptr[p] + (ptr[p+1] << 8)); +} + +StarWriterImport::StarWriterImport(KoFilter *, const char *, const TQStringList&) : KoFilter() +{ + hasHeader = false; + hasFooter = false; + tablesNumber = 1; +} + +StarWriterImport::~StarWriterImport() +{ +} + +KoFilter::ConversionStatus StarWriterImport::convert(const TQCString& from, const TQCString& to) +{ + // Check for proper conversion + // When 4.x is supported, use also: || (from != "application/x-starwriter") + if ((to != "application/x-kword") || (from != "application/vnd.stardivision.writer")) + return KoFilter::NotImplemented; + + // Read streams + POLE::Storage storage; + storage.open(m_chain->inputFile().latin1()); + + POLE::Stream* stream; + + stream = storage.stream("StarWriterDocument"); + if (!stream) return KoFilter::WrongFormat; + StarWriterDocument.resize(stream->size()); + stream->read((unsigned char*)StarWriterDocument.data(), StarWriterDocument.size()); + delete stream; + + stream = storage.stream("SwPageStyleSheets"); + if (!stream) return KoFilter::WrongFormat; + SwPageStyleSheets.resize(stream->size()); + stream->read((unsigned char*)SwPageStyleSheets.data(), SwPageStyleSheets.size()); + delete stream; + + // Check document version + if (!checkDocumentVersion()) return KoFilter::WrongFormat; + + // Algorithm for creating the main document + if (!addBody()) return KoFilter::ParsingError; + if (!addHeaders()) return KoFilter::ParsingError; + if (!addFooters()) return KoFilter::ParsingError; + if (!addStyles()) return KoFilter::ParsingError; + if (!addPageProperties()) return KoFilter::ParsingError; + maindoc = bodyStuff + tablesStuff + picturesStuff; // + lots of other things :) + + if (!addKWordHeader()) return KoFilter::ParsingError; + + // Prepare storage device and return + KoStoreDevice *out = m_chain->storageFile("maindoc.xml", KoStore::Write); + if (out) { + TQCString cstring = maindoc.utf8(); + cstring.prepend("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); + out->writeBlock((const char*) cstring, cstring.length()); + } + + return KoFilter::OK; +} + +bool StarWriterImport::checkDocumentVersion() +{ + if (SwPageStyleSheets.size() < 0x0B) return false; + if (StarWriterDocument.size() < 0x0B) return false; + + if (SwPageStyleSheets[0x00] != 'S') return false; + if (SwPageStyleSheets[0x01] != 'W') return false; + // When 4.x is supported use also: || (SwPageStyleSheets[0x02] != '4') + if (SwPageStyleSheets[0x02] != '5') return false; + if (SwPageStyleSheets[0x03] != 'H') return false; + if (SwPageStyleSheets[0x04] != 'D') return false; + if (SwPageStyleSheets[0x05] != 'R') return false; + + if (StarWriterDocument[0x00] != 'S') return false; + if (StarWriterDocument[0x01] != 'W') return false; + // When 4.x is supported use also: || (StarWriterDocument[0x02] != '4') + if (StarWriterDocument[0x02] != '5') return false; + if (StarWriterDocument[0x03] != 'H') return false; + if (StarWriterDocument[0x04] != 'D') return false; + if (StarWriterDocument[0x05] != 'R') return false; + + // Password-protection is not supported for the moment + TQ_UINT16 flags = readU16(StarWriterDocument, 0x0A); + if (flags & 0x0008) return false; + + return true; +} + +bool StarWriterImport::addKWordHeader() +{ + // Proper prolog and epilog + TQString prolog; + prolog = "<!DOCTYPE DOC>\n"; + prolog.append("<DOC mime=\"application/x-kword\" syntaxVersion=\"2\" editor=\"KWord\">\n"); + prolog.append("<PAPER width=\"595\" height=\"841\" format=\"1\" fType=\"0\" orientation=\"0\" hType=\"0\" columns=\"1\">\n"); + prolog.append(" <PAPERBORDERS left=\"36\" right=\"36\" top=\"36\" bottom=\"36\" />\n"); + prolog.append("</PAPER>\n"); + prolog.append("<ATTRIBUTES standardpage=\"1\" hasFooter=\"0\" hasHeader=\"0\" processing=\"0\" />\n"); + prolog.append("<FRAMESETS>\n"); + + maindoc.prepend(prolog); + + maindoc.append("</FRAMESETS>\n"); + maindoc.append("</DOC>"); + + return true; +} + +bool StarWriterImport::addPageProperties() +{ + return true; +} + +bool StarWriterImport::addStyles() +{ + return true; +} + +// FIXME +// 1. search for the right starting point +// 2. determine the length +// 3. parse everything with parseNodes() +bool StarWriterImport::addHeaders() +{ + return true; +} + +bool StarWriterImport::addFooters() +{ + return true; +} + +bool StarWriterImport::addBody() +{ + // Find the starting point, by: + // 1. skipping the header + TQ_UINT32 len = StarWriterDocument[0x07]; + TQ_UINT32 p = len; + + // 2. skipping 8 more bytes + p += 0x08; + + // 3. skipping useless sections + char c = StarWriterDocument[p]; + while (c != 'N') { + len = readU24(StarWriterDocument, p+1); + p += len; + c = StarWriterDocument[p]; + }; // there is at least one empty paragraph! + + // Select nodes and pass them to parseNodes() + len = readU24(StarWriterDocument, p+1); + TQByteArray data(len); + for (TQ_UINT32 k=0; k<len; k++) + data[k] = StarWriterDocument[p+k]; + bool retval = parseNodes(data); + + // add proper tags + bodyStuff.prepend(" <FRAME right=\"567\" left=\"28\" top=\"42\" bottom=\"799\" />\n"); + bodyStuff.prepend(" <FRAMESET removable=\"0\" frameType=\"1\" frameInfo=\"0\" name=\"Text Frameset 1\" autoCreateNewFrame=\"1\">\n"); + bodyStuff.append(" </FRAMESET>\n"); + + return retval; +} + +TQString StarWriterImport::convertToKWordString(TQByteArray s) +{ + TQString result; + + for (TQ_UINT32 i = 0x00; i < s.size(); i++) + if (s[i] == '&') result += "&"; + else if (s[i] == '<') result += "<"; + else if (s[i] == '>') result += ">"; + else if (s[i] == '"') result += """; + else if (s[i] == 0x27) result += "'"; + else if (s[i] == 0x09) result += "\t"; + // FIXME: more to add here + // (manual breaks, soft-hyphens, non-breaking spaces, variables) + else result += TQChar(s[i]); + + return result; +} + +bool StarWriterImport::parseNodes(TQByteArray n) +{ + TQByteArray s; + TQ_UINT32 len, p; + + // Loop + p = 0x09; // is this a fixed value? is it the same for headers/footers? + + while (p < n.size()) { + char c = n[p]; + len = readU24(n, p+1); + + s.resize(len); + for (TQ_UINT32 k = 0x00; k < len; k++) + s[k] = n[p+k]; + + switch (c) { + case 'T': + //if ((s[0x0A] == 0x01) && (s[0x0B] == 0x00) && (s[0x0C] == 0xFF)) { + // if (!parseGraphics(s)) return false; + //} + //else { + if (!parseText(s)) return false; + //} + break; + case 'E': + if (!parseTable(s)) return false; + break; + default: + break; + }; + p += len; + }; + + return true; +} + +bool StarWriterImport::parseText(TQByteArray n) +{ + TQByteArray s; + TQ_UINT16 len; + TQ_UINT32 p; + TQString text; + // TQ_UINT16 attributeStart, attributeEnd, formatPos, formatLen; + // TQString pAttributes, cAttributes, tempCAttributes; + // TQStringList cAttributesList; + + // Retrieve the paragraph (text-only) + len = readU16(n, 0x09); + s.resize(len); + for (TQ_UINT16 k = 0x00; k < len; k++) + s[k] = n[0x0B+k]; + + /* + // Retrieve paragraph and character attributes + P = len; + while (n[p] == 'S') { + p += 0x04; + // parse 'A' sub-sections and write to pAttributes + // FIXME: all this part + // get section length + // if (length > ...) { + // if (special characters found) { + // get start, len, type + // write to the list + // } + // } + // increment p + } + while (n[p] == 'A') { + // parse 'A' sections and fill cAttributesList + // FIXME: similar as above + } + // Parse list + while ((!cAttributesList.isEmpty()) || (formatPos < len)) { + formatLen = 65535; + // FIXME: point to first list item + while (FIXME: current list item < last list item) { + // FIXME: get item members + if ((attributeStart <= formatPos) && (formatPos <= attributeEnd)) { // this attribute has to be considered + // FIXME: write attribute to tempCAttributes + formatLen = min(formatLen, (attributeStart - attributeEnd)); + } + else if (attributeLen < formatPos) [ // this attribute has to be removed + // FIXME: remove list item + } + // FIXME: point to next list item + } + // FIXME: copy tempCAttributes to cAttributes + formatPos += formatLen; + } + */ + + // Write everything to the variable + text = convertToKWordString(s); + bodyStuff.append(" <PARAGRAPH>\n"); + bodyStuff.append(" <TEXT xml:space=\"preserve\">" + text + "</TEXT>\n"); + // FIXME: add FORMATS for pAttributes and cAttributes + bodyStuff.append(" </PARAGRAPH>\n"); + + return true; +} + +bool StarWriterImport::parseTable(TQByteArray n) +{ +/* + TQByteArray s; + TQ_UINT32 len, len2; + TQ_UINT16 len3; + TQ_UINT32 p, p2; + TQString text; + TQString tableCell, tableText, tableName; + TQ_UINT8 row, column; + + // Set table name + tableName = TQString("Table %1").arg(tablesNumber); + tablesNumber++; + + // Skip useless sections and retrieve the right point + p = 0x13; + while (n[p] != 'L') { + len = readU24(n, p+1); + p += len; + } + + row = 0; + + // Read rows + while (n[p] == 'L') { + column = 0; + + // Find the first 't' + while (n[p] != 't') p++; + + // Read cells + while (n[p] == 't') { + // Get cell length + len2 = readU24(n, p+1); + p2 = p + len2; + + // Find the 'T' section + while (n[p] != 'T') p++; + + // Get cell text/value + len3 = readU16(n, p+0x09); + s.resize(len3); + for (TQ_UINT16 k = 0x00; k < len3; k++) + s[k] = n[p+0x0B+k]; + text = convertToKWordString(s); + + // FIXME: check this stuff + TQString frameName = TQString("%1 Cell %2,%3").arg(tableName).arg(row).arg(column); + tableText.append(TQString(" <FRAMESET name=\"%1\" frameType=\"1\" frameInfo=\"0\" removable=\"0\" visible=\"1\" grpMgr=\"%2\" row=\"%3\" col=\"%4\" rows=\"1\" cols=\"1\" protectSize=\"0\">\n").arg(frameName).arg(tableName).arg(row).arg(column)); + tableText.append(" <FRAME runaround=\"1\" copy=\"0\" newFrameBehavior=\"1\" runaroundSide=\"biggest\" autoCreateNewFrame=\"0\" bleftpt=\"2.8\" brightpt=\"2.8\" btoppt=\"2.8\" bbottompt=\"2.8\" runaroundGap=\"2.8\" />\n"); + tableText.append(" <PARAGRAPH>\n"); + tableText.append(" <TEXT xml:space=\"preserve\">" + text + "</TEXT>\n"); + tableText.append(" </PARAGRAPH>\n"); + tableText.append(" </FRAMESET>\n"); + + // Skip other sections or bytes + p = p2; + + // Increase column pointers + column++; + } + + // Increase row pointer + row++; + } + + // Add everything to tablesStuff + tablesStuff.append(tableText); + + // Add anchor to bodyStuff + bodyStuff.append(" <PARAGRAPH>\n"); + bodyStuff.append(" <TEXT xml:space=\"preserve\">#</TEXT>\n"); + bodyStuff.append(" <FORMATS>\n"); + bodyStuff.append(" <FORMAT id=\"6\" pos=\"0\" len=\"1\">\n"); + bodyStuff.append(TQString(" <ANCHOR type=\"frameset\" instance=\"%1\" />\n").arg(tableName)); + bodyStuff.append(" </FORMAT>\n"); + bodyStuff.append(" </FORMATS>\n"); + bodyStuff.append(" </PARAGRAPH>\n"); + +*/ + return true; +} + +bool StarWriterImport::parseGraphics(TQByteArray n) +{ + return true; +} + +#include <starwriterimport.moc> |