summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/ww8')
-rw-r--r--sw/source/filter/ww8/CREDITS3
-rw-r--r--sw/source/filter/ww8/README-rtf.txt227
-rw-r--r--sw/source/filter/ww8/WW8FFData.cxx178
-rw-r--r--sw/source/filter/ww8/WW8FFData.hxx119
-rw-r--r--sw/source/filter/ww8/WW8FibData.cxx64
-rw-r--r--sw/source/filter/ww8/WW8FibData.hxx54
-rw-r--r--sw/source/filter/ww8/WW8Sttbf.cxx125
-rw-r--r--sw/source/filter/ww8/WW8Sttbf.hxx147
-rw-r--r--sw/source/filter/ww8/WW8TableInfo.cxx1514
-rw-r--r--sw/source/filter/ww8/WW8TableInfo.hxx359
-rw-r--r--sw/source/filter/ww8/attributeoutputbase.hxx591
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.cxx4168
-rw-r--r--sw/source/filter/ww8/docxattributeoutput.hxx609
-rw-r--r--sw/source/filter/ww8/docxexport.cxx768
-rw-r--r--sw/source/filter/ww8/docxexport.hxx239
-rw-r--r--sw/source/filter/ww8/docxexportfilter.cxx162
-rw-r--r--sw/source/filter/ww8/docxexportfilter.hxx69
-rw-r--r--sw/source/filter/ww8/docxfootnotes.hxx102
-rw-r--r--sw/source/filter/ww8/escher.hxx184
-rw-r--r--sw/source/filter/ww8/fields.cxx151
-rw-r--r--sw/source/filter/ww8/fields.hxx158
-rw-r--r--sw/source/filter/ww8/hash_wrap.hxx122
-rw-r--r--sw/source/filter/ww8/needed_cast.hxx64
-rw-r--r--sw/source/filter/ww8/rtfattributeoutput.cxx3464
-rw-r--r--sw/source/filter/ww8/rtfattributeoutput.hxx572
-rw-r--r--sw/source/filter/ww8/rtfexport.cxx1302
-rw-r--r--sw/source/filter/ww8/rtfexport.hxx221
-rw-r--r--sw/source/filter/ww8/rtfexportfilter.cxx138
-rw-r--r--sw/source/filter/ww8/rtfexportfilter.hxx87
-rw-r--r--sw/source/filter/ww8/rtfimportfilter.cxx139
-rw-r--r--sw/source/filter/ww8/rtfimportfilter.hxx77
-rw-r--r--sw/source/filter/ww8/rtfsdrexport.cxx588
-rw-r--r--sw/source/filter/ww8/rtfsdrexport.hxx118
-rw-r--r--sw/source/filter/ww8/sortedarray.hxx119
-rw-r--r--sw/source/filter/ww8/staticassert.hxx72
-rw-r--r--sw/source/filter/ww8/styles.cxx218
-rw-r--r--sw/source/filter/ww8/tracer.cxx209
-rw-r--r--sw/source/filter/ww8/tracer.hxx91
-rw-r--r--sw/source/filter/ww8/types.hxx58
-rw-r--r--sw/source/filter/ww8/typessw.hxx46
-rw-r--r--sw/source/filter/ww8/writerhelper.cxx784
-rw-r--r--sw/source/filter/ww8/writerhelper.hxx922
-rw-r--r--sw/source/filter/ww8/writerwordglue.cxx1026
-rw-r--r--sw/source/filter/ww8/writerwordglue.hxx164
-rw-r--r--sw/source/filter/ww8/wrtw8esh.cxx2811
-rw-r--r--sw/source/filter/ww8/wrtw8nds.cxx2757
-rw-r--r--sw/source/filter/ww8/wrtw8num.cxx918
-rw-r--r--sw/source/filter/ww8/wrtw8sty.cxx2336
-rw-r--r--sw/source/filter/ww8/wrtww8.cxx3834
-rw-r--r--sw/source/filter/ww8/wrtww8.hxx1574
-rw-r--r--sw/source/filter/ww8/wrtww8gr.cxx905
-rw-r--r--sw/source/filter/ww8/ww8atr.cxx5247
-rw-r--r--sw/source/filter/ww8/ww8attributeoutput.hxx444
-rw-r--r--sw/source/filter/ww8/ww8glsy.cxx272
-rw-r--r--sw/source/filter/ww8/ww8glsy.hxx92
-rw-r--r--sw/source/filter/ww8/ww8graf.cxx3083
-rw-r--r--sw/source/filter/ww8/ww8graf.hxx106
-rw-r--r--sw/source/filter/ww8/ww8graf2.cxx785
-rw-r--r--sw/source/filter/ww8/ww8par.cxx5675
-rw-r--r--sw/source/filter/ww8/ww8par.hxx1630
-rw-r--r--sw/source/filter/ww8/ww8par2.cxx4644
-rw-r--r--sw/source/filter/ww8/ww8par2.hxx288
-rw-r--r--sw/source/filter/ww8/ww8par3.cxx2613
-rw-r--r--sw/source/filter/ww8/ww8par4.cxx572
-rw-r--r--sw/source/filter/ww8/ww8par5.cxx3711
-rw-r--r--sw/source/filter/ww8/ww8par6.cxx6149
-rw-r--r--sw/source/filter/ww8/ww8scan.cxx7301
-rw-r--r--sw/source/filter/ww8/ww8scan.hxx1785
-rw-r--r--sw/source/filter/ww8/ww8struc.hxx991
-rw-r--r--sw/source/filter/ww8/ww8toolbar.cxx1332
-rw-r--r--sw/source/filter/ww8/ww8toolbar.hxx379
71 files changed, 82826 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/CREDITS b/sw/source/filter/ww8/CREDITS
new file mode 100644
index 000000000000..26a5285ac48c
--- /dev/null
+++ b/sw/source/filter/ww8/CREDITS
@@ -0,0 +1,3 @@
+cmc@openoffice.org:
+tono@openoffice.org: (issue 17498. CJK patches)
+ayaniger@openoffice.org (i38158)
diff --git a/sw/source/filter/ww8/README-rtf.txt b/sw/source/filter/ww8/README-rtf.txt
new file mode 100644
index 000000000000..6acddaa61eee
--- /dev/null
+++ b/sw/source/filter/ww8/README-rtf.txt
@@ -0,0 +1,227 @@
+
+---------------------------------------------------------------------
+
+Summary of new features in RtfExport
+
+---------------------------------------------------------------------
+
+Miklos Vajna
+
+<vmiklos@frugalware.org>
+---------------------------------------------------------------------
+
+Table of Contents
+
+1. Introduction
+
+ 1.1. Terminology
+ 1.2. General
+
+2. List if fixed bugs
+3. List of new features
+
+ 3.1. Nested tables
+ 3.2. Character properties
+ 3.3. Sections
+ 3.4. Graphics
+ 3.5. Bookmarks
+ 3.6. Fields
+ 3.7. Drawing
+ 3.8. Form fields
+ 3.9. OLE objects
+
+4. Changes in the source code outside RTF
+
+
+---------------------------------------------------------------------
+
+1.�Introduction
+
+---------------------------------------------------------------------
+
+The biggest difference is that the new exporter is an UNO component,
+and it?s based on the MSWord base classes, the vision here is that
+this way much less code can achieve the same set of features,
+reducing the amount of duplicated code.
+
+
+1.1.�Terminology
+
+--------------
+
+ * The "MSO OK, OOo KO" and similar abbreviations describe if the
+ given new feature is supported by the OOo RTF importer or it can
+ be tested using Microsoft Office.
+ * RtfExport refers to the new UNO-based exporter, RtfWriter refers
+ to the old built-in one.
+
+
+1.2.�General
+
+--------------
+
+RtfWriter sometimes created documents where the first { is closed in
+the middle of the document. MSO ignores this problem, but OOo stops
+parsing the rest of the document if this happens, in other words
+everything after such a bug is ignored. This can be reproduced by for
+example parprops.odt, but it?s triggered in several other cases as
+well. RtfExport has no automatic prevention for this, either - but
+during development I primarily test the output with OOo, so hopefully
+the bug will pop up less frequently.
+
+
+---------------------------------------------------------------------
+
+2.�List if fixed bugs
+
+---------------------------------------------------------------------
+
+ * http://www.openoffice.org/issues/show_bug.cgi?id=51469 postit
+ fields
+ * http://www.openoffice.org/issues/show_bug.cgi?id=66619 page
+ margins
+ * http://www.openoffice.org/issues/show_bug.cgi?id=69856 page
+ numbers
+ * http://www.openoffice.org/issues/show_bug.cgi?id=81569 { and } in
+ document title
+ * http://www.openoffice.org/issues/show_bug.cgi?id=84703 redlines
+ * http://www.openoffice.org/issues/show_bug.cgi?id=91166 russian
+ chars
+ * http://www.openoffice.org/issues/show_bug.cgi?id=92673 bookmarks
+ across tables
+ * http://www.openoffice.org/issues/show_bug.cgi?id=100507 ole
+ object export
+ * http://www.openoffice.org/issues/show_bug.cgi?id=103993 same as #
+ 81569 just for doc comments
+ * http://www.openoffice.org/issues/show_bug.cgi?id=106677
+ listoverride index starts at zero
+ * http://www.openoffice.org/issues/show_bug.cgi?id=38344 enhanced
+ character space
+
+
+---------------------------------------------------------------------
+
+3.�List of new features
+
+---------------------------------------------------------------------
+
+
+3.1.�Nested tables
+
+--------------
+
+This was new in Word2000 and it?s now supported by RtfExport (MSO OK,
+OOo KO)
+
+
+3.2.�Character properties
+
+--------------
+
+The followings are now supported:
+
+ * blinking (MSO OK, OOo KO)
+ * expanded spacing (MSO OK, OOo OK)
+ * pair kerning (MSO OK, OOo OK)
+
+
+3.3.�Sections
+
+--------------
+
+RtfExport writes:
+
+ * column breaks (MSO OK, OOo OK)
+ * special breaks (when the next page should be an odd or an even
+ page; MSO OK, OOo KO)
+ * the write-protected property of sections is experted properly
+ (MSO OK, OOo KO)
+ * better page numbers (inherited type from page styles, restarts;
+ MSO OK, OOo KO)
+ * line numbering (MSO OK, OOo KO)
+
+
+3.4.�Graphics
+
+--------------
+
+PNG graphics are exported in WMF format as well, so that not only MSO
+and OOo can display graphics from the output document, but Wordpad as
+well.
+
+
+3.5.�Bookmarks
+
+--------------
+
+Implicit bookmarks like reference to a footnote did not work in OOo
+(one got an Error: Reference source not found message when opening
+the result), this now works as expected. (MSO OK - the importer
+previously autocorrected this as well, OO OK)
+
+
+3.6.�Fields
+
+--------------
+
+ * Table of contents is now written as a field, so it?s properly
+ read-only (MSO OK, OOo KO)
+ * Postit comments are now exported. (MSO OK, OOo KO)
+
+
+3.7.�Drawing
+
+--------------
+
+Drawing objects for Word 97 through Word 2007 (shapes) are now
+implemented:
+
+ * basic shapes (rectangle, ellipse, etc.)
+ * lines, including free-form ones
+ * texts, including vertical ones and their (paragraph and
+ character) formatting
+
+(MSO OK, OOo KO)
+
+
+3.8.�Form fields
+
+--------------
+
+All types supported by the RTF format are exported, namely:
+
+ * text boxes
+ * check boxes
+ * list boxes
+
+(MSO OK, OOo KO)
+
+
+3.9.�OLE objects
+
+--------------
+
+Their result is exported as a picture - RtfWriter did not export
+anything. (MSO OK, OOo OK)
+
+For math, the native data is written as well, so you can edit the
+object, too. (MSO OK, OOo KO)
+
+
+---------------------------------------------------------------------
+
+4.�Changes in the source code outside RTF
+
+---------------------------------------------------------------------
+
+These are refactorings I needed for RTF. To my best knowledge they do
+not change the output of other filters from a user?s point of view.
+
+ * The code that splits runs according to bookmarks is moved from
+ DocxExport to MSWordExportBase
+ * WW8_SdrAttrIter has been refactored to MSWord_SdrAttrIter
+ * MSWordExportBase::SubstituteBullet can avoid replacing bullets
+ * wwFontHelper::InitFontTable can really load all fonts
+ * An obvious typo in WW8AttributeOutput::CharTwoLines has been
+ fixed
+
diff --git a/sw/source/filter/ww8/WW8FFData.cxx b/sw/source/filter/ww8/WW8FFData.cxx
new file mode 100644
index 000000000000..65fa2b6b6cd7
--- /dev/null
+++ b/sw/source/filter/ww8/WW8FFData.cxx
@@ -0,0 +1,178 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "WW8FFData.hxx"
+#include <tools/stream.hxx>
+#include <doc.hxx>
+#include "writerwordglue.hxx"
+#include "wrtww8.hxx"
+
+namespace sw
+{
+
+using sw::types::msword_cast;
+
+WW8FFData::WW8FFData()
+ :
+ mnType(0),
+ mnResult(0),
+ mbOwnHelp(false),
+ mbOwnStat(false),
+ mbProtected(false),
+ mbSize(false),
+ mnTextType(0),
+ mbRecalc(false),
+ mbListBox(false),
+ mnMaxLen(0),
+ mnCheckboxHeight(0),
+ mnDefault(0)
+{
+}
+
+WW8FFData::~WW8FFData()
+{
+}
+
+void WW8FFData::setHelp(const ::rtl::OUString & rHelp)
+{
+ msHelp = rHelp;
+ mbOwnHelp = true;
+}
+
+void WW8FFData::setStatus(const ::rtl::OUString & rStatus)
+{
+ msStatus = rStatus;
+ mbOwnStat = true;
+}
+
+void WW8FFData::addListboxEntry(const ::rtl::OUString & rEntry)
+{
+ mbListBox = true;
+ msListEntries.push_back(rEntry);
+}
+
+void WW8FFData::WriteOUString(SvStream * pDataStrm, const ::rtl::OUString & rStr,
+ bool bAddZero)
+{
+ sal_uInt16 nStrLen = msword_cast<sal_uInt16>(rStr.getLength());
+ *pDataStrm << nStrLen;
+ SwWW8Writer::WriteString16(*pDataStrm, rStr, bAddZero);
+}
+
+void WW8FFData::Write(SvStream * pDataStrm)
+{
+ sal_uLong nDataStt = pDataStrm->Tell();
+
+ static const sal_uInt8 aHeader[] =
+ {
+ 0,0,0,0, // len of struct
+ 0x44,0, // the start of "next" data
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // PIC
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0
+ };
+
+ pDataStrm->Write( aHeader, sizeof(aHeader) );
+
+ sal_uInt8 aData[10] = {
+ 0xff, 0xff, 0xff, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+ };
+
+ aData[4] = mnType | (mnResult << 2);
+
+ if (mbOwnHelp)
+ aData[4] |= (1 << 7);
+
+ aData[5] = (mnTextType << 3);
+
+ if (mbOwnStat)
+ aData[5] |= 1;
+
+ if (mbProtected)
+ aData[5] |= (1 << 1);
+
+ if (mbSize)
+ aData[5] |= (1 << 2);
+
+ if (mbRecalc)
+ aData[5] |= (1 << 6);
+
+ if (mbListBox)
+ aData[5] |= (1 << 7);
+
+ aData[6] = ::sal::static_int_cast<sal_uInt8>(mnMaxLen & 0xffff);
+ aData[7] = ::sal::static_int_cast<sal_uInt8>(mnMaxLen >> 8);
+ aData[8] = ::sal::static_int_cast<sal_uInt8>(mnCheckboxHeight & 0xffff);
+ aData[9] = ::sal::static_int_cast<sal_uInt8>(mnCheckboxHeight >> 8);
+
+ pDataStrm->Write(aData, sizeof(aData));
+
+ WriteOUString(pDataStrm, msName, true);
+
+ if (mnType == 0)
+ WriteOUString(pDataStrm, msDefault, true);
+ else
+ *pDataStrm << mnDefault;
+
+ WriteOUString(pDataStrm, msFormat, true);
+ WriteOUString(pDataStrm, msHelp, true);
+ WriteOUString(pDataStrm, msStatus, true);
+ WriteOUString(pDataStrm, msMacroEnter, true);
+ WriteOUString(pDataStrm, msMacroExit, true);
+
+ if (mnType == 2)
+ {
+ sal_uInt8 aData1[2] = { 0xff, 0xff };
+ pDataStrm->Write(aData1, sizeof(aData1));
+
+ sal_uInt32 nListboxEntries = msListEntries.size();
+ *pDataStrm << nListboxEntries;
+
+ ::std::vector< ::rtl::OUString >::const_iterator aIt = msListEntries.begin();
+
+ while (aIt != msListEntries.end())
+ {
+ const ::rtl::OUString & rEntry = *aIt;
+ WriteOUString(pDataStrm, rEntry, false);
+
+ aIt++;
+ }
+ }
+
+ SwWW8Writer::WriteLong( *pDataStrm, nDataStt,
+ pDataStrm->Tell() - nDataStt );
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/WW8FFData.hxx b/sw/source/filter/ww8/WW8FFData.hxx
new file mode 100644
index 000000000000..fcb46d5ff987
--- /dev/null
+++ b/sw/source/filter/ww8/WW8FFData.hxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <vector>
+#include <rtl/ustring.hxx>
+
+class SvStream;
+
+namespace sw
+{
+
+class WW8FFData
+{
+private:
+ // offset 0x4
+ sal_uInt8 mnType; // :2 0x3
+ sal_uInt8 mnResult; // :5 0x7c
+ bool mbOwnHelp; // :1 0x80
+
+ // offset 5
+ bool mbOwnStat; // :1 0x01
+ bool mbProtected; // :1 0x02
+ bool mbSize; // :1 0x04
+ sal_uInt8 mnTextType; // :3 0x38
+ bool mbRecalc; // :1 0x4
+ bool mbListBox; // :1 0x80
+
+ // offset 6
+ sal_uInt16 mnMaxLen; // :15 0x7fff maximum length of text field, 0 <=> no limit
+
+ // offset 8
+ sal_uInt16 mnCheckboxHeight;
+
+ // offset 10 and beyond
+ ::rtl::OUString msName;
+ ::rtl::OUString msDefault; // only for type == 0
+ sal_uInt16 mnDefault; // only for type != 0
+ ::rtl::OUString msFormat;
+ ::rtl::OUString msHelp;
+ ::rtl::OUString msStatus;
+ ::rtl::OUString msMacroEnter;
+ ::rtl::OUString msMacroExit;
+
+ ::std::vector< ::rtl::OUString > msListEntries;
+
+protected:
+ void WriteOUString(SvStream * pStream, const ::rtl::OUString & rStr, bool bAddZero);
+
+public:
+ WW8FFData();
+ ~WW8FFData();
+
+ void setType(sal_uInt8 nType) { mnType = nType; }
+ sal_uInt8 getType() const { return mnType; }
+ void setResult(sal_uInt8 nResult) { mnResult = nResult; }
+ sal_uInt8 getResult() const { return mnResult; }
+ void setProptexted(bool bProtected) { mbProtected = bProtected; }
+ bool getProtected() const { return mbProtected; }
+ void setSize(bool bSize) { mbSize = bSize; }
+ bool getSize() const { return mbSize; }
+ void setTextType(sal_uInt8 nTextType) { mnTextType = nTextType; }
+ sal_uInt8 getTextType() const { return mnTextType; }
+ void setRecalc(bool bRecalc) { mbRecalc = bRecalc; }
+ bool getRecalc() const { return mbRecalc; }
+ void setListBox(bool bListBox) { mbListBox = bListBox; }
+ bool getListBox() const { return mbListBox; }
+ void setMaxLen(sal_uInt16 nMaxLen) { mnMaxLen = nMaxLen; }
+ sal_uInt16 getMaxLen() const { return mnMaxLen; }
+ void setCheckboxHeight(sal_uInt16 nCheckboxHeight) { mnCheckboxHeight = nCheckboxHeight; }
+ sal_uInt16 getCheckboxHeight() const { return mnCheckboxHeight; }
+ void setName(const ::rtl::OUString & rName) { msName = rName; }
+ const ::rtl::OUString & getName() const { return msName; }
+ void setDefaultString(const ::rtl::OUString & rDefault) { msDefault = rDefault; }
+ const ::rtl::OUString & getDefaultString() const { return msDefault; }
+ void setDefaultResult(sal_uInt16 nDefault) { mnDefault = nDefault; }
+ sal_uInt16 getDefaultResult() const { return mnDefault; }
+ void setFormat(const ::rtl::OUString & rFormat) { msFormat = rFormat; }
+ const ::rtl::OUString & getFormat() const { return msFormat; }
+ void setHelp(const ::rtl::OUString & rHelp);
+ const ::rtl::OUString getHelp() const { return msHelp; }
+ void setStatus(const ::rtl::OUString & rStatus);
+ const ::rtl::OUString & getStatus() const { return msStatus; }
+ void setMacroEnter(const ::rtl::OUString & rMacroEnter) { msMacroEnter = rMacroEnter; }
+ const ::rtl::OUString & getMacroEnter() const { return msMacroEnter; }
+ void setMacroExit(const ::rtl::OUString & rMacroExit) { msMacroExit = rMacroExit; }
+ const ::rtl::OUString & getMacroExit() const { return msMacroExit; }
+
+ void addListboxEntry(const ::rtl::OUString & rEntry);
+
+ void Write(SvStream * pDataStrm);
+};
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/WW8FibData.cxx b/sw/source/filter/ww8/WW8FibData.cxx
new file mode 100644
index 000000000000..5226f4b0d669
--- /dev/null
+++ b/sw/source/filter/ww8/WW8FibData.cxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "WW8FibData.hxx"
+
+namespace ww8
+{
+WW8FibData::WW8FibData()
+ : m_bReadOnlyRecommended(false),
+ m_bWriteReservation(false)
+{
+}
+
+WW8FibData::~WW8FibData()
+{
+}
+
+void WW8FibData::setReadOnlyRecommended(bool bReadOnlyRecommended)
+{
+ m_bReadOnlyRecommended = bReadOnlyRecommended;
+}
+
+void WW8FibData::setWriteReservation(bool bWriteReservation)
+{
+ m_bWriteReservation = bWriteReservation;
+}
+
+bool WW8FibData::getReadOnlyRecommended() const
+{
+ return m_bReadOnlyRecommended;
+}
+
+bool WW8FibData::getWriteReservation() const
+{
+ return m_bWriteReservation;
+}
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/WW8FibData.hxx b/sw/source/filter/ww8/WW8FibData.hxx
new file mode 100644
index 000000000000..b6a886be9886
--- /dev/null
+++ b/sw/source/filter/ww8/WW8FibData.hxx
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef INCLUDED_WW8_FIB_DATA_HXX
+#define INCLUDED_WW8_FIB_DATA_HXX
+#include <IDocumentExternalData.hxx>
+
+namespace ww8
+{
+class WW8FibData : public ::sw::ExternalData
+{
+ bool m_bReadOnlyRecommended;
+ bool m_bWriteReservation;
+
+public:
+ WW8FibData();
+ virtual ~WW8FibData();
+
+ void setReadOnlyRecommended(bool bReadOnlyRecommended);
+ void setWriteReservation(bool bWriteReservation);
+
+ bool getReadOnlyRecommended() const;
+ bool getWriteReservation() const;
+};
+}
+
+#endif // INCLUDED_WW8_FIB_DATA_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/WW8Sttbf.cxx b/sw/source/filter/ww8/WW8Sttbf.cxx
new file mode 100644
index 000000000000..3b411a9b4cc9
--- /dev/null
+++ b/sw/source/filter/ww8/WW8Sttbf.cxx
@@ -0,0 +1,125 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <iostream>
+#include <dbgoutsw.hxx>
+#include "WW8Sttbf.hxx"
+#include <cstdio>
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+namespace ww8
+{
+ WW8Struct::WW8Struct(SvStream& rSt, sal_uInt32 nPos, sal_uInt32 nSize)
+ : mn_offset(0), mn_size(nSize)
+ {
+ rSt.Seek(nPos);
+
+ mp_data.reset(new sal_uInt8[nSize]);
+ rSt.Read(mp_data.get(), nSize);
+ }
+
+ WW8Struct::WW8Struct(WW8Struct * pStruct, sal_uInt32 nPos, sal_uInt32 nSize)
+ : mp_data(pStruct->mp_data), mn_offset(pStruct->mn_offset + nPos),
+ mn_size(nSize)
+ {
+ }
+
+ WW8Struct::~WW8Struct()
+ {
+ }
+
+ sal_uInt8 WW8Struct::getU8(sal_uInt32 nOffset)
+ {
+ sal_uInt8 nResult = 0;
+
+ if (nOffset < mn_size)
+ {
+ nResult = mp_data[mn_offset + nOffset];
+ }
+
+ return nResult;
+ }
+
+ ::rtl::OUString WW8Struct::getUString(sal_uInt32 nOffset,
+ sal_uInt32 nCount)
+ {
+ ::rtl::OUString aResult;
+
+ if (nCount > 0)
+ {
+ rtl_uString * pNew = 0;
+ rtl_uString_newFromStr_WithLength
+ (&pNew, reinterpret_cast<const sal_Unicode *>(&mp_data[mn_offset + nOffset]),
+ nCount);
+
+ aResult = rtl::OUString(pNew);
+ }
+
+#ifdef DEBUG
+ char sBuffer[256];
+ snprintf(sBuffer, sizeof(sBuffer), "offset=\"%" SAL_PRIuUINT32 "\" count=\"%" SAL_PRIuUINT32 "\"",
+ nOffset, nCount);
+ ::std::clog << "<WW8Struct-getUString" << sBuffer << ">"
+ << dbg_out(aResult) << "</WW8Struct-getUString>"
+ << ::std::endl;
+#endif
+
+ return aResult;
+
+ }
+
+ ::rtl::OUString WW8Struct::getString(sal_uInt32 nOffset,
+ sal_uInt32 nCount)
+ {
+ ::rtl::OUString aResult;
+
+ if (nCount > 0)
+ {
+ ::rtl::OString aOStr(reinterpret_cast<const sal_Char *>(&mp_data[mn_offset + nOffset]),
+ nCount);
+ ::rtl::OUString aOUStr(rtl::OStringToOUString(aOStr, RTL_TEXTENCODING_ASCII_US));
+ aResult = rtl::OUString(aOUStr);
+ }
+
+#ifdef DEBUG
+ char sBuffer[256];
+ snprintf(sBuffer, sizeof(sBuffer), "offset=\"%" SAL_PRIuUINT32 "\" count=\"%" SAL_PRIuUINT32 "\"",
+ nOffset, nCount);
+ ::std::clog << "<WW8Struct-getString " << sBuffer << ">"
+ << dbg_out(aResult) << "</WW8Struct-getUString>"
+ << ::std::endl;
+#endif
+
+ return aResult;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/WW8Sttbf.hxx b/sw/source/filter/ww8/WW8Sttbf.hxx
new file mode 100644
index 000000000000..f4c2e6b08bf6
--- /dev/null
+++ b/sw/source/filter/ww8/WW8Sttbf.hxx
@@ -0,0 +1,147 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include <boost/shared_array.hpp>
+#include <tools/solar.h>
+#include <rtl/ustring.hxx>
+#include <tools/stream.hxx>
+#include <IDocumentExternalData.hxx>
+
+namespace ww8
+{
+ typedef boost::shared_array<sal_uInt8> DataArray_t;
+
+class WW8Struct : public ::sw::ExternalData
+ {
+ DataArray_t mp_data;
+ sal_uInt32 mn_offset;
+ sal_uInt32 mn_size;
+
+ public:
+ WW8Struct(SvStream& rSt, sal_uInt32 nPos, sal_uInt32 nSize);
+ WW8Struct(WW8Struct * pStruct, sal_uInt32 nPos, sal_uInt32 nSize);
+ virtual ~WW8Struct();
+
+ sal_uInt8 getU8(sal_uInt32 nOffset);
+
+ sal_uInt16 getU16(sal_uInt32 nOffset)
+ { return getU8(nOffset) + (getU8(nOffset + 1) << 8); }
+
+ sal_uInt32 getU32(sal_uInt32 nOffset)
+ { return getU16(nOffset) + (getU16(nOffset + 1) << 16); }
+
+ ::rtl::OUString getUString(sal_uInt32 nOffset, sal_uInt32 nCount);
+
+ ::rtl::OUString getString(sal_uInt32 nOffset, sal_uInt32 nCount);
+ };
+
+typedef ::std::vector<rtl::OUString> StringVector_t;
+ template <class T>
+ class WW8Sttb : public WW8Struct
+ {
+ typedef ::boost::shared_ptr< void > ExtraPointer_t;
+ typedef ::std::vector< ExtraPointer_t > ExtrasVector_t;
+ bool bDoubleByteCharacters;
+ StringVector_t m_Strings;
+ ExtrasVector_t m_Extras;
+
+ public:
+ WW8Sttb(SvStream& rSt, sal_Int32 nPos, sal_uInt32 nSize);
+ virtual ~WW8Sttb();
+
+ sal_uInt32 getCount() const;
+ ::rtl::OUString getEntry(sal_uInt32 nEntry) const
+ {
+ return m_Strings[nEntry];
+ }
+
+ StringVector_t & getStrings()
+ {
+ return m_Strings;
+ }
+
+ const T * getExtra(sal_uInt32 nEntry) const
+ {
+ return dynamic_cast<const T *> (m_Extras[nEntry].get());
+ }
+ };
+
+ template <class T>
+ WW8Sttb<T>::WW8Sttb(SvStream& rSt, sal_Int32 nPos, sal_uInt32 nSize)
+ : WW8Struct(rSt, nPos, nSize), bDoubleByteCharacters(false)
+ {
+ sal_uInt32 nOffset = 0;
+
+ if (getU16(nOffset) == 0xffff)
+ {
+ bDoubleByteCharacters = true;
+ nOffset += 2;
+ }
+
+ sal_uInt16 nCount = getU16(nOffset);
+ sal_uInt16 ncbExtra = getU16(nOffset + 2);
+
+ nOffset += 4;
+ for (sal_uInt16 i = 0; i < nCount; i++)
+ {
+ if (bDoubleByteCharacters)
+ {
+ sal_uInt16 nStrLen = getU16(nOffset);
+
+ m_Strings.push_back(getUString(nOffset +2, nStrLen));
+
+ nOffset += 2 + 2 * nStrLen;
+ }
+ else
+ {
+ sal_uInt8 nStrLen = getU8(nOffset);
+
+ m_Strings.push_back(getUString(nOffset, nStrLen));
+
+ nOffset += 1 + nStrLen;
+ }
+
+ if (ncbExtra > 0)
+ {
+ ExtraPointer_t pExtra(new T(this, nOffset, ncbExtra));
+ m_Extras.push_back(pExtra);
+
+ nOffset += ncbExtra;
+ }
+ }
+ }
+
+ template <class T>
+ WW8Sttb<T>::~WW8Sttb()
+ {
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/WW8TableInfo.cxx b/sw/source/filter/ww8/WW8TableInfo.cxx
new file mode 100644
index 000000000000..665a73f2721f
--- /dev/null
+++ b/sw/source/filter/ww8/WW8TableInfo.cxx
@@ -0,0 +1,1514 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <iostream>
+#include <set>
+#include <stdio.h>
+#include "WW8TableInfo.hxx"
+#include "fmtfsize.hxx"
+#include "attributeoutputbase.hxx"
+#include "swtable.hxx"
+#include "frmfmt.hxx"
+#include "pam.hxx"
+#include "ndtxt.hxx"
+#include "dbgoutsw.hxx"
+
+namespace ww8
+{
+
+// WW8TableNodeInfoInner
+
+WW8TableNodeInfoInner::WW8TableNodeInfoInner(WW8TableNodeInfo * pParent)
+: mpParent(pParent)
+, mnCell(0)
+, mnRow(0)
+, mnShadowsBefore(0)
+, mnShadowsAfter(0)
+, mbEndOfLine(false)
+, mbEndOfCell(false)
+, mbFirstInTable(false)
+, mbVertMerge(false)
+, mpTableBox(NULL)
+, mpTable(NULL)
+{
+}
+
+WW8TableNodeInfoInner::~WW8TableNodeInfoInner()
+{
+}
+
+void WW8TableNodeInfoInner::setDepth(sal_uInt32 nDepth)
+{
+ mnDepth = nDepth;
+}
+
+void WW8TableNodeInfoInner::setCell(sal_uInt32 nCell)
+{
+ mnCell = nCell;
+}
+
+void WW8TableNodeInfoInner::setRow(sal_uInt32 nRow)
+{
+ mnRow = nRow;
+}
+
+void WW8TableNodeInfoInner::setShadowsBefore(sal_uInt32 nShadowsBefore)
+{
+ mnShadowsBefore = nShadowsBefore;
+}
+
+void WW8TableNodeInfoInner::setShadowsAfter(sal_uInt32 nShadowsAfter)
+{
+ mnShadowsAfter = nShadowsAfter;
+}
+
+void WW8TableNodeInfoInner::setEndOfLine(bool bEndOfLine)
+{
+ mbEndOfLine = bEndOfLine;
+}
+
+void WW8TableNodeInfoInner::setEndOfCell(bool bEndOfCell)
+{
+ mbEndOfCell = bEndOfCell;
+}
+
+void WW8TableNodeInfoInner::setFirstInTable(bool bFirstInTable)
+{
+ mbFirstInTable = bFirstInTable;
+}
+
+void WW8TableNodeInfoInner::setVertMerge(bool bVertMerge)
+
+{
+ mbVertMerge = bVertMerge;
+}
+
+void WW8TableNodeInfoInner::setTableBox(const SwTableBox * pTableBox)
+{
+ mpTableBox = pTableBox;
+}
+
+void WW8TableNodeInfoInner::setTable(const SwTable * pTable)
+{
+ mpTable = pTable;
+}
+
+void WW8TableNodeInfoInner::setRect(const SwRect & rRect)
+{
+ maRect = rRect;
+}
+
+sal_uInt32 WW8TableNodeInfoInner::getDepth() const
+{
+ return mnDepth;
+}
+
+sal_uInt32 WW8TableNodeInfoInner::getCell() const
+{
+ return mnCell;
+}
+
+sal_uInt32 WW8TableNodeInfoInner::getRow() const
+{
+ return mnRow;
+}
+
+sal_uInt32 WW8TableNodeInfoInner::getShadowsBefore() const
+{
+ return mnShadowsBefore;
+}
+
+sal_uInt32 WW8TableNodeInfoInner::getShadowsAfter() const
+{
+ return mnShadowsAfter;
+}
+
+bool WW8TableNodeInfoInner::isEndOfCell() const
+{
+ return mbEndOfCell;
+}
+
+bool WW8TableNodeInfoInner::isEndOfLine() const
+{
+ return mbEndOfLine;
+}
+
+bool WW8TableNodeInfoInner::isFirstInTable() const
+{
+ return mbFirstInTable;
+}
+
+const SwNode * WW8TableNodeInfoInner::getNode() const
+{
+ const SwNode * pResult = NULL;
+
+ if (mpParent != NULL)
+ pResult = mpParent->getNode();
+
+ return pResult;
+}
+
+TableBoxVectorPtr WW8TableNodeInfoInner::getTableBoxesOfRow()
+{
+ TableBoxVectorPtr pResult(new TableBoxVector);
+
+ WW8TableCellGrid::Pointer_t pCellGrid =
+ mpParent->getParent()->getCellGridForTable(getTable(), false);
+
+ if (pCellGrid.get() == NULL)
+ {
+ const SwTableLine * pTabLine = getTableBox()->GetUpper();
+ const SwTableBoxes & rTblBoxes = pTabLine->GetTabBoxes();
+
+ sal_uInt8 nBoxes = rTblBoxes.Count();
+ for ( sal_uInt8 n = 0; n < nBoxes; n++ )
+ {
+ pResult->push_back(rTblBoxes[n]);
+ }
+ }
+ else
+ pResult = pCellGrid->getTableBoxesOfRow(this);
+
+ return pResult;
+}
+
+GridColsPtr WW8TableNodeInfoInner::getGridColsOfRow(AttributeOutputBase & rBase)
+{
+ GridColsPtr pResult(new GridCols);
+ WidthsPtr pWidths(getWidthsOfRow());
+
+ const SwFrmFmt *pFmt = getTable()->GetFrmFmt();
+ OSL_ENSURE(pFmt,"Impossible");
+ if (!pFmt)
+ return pResult;
+
+ const SwFmtFrmSize &rSize = pFmt->GetFrmSize();
+ unsigned long nTblSz = static_cast<unsigned long>(rSize.GetWidth());
+
+ sal_uInt32 nPageSize = 0;
+ bool bRelBoxSize = false;
+
+ rBase.GetTablePageSize
+ ( this, nPageSize, bRelBoxSize );
+
+ SwTwips nSz = 0;
+ Widths::const_iterator aWidthsEnd = pWidths->end();
+ for ( Widths::const_iterator aIt = pWidths->begin();
+ aIt != aWidthsEnd;
+ ++aIt)
+ {
+ nSz += *aIt;
+ SwTwips nCalc = nSz;
+ if ( bRelBoxSize )
+ nCalc = ( nCalc * nPageSize ) / nTblSz;
+
+ pResult->push_back( nCalc );
+ }
+
+ return pResult;
+}
+
+WidthsPtr WW8TableNodeInfoInner::getWidthsOfRow()
+{
+ WidthsPtr pWidths;
+
+ WW8TableCellGrid::Pointer_t pCellGrid =
+ mpParent->getParent()->getCellGridForTable(getTable(), false);
+
+ if (pCellGrid.get() == NULL)
+ {
+ const SwTableBox * pTabBox = getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
+
+ pWidths = WidthsPtr(new Widths);
+ // number of cell written
+ sal_uInt32 nBoxes = rTabBoxes.Count();
+ for (sal_uInt32 n = 0; n < nBoxes; n++)
+ {
+ const SwFrmFmt* pBoxFmt = rTabBoxes[ n ]->GetFrmFmt();
+ const SwFmtFrmSize& rLSz = pBoxFmt->GetFrmSize();
+
+ pWidths->push_back(rLSz.GetWidth());
+ }
+ }
+ else
+ pWidths = pCellGrid->getWidthsOfRow(this);
+
+ return pWidths;
+}
+
+RowSpansPtr WW8TableNodeInfoInner::getRowSpansOfRow()
+{
+ RowSpansPtr pResult(new RowSpans);
+
+ WW8TableCellGrid::Pointer_t pCellGrid =
+ mpParent->getParent()->getCellGridForTable(getTable(), false);
+
+ if (pCellGrid.get() == NULL)
+ {
+ const SwTableBox * pTabBox = getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
+
+ sal_uInt32 nBoxes = rTabBoxes.Count();
+ for (sal_uInt32 n = 0; n < nBoxes; ++n)
+ {
+ pResult->push_back(rTabBoxes[n]->getRowSpan());
+ }
+ }
+ else
+ pResult = pCellGrid->getRowSpansOfRow(this);
+
+ return pResult;
+ }
+
+const SwTableBox * WW8TableNodeInfoInner::getTableBox() const
+{
+ return mpTableBox;
+}
+
+const SwTable * WW8TableNodeInfoInner::getTable() const
+{
+ return mpTable;
+}
+
+const SwRect & WW8TableNodeInfoInner::getRect() const
+{
+ return maRect;
+}
+
+string WW8TableNodeInfoInner::toString() const
+{
+ static char buffer[256];
+ snprintf(buffer, sizeof(buffer),
+ "<tableinner depth=\"%" SAL_PRIuUINT32 "\""
+ " cell=\"%" SAL_PRIuUINT32 "\""
+ " row=\"%" SAL_PRIuUINT32 "\""
+ " endOfCell=\"%s\""
+ " endOfLine=\"%s\""
+ " shadowsBefore=\"%" SAL_PRIuUINT32 "\""
+ " shadowsAfter=\"%" SAL_PRIuUINT32 "\""
+ " vertMerge=\"%s\"/>",
+ mnDepth, mnCell, mnRow,
+ mbEndOfCell ? "yes" : "no",
+ mbEndOfLine ? "yes" : "no",
+ mnShadowsBefore,
+ mnShadowsAfter,
+ mbVertMerge ? "yes" : "no");
+
+ return string(buffer);
+}
+// WW8TableTextNodeInfo
+
+WW8TableNodeInfo::WW8TableNodeInfo(WW8TableInfo * pParent,
+ const SwNode * pNode)
+: mpParent(pParent),
+ mnDepth(0),
+ mpNode(pNode),
+ mpNext(NULL),
+ mpNextNode(NULL)
+{
+}
+
+WW8TableNodeInfo::~WW8TableNodeInfo()
+{
+}
+
+::std::string WW8TableNodeInfo::toString() const
+{
+ static char buffer[1024];
+ snprintf(buffer, sizeof(buffer),
+ "<tableNodeInfo p=\"%p\" depth=\"%" SAL_PRIuUINT32 "\">"
+ ,this, getDepth());
+
+ ::std::string sResult(buffer);
+
+ Inners_t::const_iterator aIt(mInners.begin());
+ Inners_t::const_iterator aEnd(mInners.end());
+
+ while (aIt != aEnd)
+ {
+ WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
+ sResult += pInner->toString();
+
+ aIt++;
+ }
+#ifdef DEBUG
+ sResult += dbg_out(*mpNode);
+#endif
+ sResult += "</tableNodeInfo>";
+
+ return sResult;
+}
+void WW8TableNodeInfo::setDepth(sal_uInt32 nDepth)
+{
+ mnDepth = nDepth;
+
+ Inners_t::iterator aIt = mInners.find(mnDepth);
+
+ if (aIt == mInners.end())
+ mInners[mnDepth] = WW8TableNodeInfoInner::Pointer_t(new WW8TableNodeInfoInner(this));
+
+ mInners[mnDepth]->setDepth(mnDepth);
+}
+
+void WW8TableNodeInfo::setEndOfLine(bool bEndOfLine)
+{
+ WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
+ pInner->setEndOfLine(bEndOfLine);
+
+#ifdef DEBUG
+ ::std::clog << "<endOfLine depth=\"" << mnDepth << "\">"
+ << toString() << "</endOfLine>" << ::std::endl;
+#endif
+}
+
+void WW8TableNodeInfo::setEndOfCell(bool bEndOfCell)
+{
+ WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
+ pInner->setEndOfCell(bEndOfCell);
+
+#ifdef DEBUG
+ ::std::clog << "<endOfCell depth=\"" << mnDepth << "\">"
+ << toString() << "</endOfCell>" << ::std::endl;
+#endif
+}
+
+void WW8TableNodeInfo::setFirstInTable(bool bFirstInTable)
+{
+ WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
+
+ pInner->setFirstInTable(bFirstInTable);
+
+#ifdef DEBUG
+ ::std::clog << "<firstInTable depth=\"" << mnDepth << "\">"
+ << toString() << "</firstInTable>" << ::std::endl;
+#endif
+}
+
+void WW8TableNodeInfo::setVertMerge(bool bVertMerge)
+{
+ WW8TableNodeInfoInner::Pointer_t pInner = getInnerForDepth(mnDepth);
+
+ pInner->setVertMerge(bVertMerge);
+
+
+#ifdef DEBUG
+ ::std::clog << "<vertMerge depth=\"" << mnDepth << "\">"
+ << toString() << "</vertMerge>" << ::std::endl;
+#endif
+}
+
+void WW8TableNodeInfo::setTableBox(const SwTableBox * pTableBox)
+{
+ getInnerForDepth(mnDepth)->setTableBox(pTableBox);
+}
+
+void WW8TableNodeInfo::setTable(const SwTable * pTable)
+{
+ getInnerForDepth(mnDepth)->setTable(pTable);
+}
+
+void WW8TableNodeInfo::setNext(WW8TableNodeInfo * pNext)
+{
+ mpNext = pNext;
+
+#ifdef DEBUG
+ ::std::clog << "<setnext><from>" << toString() << "</from><to>"
+ << pNext->toString() << "</to></setnext>"
+ << ::std::endl;
+#endif
+}
+
+void WW8TableNodeInfo::setNextNode(const SwNode * pNode)
+{
+ mpNextNode = pNode;
+}
+
+void WW8TableNodeInfo::setRect(const SwRect & rRect)
+{
+ getInnerForDepth(mnDepth)->setRect(rRect);
+}
+
+void WW8TableNodeInfo::setCell(sal_uInt32 nCell)
+{
+ getInnerForDepth(mnDepth)->setCell(nCell);
+}
+
+void WW8TableNodeInfo::setRow(sal_uInt32 nRow)
+{
+ getInnerForDepth(mnDepth)->setRow(nRow);
+}
+
+void WW8TableNodeInfo::setShadowsBefore(sal_uInt32 nShadowsBefore)
+{
+ getInnerForDepth(mnDepth)->setShadowsBefore(nShadowsBefore);
+}
+
+void WW8TableNodeInfo::setShadowsAfter(sal_uInt32 nShadowsAfter)
+{
+ getInnerForDepth(mnDepth)->setShadowsAfter(nShadowsAfter);
+}
+
+WW8TableInfo * WW8TableNodeInfo::getParent() const
+{
+ return mpParent;
+}
+
+sal_uInt32 WW8TableNodeInfo::getDepth() const
+{
+ if (mInners.size() > 0)
+ return mInners.begin()->second->getDepth();
+
+ return mnDepth;
+}
+
+const SwNode * WW8TableNodeInfo::getNode() const
+{
+ return mpNode;
+}
+
+const SwTableBox * WW8TableNodeInfo::getTableBox() const
+{
+ return getInnerForDepth(mnDepth)->getTableBox();
+}
+
+const SwTable * WW8TableNodeInfo::getTable() const
+{
+ return getInnerForDepth(mnDepth)->getTable();
+}
+
+WW8TableNodeInfo * WW8TableNodeInfo::getNext() const
+{
+ return mpNext;
+}
+
+const SwNode * WW8TableNodeInfo::getNextNode() const
+{
+ return mpNextNode;
+}
+
+const SwRect & WW8TableNodeInfo::getRect() const
+{
+ return getInnerForDepth(mnDepth)->getRect();
+}
+
+bool WW8TableNodeInfo::isEndOfLine() const
+{
+ return getInnerForDepth(mnDepth)->isEndOfLine();
+}
+
+bool WW8TableNodeInfo::isEndOfCell() const
+{
+ return getInnerForDepth(mnDepth)->isEndOfCell();
+}
+
+sal_uInt32 WW8TableNodeInfo::getCell() const
+{
+ return getInnerForDepth(mnDepth)->getCell();
+}
+
+sal_uInt32 WW8TableNodeInfo::getRow() const
+{
+ return getInnerForDepth(mnDepth)->getRow();
+}
+
+const ww8::WW8TableNodeInfo::Inners_t & WW8TableNodeInfo::getInners() const
+{
+ return mInners;
+}
+
+const WW8TableNodeInfoInner::Pointer_t WW8TableNodeInfo::getFirstInner() const
+{
+ WW8TableNodeInfoInner::Pointer_t pResult;
+
+ if (mInners.size() > 0)
+ pResult = mInners.begin()->second;
+
+ return pResult;
+}
+
+const WW8TableNodeInfoInner::Pointer_t WW8TableNodeInfo::getInnerForDepth(sal_uInt32 nDepth) const
+{
+ WW8TableNodeInfoInner::Pointer_t pResult;
+
+ Inners_t::const_iterator aIt = mInners.find(nDepth);
+ if (aIt != mInners.end())
+ {
+ pResult = aIt->second;
+ }
+
+ return pResult;
+}
+
+// WW8TableInfo
+
+WW8TableInfo::WW8TableInfo()
+{
+}
+
+WW8TableInfo::~WW8TableInfo()
+{
+}
+
+WW8TableNodeInfo *
+WW8TableInfo::processSwTableByLayout(const SwTable * pTable)
+{
+ SwTableCellInfo aTableCellInfo(pTable);
+ WW8TableNodeInfo * pPrev = NULL;
+
+ while (aTableCellInfo.getNext())
+ {
+ SwRect aRect = aTableCellInfo.getRect();
+
+#ifdef DEBUG
+ static char sBuffer[1024];
+ ::std::clog << "<CellFrm>" << ::std::endl;
+
+ snprintf(sBuffer, sizeof(sBuffer),
+ "<rect top=\"%ld\" bottom=\"%ld\" left=\"%ld\" right=\"%ld\"/>",
+ aRect.Top(), aRect.Bottom(), aRect.Left(), aRect.Right());
+ ::std::clog << sBuffer << ::std::endl;
+#endif
+ const SwTableBox * pTableBox = aTableCellInfo.getTableBox();
+ const SwStartNode * pSttNd = pTableBox->GetSttNd();
+
+ if (pSttNd != NULL)
+ {
+ SwPaM aPam(*pSttNd, 0);
+
+ bool bDone = false;
+ do
+ {
+ SwNode & rNode = aPam.GetPoint()->nNode.GetNode();
+
+ insertTableNodeInfo(&rNode, pTable, pTableBox, 0, 0, 1, & aRect);
+
+ if (rNode.IsEndNode())
+ {
+ SwEndNode * pEndNode = rNode.GetEndNode();
+ SwStartNode * pTmpSttNd = pEndNode->StartOfSectionNode();
+
+ if (pTmpSttNd == pSttNd)
+ bDone = true;
+ }
+
+ aPam.GetPoint()->nNode++;
+ }
+ while (!bDone);
+ }
+
+#ifdef DEBUG
+ ::std::clog << "</CellFrm>" << ::std::endl;
+#endif
+ }
+
+ pPrev = reorderByLayout(pTable);
+
+ return pPrev;
+}
+
+void WW8TableInfo::processSwTable(const SwTable * pTable)
+{
+#ifdef DEBUG
+ ::std::clog << "<processSwTable>" << ::std::endl;
+#endif
+
+ WW8TableNodeInfo * pPrev = NULL;
+
+ SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
+ if (pFrmFmt != NULL && pTable->IsTblComplex())
+ {
+ pPrev = processSwTableByLayout(pTable);
+
+#ifdef DEBUG
+ WW8TableCellGrid::Pointer_t pCellGrid(getCellGridForTable(pTable));
+ ::std::clog << pCellGrid->toString() << ::std::endl;
+#endif
+ }
+ else
+ {
+ const SwTableLines & rLines = pTable->GetTabLines();
+
+ for (sal_uInt16 n = 0; n < rLines.Count(); n++)
+ {
+ const SwTableLine * pLine = rLines[n];
+
+ pPrev = processTableLine(pTable, pLine, n, 1, pPrev);
+ }
+
+ }
+
+ if (pPrev != NULL)
+ {
+ SwTableNode * pTableNode = pTable->GetTableNode();
+ SwEndNode * pEndNode = pTableNode->EndOfSectionNode();
+
+ pPrev->setNextNode(pEndNode);
+ }
+#ifdef DEBUG
+ ::std::clog << "</processSwTable>" << ::std::endl;
+#endif
+}
+
+WW8TableNodeInfo *
+WW8TableInfo::processTableLine(const SwTable * pTable,
+ const SwTableLine * pTableLine,
+ sal_uInt32 nRow,
+ sal_uInt32 nDepth, WW8TableNodeInfo * pPrev)
+{
+#ifdef DEBUG
+ ::std::clog << "<processTableLine row=\"" << nRow << "\" depth=\""
+ << nDepth << "\">" << ::std::endl;
+#endif
+
+ const SwTableBoxes & rBoxes = pTableLine->GetTabBoxes();
+
+ WW8TableNodeInfo::Pointer_t pTextNodeInfo;
+
+ for (sal_uInt16 n = 0; n < rBoxes.Count(); n++)
+ {
+ const SwTableBox * pBox = rBoxes[n];
+
+ pPrev = processTableBox(pTable, pBox, nRow, n, nDepth, n == rBoxes.Count() - 1, pPrev);
+ }
+
+#ifdef DEBUG
+ ::std::clog << "</processTableLine>" << ::std::endl;
+#endif
+
+ return pPrev;
+}
+
+WW8TableNodeInfo::Pointer_t
+WW8TableInfo::processTableBoxLines(const SwTableBox * pBox,
+ const SwTable * pTable,
+ const SwTableBox * pBoxToSet,
+ sal_uInt32 nRow,
+ sal_uInt32 nCell,
+ sal_uInt32 nDepth)
+{
+#ifdef DEBUG
+ ::std::clog << "<processTableBoxLines depth=\"" << nDepth
+ << "\" row=\"" << nRow << "\" cell=\"" << nCell << "\">" << ::std::endl;
+#endif
+
+ const SwTableLines & rLines = pBox->GetTabLines();
+ WW8TableNodeInfo::Pointer_t pNodeInfo;
+
+ if (rLines.Count() > 0)
+ {
+ for (sal_uInt32 n = 0; n < rLines.Count(); n++)
+ {
+ const SwTableLine * pLine = rLines[n];
+ const SwTableBoxes & rBoxes = pLine->GetTabBoxes();
+
+ for (sal_uInt16 nBox = 0; nBox < rBoxes.Count(); nBox++)
+ pNodeInfo = processTableBoxLines(rBoxes[nBox], pTable, pBoxToSet, nRow, nCell, nDepth);
+ }
+ }
+ else
+ {
+ const SwStartNode * pSttNd = pBox->GetSttNd();
+ const SwEndNode * pEndNd = pSttNd->EndOfSectionNode();
+ SwPaM aPaM(*pSttNd, 0);
+ SwPaM aEndPaM(*pEndNd, 0);
+
+ bool bDone = false;
+ while (!bDone)
+ {
+ SwNode & rNode = aPaM.GetPoint()->nNode.GetNode();
+
+ pNodeInfo = insertTableNodeInfo(&rNode, pTable, pBoxToSet, nRow, nCell, nDepth);
+
+ if (aPaM.GetPoint()->nNode == aEndPaM.GetPoint()->nNode)
+ bDone = true;
+ else
+ aPaM.GetPoint()->nNode++;
+ }
+ }
+
+#ifdef DEBUG
+ ::std::clog << "</processTableBoxLines>" << ::std::endl;
+#endif
+
+ return pNodeInfo;
+}
+
+WW8TableNodeInfo *
+WW8TableInfo::processTableBox(const SwTable * pTable,
+ const SwTableBox * pBox,
+ sal_uInt32 nRow,
+ sal_uInt32 nCell,
+ sal_uInt32 nDepth,
+ bool bEndOfLine,
+ WW8TableNodeInfo * pPrev)
+{
+#ifdef DEBUG
+ ::std::clog << "<processTableBox row=\"" << nRow << "\" cell=\"" << nCell
+ << "\" depth=\"" << nDepth << "\">" << ::std::endl;
+#endif
+
+ WW8TableNodeInfo::Pointer_t pNodeInfo;
+ const SwTableLines & rLines = pBox->GetTabLines();
+ const SwStartNode * pSttNd = pBox->GetSttNd();
+ WW8TableNodeInfo::Pointer_t pEndOfCellInfo;
+
+ if (rLines.Count() > 0)
+ {
+ pNodeInfo = processTableBoxLines(pBox, pTable, pBox, nRow, nCell, nDepth);
+ pNodeInfo->setEndOfCell(true);
+ if (bEndOfLine)
+ pNodeInfo->setEndOfLine(true);
+
+ for (sal_uInt32 n = 0; n < rLines.Count(); n++)
+ {
+ const SwTableLine * pLine = rLines[n];
+
+ pPrev = processTableLine(pTable, pLine, n, 1, pPrev);
+ }
+ }
+ else
+ {
+ SwPaM aPaM(*pSttNd, 0);
+
+ bool bDone = false;
+ sal_uInt32 nDepthInsideCell = 0;
+
+ do
+ {
+ SwNode & rNode = aPaM.GetPoint()->nNode.GetNode();
+
+ if (rNode.IsStartNode())
+ {
+ if (nDepthInsideCell > 0)
+ pEndOfCellInfo.reset();
+
+ nDepthInsideCell++;
+ }
+
+ pNodeInfo = insertTableNodeInfo(&rNode, pTable, pBox, nRow, nCell, nDepth);
+
+ if (pPrev != NULL)
+ pPrev->setNext(pNodeInfo.get());
+
+ pPrev = pNodeInfo.get();
+
+ if (nDepthInsideCell == 1 && rNode.IsTxtNode())
+ pEndOfCellInfo = pNodeInfo;
+
+ if (rNode.IsEndNode())
+ {
+ nDepthInsideCell--;
+
+ if (nDepthInsideCell == 0 && pEndOfCellInfo.get() == NULL)
+ pEndOfCellInfo = pNodeInfo;
+
+ SwEndNode * pEndNode = rNode.GetEndNode( );
+ SwStartNode * pTmpSttNd = pEndNode->StartOfSectionNode();
+ if (pTmpSttNd == pSttNd)
+ bDone = true;
+ }
+
+ aPaM.GetPoint()->nNode++;
+ }
+ while (!bDone);
+
+ if (pEndOfCellInfo.get() != NULL)
+ {
+ pEndOfCellInfo->setEndOfCell(true);
+
+ if (bEndOfLine)
+ pEndOfCellInfo->setEndOfLine(true);
+ }
+ }
+
+#ifdef DEBUG
+ ::std::clog << "</processTableBox>" << ::std::endl;
+#endif
+
+ return pPrev;
+}
+
+WW8TableNodeInfo::Pointer_t WW8TableInfo::insertTableNodeInfo
+(const SwNode * pNode,
+ const SwTable * pTable,
+ const SwTableBox * pTableBox,
+ sal_uInt32 nRow,
+ sal_uInt32 nCell,
+ sal_uInt32 nDepth,
+ SwRect * pRect)
+{
+ WW8TableNodeInfo::Pointer_t pNodeInfo = getTableNodeInfo(pNode);
+
+ if (pNodeInfo.get() == NULL)
+ {
+ pNodeInfo =
+ WW8TableNodeInfo::Pointer_t(new WW8TableNodeInfo(this, pNode));
+ mMap.insert(Map_t::value_type(pNode, pNodeInfo));
+ }
+
+ pNodeInfo->setDepth(nDepth + pNodeInfo->getDepth());
+
+ pNodeInfo->setTable(pTable);
+ pNodeInfo->setTableBox(pTableBox);
+
+ pNodeInfo->setCell(nCell);
+ pNodeInfo->setRow(nRow);
+
+ if (pNode->IsTxtNode())
+ {
+ FirstInTableMap_t::const_iterator aIt = mFirstInTableMap.find(pTable);
+ if (aIt == mFirstInTableMap.end())
+ {
+ mFirstInTableMap[pTable] = pNode;
+ pNodeInfo->setFirstInTable(true);
+ }
+ }
+
+ if (pRect)
+ {
+ WW8TableCellGrid::Pointer_t pCellGrid = getCellGridForTable(pTable);
+
+ pCellGrid->insert(*pRect, pNodeInfo.get());
+ pNodeInfo->setRect(*pRect);
+ }
+
+#ifdef DEBUG
+ ::std::clog << pNodeInfo->toString() << ::std::endl;
+#endif
+
+ return pNodeInfo;
+}
+
+WW8TableCellGrid::Pointer_t WW8TableInfo::getCellGridForTable
+(const SwTable * pTable, bool bCreate)
+{
+ WW8TableCellGrid::Pointer_t pResult;
+ CellGridMap_t::iterator aIt = mCellGridMap.find(pTable);
+
+ if (aIt == mCellGridMap.end())
+ {
+ if (bCreate)
+ {
+ pResult = WW8TableCellGrid::Pointer_t(new WW8TableCellGrid);
+ mCellGridMap[pTable] = pResult;
+ }
+ }
+ else
+ pResult = mCellGridMap[pTable];
+
+ return pResult;
+}
+
+WW8TableNodeInfo::Pointer_t WW8TableInfo::getTableNodeInfo
+(const SwNode * pNode)
+{
+ WW8TableNodeInfo::Pointer_t pResult;
+ Map_t::iterator aIt = mMap.find(pNode);
+
+ if (aIt != mMap.end())
+ pResult = (*aIt).second;
+
+ return pResult;
+}
+
+const SwNode * WW8TableInfo::getNextNode(const SwNode * pNode)
+{
+ const SwNode * pResult = NULL;
+
+ WW8TableNodeInfo::Pointer_t pNodeInfo = getTableNodeInfo(pNode);
+
+ if (pNodeInfo.get() != NULL)
+ {
+ WW8TableNodeInfo * pNextInfo = pNodeInfo->getNext();
+
+ if (pNextInfo != NULL)
+ pResult = pNextInfo->getNode();
+ else
+ {
+ const SwNode * pNextNode = pNodeInfo->getNextNode();
+
+ if (pNextNode != NULL)
+ pResult = pNextNode;
+ }
+ }
+
+ return pResult;
+}
+
+bool WW8TableNodeInfo::operator < (const WW8TableNodeInfo & rInfo) const
+{
+ bool bRet = false;
+
+ if (rInfo.mpNode != NULL)
+ {
+ if (mpNode == NULL)
+ {
+ bRet = true;
+ }
+ else
+ {
+ if (mpNode->GetIndex() < rInfo.mpNode->GetIndex())
+ bRet = true;
+ }
+ }
+
+ return bRet;
+}
+
+bool CellInfo::operator < (const CellInfo & aCellInfo) const
+{
+ bool aRet = false;
+
+ if (top() < aCellInfo.top())
+ aRet = true;
+ else if (top() == aCellInfo.top())
+ {
+ if (left() < aCellInfo.left())
+ aRet = true;
+ else if (left() == aCellInfo.left())
+ {
+ if (width() < aCellInfo.width())
+ aRet = true;
+ else if (width() == aCellInfo.width())
+ {
+ if (height() < aCellInfo.height())
+ aRet = true;
+ else if (height() == aCellInfo.height())
+ {
+ if (aCellInfo.getTableNodeInfo() != NULL)
+ {
+ if (m_pNodeInfo == NULL)
+ aRet = true;
+ else
+ {
+ aRet = *m_pNodeInfo < *aCellInfo.getTableNodeInfo();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return aRet;
+}
+
+::std::string CellInfo::toString() const
+{
+ static char sBuffer[256];
+
+ snprintf(sBuffer, sizeof(sBuffer),
+ "<cellinfo left=\"%ld\""
+ " right=\"%ld\""
+ " top=\"%ld\""
+ " bottom=\"%ld\""
+ " node=\"%p\"/>",
+ left(),
+ right(),
+ top(),
+ bottom(),
+ m_pNodeInfo);
+
+ return sBuffer;
+}
+
+WW8TableNodeInfo * WW8TableInfo::reorderByLayout(const SwTable * pTable)
+{
+ WW8TableNodeInfo * pPrev = NULL;
+ WW8TableCellGrid::Pointer_t pCellGrid = getCellGridForTable(pTable);
+
+#ifdef DEBUG
+ ::std::clog << pCellGrid->toString() << ::std::endl;
+#endif
+
+ pCellGrid->addShadowCells();
+ pPrev = pCellGrid->connectCells();
+
+ return pPrev;
+}
+
+WW8TableCellGrid::WW8TableCellGrid()
+{
+}
+
+WW8TableCellGrid::~WW8TableCellGrid()
+{
+}
+
+WW8TableCellGridRow::Pointer_t WW8TableCellGrid::getRow(long nTop, bool bCreate)
+{
+ WW8TableCellGridRow::Pointer_t pResult;
+
+ RowTops_t::iterator aIt = m_aRowTops.find(nTop);
+
+ if (aIt == m_aRowTops.end())
+ {
+ if (bCreate)
+ {
+ pResult = WW8TableCellGridRow::Pointer_t(new WW8TableCellGridRow);
+ m_aRows[nTop] = pResult;
+ m_aRowTops.insert(nTop);
+ }
+ }
+ else
+ pResult = m_aRows[nTop];
+
+ return pResult;
+}
+
+WW8TableCellGrid::RowTops_t::const_iterator WW8TableCellGrid::getRowTopsBegin() const
+{
+ return m_aRowTops.begin();
+}
+
+WW8TableCellGrid::RowTops_t::const_iterator WW8TableCellGrid::getRowTopsEnd() const
+{
+ return m_aRowTops.end();
+}
+
+CellInfoMultiSet::const_iterator WW8TableCellGrid::getCellsBegin(long nTop)
+{
+ return getRow(nTop)->begin();
+}
+
+CellInfoMultiSet::const_iterator WW8TableCellGrid::getCellsEnd(long nTop)
+{
+ return getRow(nTop)->end();
+}
+
+void WW8TableCellGrid::insert(const SwRect & rRect,
+ WW8TableNodeInfo * pNodeInfo,
+ unsigned long * pFmtFrmWidth)
+{
+ CellInfo aCellInfo(rRect, pNodeInfo);
+
+ if (pFmtFrmWidth != NULL)
+ aCellInfo.setFmtFrmWidth(*pFmtFrmWidth);
+
+ WW8TableCellGridRow::Pointer_t pRow = getRow(rRect.Top());
+ pRow->insert(aCellInfo);
+}
+
+void WW8TableCellGrid::addShadowCells()
+{
+#ifdef DEBUG
+ ::std::clog << "<addShadowCells>" << ::std::endl;
+#endif
+
+ RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
+
+ while (aTopsIt != getRowTopsEnd())
+ {
+#ifdef DEBUG
+ long nTop = *aTopsIt;
+ (void) nTop;
+#endif
+ CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
+ CellInfoMultiSet::const_iterator aCellEndIt = getCellsEnd(*aTopsIt);
+
+ RowSpansPtr pRowSpans(new RowSpans);
+
+ bool bBeginningOfCell = true;
+ bool bVertMerge = false;
+ SwRect aRect = aCellIt->getRect();
+ long nRowSpan = 1;
+ while (aCellIt != aCellEndIt)
+ {
+ WW8TableNodeInfo * pNodeInfo = aCellIt->getTableNodeInfo();
+
+ if (bBeginningOfCell)
+ {
+ RowTops_t::const_iterator aRowSpanIt(aTopsIt);
+ ++aRowSpanIt;
+
+ if (aRowSpanIt != getRowTopsEnd() &&
+ *aRowSpanIt < aCellIt->bottom())
+ {
+ aRect.Top(*aRowSpanIt);
+ unsigned long nFmtFrmWidth = aCellIt->getFmtFrmWidth();
+ insert(aRect, NULL, &nFmtFrmWidth);
+
+ bVertMerge = true;
+ }
+ else
+ bVertMerge = false;
+
+ nRowSpan = 1;
+ while (aRowSpanIt != getRowTopsEnd() &&
+ *aRowSpanIt < aCellIt->bottom())
+ {
+ ++aRowSpanIt;
+ nRowSpan++;
+ }
+
+ if (pNodeInfo != NULL)
+ pRowSpans->push_back(nRowSpan);
+ else
+ pRowSpans->push_back(-nRowSpan);
+ }
+
+ if (pNodeInfo != NULL)
+ {
+ pNodeInfo->setVertMerge(bVertMerge);
+ }
+
+ ++aCellIt;
+
+ bBeginningOfCell = (aRect.Left() != aCellIt->left());
+ aRect = aCellIt->getRect();
+ }
+
+ WW8TableCellGridRow::Pointer_t pRow = getRow(*aTopsIt);
+ if (pRow.get() != NULL)
+ pRow->setRowSpans(pRowSpans);
+
+ ++aTopsIt;
+ }
+#ifdef DEBUG
+ ::std::clog << "</addShadowCells>" << ::std::endl;
+#endif
+}
+
+WW8TableNodeInfo * WW8TableCellGrid::connectCells()
+{
+ RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
+ sal_uInt32 nRow = 0;
+ WW8TableNodeInfo * pLastNodeInfo = NULL;
+
+ while (aTopsIt != getRowTopsEnd())
+ {
+ CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
+ CellInfoMultiSet::const_iterator aCellEndIt = getCellsEnd(*aTopsIt);
+ GridColsPtr pWidths(new Widths);
+ TableBoxVectorPtr pTableBoxes(new TableBoxVector);
+
+ sal_uInt32 nShadows = 0;
+ sal_uInt32 nCell = 0;
+ bool bBeginningOfCell = true;
+ WW8TableNodeInfo * pEndOfCellInfo = NULL;
+ sal_uInt32 nDepthInCell = 0;
+ while (aCellIt != aCellEndIt)
+ {
+ long nCellX = aCellIt->left();
+ WW8TableNodeInfo * pNodeInfo = aCellIt->getTableNodeInfo();
+ if (pNodeInfo != NULL)
+ {
+ const SwNode * pNode = pNodeInfo->getNode();
+
+ if (pNode->IsStartNode())
+ {
+ nDepthInCell++;
+ pEndOfCellInfo = NULL;
+ }
+
+ if (nDepthInCell == 1 && pNode->IsTxtNode())
+ pEndOfCellInfo = pNodeInfo;
+
+ pNodeInfo->setShadowsBefore(nShadows);
+ pNodeInfo->setCell(nCell);
+ pNodeInfo->setRow(nRow);
+ if (pLastNodeInfo != NULL)
+ {
+ pLastNodeInfo->setNext(pNodeInfo);
+ pLastNodeInfo->setNextNode(pNode);
+ }
+ pLastNodeInfo = pNodeInfo;
+ nShadows = 0;
+
+ if (pNode->IsEndNode())
+ {
+ nDepthInCell--;
+
+ if (nDepthInCell == 0 && pEndOfCellInfo == NULL)
+ pEndOfCellInfo = pNodeInfo;
+ }
+ }
+ else
+ {
+ nShadows++;
+ }
+
+ if (bBeginningOfCell)
+ {
+ pWidths->push_back(aCellIt->getFmtFrmWidth());
+
+ if (pNodeInfo != NULL)
+ pTableBoxes->push_back(pNodeInfo->getTableBox());
+ else
+ pTableBoxes->push_back(NULL);
+ }
+
+ ++aCellIt;
+ bBeginningOfCell = false;
+
+ if (aCellIt != aCellEndIt && aCellIt->left() != nCellX)
+ {
+ nCell++;
+ bBeginningOfCell = true;
+
+ if (pEndOfCellInfo != NULL)
+ {
+ pEndOfCellInfo->setEndOfCell(true);
+ }
+
+ pEndOfCellInfo = NULL;
+ }
+ }
+
+ pLastNodeInfo->setShadowsAfter(nShadows);
+
+ if (pEndOfCellInfo == NULL)
+ {
+ pEndOfCellInfo = pLastNodeInfo;
+ }
+
+ pEndOfCellInfo->setEndOfCell(true);
+ pLastNodeInfo->setEndOfLine(true);
+
+ WW8TableCellGridRow::Pointer_t pRow(getRow(*aTopsIt));
+ pRow->setTableBoxVector(pTableBoxes);
+ pRow->setWidths(pWidths);
+
+ nShadows = 0;
+
+ ++aTopsIt;
+ nRow++;
+ }
+
+ return pLastNodeInfo;
+}
+
+string WW8TableCellGrid::toString()
+{
+ string sResult = "<WW8TableCellGrid>";
+
+ RowTops_t::const_iterator aTopsIt = getRowTopsBegin();
+ static char sBuffer[1024];
+ while (aTopsIt != getRowTopsEnd())
+ {
+ sprintf(sBuffer, "<row y=\"%ld\">", *aTopsIt);
+ sResult += sBuffer;
+
+ CellInfoMultiSet::const_iterator aCellIt = getCellsBegin(*aTopsIt);
+ CellInfoMultiSet::const_iterator aCellsEnd = getCellsEnd(*aTopsIt);
+
+ while (aCellIt != aCellsEnd)
+ {
+ snprintf(sBuffer, sizeof(sBuffer), "<cellInfo top=\"%ld\" bottom=\"%ld\" left=\"%ld\" right=\"%ld\">",
+ aCellIt->top(), aCellIt->bottom(), aCellIt->left(), aCellIt->right());
+ sResult += sBuffer;
+
+ WW8TableNodeInfo * pInfo = aCellIt->getTableNodeInfo();
+ if (pInfo != NULL)
+ sResult += pInfo->toString();
+ else
+ sResult += "<shadow/>\n";
+
+ sResult += "</cellInfo>\n";
+ ++aCellIt;
+ }
+
+ WW8TableCellGridRow::Pointer_t pRow = getRow(*aTopsIt);
+ WidthsPtr pWidths = pRow->getWidths();
+ if (pWidths != NULL)
+ {
+ sResult += "<widths>";
+
+ Widths::const_iterator aItEnd = pWidths->end();
+ for (Widths::const_iterator aIt = pWidths->begin();
+ aIt != aItEnd;
+ ++aIt)
+ {
+ if (aIt != pWidths->begin())
+ sResult += ", ";
+
+ snprintf(sBuffer, sizeof(sBuffer), "%" SAL_PRIxUINT32 "", *aIt);
+ sResult += sBuffer;
+ }
+
+ sResult += "</widths>";
+ }
+
+ RowSpansPtr pRowSpans = pRow->getRowSpans();
+ if (pRowSpans.get() != NULL)
+ {
+ sResult += "<rowspans>";
+
+ RowSpans::const_iterator aItEnd = pRowSpans->end();
+ for (RowSpans::const_iterator aIt = pRowSpans->begin();
+ aIt != aItEnd;
+ ++aIt)
+ {
+ if (aIt != pRowSpans->begin())
+ sResult += ", ";
+
+ snprintf(sBuffer, sizeof(sBuffer), "%" SAL_PRIxUINT32 "", *aIt);
+ sResult += sBuffer;
+ }
+
+ sResult += "</rowspans>";
+ }
+
+ sResult += "</row>\n";
+ ++aTopsIt;
+ }
+
+ sResult += "</WW8TableCellGrid>\n";
+
+ return sResult;
+}
+
+TableBoxVectorPtr WW8TableCellGrid::getTableBoxesOfRow
+(WW8TableNodeInfoInner * pNodeInfoInner)
+{
+ TableBoxVectorPtr pResult;
+ WW8TableCellGridRow::Pointer_t pRow =
+ getRow(pNodeInfoInner->getRect().Top(), false);
+
+ if (pRow.get() != NULL)
+ {
+ pResult = pRow->getTableBoxVector();
+ }
+
+ return pResult;
+}
+
+WidthsPtr WW8TableCellGrid::getWidthsOfRow
+(WW8TableNodeInfoInner * pNodeInfoInner)
+{
+ GridColsPtr pResult;
+
+ WW8TableCellGridRow::Pointer_t pRow =
+ getRow(pNodeInfoInner->getRect().Top(), false);
+
+ if (pRow.get() != NULL)
+ {
+ pResult = pRow->getWidths();
+ }
+
+ return pResult;
+}
+
+RowSpansPtr WW8TableCellGrid::getRowSpansOfRow
+(WW8TableNodeInfoInner * pNodeInfoInner)
+{
+ RowSpansPtr pResult;
+
+ WW8TableCellGridRow::Pointer_t pRow =
+ getRow(pNodeInfoInner->getRect().Top(), false);
+
+ if (pRow.get() != NULL)
+ {
+ pResult = pRow->getRowSpans();
+ }
+
+ return pResult;
+}
+
+WW8TableCellGridRow::WW8TableCellGridRow()
+: m_pCellInfos(new CellInfoMultiSet)
+{
+}
+
+WW8TableCellGridRow::~WW8TableCellGridRow()
+{
+}
+
+void WW8TableCellGridRow::insert(const CellInfo & rCellInfo)
+{
+ m_pCellInfos->insert(rCellInfo);
+
+#ifdef DEBUG
+ ::std::clog << "<gridRowInsert>"
+ << rCellInfo.toString()
+ << "</gridRowInsert>"
+ << ::std::endl;
+#endif
+}
+
+CellInfoMultiSet::const_iterator WW8TableCellGridRow::begin() const
+{
+ return m_pCellInfos->begin();
+}
+
+CellInfoMultiSet::const_iterator WW8TableCellGridRow::end() const
+{
+ return m_pCellInfos->end();
+}
+
+void WW8TableCellGridRow::setTableBoxVector(TableBoxVectorPtr pTableBoxVector)
+{
+ m_pTableBoxVector = pTableBoxVector;
+}
+
+void WW8TableCellGridRow::setWidths(WidthsPtr pWidths)
+{
+ m_pWidths = pWidths;
+}
+
+void WW8TableCellGridRow::setRowSpans(RowSpansPtr pRowSpans)
+{
+ m_pRowSpans = pRowSpans;
+}
+
+TableBoxVectorPtr WW8TableCellGridRow::getTableBoxVector() const
+{
+ return m_pTableBoxVector;
+}
+
+WidthsPtr WW8TableCellGridRow::getWidths() const
+{
+ return m_pWidths;
+}
+
+RowSpansPtr WW8TableCellGridRow::getRowSpans() const
+{
+ return m_pRowSpans;
+}
+
+CellInfo::CellInfo(const SwRect & aRect, WW8TableNodeInfo * pNodeInfo)
+: m_aRect(aRect), m_pNodeInfo(pNodeInfo), m_nFmtFrmWidth(0)
+{
+ if (pNodeInfo != NULL)
+ {
+ const SwTableBox * pBox = pNodeInfo->getTableBox();
+ const SwFrmFmt * pFrmFmt = pBox->GetFrmFmt();
+ const SwFmtFrmSize & rSize = pFrmFmt->GetFrmSize();
+
+ m_nFmtFrmWidth = rSize.GetWidth();
+ }
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/WW8TableInfo.hxx b/sw/source/filter/ww8/WW8TableInfo.hxx
new file mode 100644
index 000000000000..2ba703ab031f
--- /dev/null
+++ b/sw/source/filter/ww8/WW8TableInfo.hxx
@@ -0,0 +1,359 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef WW8_TABLE_INFO_HXX
+#define WW8_TABLE_INFO_HXX
+#include <boost/unordered_map.hpp>
+#include <string>
+#include <map>
+#include <set>
+#include <functional>
+#include <boost/shared_ptr.hpp>
+#include <vector>
+#include <sal/types.h>
+#include <swrect.hxx>
+
+class SwTable;
+class SwTableLine;
+class SwTableBox;
+class SwNode;
+class SwWW8Writer;
+class AttributeOutputBase;
+
+namespace ww8
+{
+using namespace ::std;
+
+class WW8TableNodeInfo;
+typedef boost::shared_ptr<SwRect> SwRectPtr;
+typedef ::std::vector<const SwTableBox *> TableBoxVector;
+typedef boost::shared_ptr<TableBoxVector> TableBoxVectorPtr;
+typedef ::std::vector<sal_uInt32> GridCols;
+typedef boost::shared_ptr<GridCols> GridColsPtr;
+typedef ::std::vector<sal_uInt32> RowSpans;
+typedef boost::shared_ptr<RowSpans> RowSpansPtr;
+typedef ::std::vector<sal_uInt32> Widths;
+typedef boost::shared_ptr<Widths> WidthsPtr;
+
+class WW8TableNodeInfoInner
+{
+ WW8TableNodeInfo * mpParent;
+ sal_uInt32 mnDepth;
+ sal_uInt32 mnCell;
+ sal_uInt32 mnRow;
+ sal_uInt32 mnShadowsBefore;
+ sal_uInt32 mnShadowsAfter;
+ bool mbEndOfLine;
+ bool mbEndOfCell;
+ bool mbFirstInTable;
+ bool mbVertMerge;
+ const SwTableBox * mpTableBox;
+ const SwTable * mpTable;
+ SwRect maRect;
+
+public:
+ typedef boost::shared_ptr<WW8TableNodeInfoInner> Pointer_t;
+
+ WW8TableNodeInfoInner(WW8TableNodeInfo * pParent);
+ ~WW8TableNodeInfoInner();
+
+ void setDepth(sal_uInt32 nDepth);
+ void setCell(sal_uInt32 nCell);
+ void setRow(sal_uInt32 nRow);
+ void setShadowsBefore(sal_uInt32 nShadowsBefore);
+ void setShadowsAfter(sal_uInt32 nShadowsAfter);
+ void setEndOfLine(bool bEndOfLine);
+ void setEndOfCell(bool bEndOfCell);
+ void setFirstInTable(bool bFirstInTable);
+ void setVertMerge(bool bVertMErge);
+ void setTableBox(const SwTableBox * pTableBox);
+ void setTable(const SwTable * pTable);
+ void setRect(const SwRect & rRect);
+
+ sal_uInt32 getDepth() const;
+ sal_uInt32 getCell() const;
+ sal_uInt32 getRow() const;
+ sal_uInt32 getShadowsBefore() const;
+ sal_uInt32 getShadowsAfter() const;
+ bool isEndOfCell() const;
+ bool isEndOfLine() const;
+ bool isFirstInTable() const;
+ bool isVertMerge() const;
+ const SwTableBox * getTableBox() const;
+ const SwTable * getTable() const;
+ const SwRect & getRect() const;
+
+ const SwNode * getNode() const;
+
+ TableBoxVectorPtr getTableBoxesOfRow();
+ WidthsPtr getWidthsOfRow();
+ GridColsPtr getGridColsOfRow(AttributeOutputBase & rBase);
+ RowSpansPtr getRowSpansOfRow();
+
+ string toString() const;
+};
+
+class CellInfo;
+typedef ::std::multiset<CellInfo, less<CellInfo> > CellInfoMultiSet;
+typedef boost::shared_ptr<CellInfoMultiSet> CellInfoMultiSetPtr;
+
+class WW8TableInfo;
+class WW8TableNodeInfo
+{
+public:
+ typedef map<sal_uInt32, WW8TableNodeInfoInner::Pointer_t,
+ greater<sal_uInt32> > Inners_t;
+
+private:
+ WW8TableInfo * mpParent;
+ sal_uInt32 mnDepth;
+ const SwNode * mpNode;
+ Inners_t mInners;
+ WW8TableNodeInfo * mpNext;
+ const SwNode * mpNextNode;
+
+public:
+ typedef boost::shared_ptr<WW8TableNodeInfo> Pointer_t;
+
+ WW8TableNodeInfo(WW8TableInfo * pParent, const SwNode * pTxtNode);
+ virtual ~WW8TableNodeInfo();
+
+ void setDepth(sal_uInt32 nDepth);
+ void setEndOfLine(bool bEndOfLine);
+ void setEndOfCell(bool bEndOfCell);
+ void setFirstInTable(bool bFirstInTable);
+ void setVertMerge(bool bVertMerge);
+ void setTableBox(const SwTableBox *pTableBox);
+ void setTable(const SwTable * pTable);
+ void setCell(sal_uInt32 nCell);
+ void setRow(sal_uInt32 nRow);
+ void setShadowsBefore(sal_uInt32 nShadowsBefore);
+ void setShadowsAfter(sal_uInt32 nShadowsAfter);
+ void setNext(WW8TableNodeInfo * pNext);
+ void setNextNode(const SwNode * pNode);
+ void setRect(const SwRect & rRect);
+
+ WW8TableInfo * getParent() const;
+ sal_uInt32 getDepth() const;
+ bool isEndOfLine() const;
+ bool isEndOfCell() const;
+ bool isFirstInTable() const;
+ const SwNode * getNode() const;
+ const SwTableBox * getTableBox() const;
+ const SwTable * getTable() const;
+ WW8TableNodeInfo * getNext() const;
+ const SwNode * getNextNode() const;
+ const SwRect & getRect() const;
+
+ const Inners_t & getInners() const;
+ const WW8TableNodeInfoInner::Pointer_t getFirstInner() const;
+ const WW8TableNodeInfoInner::Pointer_t getInnerForDepth(sal_uInt32 nDepth) const;
+
+ sal_uInt32 getCell() const;
+ sal_uInt32 getRow() const;
+
+ ::std::string toString() const;
+
+ bool operator < (const WW8TableNodeInfo & rInfo) const;
+};
+
+struct hashNode
+{
+ size_t operator()(const SwNode * pNode) const
+ { return reinterpret_cast<size_t>(pNode); }
+};
+
+struct hashTable
+{
+ size_t operator()(const SwTable * pTable) const
+ { return reinterpret_cast<size_t>(pTable); }
+};
+
+class WW8TableCellGridRow
+{
+ CellInfoMultiSetPtr m_pCellInfos;
+ TableBoxVectorPtr m_pTableBoxVector;
+ WidthsPtr m_pWidths;
+ RowSpansPtr m_pRowSpans;
+
+public:
+ typedef boost::shared_ptr<WW8TableCellGridRow> Pointer_t;
+ WW8TableCellGridRow();
+ ~WW8TableCellGridRow();
+
+ void insert(const CellInfo & rCellInfo);
+ CellInfoMultiSet::const_iterator begin() const;
+ CellInfoMultiSet::const_iterator end() const;
+
+ void setTableBoxVector(TableBoxVectorPtr pTableBoxVector);
+ void setWidths(WidthsPtr pGridCols);
+ void setRowSpans(RowSpansPtr pRowSpans);
+
+ TableBoxVectorPtr getTableBoxVector() const;
+ WidthsPtr getWidths() const;
+ RowSpansPtr getRowSpans() const;
+};
+
+class WW8TableCellGrid
+{
+ typedef ::std::set<long> RowTops_t;
+ typedef ::std::map<long, WW8TableCellGridRow::Pointer_t> Rows_t;
+
+ RowTops_t m_aRowTops;
+ Rows_t m_aRows;
+
+ WW8TableCellGridRow::Pointer_t getRow(long nTop, bool bCreate = true);
+ RowTops_t::const_iterator getRowTopsBegin() const;
+ RowTops_t::const_iterator getRowTopsEnd() const;
+ CellInfoMultiSet::const_iterator getCellsBegin(long nTop);
+ CellInfoMultiSet::const_iterator getCellsEnd(long nTop);
+
+public:
+ typedef ::boost::shared_ptr<WW8TableCellGrid> Pointer_t;
+
+ WW8TableCellGrid();
+ ~WW8TableCellGrid();
+
+ void insert(const SwRect & rRect, WW8TableNodeInfo * pNodeInfo,
+ unsigned long * pFmtFrmWidth = NULL);
+ void addShadowCells();
+ WW8TableNodeInfo * connectCells();
+
+ string toString();
+
+ TableBoxVectorPtr getTableBoxesOfRow(WW8TableNodeInfoInner * pNodeInfo);
+ WidthsPtr getWidthsOfRow(WW8TableNodeInfoInner * pNodeInfo);
+ RowSpansPtr getRowSpansOfRow(WW8TableNodeInfoInner * pNodeInfo);
+};
+
+class WW8TableInfo
+{
+ friend class WW8TableNodeInfoInner;
+ typedef boost::unordered_map<const SwNode *, WW8TableNodeInfo::Pointer_t, hashNode > Map_t;
+ Map_t mMap;
+
+ typedef boost::unordered_map<const SwTable *, WW8TableCellGrid::Pointer_t, hashTable > CellGridMap_t;
+ CellGridMap_t mCellGridMap;
+
+ typedef boost::unordered_map<const SwTable *, const SwNode *, hashTable > FirstInTableMap_t;
+ FirstInTableMap_t mFirstInTableMap;
+
+ WW8TableNodeInfo *
+ processTableLine(const SwTable * pTable,
+ const SwTableLine * pTableLine,
+ sal_uInt32 nRow,
+ sal_uInt32 nDepth, WW8TableNodeInfo * pPrev);
+
+ WW8TableNodeInfo *
+ processTableBox(const SwTable * pTable,
+ const SwTableBox * pTableBox,
+ sal_uInt32 nRow,
+ sal_uInt32 nCell,
+ sal_uInt32 nDepth, bool bEndOfLine, WW8TableNodeInfo * pPrev);
+
+ WW8TableNodeInfo::Pointer_t
+ processTableBoxLines(const SwTableBox * pBox,
+ const SwTable * pTable,
+ const SwTableBox * pBoxToSet,
+ sal_uInt32 nRow,
+ sal_uInt32 nCell,
+ sal_uInt32 nDepth);
+
+ WW8TableNodeInfo::Pointer_t
+ insertTableNodeInfo(const SwNode * pNode,
+ const SwTable * pTable,
+ const SwTableBox * pTableBox,
+ sal_uInt32 nRow,
+ sal_uInt32 nCell,
+ sal_uInt32 nDepth,
+ SwRect * pRect = NULL);
+
+ WW8TableCellGrid::Pointer_t getCellGridForTable(const SwTable * pTable,
+ bool bCreate = true);
+
+public:
+ typedef boost::shared_ptr<WW8TableInfo> Pointer_t;
+
+ WW8TableInfo();
+ virtual ~WW8TableInfo();
+
+ void processSwTable(const SwTable * pTable);
+ WW8TableNodeInfo * processSwTableByLayout(const SwTable * pTable);
+ WW8TableNodeInfo::Pointer_t getTableNodeInfo(const SwNode * pNode);
+ const SwNode * getNextNode(const SwNode * pNode);
+ const WW8TableNodeInfo * getFirstTableNodeInfo() const;
+
+ WW8TableNodeInfo * reorderByLayout(const SwTable * pTable);
+};
+
+class CellInfo
+{
+ SwRect m_aRect;
+ WW8TableNodeInfo * m_pNodeInfo;
+ unsigned long m_nFmtFrmWidth;
+
+public:
+ CellInfo(const SwRect & aRect, WW8TableNodeInfo * pNodeInfo);
+
+ CellInfo(const CellInfo & aRectAndTableInfo)
+ : m_aRect(aRectAndTableInfo.m_aRect),
+ m_pNodeInfo(aRectAndTableInfo.m_pNodeInfo),
+ m_nFmtFrmWidth(aRectAndTableInfo.m_nFmtFrmWidth)
+ {
+ }
+
+ ~CellInfo() {}
+
+ bool operator < (const CellInfo & aCellInfo) const;
+
+ long top() const { return m_aRect.Top(); }
+ long bottom() const { return m_aRect.Bottom(); }
+ long left() const { return m_aRect.Left(); }
+ long right() const { return m_aRect.Right(); }
+ long width() const { return m_aRect.Width(); }
+ long height() const { return m_aRect.Height(); }
+ SwRect getRect() const { return m_aRect; }
+ WW8TableNodeInfo * getTableNodeInfo() const
+ { return m_pNodeInfo; }
+ unsigned long getFmtFrmWidth() const
+ {
+ return m_nFmtFrmWidth;
+ }
+
+ void setFmtFrmWidth(unsigned long nFmtFrmWidth)
+ {
+ m_nFmtFrmWidth = nFmtFrmWidth;
+ }
+
+ ::std::string toString() const;
+};
+
+}
+#endif // WW8_TABLE_INFO_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/attributeoutputbase.hxx b/sw/source/filter/ww8/attributeoutputbase.hxx
new file mode 100644
index 000000000000..25fc96566def
--- /dev/null
+++ b/sw/source/filter/ww8/attributeoutputbase.hxx
@@ -0,0 +1,591 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _ATTRIBUTEOUTPUTBASE_HXX_
+#define _ATTRIBUTEOUTPUTBASE_HXX_
+
+#include "fields.hxx"
+#include "WW8TableInfo.hxx"
+
+#include <rtl/textenc.h>
+#include <editeng/svxenum.hxx>
+#include <tools/solar.h>
+
+#include <swtypes.hxx>
+#include <wrtswtbl.hxx>
+#include <fldbas.hxx>
+
+#include <vector>
+
+class Point;
+class SvxCaseMapItem;
+class SvxColorItem;
+class SvxContourItem;
+class SvxCrossedOutItem;
+class SvxEscapementItem;
+class SvxFontItem;
+class SvxFontHeightItem;
+class SvxKerningItem;
+class SvxLanguageItem;
+class SvxPostureItem;
+class SvxShadowedItem;
+class SvxUnderlineItem;
+class SvxWeightItem;
+class SvxAutoKernItem;
+class SvxBlinkItem;
+class SvxBrushItem;
+class SvxFontItem;
+class SvxFontHeightItem;
+class SvxLanguageItem;
+class SvxPostureItem;
+class SvxWeightItem;
+class SvxFontItem;
+class SvxFontHeightItem;
+class SvxLanguageItem;
+class SvxPostureItem;
+class SvxWeightItem;
+class SvxCharRotateItem;
+class SvxEmphasisMarkItem;
+class SvxTwoLinesItem;
+class SvxCharScaleWidthItem;
+class SvxCharReliefItem;
+class SvxCharHiddenItem;
+class SwFmtINetFmt;
+class SwFmtCharFmt;
+class SwFmtFld;
+class SwFmtFlyCnt;
+class SwFmtFtn;
+class SwFmtHardBlank;
+class SvxLineSpacingItem;
+class SvxAdjustItem;
+class SvxFmtSplitItem;
+class SvxWidowsItem;
+class SvxTabStopItem;
+class SvxHyphenZoneItem;
+class SwNumRuleItem;
+class SfxBoolItem;
+class SfxPoolItem;
+class SfxItemSet;
+class SvxParaVertAlignItem;
+class SvxParaGridItem;
+class SwFmtFrmSize;
+class SvxPaperBinItem;
+class SvxLRSpaceItem;
+class SvxULSpaceItem;
+class SwFmtPageDesc;
+class SvxFmtBreakItem;
+class SwFmtSurround;
+class SwFmtVertOrient;
+class SwFmtHoriOrient;
+class SwFmtAnchor;
+class SvxBrushItem;
+class SvxBoxItem;
+class SwFmtCol;
+class SvxFmtKeepItem;
+class SwTextGridItem;
+class SwFmtLineNumber;
+class SvxFrameDirectionItem;
+class SwFmtRuby;
+class SwTxtNode;
+class SwTOXMark;
+class SwRedlineData;
+class SwSection;
+class SwFmtDrop;
+class SwFrmFmt;
+class SwNumFmt;
+class SwFmt;
+class SwTableNode;
+struct WW8_SepInfo;
+struct WW8_PdAttrDesc;
+class SwLineNumberInfo;
+class SwNumRule;
+class wwFont;
+
+class String;
+
+class MSWordExportBase;
+
+namespace sw { class Frame; }
+
+namespace msword {
+ const sal_uInt8 ColumnBreak = 0xE;
+ const sal_uInt8 PageBreak = 0xC;
+}
+
+class AttributeOutputBase
+{
+public:
+ /// Export the state of RTL/CJK.
+ virtual void RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript ) = 0;
+
+ /// Start of the paragraph.
+ virtual void StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo ) = 0;
+
+ /// End of the paragraph.
+ virtual void EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner ) = 0;
+
+ /// Called before we start outputting the attributes.
+ virtual void StartParagraphProperties( const SwTxtNode& rNode ) = 0;
+
+ /// Called after we end outputting the attributes.
+ virtual void EndParagraphProperties() = 0;
+
+ /// Empty paragraph.
+ virtual void EmptyParagraph() = 0;
+
+ /// Start of the text run.
+ virtual void StartRun( const SwRedlineData* pRedlineData ) = 0;
+
+ /// End of the text run.
+ virtual void EndRun() = 0;
+
+ /// Called before we start outputting the attributes.
+ virtual void StartRunProperties() = 0;
+
+ /// Called after we end outputting the attributes.
+ virtual void EndRunProperties( const SwRedlineData* pRedlineData ) = 0;
+
+ /// docx requires footnoteRef/endnoteRef tag at the beginning of each of them
+ virtual void FootnoteEndnoteRefTag() {};
+
+ /// Output text (inside a run).
+ virtual void RunText( const String& rText, rtl_TextEncoding eCharSet ) = 0;
+
+ /// Output text (without markup).
+ virtual void RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet ) = 0;
+
+ /// Output ruby start.
+ virtual void StartRuby( const SwTxtNode& rNode, xub_StrLen nPos, const SwFmtRuby& rRuby ) = 0;
+
+ /// Output ruby end.
+ virtual void EndRuby() = 0;
+
+ /// Output URL start.
+ virtual bool StartURL( const String& rUrl, const String& rTarget ) = 0;
+
+ /// Output URL end.
+ virtual bool EndURL() = 0;
+
+ virtual void FieldVanish( const String& rTxt, ww::eField eType ) = 0;
+
+ void StartTOX( const SwSection& rSect );
+
+ void EndTOX( const SwSection& rSect );
+
+ virtual void TOXMark( const SwTxtNode& rNode, const SwTOXMark& rAttr );
+
+ /// Output redlining.
+ virtual void Redline( const SwRedlineData* pRedline ) = 0;
+
+ virtual void FormatDrop( const SwTxtNode& rNode, const SwFmtDrop& rSwFmtDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner ) = 0;
+
+ /// Output FKP (Formatted disK Page) - necessary for binary formats only.
+ /// FIXME having it in AttributeOutputBase is probably a hack, it
+ /// should be in WW8AttributeOutput only...
+ virtual void OutputFKP() {}
+
+ /// Output style.
+ virtual void ParagraphStyle( sal_uInt16 nStyle ) = 0;
+
+ virtual void TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo ) = 0;
+
+ virtual void TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo ) = 0;
+
+ virtual void TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo ) = 0;
+
+ virtual void TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo ) = 0;
+
+ virtual void TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo ) = 0;
+
+ virtual void TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo ) = 0;
+
+ virtual void TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo ) = 0;
+
+ virtual void TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo ) = 0;
+
+ virtual void TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo ) = 0;
+
+ virtual void TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo ) = 0;
+
+ virtual void TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner ) = 0;
+
+ virtual void TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner ) = 0;
+
+ virtual void TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner ) = 0;
+
+ virtual void TableRowEnd( sal_uInt32 nDepth ) = 0;
+
+ /// Start of the styles table.
+ virtual void StartStyles() = 0;
+
+ /// End of the styles table.
+ virtual void EndStyles( sal_uInt16 nNumberOfStyles ) = 0;
+
+ /// Write default style.
+ virtual void DefaultStyle( sal_uInt16 nStyle ) = 0;
+
+ /// Start of a style in the styles table.
+ virtual void StartStyle( const String& rName, bool bPapFmt,
+ sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 nWwId, sal_uInt16 nId,
+ bool bAutoUpdate ) = 0;
+
+ /// End of a style in the styles table.
+ virtual void EndStyle() = 0;
+
+ /// Start of (paragraph or run) properties of a style.
+ virtual void StartStyleProperties( bool bParProp, sal_uInt16 nStyle ) = 0;
+
+ /// End of (paragraph or run) properties of a style.
+ virtual void EndStyleProperties( bool bParProp ) = 0;
+
+ /// Numbering rule and Id.
+ virtual void OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt& rNFmt, const SwFmt& rFmt ) = 0;
+
+ /// Page break
+ /// As a paragraph property - the paragraph should be on the next page.
+ virtual void PageBreakBefore( bool bBreak ) = 0;
+
+ /// Write a section break
+ /// msword::ColumnBreak or msword::PageBreak
+ virtual void SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo = NULL ) = 0;
+
+ /// Start of the section properties.
+ virtual void StartSection() = 0;
+
+ /// End of the section properties.
+ virtual void EndSection() = 0;
+
+ /// Protection of forms.
+ virtual void SectionFormProtection( bool bProtected ) = 0;
+
+ /// Numbering of the lines in the document.
+ virtual void SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo ) = 0;
+
+ /// Has different headers/footers for the title page.
+ virtual void SectionTitlePage() = 0;
+
+ /// Description of the page borders.
+ virtual void SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* pFirstPageFmt ) = 0;
+
+ /// Columns populated from right/numbers on the right side?
+ virtual void SectionBiDi( bool bBiDi ) = 0;
+
+ /// The style of the page numbers.
+ ///
+ /// nPageRestartNumberr being 0 means no restart.
+ virtual void SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber ) = 0;
+
+ /// The type of breaking.
+ virtual void SectionType( sal_uInt8 nBreakCode ) = 0;
+
+ /// Special header/footer flags, needed for old versions only.
+ virtual void SectionWW6HeaderFooterFlags( sal_uInt8 /*nHeadFootFlags*/ ) {}
+
+ /// Definition of a numbering instance.
+ virtual void NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule ) = 0;
+
+ /// Start of the abstract numbering definition instance.
+ virtual void StartAbstractNumbering( sal_uInt16 /*nId*/ ) {}
+
+ /// End of the abstract numbering definition instance.
+ virtual void EndAbstractNumbering() {}
+
+ /// All the numbering level information.
+ virtual void NumberingLevel( sal_uInt8 nLevel,
+ sal_uInt16 nStart,
+ sal_uInt16 nNumberingType,
+ SvxAdjust eAdjust,
+ const sal_uInt8 *pNumLvlPos,
+ sal_uInt8 nFollow,
+ const wwFont *pFont,
+ const SfxItemSet *pOutSet,
+ sal_Int16 nIndentAt,
+ sal_Int16 nFirstLineIndex,
+ sal_Int16 nListTabPos,
+ const String &rNumberingString ) = 0;
+
+protected:
+
+ void GetNumberPara( String& rStr, const SwField& rFld );
+
+ /// Output frames - the implementation.
+ virtual void OutputFlyFrame_Impl( const sw::Frame& rFmt, const Point& rNdTopLeft ) = 0;
+
+ /// Sfx item Sfx item RES_CHRATR_CASEMAP
+ virtual void CharCaseMap( const SvxCaseMapItem& ) = 0;
+
+ /// Sfx item Sfx item RES_CHRATR_COLOR
+ virtual void CharColor( const SvxColorItem& ) = 0;
+
+ /// Sfx item Sfx item RES_CHRATR_CONTOUR
+ virtual void CharContour( const SvxContourItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CROSSEDOUT
+ virtual void CharCrossedOut( const SvxCrossedOutItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_ESCAPEMENT
+ virtual void CharEscapement( const SvxEscapementItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_FONT
+ virtual void CharFont( const SvxFontItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_FONTSIZE
+ virtual void CharFontSize( const SvxFontHeightItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_KERNING
+ virtual void CharKerning( const SvxKerningItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_LANGUAGE
+ virtual void CharLanguage( const SvxLanguageItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_POSTURE
+ virtual void CharPosture( const SvxPostureItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_SHADOWED
+ virtual void CharShadow( const SvxShadowedItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_UNDERLINE
+ virtual void CharUnderline( const SvxUnderlineItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_WEIGHT
+ virtual void CharWeight( const SvxWeightItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_AUTOKERN
+ virtual void CharAutoKern( const SvxAutoKernItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_BLINK
+ virtual void CharAnimatedText( const SvxBlinkItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_BACKGROUND
+ virtual void CharBackground( const SvxBrushItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CJK_FONT
+ virtual void CharFontCJK( const SvxFontItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CJK_FONTSIZE
+ virtual void CharFontSizeCJK( const SvxFontHeightItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CJK_LANGUAGE
+ virtual void CharLanguageCJK( const SvxLanguageItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CJK_POSTURE
+ virtual void CharPostureCJK( const SvxPostureItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CJK_WEIGHT
+ virtual void CharWeightCJK( const SvxWeightItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CTL_FONT
+ virtual void CharFontCTL( const SvxFontItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CTL_FONTSIZE
+ virtual void CharFontSizeCTL( const SvxFontHeightItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CTL_LANGUAGE
+ virtual void CharLanguageCTL( const SvxLanguageItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CTL_POSTURE
+ virtual void CharPostureCTL( const SvxPostureItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_CTL_WEIGHT
+ virtual void CharWeightCTL( const SvxWeightItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_ROTATE
+ virtual void CharRotate( const SvxCharRotateItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_EMPHASIS_MARK
+ virtual void CharEmphasisMark( const SvxEmphasisMarkItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_TWO_LINES
+ virtual void CharTwoLines( const SvxTwoLinesItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_SCALEW
+ virtual void CharScaleWidth( const SvxCharScaleWidthItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_RELIEF
+ virtual void CharRelief( const SvxCharReliefItem& ) = 0;
+
+ /// Sfx item RES_CHRATR_HIDDEN
+ virtual void CharHidden( const SvxCharHiddenItem& ) = 0;
+
+ /// Sfx item RES_TXTATR_INETFMT
+ virtual void TextINetFormat( const SwFmtINetFmt& ) = 0;
+
+ /// Sfx item RES_TXTATR_CHARFMT
+ virtual void TextCharFormat( const SwFmtCharFmt& ) = 0;
+
+ /// Sfx item RES_TXTATR_FIELD
+ void TextField( const SwFmtFld& );
+
+ /// Sfx item RES_TXTATR_FLYCNT
+ virtual void TextFlyContent( const SwFmtFlyCnt& );
+
+ /// Sfx item RES_TXTATR_FTN
+ ///
+ /// This one is common for both WW8AttributeOutput as well as
+ /// DocxAttributeOutput.
+ void TextFootnote( const SwFmtFtn& );
+
+ /// Sfx item RES_TXTATR_FTN
+ virtual void TextFootnote_Impl( const SwFmtFtn& ) = 0;
+
+ /// Sfx item RES_PARATR_LINESPACING
+ void ParaLineSpacing( const SvxLineSpacingItem& );
+
+ /// Count the values in ParaLineSpacing, and pass theme here.
+ virtual void ParaLineSpacing_Impl( short nSpace, short nMulti ) = 0;
+
+ /// Sfx item RES_PARATR_ADJUST
+ virtual void ParaAdjust( const SvxAdjustItem& ) = 0;
+
+ /// Sfx item RES_PARATR_SPLIT
+ virtual void ParaSplit( const SvxFmtSplitItem& ) = 0;
+
+ /// Sfx item RES_PARATR_WIDOWS
+ virtual void ParaWidows( const SvxWidowsItem& ) = 0;
+
+ /// Sfx item RES_PARATR_TABSTOP
+ virtual void ParaTabStop( const SvxTabStopItem& ) = 0;
+
+ /// Sfx item RES_PARATR_HYPHENZONE
+ virtual void ParaHyphenZone( const SvxHyphenZoneItem& ) = 0;
+
+ /// Sfx item RES_PARATR_NUMRULE
+ void ParaNumRule( const SwNumRuleItem& );
+
+ /// Numbering - the implementation.
+ virtual void ParaNumRule_Impl( const SwTxtNode *pTxtNd, sal_Int32 nLvl, sal_Int32 nNumId ) = 0;
+
+ /// Sfx item RES_PARATR_SCRIPTSPACE
+ virtual void ParaScriptSpace( const SfxBoolItem& ) = 0;
+
+ /// Sfx item RES_PARATR_HANGINGPUNCTUATION
+ void ParaHangingPunctuation( const SfxBoolItem& rHt ) { ParaScriptSpace( rHt ); };
+
+ /// Sfx item RES_PARATR_FORBIDDEN_RULES
+ void ParaForbiddenRules( const SfxBoolItem& rHt ) { ParaScriptSpace( rHt ); };
+
+ /// Sfx item RES_PARATR_VERTALIGN
+ virtual void ParaVerticalAlign( const SvxParaVertAlignItem& ) = 0;
+
+ /// Sfx item RES_PARATR_SNAPTOGRID
+ virtual void ParaSnapToGrid( const SvxParaGridItem& ) = 0;
+
+ /// Sfx item RES_FRM_SIZE
+ virtual void FormatFrameSize( const SwFmtFrmSize& ) = 0;
+
+ /// Sfx item RES_PAPER_BIN
+ virtual void FormatPaperBin( const SvxPaperBinItem& ) = 0;
+
+ /// Sfx item RES_LR_SPACE
+ virtual void FormatLRSpace( const SvxLRSpaceItem& ) = 0;
+
+ /// Sfx item RES_UL_SPACE
+ virtual void FormatULSpace( const SvxULSpaceItem& ) = 0;
+
+ /// Sfx item RES_PAGEDESC
+ void FormatPageDescription( const SwFmtPageDesc& );
+
+ /// Sfx item RES_BREAK
+ void FormatBreak( const SvxFmtBreakItem& );
+
+ /// Sfx item RES_SURROUND
+ virtual void FormatSurround( const SwFmtSurround& ) = 0;
+
+ /// Sfx item RES_VERT_ORIENT
+ virtual void FormatVertOrientation( const SwFmtVertOrient& ) = 0;
+
+ /// Sfx item RES_HORI_ORIENT
+ virtual void FormatHorizOrientation( const SwFmtHoriOrient& ) = 0;
+
+ /// Sfx item RES_ANCHOR
+ virtual void FormatAnchor( const SwFmtAnchor& ) = 0;
+
+ /// Sfx item RES_BACKGROUND
+ virtual void FormatBackground( const SvxBrushItem& ) = 0;
+
+ /// Sfx item RES_BOX
+ virtual void FormatBox( const SvxBoxItem& ) = 0;
+
+ /// Sfx item RES_COL
+ void FormatColumns( const SwFmtCol& );
+
+ virtual void FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol & rCol, bool bEven, SwTwips nPageSize ) = 0;
+
+ /// Sfx item RES_KEEP
+ virtual void FormatKeep( const SvxFmtKeepItem& ) = 0;
+
+ /// Sfx item RES_TEXTGRID
+ virtual void FormatTextGrid( const SwTextGridItem& ) = 0;
+
+ /// Sfx item RES_LINENUMBER
+ virtual void FormatLineNumbering( const SwFmtLineNumber& ) = 0;
+
+ /// Sfx item RES_FRAMEDIR
+ virtual void FormatFrameDirection( const SvxFrameDirectionItem& ) = 0;
+
+ /// Write the expanded field
+ virtual void WriteExpand( const SwField* pFld ) = 0;
+
+ virtual void RefField( const SwField& rFld, const String& rRef ) = 0;
+ virtual void HiddenField( const SwField& rFld ) = 0;
+ virtual void SetField( const SwField& rFld, ww::eField eType, const String& rCmd ) = 0;
+ virtual void PostitField( const SwField* pFld ) = 0;
+ virtual bool DropdownField( const SwField* pFld ) = 0;
+
+ virtual bool AnalyzeURL( const String& rUrl, const String& rTarget, String* pLinkURL, String* pMark );
+
+ ww8::GridColsPtr GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+
+public:
+ AttributeOutputBase() {}
+ virtual ~AttributeOutputBase() {}
+
+ /// Return the right export class.
+ virtual MSWordExportBase& GetExport() = 0;
+
+ /// @overload
+ const MSWordExportBase& GetExport() const { return const_cast< AttributeOutputBase* >( this )->GetExport(); }
+
+ /// Call the right virtual function according to the type of the item.
+ void OutputItem( const SfxPoolItem& rHt );
+
+ /// Use OutputItem() on an item set - for styles.
+ void OutputStyleItemSet( const SfxItemSet& rSet, sal_Bool bDeep, sal_Bool bTestForDefault );
+
+ /// Output frames.
+ void OutputFlyFrame( const sw::Frame& rFmt );
+
+ void GetTablePageSize
+ ( ww8::WW8TableNodeInfoInner * pTableTextNodeInfoInner,
+ sal_uInt32& rPageSize, bool& rRelBoxSize );
+
+};
+
+#endif // _ATTRIBUTEOUTPUTBASE_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxattributeoutput.cxx b/sw/source/filter/ww8/docxattributeoutput.cxx
new file mode 100644
index 000000000000..bc60b3e21e74
--- /dev/null
+++ b/sw/source/filter/ww8/docxattributeoutput.cxx
@@ -0,0 +1,4168 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "docxattributeoutput.hxx"
+#include "docxexport.hxx"
+#include "docxexportfilter.hxx"
+#include "docxfootnotes.hxx"
+#include "writerwordglue.hxx"
+#include "wrtww8.hxx"
+#include "ww8par.hxx"
+#include "fmtcntnt.hxx"
+#include "fmtsrnd.hxx"
+#include "fchrfmt.hxx"
+#include "tgrditem.hxx"
+#include "fmtruby.hxx"
+#include "charfmt.hxx"
+#include "breakit.hxx"
+
+#include <oox/token/tokens.hxx>
+#include <oox/export/drawingml.hxx>
+#include <oox/export/utils.hxx>
+#include <oox/export/vmlexport.hxx>
+
+#include <i18npool/mslangid.hxx>
+
+#include <hintids.hxx>
+
+#include <svl/poolitem.hxx>
+
+#include <editeng/fontitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/hyznitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/paravertalignitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/blnkitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdobj.hxx>
+
+#include <anchoredobject.hxx>
+#include <docufld.hxx>
+#include <flddropdown.hxx>
+#include <format.hxx>
+#include <fmtanchr.hxx>
+#include <fmtclds.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtfld.hxx>
+#include <fmtfsize.hxx>
+#include <fmtftn.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmtline.hxx>
+#include <frmfmt.hxx>
+#include <frmatr.hxx>
+#include <ftninfo.hxx>
+#include <htmltbl.hxx>
+#include <lineinfo.hxx>
+#include <ndgrf.hxx>
+#include <ndtxt.hxx>
+#include <node.hxx>
+#include <pagedesc.hxx>
+#include <paratr.hxx>
+#include <swmodule.hxx>
+#include <swtable.hxx>
+#include <txtftn.hxx>
+#include <txtinet.hxx>
+#include <numrule.hxx>
+
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+
+#include <tools/color.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+#include <IMark.hxx>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+using ::editeng::SvxBorderLine;
+using rtl::OString;
+using rtl::OStringBuffer;
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using rtl::OUStringToOString;
+
+using namespace oox;
+using namespace docx;
+using namespace sax_fastparser;
+using namespace nsSwDocInfoSubType;
+using namespace nsFieldFlags;
+using namespace sw::util;
+using namespace ::com::sun::star;
+
+class FFDataWriterHelper
+{
+ ::sax_fastparser::FSHelperPtr m_pSerializer;
+ void writeCommonStart( const rtl::OUString& rName )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_ffData, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_name,
+ FSNS( XML_w, XML_val ), OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_enabled, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_calcOnExit,
+ FSNS( XML_w, XML_val ),
+ "0", FSEND );
+ }
+ void writeFinish()
+ {
+ m_pSerializer->endElementNS( XML_w, XML_ffData );
+ }
+public:
+ FFDataWriterHelper( const ::sax_fastparser::FSHelperPtr pSerializer ) : m_pSerializer( pSerializer ){}
+ void WriteFormCheckbox( const rtl::OUString& rName, const rtl::OUString& rDefault, bool bChecked )
+ {
+ writeCommonStart( rName );
+ // Checkbox specific bits
+ m_pSerializer->startElementNS( XML_w, XML_checkBox, FSEND );
+ // currently hardcoding autosize
+ // #TODO check if this defaulted
+ m_pSerializer->startElementNS( XML_w, XML_sizeAuto, FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_sizeAuto );
+ if ( rDefault.getLength() )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_default,
+ FSNS( XML_w, XML_val ),
+ rtl::OUStringToOString( rDefault, RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
+ }
+ if ( bChecked )
+ m_pSerializer->singleElementNS( XML_w, XML_checked, FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_checkBox );
+ writeFinish();
+ }
+ void WriteFormText( const rtl::OUString& rName, const rtl::OUString& rDefault )
+ {
+ writeCommonStart( rName );
+ if ( rDefault.getLength() )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_textInput, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_default,
+ FSNS( XML_w, XML_val ),
+ rtl::OUStringToOString( rDefault, RTL_TEXTENCODING_UTF8 ).getStr(), FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_textInput );
+ }
+ writeFinish();
+ }
+};
+
+class FieldMarkParamsHelper
+{
+ const sw::mark::IFieldmark& mrFieldmark;
+ public:
+ FieldMarkParamsHelper( const sw::mark::IFieldmark& rFieldmark ) : mrFieldmark( rFieldmark ) {}
+ rtl::OUString getName() { return mrFieldmark.GetName(); }
+ template < typename T >
+ bool extractParam( const rtl::OUString& rKey, T& rResult )
+ {
+ bool bResult = false;
+ if ( mrFieldmark.GetParameters() )
+ {
+ sw::mark::IFieldmark::parameter_map_t::const_iterator it = mrFieldmark.GetParameters()->find( rKey );
+ if ( it != mrFieldmark.GetParameters()->end() )
+ bResult = ( it->second >>= rResult );
+ }
+ return bResult;
+ }
+};
+void DocxAttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 /*nScript*/ )
+{
+ if (bIsRTL)
+ m_pSerializer->singleElementNS( XML_w, XML_rtl, FSNS( XML_w, XML_val ), "true", FSEND );
+}
+
+void DocxAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo )
+{
+ if ( m_nColBreakStatus == COLBRK_POSTPONE )
+ m_nColBreakStatus = COLBRK_WRITE;
+
+ // Output table/table row/table cell starts if needed
+ if ( pTextNodeInfo.get() )
+ {
+ sal_uInt32 nRow = pTextNodeInfo->getRow();
+ sal_uInt32 nCell = pTextNodeInfo->getCell();
+
+ // New cell/row?
+ if ( m_nTableDepth > 0 && !m_bTableCellOpen )
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_nTableDepth ) );
+ if ( pDeepInner->getCell() == 0 )
+ StartTableRow( pDeepInner );
+
+ StartTableCell( pDeepInner );
+ }
+
+ if ( nRow == 0 && nCell == 0 )
+ {
+ // Do we have to start the table?
+ // [If we are at the rigth depth already, it means that we
+ // continue the table cell]
+ sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth();
+
+ if ( nCurrentDepth > m_nTableDepth )
+ {
+ // Start all the tables that begin here
+ for ( sal_uInt32 nDepth = m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth )
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) );
+
+ StartTable( pInner );
+ StartTableRow( pInner );
+ StartTableCell( pInner );
+ }
+
+ m_nTableDepth = nCurrentDepth;
+ }
+ }
+ }
+
+ m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
+
+ // postpone the output of the run (we get it before the paragraph
+ // properties, but must write it after them)
+ m_pSerializer->mark();
+
+ // no section break in this paragraph yet; can be set in SectionBreak()
+ m_pSectionInfo = NULL;
+
+ m_bParagraphOpened = true;
+}
+
+void DocxAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
+{
+ // write the paragraph properties + the run, already in the correct order
+ m_pSerializer->mergeTopMarks();
+ m_pSerializer->endElementNS( XML_w, XML_p );
+
+ // Check for end of cell, rows, tables here
+ FinishTableRowCell( pTextNodeInfoInner );
+
+ m_bParagraphOpened = false;
+
+ // Write the anchored frame if any
+ if ( m_pParentFrame )
+ {
+ const SwFrmFmt& rFrmFmt = m_pParentFrame->GetFrmFmt( );
+ const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
+
+ sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
+ sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
+
+ m_rExport.SaveData( nStt, nEnd );
+
+ m_rExport.mpParentFrame = m_pParentFrame;
+ m_pParentFrame = NULL;
+
+ m_rExport.WriteText( );
+
+ m_rExport.RestoreData();
+ }
+}
+
+void DocxAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph )
+{
+ if ( pInner.get() )
+ {
+ // Where are we in the table
+ sal_uInt32 nRow = pInner->getRow( );
+
+ const SwTable *pTable = pInner->getTable( );
+ const SwTableLines& rLines = pTable->GetTabLines( );
+ sal_uInt16 nLinesCount = rLines.Count( );
+ // HACK
+ // msoffice seems to have an internal limitation of 63 columns for tables
+ // and refuses to load .docx with more, even though the spec seems to allow that;
+ // so simply if there are more columns, don't close the last one msoffice will handle
+ // and merge the contents of the remaining ones into it (since we don't close the cell
+ // here, following ones will not be opened)
+ bool limitWorkaround = ( pInner->getCell() >= 62 && !pInner->isEndOfLine());
+
+ if ( pInner->isEndOfCell() && !limitWorkaround )
+ {
+ if ( bForceEmptyParagraph )
+ m_pSerializer->singleElementNS( XML_w, XML_p, FSEND );
+
+ EndTableCell();
+ }
+
+ // This is a line end
+ if ( pInner->isEndOfLine() )
+ EndTableRow();
+
+ // This is the end of the table
+ if ( pInner->isEndOfLine( ) && ( nRow + 1 ) == nLinesCount )
+ EndTable();
+ }
+}
+
+void DocxAttributeOutput::EmptyParagraph()
+{
+ m_pSerializer->singleElementNS( XML_w, XML_p, FSEND );
+}
+
+void DocxAttributeOutput::StartParagraphProperties( const SwTxtNode& rNode )
+{
+ // output page/section breaks
+ // Writer can have them at the beginning of a paragraph, or at the end, but
+ // in docx, we have to output them in the paragraph properties of the last
+ // paragraph in a section. To get it right, we have to switch to the next
+ // paragraph, and detect the section breaks there.
+ SwNodeIndex aNextIndex( rNode, 1 );
+ if ( aNextIndex.GetNode().IsTxtNode() )
+ {
+ const SwTxtNode* pTxtNode = static_cast< SwTxtNode* >( &aNextIndex.GetNode() );
+ m_rExport.OutputSectionBreaks( pTxtNode->GetpSwAttrSet(), *pTxtNode );
+ }
+ else if ( aNextIndex.GetNode().IsTableNode() )
+ {
+ const SwTableNode* pTableNode = static_cast< SwTableNode* >( &aNextIndex.GetNode() );
+ const SwFrmFmt *pFmt = pTableNode->GetTable().GetFrmFmt();
+ m_rExport.OutputSectionBreaks( &(pFmt->GetAttrSet()), *pTableNode );
+ }
+
+ m_pSerializer->mark( );
+
+ m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
+
+ // and output the section break now (if it appeared)
+ if ( m_pSectionInfo )
+ {
+ m_rExport.SectionProperties( *m_pSectionInfo );
+ m_pSectionInfo = NULL;
+ }
+
+ InitCollectedParagraphProperties();
+}
+
+void DocxAttributeOutput::InitCollectedParagraphProperties()
+{
+ m_pParagraphSpacingAttrList = NULL;
+
+ // Write the elements in the spec order
+ static const sal_Int32 aOrder[] =
+ {
+ FSNS( XML_w, XML_pStyle ),
+ FSNS( XML_w, XML_keepNext ),
+ FSNS( XML_w, XML_keepLines ),
+ FSNS( XML_w, XML_pageBreakBefore ),
+ FSNS( XML_w, XML_framePr ),
+ FSNS( XML_w, XML_widowControl ),
+ FSNS( XML_w, XML_numPr ),
+ FSNS( XML_w, XML_suppressLineNumbers ),
+ FSNS( XML_w, XML_pBdr ),
+ FSNS( XML_w, XML_shd ),
+ FSNS( XML_w, XML_tabs ),
+ FSNS( XML_w, XML_suppressAutoHyphens ),
+ FSNS( XML_w, XML_kinsoku ),
+ FSNS( XML_w, XML_wordWrap ),
+ FSNS( XML_w, XML_overflowPunct ),
+ FSNS( XML_w, XML_topLinePunct ),
+ FSNS( XML_w, XML_autoSpaceDE ),
+ FSNS( XML_w, XML_autoSpaceDN ),
+ FSNS( XML_w, XML_bidi ),
+ FSNS( XML_w, XML_adjustRightInd ),
+ FSNS( XML_w, XML_snapToGrid ),
+ FSNS( XML_w, XML_spacing ),
+ FSNS( XML_w, XML_ind ),
+ FSNS( XML_w, XML_contextualSpacing ),
+ FSNS( XML_w, XML_mirrorIndents ),
+ FSNS( XML_w, XML_suppressOverlap ),
+ FSNS( XML_w, XML_jc ),
+ FSNS( XML_w, XML_textDirection ),
+ FSNS( XML_w, XML_textAlignment ),
+ FSNS( XML_w, XML_textboxTightWrap ),
+ FSNS( XML_w, XML_outlineLvl ),
+ FSNS( XML_w, XML_divId ),
+ FSNS( XML_w, XML_cnfStyle ),
+ FSNS( XML_w, XML_rPr ),
+ FSNS( XML_w, XML_sectPr ),
+ FSNS( XML_w, XML_pPrChange )
+ };
+
+ // postpone the output so that we can later [in EndParagraphProperties()]
+ // prepend the properties before the run
+ sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
+ uno::Sequence< sal_Int32 > aSeqOrder( len );
+ for ( sal_Int32 i = 0; i < len; i++ )
+ aSeqOrder[i] = aOrder[i];
+
+ m_pSerializer->mark( aSeqOrder );
+}
+
+void DocxAttributeOutput::WriteCollectedParagraphProperties()
+{
+ if ( m_pFlyAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pFlyAttrList );
+ m_pFlyAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_framePr, xAttrList );
+ }
+
+ if ( m_pParagraphSpacingAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pParagraphSpacingAttrList );
+ m_pParagraphSpacingAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_spacing, xAttrList );
+ }
+
+ // Merge the marks for the ordered elements
+ m_pSerializer->mergeTopMarks( );
+}
+
+void DocxAttributeOutput::EndParagraphProperties()
+{
+ WriteCollectedParagraphProperties();
+
+ m_pSerializer->endElementNS( XML_w, XML_pPr );
+
+ if ( m_nColBreakStatus == COLBRK_WRITE )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_br,
+ FSNS( XML_w, XML_type ), "column", FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+
+ m_nColBreakStatus = COLBRK_NONE;
+ }
+
+ // merge the properties _before_ the run (strictly speaking, just
+ // after the start of the paragraph)
+ m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
+}
+
+void DocxAttributeOutput::StartRun( const SwRedlineData* pRedlineData )
+{
+ // if there is some redlining in the document, output it
+ StartRedline( pRedlineData );
+
+ // postpone the output of the start of a run (there are elements that need
+ // to be written before the start of the run, but we learn which they are
+ // _inside_ of the run)
+ m_pSerializer->mark(); // let's call it "postponed run start"
+
+ // postpone the output of the text (we get it before the run properties,
+ // but must write it after them)
+ m_pSerializer->mark(); // let's call it "postponed text"
+}
+
+void DocxAttributeOutput::EndRun()
+{
+ // Write field starts
+ for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); ++pIt )
+ {
+ // Add the fields starts for all but hyperlinks and TOCs
+ if ( pIt->bOpen && pIt->pField )
+ {
+ StartField_Impl( *pIt );
+
+ // Remove the field from the stack if only the start has to be written
+ // Unknown fields sould be removed too
+ if ( !pIt->bClose || ( pIt->eType == ww::eUNKNOWN ) )
+ {
+ m_Fields.erase( pIt );
+ --pIt;
+ }
+ }
+ }
+
+ // write the run properties + the text, already in the correct order
+ m_pSerializer->mergeTopMarks(); // merges with "postponed text", see above
+
+ // level down, to be able to prepend the actual run start attribute (just
+ // before "postponed run start")
+ m_pSerializer->mark(); // let's call it "actual run start"
+
+ // prepend the actual run start
+ if ( m_pHyperlinkAttrList )
+ {
+ XFastAttributeListRef xAttrList ( m_pHyperlinkAttrList );
+
+ m_pSerializer->startElementNS( XML_w, XML_hyperlink, xAttrList );
+ }
+
+ // Write the hyperlink and toc fields starts
+ for ( std::vector<FieldInfos>::iterator pIt = m_Fields.begin(); pIt != m_Fields.end(); ++pIt )
+ {
+ // Add the fields starts for hyperlinks, TOCs and index marks
+ if ( pIt->bOpen && !pIt->pField )
+ {
+ StartField_Impl( *pIt, sal_True );
+
+ // Remove the field if no end needs to be written
+ if ( !pIt->bClose ) {
+ m_Fields.erase( pIt );
+ --pIt;
+ }
+ }
+ }
+
+ DoWriteBookmarks( );
+
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND ); // merges with "postponed run start", see above
+
+ // write the run start + the run content
+ m_pSerializer->mergeTopMarks(); // merges the "actual run start"
+
+ // append the actual run end
+ m_pSerializer->endElementNS( XML_w, XML_r );
+
+ if ( m_pHyperlinkAttrList )
+ {
+ m_pSerializer->endElementNS( XML_w, XML_hyperlink );
+ m_pHyperlinkAttrList = NULL;
+ }
+
+ while ( m_Fields.begin() != m_Fields.end() )
+ {
+ EndField_Impl( m_Fields.front( ) );
+ m_Fields.erase( m_Fields.begin( ) );
+ }
+
+ // if there is some redlining in the document, output it
+ EndRedline();
+}
+
+void DocxAttributeOutput::DoWriteBookmarks()
+{
+ // Write the start bookmarks
+ for ( std::vector< OString >::const_iterator it = m_rMarksStart.begin(), end = m_rMarksStart.end();
+ it < end; ++it )
+ {
+ const OString& rName = *it;
+
+ // Output the bookmark
+ sal_uInt16 nId = m_nNextMarkId++;
+ m_rOpenedMarksIds[rName] = nId;
+ m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
+ FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( nId ) ).getStr( ),
+ FSNS( XML_w, XML_name ), rName.getStr(),
+ FSEND );
+ }
+ m_rMarksStart.clear();
+
+ // export the end bookmarks
+ for ( std::vector< OString >::const_iterator it = m_rMarksEnd.begin(), end = m_rMarksEnd.end();
+ it < end; ++it )
+ {
+ const OString& rName = *it;
+
+ // Get the id of the bookmark
+ std::map< OString, sal_uInt16 >::iterator pPos = m_rOpenedMarksIds.find( rName );
+ if ( pPos != m_rOpenedMarksIds.end( ) )
+ {
+ sal_uInt16 nId = ( *pPos ).second;
+ m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
+ FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( nId ) ).getStr( ),
+ FSEND );
+ m_rOpenedMarksIds.erase( rName );
+ }
+ }
+ m_rMarksEnd.clear();
+}
+
+void DocxAttributeOutput::WriteFFData( const FieldInfos& rInfos )
+{
+ const ::sw::mark::IFieldmark& rFieldmark = *rInfos.pFieldmark;
+ if ( rInfos.eType == ww::eFORMDROPDOWN )
+ {
+ uno::Sequence< ::rtl::OUString> vListEntries;
+ rtl::OUString sName, sHelp, sToolTip, sSelected;
+
+ FieldMarkParamsHelper params( rFieldmark );
+ params.extractParam( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_LISTENTRY) ), vListEntries );
+ sName = params.getName();
+ sal_Int32 nSelectedIndex = 0;
+
+ if ( params.extractParam( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_RESULT) ), nSelectedIndex ) )
+ {
+ if (nSelectedIndex < vListEntries.getLength() )
+ sSelected = vListEntries[ nSelectedIndex ];
+ }
+
+ GetExport().DoComboBox( sName, sHelp, sToolTip, sSelected, vListEntries );
+ }
+ else if ( rInfos.eType == ww::eFORMCHECKBOX )
+ {
+ rtl::OUString sName, sDefault;
+ bool bChecked = false;
+
+ FieldMarkParamsHelper params( rFieldmark );
+ params.extractParam( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_FORMCHECKBOX_NAME ) ), sName );
+
+ const sw::mark::ICheckboxFieldmark* pCheckboxFm = NULL;
+ if ( rFieldmark.GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) ) )
+ pCheckboxFm = reinterpret_cast<const sw::mark::ICheckboxFieldmark*>(&rFieldmark);
+ if ( pCheckboxFm && pCheckboxFm->IsChecked() )
+ bChecked = true;
+
+ FFDataWriterHelper ffdataOut( m_pSerializer );
+ ffdataOut.WriteFormCheckbox( sName, rtl::OUString(), bChecked );
+ }
+ else if ( rInfos.eType == ww::eFORMTEXT )
+ {
+ FieldMarkParamsHelper params( rFieldmark );
+ FFDataWriterHelper ffdataOut( m_pSerializer );
+ ffdataOut.WriteFormText( params.getName(), rtl::OUString() );
+ }
+}
+
+void DocxAttributeOutput::StartField_Impl( FieldInfos& rInfos, sal_Bool bWriteRun )
+{
+ if ( rInfos.pField && rInfos.eType == ww::eUNKNOWN )
+ {
+ // Expand unsupported fields
+ RunText( rInfos.pField->GetFieldName() );
+ }
+ else if ( rInfos.eType != ww::eNONE ) // HYPERLINK fields are just commands
+ {
+ if ( bWriteRun )
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+
+ if ( rInfos.eType == ww::eFORMDROPDOWN )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "begin",
+ FSEND );
+ if ( rInfos.pFieldmark && !rInfos.pField )
+ WriteFFData( rInfos );
+ if ( rInfos.pField )
+ {
+ const SwDropDownField& rFld2 = *(SwDropDownField*)rInfos.pField;
+ uno::Sequence<rtl::OUString> aItems =
+ rFld2.GetItemSequence();
+ GetExport().DoComboBox(rFld2.GetName(),
+ rFld2.GetHelp(),
+ rFld2.GetToolTip(),
+ rFld2.GetSelectedItem(), aItems);
+ }
+ m_pSerializer->endElementNS( XML_w, XML_fldChar );
+
+ if ( bWriteRun )
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ if ( !rInfos.pField )
+ CmdField_Impl( rInfos );
+
+ }
+ else
+ {
+ // Write the field start
+ m_pSerializer->startElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "begin",
+ FSEND );
+
+ if ( rInfos.pFieldmark )
+ WriteFFData( rInfos );
+
+ m_pSerializer->endElementNS( XML_w, XML_fldChar );
+
+ if ( bWriteRun )
+ m_pSerializer->endElementNS( XML_w, XML_r );
+
+ // The hyperlinks fields can't be expanded: the value is
+ // normally in the text run
+ if ( !rInfos.pField )
+ CmdField_Impl( rInfos );
+ }
+ }
+}
+
+void DocxAttributeOutput::DoWriteCmd( String& rCmd )
+{
+ // Write the Field command
+ m_pSerializer->startElementNS( XML_w, XML_instrText, FSEND );
+ m_pSerializer->writeEscaped( OUString( rCmd ) );
+ m_pSerializer->endElementNS( XML_w, XML_instrText );
+
+}
+
+void DocxAttributeOutput::CmdField_Impl( FieldInfos& rInfos )
+{
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ xub_StrLen nNbToken = rInfos.sCmd.GetTokenCount( '\t' );
+
+ for ( xub_StrLen i = 0; i < nNbToken; i++ )
+ {
+ String sToken = rInfos.sCmd.GetToken( i, '\t' );
+ // Write the Field command
+ DoWriteCmd( sToken );
+
+ // Replace tabs by </instrText><tab/><instrText>
+ if ( i < ( nNbToken - 1 ) )
+ RunText( String::CreateFromAscii( "\t" ) );
+ }
+
+ m_pSerializer->endElementNS( XML_w, XML_r );
+
+ // Write the Field separator
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "separate",
+ FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+}
+
+void DocxAttributeOutput::EndField_Impl( FieldInfos& rInfos )
+{
+ // The command has to be written before for the hyperlinks
+ if ( rInfos.pField )
+ {
+ CmdField_Impl( rInfos );
+ }
+
+ // Write the bookmark start if any
+ OUString aBkmName( m_sFieldBkm );
+ if ( aBkmName.getLength( ) > 0 )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_bookmarkStart,
+ FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( m_nNextMarkId ) ).getStr( ),
+ FSNS( XML_w, XML_name ), OUStringToOString( aBkmName, RTL_TEXTENCODING_UTF8 ).getStr( ),
+ FSEND );
+ }
+
+ if (rInfos.pField ) // For hyperlinks and TOX
+ {
+ // Write the Field latest value
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+
+ // Find another way for hyperlinks
+ RunText( rInfos.pField->GetFieldName() );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ }
+
+ // Write the bookmark end if any
+ if ( aBkmName.getLength( ) > 0 )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_bookmarkEnd,
+ FSNS( XML_w, XML_id ), OString::valueOf( sal_Int32( m_nNextMarkId ) ).getStr( ),
+ FSEND );
+
+ m_nNextMarkId++;
+ }
+
+ // Write the Field end
+ if ( rInfos.bClose )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "end",
+ FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ }
+ // Write the ref field if a bookmark had to be set and the field
+ // should be visible
+ if ( rInfos.pField )
+ {
+ sal_uInt16 nSubType = rInfos.pField->GetSubType( );
+ bool bIsSetField = rInfos.pField->GetTyp( )->Which( ) == RES_SETEXPFLD;
+ bool bShowRef = ( !bIsSetField || ( nSubType & nsSwExtendedSubType::SUB_INVISIBLE ) ) ? false : true;
+
+ if ( ( m_sFieldBkm.Len( ) > 0 ) && bShowRef )
+ {
+ // Write the field beginning
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_fldChar,
+ FSNS( XML_w, XML_fldCharType ), "begin",
+ FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+
+ rInfos.sCmd = FieldString( ww::eREF );
+ rInfos.sCmd.APPEND_CONST_ASC( "\"" );
+ rInfos.sCmd += m_sFieldBkm;
+ rInfos.sCmd.APPEND_CONST_ASC( "\" " );
+
+ // Clean the field bookmark data to avoid infinite loop
+ m_sFieldBkm = String( );
+
+ // Write the end of the field
+ EndField_Impl( rInfos );
+ }
+ }
+}
+
+void DocxAttributeOutput::StartRunProperties()
+{
+ // postpone the output so that we can later [in EndRunProperties()]
+ // prepend the properties before the text
+ m_pSerializer->mark();
+
+ m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
+
+ InitCollectedRunProperties();
+}
+
+void DocxAttributeOutput::InitCollectedRunProperties()
+{
+ m_pFontsAttrList = NULL;
+ m_pEastAsianLayoutAttrList = NULL;
+ m_pCharLangAttrList = NULL;
+
+ // Write the elements in the spec order
+ static const sal_Int32 aOrder[] =
+ {
+ FSNS( XML_w, XML_rStyle ),
+ FSNS( XML_w, XML_rFonts ),
+ FSNS( XML_w, XML_b ),
+ FSNS( XML_w, XML_bCs ),
+ FSNS( XML_w, XML_i ),
+ FSNS( XML_w, XML_iCs ),
+ FSNS( XML_w, XML_caps ),
+ FSNS( XML_w, XML_smallCaps ),
+ FSNS( XML_w, XML_strike ),
+ FSNS( XML_w, XML_dstrike ),
+ FSNS( XML_w, XML_outline ),
+ FSNS( XML_w, XML_shadow ),
+ FSNS( XML_w, XML_emboss ),
+ FSNS( XML_w, XML_imprint ),
+ FSNS( XML_w, XML_noProof ),
+ FSNS( XML_w, XML_snapToGrid ),
+ FSNS( XML_w, XML_vanish ),
+ FSNS( XML_w, XML_webHidden ),
+ FSNS( XML_w, XML_color ),
+ FSNS( XML_w, XML_spacing ),
+ FSNS( XML_w, XML_w ),
+ FSNS( XML_w, XML_kern ),
+ FSNS( XML_w, XML_position ),
+ FSNS( XML_w, XML_sz ),
+ FSNS( XML_w, XML_szCs ),
+ FSNS( XML_w, XML_highlight ),
+ FSNS( XML_w, XML_u ),
+ FSNS( XML_w, XML_effect ),
+ FSNS( XML_w, XML_bdr ),
+ FSNS( XML_w, XML_shd ),
+ FSNS( XML_w, XML_fitText ),
+ FSNS( XML_w, XML_vertAlign ),
+ FSNS( XML_w, XML_rtl ),
+ FSNS( XML_w, XML_cs ),
+ FSNS( XML_w, XML_em ),
+ FSNS( XML_w, XML_lang ),
+ FSNS( XML_w, XML_eastAsianLayout ),
+ FSNS( XML_w, XML_specVanish ),
+ FSNS( XML_w, XML_oMath ),
+ FSNS( XML_w, XML_rPrChange )
+ };
+
+ // postpone the output so that we can later [in EndParagraphProperties()]
+ // prepend the properties before the run
+ sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
+ uno::Sequence< sal_Int32 > aSeqOrder( len );
+ for ( sal_Int32 i = 0; i < len; i++ )
+ aSeqOrder[i] = aOrder[i];
+
+ m_pSerializer->mark( aSeqOrder );
+
+}
+
+void DocxAttributeOutput::WriteCollectedRunProperties()
+{
+ // Write all differed properties
+ if ( m_pFontsAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pFontsAttrList );
+ m_pFontsAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_rFonts, xAttrList );
+ }
+
+ if ( m_pEastAsianLayoutAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pEastAsianLayoutAttrList );
+ m_pEastAsianLayoutAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_eastAsianLayout, xAttrList );
+ }
+
+ if ( m_pCharLangAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pCharLangAttrList );
+ m_pCharLangAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_lang, xAttrList );
+ }
+
+ // Merge the marks for the ordered elements
+ m_pSerializer->mergeTopMarks();
+}
+
+void DocxAttributeOutput::EndRunProperties( const SwRedlineData* /*pRedlineData*/ )
+{
+ WriteCollectedRunProperties();
+
+ m_pSerializer->endElementNS( XML_w, XML_rPr );
+
+ // write footnotes/endnotes if we have any
+ FootnoteEndnoteReference();
+
+ // merge the properties _before_ the run text (strictly speaking, just
+ // after the start of the run)
+ m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
+}
+
+void DocxAttributeOutput::FootnoteEndnoteRefTag()
+{
+ if( m_footnoteEndnoteRefTag == 0 )
+ return;
+ m_pSerializer->singleElementNS( XML_w, m_footnoteEndnoteRefTag, FSEND );
+ m_footnoteEndnoteRefTag = 0;
+}
+
+/** Output sal_Unicode* as a run text (<t>the text</t>).
+
+ When bMove is true, update rBegin to point _after_ the end of the text +
+ 1, meaning that it skips one character after the text. This is to make
+ the switch in DocxAttributeOutput::RunText() nicer ;-)
+ */
+static void impl_WriteRunText( FSHelperPtr pSerializer, sal_Int32 nTextToken,
+ const sal_Unicode* &rBegin, const sal_Unicode* pEnd, bool bMove = true )
+{
+ const sal_Unicode *pBegin = rBegin;
+
+ // skip one character after the end
+ if ( bMove )
+ rBegin = pEnd + 1;
+
+ if ( pBegin >= pEnd )
+ return; // we want to write at least one character
+
+ // we have to add 'preserve' when starting/ending with space
+ if ( *pBegin == sal_Unicode( ' ' ) || *( pEnd - 1 ) == sal_Unicode( ' ' ) )
+ {
+ pSerializer->startElementNS( XML_w, nTextToken, FSNS( XML_xml, XML_space ), "preserve", FSEND );
+ }
+ else
+ pSerializer->startElementNS( XML_w, nTextToken, FSEND );
+
+ pSerializer->writeEscaped( OUString( pBegin, pEnd - pBegin ) );
+
+ pSerializer->endElementNS( XML_w, nTextToken );
+}
+
+void DocxAttributeOutput::RunText( const String& rText, rtl_TextEncoding /*eCharSet*/ )
+{
+ OUString aText( rText );
+
+ // one text can be split into more <w:t>blah</w:t>'s by line breaks etc.
+ const sal_Unicode *pBegin = aText.getStr();
+ const sal_Unicode *pEnd = pBegin + aText.getLength();
+
+ // the text run is usually XML_t, with the exception of the deleted text
+ sal_Int32 nTextToken = XML_t;
+ if ( m_pRedlineData && m_pRedlineData->GetType() == nsRedlineType_t::REDLINE_DELETE )
+ nTextToken = XML_delText;
+
+ for ( const sal_Unicode *pIt = pBegin; pIt < pEnd; ++pIt )
+ {
+ switch ( *pIt )
+ {
+ case 0x09: // tab
+ impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
+ m_pSerializer->singleElementNS( XML_w, XML_tab, FSEND );
+ break;
+ case 0x0b: // line break
+ impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
+ m_pSerializer->singleElementNS( XML_w, XML_br, FSEND );
+ break;
+ default:
+ if ( *pIt < 0x0020 ) // filter out the control codes
+ {
+ impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pIt );
+ OSL_TRACE( "Ignored control code %x in a text run.", *pIt );
+ }
+ break;
+ }
+ }
+
+ impl_WriteRunText( m_pSerializer, nTextToken, pBegin, pEnd, false );
+}
+
+void DocxAttributeOutput::RawText( const String& /*rText*/, bool /*bForceUnicode*/, rtl_TextEncoding /*eCharSet*/ )
+{
+ OSL_TRACE("TODO DocxAttributeOutput::RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet )\n" );
+}
+
+void DocxAttributeOutput::StartRuby( const SwTxtNode& rNode, xub_StrLen nPos, const SwFmtRuby& rRuby )
+{
+ OSL_TRACE("TODO DocxAttributeOutput::StartRuby( const SwTxtNode& rNode, const SwFmtRuby& rRuby )\n" );
+ m_pSerializer->startElementNS( XML_w, XML_ruby, FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_rubyPr, FSEND );
+ // hps
+ // hpsBaseText
+ // hpsRaise
+ // lid
+ lang::Locale aLocale( SwBreakIt::Get()->GetLocale(
+ rNode.GetLang( nPos ) ) );
+ OUString sLang( aLocale.Language );
+ if ( aLocale.Country.getLength( ) > 0 )
+ sLang += OUString(RTL_CONSTASCII_USTRINGPARAM( "-" )) + OUString( aLocale.Country );
+ m_pSerializer->singleElementNS( XML_w, XML_lid,
+ FSNS( XML_w, XML_val ),
+ OUStringToOString( sLang, RTL_TEXTENCODING_UTF8 ).getStr( ), FSEND );
+
+ OString sAlign ( "center" );
+ switch ( rRuby.GetAdjustment( ) )
+ {
+ case 0:
+ sAlign = OString( "left" );
+ break;
+ case 1:
+ // Defaults to center
+ break;
+ case 2:
+ sAlign = OString( "right" );
+ break;
+ case 3:
+ sAlign = OString( "distributeLetter" );
+ break;
+ case 4:
+ sAlign = OString( "distributeSpace" );
+ break;
+ default:
+ break;
+ }
+ m_pSerializer->singleElementNS( XML_w, XML_rubyAlign,
+ FSNS( XML_w, XML_val ), sAlign.getStr(), FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_rubyPr );
+
+ m_pSerializer->startElementNS( XML_w, XML_rt, FSEND );
+ StartRun( NULL );
+ StartRunProperties( );
+ SwWW8AttrIter aAttrIt( m_rExport, rNode );
+ aAttrIt.OutAttr( nPos, true );
+ sal_uInt16 nStyle = m_rExport.GetId( *rRuby.GetTxtRuby()->GetCharFmt() );
+ OString aStyleId( "style" );
+ aStyleId += OString::valueOf( sal_Int32( nStyle ) );
+ m_pSerializer->singleElementNS( XML_w, XML_rStyle,
+ FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
+ EndRunProperties( NULL );
+ RunText( rRuby.GetText( ) );
+ EndRun( );
+ m_pSerializer->endElementNS( XML_w, XML_rt );
+
+ m_pSerializer->startElementNS( XML_w, XML_rubyBase, FSEND );
+ StartRun( NULL );
+}
+
+void DocxAttributeOutput::EndRuby()
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::EndRuby()\n" );
+ EndRun( );
+ m_pSerializer->endElementNS( XML_w, XML_rubyBase );
+ m_pSerializer->endElementNS( XML_w, XML_ruby );
+}
+
+bool DocxAttributeOutput::AnalyzeURL( const String& rUrl, const String& rTarget, String* pLinkURL, String* pMark )
+{
+ bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark );
+
+ String sURL = *pLinkURL;
+ String sMark = *pMark;
+
+ bool bOutputField = sMark.Len();
+
+ if ( bOutputField )
+ {
+ if ( bBookMarkOnly )
+ sURL = FieldString( ww::eHYPERLINK );
+ else
+ {
+ String sFld( FieldString( ww::eHYPERLINK ) );
+ sFld.APPEND_CONST_ASC( "\"" );
+ sURL.Insert( sFld, 0 );
+ sURL += '\"';
+ }
+
+ if ( sMark.Len() )
+ ( ( sURL.APPEND_CONST_ASC( " \\l \"" ) ) += sMark ) += '\"';
+
+ if ( rTarget.Len() )
+ ( sURL.APPEND_CONST_ASC( " \\n " ) ) += rTarget;
+ }
+
+ *pLinkURL = sURL;
+ *pMark = sMark;
+
+ return bBookMarkOnly;
+}
+
+bool DocxAttributeOutput::StartURL( const String& rUrl, const String& rTarget )
+{
+ String sMark;
+ String sUrl;
+
+ bool bBookmarkOnly = AnalyzeURL( rUrl, rTarget, &sUrl, &sMark );
+
+ if ( sMark.Len() && !bBookmarkOnly )
+ {
+ m_rExport.OutputField( NULL, ww::eHYPERLINK, sUrl );
+ }
+ else
+ {
+ // Output a hyperlink XML element
+
+ m_pHyperlinkAttrList = m_pSerializer->createAttrList();
+ if ( !bBookmarkOnly )
+ {
+ OUString osUrl( sUrl );
+
+ ::rtl::OString sId = m_rExport.AddRelation(
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink" ),
+ osUrl, S("External") );
+ m_pHyperlinkAttrList->add( FSNS( XML_r, XML_id), sId.getStr());
+ }
+ else
+ m_pHyperlinkAttrList->add( FSNS( XML_w, XML_anchor ),
+ OUStringToOString( OUString( sMark ), RTL_TEXTENCODING_UTF8 ).getStr( ) );
+
+ OUString sTarget( rTarget );
+ if ( sTarget.getLength( ) > 0 )
+ {
+ OString soTarget = OUStringToOString( sTarget, RTL_TEXTENCODING_UTF8 );
+ m_pHyperlinkAttrList->add(FSNS( XML_w, XML_tgtFrame ), soTarget.getStr());
+ }
+ }
+
+ return true;
+}
+
+bool DocxAttributeOutput::EndURL()
+{
+ return true;
+}
+
+void DocxAttributeOutput::FieldVanish( const String& rTxt, ww::eField eType )
+{
+ WriteField_Impl( NULL, eType, rTxt, WRITEFIELD_ALL );
+}
+
+void DocxAttributeOutput::Redline( const SwRedlineData* /*pRedline*/ )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::Redline( const SwRedlineData* pRedline )\n" );
+}
+
+/// Append the number as 2-digit when less than 10.
+static void impl_AppendTwoDigits( OStringBuffer &rBuffer, sal_Int32 nNum )
+{
+ if ( nNum < 0 || nNum > 99 )
+ {
+ rBuffer.append( "00" );
+ return;
+ }
+
+ if ( nNum < 10 )
+ rBuffer.append( '0' );
+
+ rBuffer.append( nNum );
+}
+
+/** Convert DateTime to xsd::dateTime string.
+
+I guess there must be an implementation of this somewhere in OOo, but I failed
+to find it, unfortunately :-(
+*/
+static OString impl_DateTimeToOString( const DateTime& rDateTime )
+{
+ DateTime aInUTC( rDateTime );
+ aInUTC.ConvertToUTC();
+
+ OStringBuffer aBuffer( 25 );
+ aBuffer.append( sal_Int32( aInUTC.GetYear() ) );
+ aBuffer.append( '-' );
+
+ impl_AppendTwoDigits( aBuffer, aInUTC.GetMonth() );
+ aBuffer.append( '-' );
+
+ impl_AppendTwoDigits( aBuffer, aInUTC.GetDay() );
+ aBuffer.append( 'T' );
+
+ impl_AppendTwoDigits( aBuffer, aInUTC.GetHour() );
+ aBuffer.append( ':' );
+
+ impl_AppendTwoDigits( aBuffer, aInUTC.GetMin() );
+ aBuffer.append( ':' );
+
+ impl_AppendTwoDigits( aBuffer, aInUTC.GetSec() );
+ aBuffer.append( 'Z' ); // we are in UTC
+
+ return aBuffer.makeStringAndClear();
+}
+
+void DocxAttributeOutput::StartRedline( const SwRedlineData* pRedlineData )
+{
+ m_pRedlineData = pRedlineData;
+
+ if ( !m_pRedlineData )
+ return;
+
+ // FIXME check if it's necessary to travel over the Next()'s in pRedlineData
+
+ OString aId( OString::valueOf( m_nRedlineId++ ) );
+
+ const String &rAuthor( SW_MOD()->GetRedlineAuthor( pRedlineData->GetAuthor() ) );
+ OString aAuthor( OUStringToOString( rAuthor, RTL_TEXTENCODING_UTF8 ) );
+
+ OString aDate( impl_DateTimeToOString( pRedlineData->GetTimeStamp() ) );
+
+ switch ( pRedlineData->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ m_pSerializer->startElementNS( XML_w, XML_ins,
+ FSNS( XML_w, XML_id ), aId.getStr(),
+ FSNS( XML_w, XML_author ), aAuthor.getStr(),
+ FSNS( XML_w, XML_date ), aDate.getStr(),
+ FSEND );
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE:
+ m_pSerializer->startElementNS( XML_w, XML_del,
+ FSNS( XML_w, XML_id ), aId.getStr(),
+ FSNS( XML_w, XML_author ), aAuthor.getStr(),
+ FSNS( XML_w, XML_date ), aDate.getStr(),
+ FSEND );
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ OSL_TRACE( "TODO DocxAttributeOutput::StartRedline()\n" );
+ default:
+ break;
+ }
+}
+
+void DocxAttributeOutput::EndRedline()
+{
+ if ( !m_pRedlineData )
+ return;
+
+ switch ( m_pRedlineData->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ m_pSerializer->endElementNS( XML_w, XML_ins );
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE:
+ m_pSerializer->endElementNS( XML_w, XML_del );
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ OSL_TRACE( "TODO DocxAttributeOutput::EndRedline()\n" );
+ break;
+ default:
+ break;
+ }
+
+ m_pRedlineData = NULL;
+}
+
+void DocxAttributeOutput::FormatDrop( const SwTxtNode& /*rNode*/, const SwFmtDrop& /*rSwFmtDrop*/, sal_uInt16 /*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::FormatDrop( const SwTxtNode& rNode, const SwFmtDrop& rSwFmtDrop, sal_uInt16 nStyle )\n" );
+}
+
+void DocxAttributeOutput::ParagraphStyle( sal_uInt16 nStyle )
+{
+ OString aStyleId( "style" );
+ aStyleId += OString::valueOf( sal_Int32( nStyle ) );
+
+ m_pSerializer->singleElementNS( XML_w, XML_pStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
+}
+
+static OString impl_ConvertColor( const Color &rColor )
+{
+ OString color( "auto" );
+ if ( rColor.GetColor() != COL_AUTO )
+ {
+ const char pHexDigits[] = "0123456789ABCDEF";
+ char pBuffer[] = "000000";
+
+ pBuffer[0] = pHexDigits[ ( rColor.GetRed() >> 4 ) & 0x0F ];
+ pBuffer[1] = pHexDigits[ rColor.GetRed() & 0x0F ];
+ pBuffer[2] = pHexDigits[ ( rColor.GetGreen() >> 4 ) & 0x0F ];
+ pBuffer[3] = pHexDigits[ rColor.GetGreen() & 0x0F ];
+ pBuffer[4] = pHexDigits[ ( rColor.GetBlue() >> 4 ) & 0x0F ];
+ pBuffer[5] = pHexDigits[ rColor.GetBlue() & 0x0F ];
+
+ color = OString( pBuffer );
+ }
+ return color;
+}
+
+static void impl_borderLine( FSHelperPtr pSerializer, sal_Int32 elementToken, const SvxBorderLine* pBorderLine, sal_uInt16 nDist )
+{
+ FastAttributeList* pAttr = pSerializer->createAttrList();
+
+
+ // Compute val attribute value
+ // Can be one of:
+ // single, double,
+ // basicWideOutline, basicWideInline
+ // OOXml also supports those types of borders, but we'll try to play with the first ones.
+ // thickThinMediumGap, thickThinLargeGap, thickThinSmallGap
+ // thinThickLargeGap, thinThickMediumGap, thinThickSmallGap
+ const char* pVal = "none";
+ if ( !pBorderLine->isEmpty( ) )
+ {
+ switch ( pBorderLine->GetStyle( ) )
+ {
+ case ::editeng::SOLID:
+ pVal = ( sal_Char* )"single";
+ break;
+ case ::editeng::DOTTED:
+ pVal = ( sal_Char* )"dotted";
+ break;
+ case ::editeng::DASHED:
+ pVal = ( sal_Char* )"dashed";
+ break;
+ case ::editeng::DOUBLE:
+ pVal = ( sal_Char* )"double";
+ break;
+ case ::editeng::THINTHICK_SMALLGAP:
+ pVal = ( sal_Char* )"thinThickSmallGap";
+ break;
+ case ::editeng::THINTHICK_MEDIUMGAP:
+ pVal = ( sal_Char* )"thinThickMediumGap";
+ break;
+ case ::editeng::THINTHICK_LARGEGAP:
+ pVal = ( sal_Char* )"thinThickLargeGap";
+ break;
+ case ::editeng::THICKTHIN_SMALLGAP:
+ pVal = ( sal_Char* )"thickThinSmallGap";
+ break;
+ case ::editeng::THICKTHIN_MEDIUMGAP:
+ pVal = ( sal_Char* )"thickThinMediumGap";
+ break;
+ case ::editeng::THICKTHIN_LARGEGAP:
+ pVal = ( sal_Char* )"thickThinLargeGap";
+ break;
+ case ::editeng::EMBOSSED:
+ pVal = ( sal_Char* )"threeDEmboss";
+ break;
+ case ::editeng::ENGRAVED:
+ pVal = ( sal_Char* )"threeDEngrave";
+ break;
+ case ::editeng::OUTSET:
+ pVal = ( sal_Char* )"outset";
+ break;
+ case ::editeng::INSET:
+ pVal = ( sal_Char* )"inset";
+ break;
+ case ::editeng::NO_STYLE:
+ default:
+ break;
+ }
+ }
+
+ pAttr->add( FSNS( XML_w, XML_val ), OString( pVal ) );
+
+ if ( !pBorderLine->isEmpty() )
+ {
+ // Compute the sz attribute
+
+ // The unit is the 8th of point
+ sal_Int32 nWidth = sal_Int32( pBorderLine->GetWidth() / 2.5 );
+ sal_uInt16 nMinWidth = 2;
+ sal_uInt16 nMaxWidth = 96;
+
+ if ( nWidth > nMaxWidth )
+ nWidth = nMaxWidth;
+ else if ( nWidth < nMinWidth )
+ nWidth = nMinWidth;
+
+ pAttr->add( FSNS( XML_w, XML_sz ), OString::valueOf( sal_Int32( nWidth ) ) );
+
+ // Get the distance (in pt)
+ pAttr->add( FSNS( XML_w, XML_space ), OString::valueOf( sal_Int32( nDist / 20 ) ) );
+
+ // Get the color code as an RRGGBB hex value
+ OString sColor( impl_ConvertColor( pBorderLine->GetColor( ) ) );
+ pAttr->add( FSNS( XML_w, XML_color ), sColor );
+ }
+
+ XFastAttributeListRef xAttrs( pAttr );
+ pSerializer->singleElementNS( XML_w, elementToken, xAttrs );
+}
+
+static void impl_pageBorders( FSHelperPtr pSerializer, const SvxBoxItem& rBox, bool bUseStartEnd = false )
+{
+ static const sal_uInt16 aBorders[] =
+ {
+ BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
+ };
+
+ const sal_Int32 aXmlElements[] =
+ {
+ XML_top,
+ bUseStartEnd ? XML_start : XML_left,
+ XML_bottom,
+ bUseStartEnd ? XML_end : XML_right
+ };
+ const sal_uInt16* pBrd = aBorders;
+ for( int i = 0; i < 4; ++i, ++pBrd )
+ {
+ const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
+ if ( pLn )
+ impl_borderLine( pSerializer, aXmlElements[i], pLn, 0 );
+ }
+}
+
+void DocxAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ m_pSerializer->startElementNS( XML_w, XML_tcPr, FSEND );
+
+ const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
+
+ bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
+
+ // Cell prefered width
+ SwTwips nWidth = GetGridCols( pTableTextNodeInfoInner )->at( pTableTextNodeInfoInner->getCell() );
+ m_pSerializer->singleElementNS( XML_w, XML_tcW,
+ FSNS( XML_w, XML_w ), OString::valueOf( sal_Int32( nWidth ) ).getStr( ),
+ FSNS( XML_w, XML_type ), "dxa",
+ FSEND );
+
+ // Horizontal spans
+ const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
+ SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
+ SwWriteTableCell *pCell = pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
+
+ sal_uInt16 nColSpan = pCell->GetColSpan();
+ if ( nColSpan > 1 )
+ m_pSerializer->singleElementNS( XML_w, XML_gridSpan,
+ FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nColSpan ) ).getStr(),
+ FSEND );
+
+ // Vertical merges
+ long vSpan = pTblBox->getRowSpan( );
+ if ( vSpan > 1 )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_vMerge,
+ FSNS( XML_w, XML_val ), "restart",
+ FSEND );
+ }
+ else if ( vSpan < 0 )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_vMerge,
+ FSNS( XML_w, XML_val ), "continue",
+ FSEND );
+ }
+
+ // The cell borders
+ m_pSerializer->startElementNS( XML_w, XML_tcBorders, FSEND );
+ SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
+ impl_pageBorders( m_pSerializer, pFmt->GetBox( ), !bEcma );
+ m_pSerializer->endElementNS( XML_w, XML_tcBorders );
+
+ TableBackgrounds( pTableTextNodeInfoInner );
+
+ // Cell margins
+ m_pSerializer->startElementNS( XML_w, XML_tcMar, FSEND );
+ const SvxBoxItem& rBox = pFmt->GetBox( );
+ static const sal_uInt16 aBorders[] =
+ {
+ BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
+ };
+
+ const sal_Int32 aXmlElements[] =
+ {
+ XML_top,
+ bEcma ? XML_left : XML_start,
+ XML_bottom,
+ bEcma ? XML_right : XML_end
+ };
+ const sal_uInt16* pBrd = aBorders;
+ for( int i = 0; i < 4; ++i, ++pBrd )
+ {
+ sal_Int32 nDist = sal_Int32( rBox.GetDistance( *pBrd ) );
+ m_pSerializer->singleElementNS( XML_w, aXmlElements[i],
+ FSNS( XML_w, XML_w ), OString::valueOf( nDist ).getStr( ),
+ FSNS( XML_w, XML_type ), "dxa",
+ FSEND );
+ }
+
+ m_pSerializer->endElementNS( XML_w, XML_tcMar );
+
+ TableVerticalCell( pTableTextNodeInfoInner );
+
+ m_pSerializer->endElementNS( XML_w, XML_tcPr );
+}
+
+void DocxAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ sal_uInt32 nPageSize = 0;
+ bool bRelBoxSize = false;
+
+ // Create the SwWriteTable instance to use col spans (and maybe other infos)
+ GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
+
+ const SwTable* pTable = pTableTextNodeInfoInner->getTable( );
+ const SwFrmFmt *pFmt = pTable->GetFrmFmt( );
+ SwTwips nTblSz = pFmt->GetFrmSize( ).GetWidth( );
+
+ const SwHTMLTableLayout *pLayout = pTable->GetHTMLTableLayout();
+ if( pLayout && pLayout->IsExportable() )
+ m_pTableWrt = new SwWriteTable( pLayout );
+ else
+ m_pTableWrt = new SwWriteTable( pTable->GetTabLines(), (sal_uInt16)nPageSize,
+ (sal_uInt16)nTblSz, false);
+}
+
+void DocxAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ m_pSerializer->startElementNS( XML_w, XML_tbl, FSEND );
+
+ InitTableHelper( pTableTextNodeInfoInner );
+ TableDefinition( pTableTextNodeInfoInner );
+}
+
+void DocxAttributeOutput::EndTable()
+{
+ m_pSerializer->endElementNS( XML_w, XML_tbl );
+
+ if ( m_nTableDepth > 0 )
+ --m_nTableDepth;
+
+ // We closed the table; if it is a nested table, the cell that contains it
+ // still continues
+ m_bTableCellOpen = true;
+
+ // Cleans the table helper
+ delete m_pTableWrt, m_pTableWrt = NULL;
+}
+
+void DocxAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ m_pSerializer->startElementNS( XML_w, XML_tr, FSEND );
+
+ // Output the row properties
+ m_pSerializer->startElementNS( XML_w, XML_trPr, FSEND );
+
+ // Header row: tblHeader
+ const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
+ if ( pTable->GetRowsToRepeat( ) > pTableTextNodeInfoInner->getRow( ) )
+ m_pSerializer->singleElementNS( XML_w, XML_tblHeader,
+ FSNS( XML_w, XML_val ), "true",
+ FSEND );
+
+ TableHeight( pTableTextNodeInfoInner );
+ TableCanSplit( pTableTextNodeInfoInner );
+
+ m_pSerializer->endElementNS( XML_w, XML_trPr );
+}
+
+void DocxAttributeOutput::EndTableRow( )
+{
+ m_pSerializer->endElementNS( XML_w, XML_tr );
+}
+
+void DocxAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ if ( !m_pTableWrt )
+ InitTableHelper( pTableTextNodeInfoInner );
+
+ m_pSerializer->startElementNS( XML_w, XML_tc, FSEND );
+
+ // Write the cell properties here
+ TableCellProperties( pTableTextNodeInfoInner );
+
+ m_bTableCellOpen = true;
+}
+
+void DocxAttributeOutput::EndTableCell( )
+{
+ m_pSerializer->endElementNS( XML_w, XML_tc );
+
+ m_bTableCellOpen = false;
+}
+
+void DocxAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
+{
+}
+
+void DocxAttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfo*/ )
+{
+}
+
+void DocxAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
+
+ // Write the table properties
+ m_pSerializer->startElementNS( XML_w, XML_tblPr, FSEND );
+
+ sal_uInt32 nPageSize = 0;
+ bool bRelBoxSize = false;
+
+ // Create the SwWriteTable instance to use col spans (and maybe other infos)
+ GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
+
+ // Output the table prefered width
+ if ( nPageSize != 0 )
+ m_pSerializer->singleElementNS( XML_w, XML_tblW,
+ FSNS( XML_w, XML_w ), OString::valueOf( sal_Int32( nPageSize ) ).getStr( ),
+ FSNS( XML_w, XML_type ), "dxa",
+ FSEND );
+
+ // Output the table alignement
+ const SwTable *pTable = pTableTextNodeInfoInner->getTable();
+ SwFrmFmt *pTblFmt = pTable->GetFrmFmt( );
+ const char* pJcVal;
+ sal_Int32 nIndent = 0;
+ switch ( pTblFmt->GetHoriOrient( ).GetHoriOrient( ) )
+ {
+ case text::HoriOrientation::CENTER:
+ pJcVal = "center";
+ break;
+ case text::HoriOrientation::RIGHT:
+ if ( bEcma )
+ pJcVal = "right";
+ else
+ pJcVal = "end";
+ break;
+ default:
+ case text::HoriOrientation::NONE:
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ {
+ if ( bEcma )
+ pJcVal = "left";
+ else
+ pJcVal = "start";
+ nIndent = sal_Int32( pTblFmt->GetLRSpace( ).GetLeft( ) );
+ break;
+ }
+ }
+ m_pSerializer->singleElementNS( XML_w, XML_jc,
+ FSNS( XML_w, XML_val ), pJcVal,
+ FSEND );
+
+ // Output the table borders
+ TableDefaultBorders( pTableTextNodeInfoInner );
+ TableBidi( pTableTextNodeInfoInner );
+
+ // Table indent
+ if ( nIndent != 0 )
+ m_pSerializer->singleElementNS( XML_w, XML_tblInd,
+ FSNS( XML_w, XML_w ), OString::valueOf( nIndent ).getStr( ),
+ FSNS( XML_w, XML_type ), "dxa",
+ FSEND );
+
+ m_pSerializer->endElementNS( XML_w, XML_tblPr );
+
+ // Write the table grid infos
+ m_pSerializer->startElementNS( XML_w, XML_tblGrid, FSEND );
+
+ ww8::GridColsPtr pGridCols = GetGridCols( pTableTextNodeInfoInner );
+ for ( ww8::GridCols::const_iterator it = pGridCols->begin(); it != pGridCols->end(); ++it )
+ m_pSerializer->singleElementNS( XML_w, XML_gridCol,
+ FSNS( XML_w, XML_w ), OString::valueOf( sal_Int32( *it ) ).getStr( ),
+ FSEND );
+
+ m_pSerializer->endElementNS( XML_w, XML_tblGrid );
+}
+
+void DocxAttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
+
+ bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
+
+ // the defaults of the table are taken from the top-left cell
+ m_pSerializer->startElementNS( XML_w, XML_tblBorders, FSEND );
+ impl_pageBorders( m_pSerializer, pFrmFmt->GetBox( ), !bEcma );
+ m_pSerializer->endElementNS( XML_w, XML_tblBorders );
+}
+
+void DocxAttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
+ const SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
+ const SfxPoolItem *pI = NULL;
+
+ Color aColor;
+ if ( SFX_ITEM_ON == pFmt->GetAttrSet().GetItemState( RES_BACKGROUND, false, &pI ) )
+ aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
+ else
+ aColor = COL_AUTO;
+
+ OString sColor = impl_ConvertColor( aColor );
+ m_pSerializer->singleElementNS( XML_w, XML_shd,
+ FSNS( XML_w, XML_fill ), sColor.getStr( ),
+ FSNS( XML_w, XML_val ), "clear",
+ FSEND );
+}
+
+void DocxAttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
+
+ const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
+ if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
+ {
+ sal_Int32 nHeight = rLSz.GetHeight();
+ const char *pRule = NULL;
+
+ switch ( rLSz.GetHeightSizeType() )
+ {
+ case ATT_FIX_SIZE: pRule = "exact"; break;
+ case ATT_MIN_SIZE: pRule = "atLeast"; break;
+ default: break;
+ }
+
+ if ( pRule )
+ m_pSerializer->singleElementNS( XML_w, XML_trHeight,
+ FSNS( XML_w, XML_val ), OString::valueOf( nHeight ).getStr( ),
+ FSNS( XML_w, XML_hRule ), pRule,
+ FSEND );
+ }
+}
+
+void DocxAttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
+
+ const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit( );
+ const char* pCantSplit = ( !rSplittable.GetValue( ) ) ? "true" : "false";
+
+ m_pSerializer->singleElementNS( XML_w, XML_cantSplit,
+ FSNS( XML_w, XML_val ), pCantSplit,
+ FSEND );
+}
+
+void DocxAttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTable * pTable = pTableTextNodeInfoInner->getTable();
+ const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
+
+ if ( m_rExport.TrueFrameDirection( *pFrmFmt ) == FRMDIR_HORI_RIGHT_TOP )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_bidiVisual,
+ FSNS( XML_w, XML_val ), "true",
+ FSEND );
+ }
+}
+
+void DocxAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwFrmFmt *pFrmFmt = pTabBox->GetFrmFmt( );
+
+ if ( FRMDIR_VERT_TOP_RIGHT == m_rExport.TrueFrameDirection( *pFrmFmt ) )
+ m_pSerializer->singleElementNS( XML_w, XML_textDirection,
+ FSNS( XML_w, XML_val ), "tbRl",
+ FSEND );
+}
+
+void DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t /*pNodeInfo*/ )
+{
+ OSL_TRACE( "TODO: DocxAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo )\n" );
+}
+
+void DocxAttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
+{
+ // This is called when the nested table ends in a cell, and there's no
+ // paragraph benhind that; so we must check for the ends of cell, rows,
+ // tables
+ // ['true' to write an empty paragraph, MS Word insists on that]
+ FinishTableRowCell( pNodeInfoInner, true );
+}
+
+void DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
+{
+ OSL_TRACE( "TODO: DocxAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )\n" );
+}
+
+void DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
+{
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "TODO: DocxAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )\n" );
+#endif
+}
+
+void DocxAttributeOutput::TableRowEnd( sal_uInt32 /*nDepth*/ )
+{
+ OSL_TRACE( "TODO: DocxAttributeOutput::TableRowEnd( sal_uInt32 nDepth = 1 )\n" );
+}
+
+void DocxAttributeOutput::StartStyles()
+{
+ m_pSerializer->startElementNS( XML_w, XML_styles,
+ FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
+ FSEND );
+}
+
+void DocxAttributeOutput::EndStyles( sal_uInt16 /*nNumberOfStyles*/ )
+{
+ m_pSerializer->endElementNS( XML_w, XML_styles );
+}
+
+void DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )
+{
+ // are these the values of enum ww::sti (see ../inc/wwstyles.hxx)?
+#if OSL_DEBUG_LEVEL > 1
+ OSL_TRACE( "TODO DocxAttributeOutput::DefaultStyle( sal_uInt16 nStyle )- %d\n", nStyle );
+#else
+ (void) nStyle; // to quiet the warning
+#endif
+}
+
+void DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode& rGrfNode, const Size& rSize )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::FlyFrameGraphic( const SwGrfNode& rGrfNode, const Size& rSize ) - some stuff still missing\n" );
+ // create the relation ID
+ OString aRelId;
+ sal_Int32 nImageType;
+ if ( rGrfNode.IsLinkedFile() )
+ {
+ // linked image, just create the relation
+ String aFileName;
+ rGrfNode.GetFileFilterNms( &aFileName, 0 );
+
+ // TODO Convert the file name to relative for better interoperability
+
+ aRelId = m_rExport.AddRelation(
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image" ),
+ OUString( aFileName ),
+ S( "External" ) );
+
+ nImageType = XML_link;
+ }
+ else
+ {
+ // inline, we also have to write the image itself
+ Graphic& rGraphic = const_cast< Graphic& >( rGrfNode.GetGrf() );
+
+ m_rDrawingML.SetFS( m_pSerializer ); // to be sure that we write to the right stream
+ OUString aImageId = m_rDrawingML.WriteImage( rGraphic );
+
+ aRelId = OUStringToOString( aImageId, RTL_TEXTENCODING_UTF8 );
+
+ nImageType = XML_embed;
+ }
+
+ if ( aRelId.getLength() == 0 )
+ return;
+
+ m_pSerializer->startElementNS( XML_w, XML_drawing,
+ FSEND );
+ bool isAnchor = rGrfNode.GetFlyFmt()->GetAnchor().GetAnchorId() != FLY_AS_CHAR;
+ if( isAnchor )
+ {
+ m_pSerializer->startElementNS( XML_wp, XML_anchor,
+ XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0", XML_simplePos, "0",
+ XML_relativeHeight, "0", // TODO
+ XML_behindDoc, rGrfNode.GetFlyFmt()->GetOpaque().GetValue() ? "0" : "1",
+ XML_locked, "0", XML_layoutInCell, "1", XML_allowOverlap, "1", // TODO
+ FSEND );
+ m_pSerializer->singleElementNS( XML_wp, XML_simplePos, XML_x, "0", XML_y, "0", FSEND ); // required, unused
+ const char* relativeFromH;
+ const char* relativeFromV;
+ switch( rGrfNode.GetFlyFmt()->GetAnchor().GetAnchorId())
+ {
+ case FLY_AT_PAGE:
+ relativeFromV = relativeFromH = "page";
+ break;
+ case FLY_AT_PARA:
+ relativeFromH = "column";
+ relativeFromV = "paragraph";
+ break;
+ case FLY_AT_CHAR:
+ default:
+ relativeFromH = "character";
+ relativeFromV = "line";
+ break;
+ };
+ Point pos( 0, 0 );
+ if( SwFlyFrmFmt* flyfmt = dynamic_cast<SwFlyFrmFmt*>(rGrfNode.GetFlyFmt())) // TODO is always true?
+ pos = flyfmt->GetAnchoredObj()->GetCurrRelPos();
+ OString x( OString::valueOf( TwipsToEMU( pos.X())));
+ OString y( OString::valueOf( TwipsToEMU( pos.Y())));
+ m_pSerializer->startElementNS( XML_wp, XML_positionH, XML_relativeFrom, relativeFromH, FSEND );
+ m_pSerializer->startElementNS( XML_wp, XML_posOffset, FSEND );
+ m_pSerializer->write( x );
+ m_pSerializer->endElementNS( XML_wp, XML_posOffset );
+ m_pSerializer->endElementNS( XML_wp, XML_positionH );
+ m_pSerializer->startElementNS( XML_wp, XML_positionV, XML_relativeFrom, relativeFromV, FSEND );
+ m_pSerializer->startElementNS( XML_wp, XML_posOffset, FSEND );
+ m_pSerializer->write( y );
+ m_pSerializer->endElementNS( XML_wp, XML_posOffset );
+ m_pSerializer->endElementNS( XML_wp, XML_positionV );
+ }
+ else
+ {
+ m_pSerializer->startElementNS( XML_wp, XML_inline,
+ XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0",
+ FSEND );
+ }
+ // now the common parts
+ // extent of the image
+ OString aWidth( OString::valueOf( TwipsToEMU( rSize.Width() ) ) );
+ OString aHeight( OString::valueOf( TwipsToEMU( rSize.Height() ) ) );
+ m_pSerializer->singleElementNS( XML_wp, XML_extent,
+ XML_cx, aWidth.getStr(),
+ XML_cy, aHeight.getStr(),
+ FSEND );
+ // TODO - the right effectExtent, extent including the effect
+ m_pSerializer->singleElementNS( XML_wp, XML_effectExtent,
+ XML_l, "0", XML_t, "0", XML_r, "0", XML_b, "0",
+ FSEND );
+
+ if( isAnchor )
+ {
+ switch( rGrfNode.GetFlyFmt()->GetSurround().GetValue())
+ {
+ case SURROUND_NONE:
+ m_pSerializer->singleElementNS( XML_wp, XML_wrapTopAndBottom, FSEND );
+ break;
+ case SURROUND_THROUGHT:
+ m_pSerializer->singleElementNS( XML_wp, XML_wrapNone, FSEND );
+ break;
+ case SURROUND_PARALLEL:
+ m_pSerializer->singleElementNS( XML_wp, XML_wrapSquare,
+ XML_wrapText, "bothSides", FSEND );
+ break;
+ case SURROUND_IDEAL:
+ default:
+ m_pSerializer->singleElementNS( XML_wp, XML_wrapSquare,
+ XML_wrapText, "largest", FSEND );
+ break;
+ }
+ }
+ // picture description
+ // TODO the right image description
+ m_pSerializer->startElementNS( XML_wp, XML_docPr,
+ XML_id, "1",
+ XML_name, "Picture",
+ XML_descr, "A description...",
+ FSEND );
+ // TODO hyperlink
+ // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
+ // FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
+ // FSNS( XML_r, XML_id ), "rId4",
+ // FSEND );
+ m_pSerializer->endElementNS( XML_wp, XML_docPr );
+
+ m_pSerializer->startElementNS( XML_wp, XML_cNvGraphicFramePr,
+ FSEND );
+ // TODO change aspect?
+ m_pSerializer->singleElementNS( XML_a, XML_graphicFrameLocks,
+ FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
+ XML_noChangeAspect, "1",
+ FSEND );
+ m_pSerializer->endElementNS( XML_wp, XML_cNvGraphicFramePr );
+
+ m_pSerializer->startElementNS( XML_a, XML_graphic,
+ FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
+ FSEND );
+ m_pSerializer->startElementNS( XML_a, XML_graphicData,
+ XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/picture",
+ FSEND );
+
+ m_pSerializer->startElementNS( XML_pic, XML_pic,
+ FSNS( XML_xmlns, XML_pic ), "http://schemas.openxmlformats.org/drawingml/2006/picture",
+ FSEND );
+
+ m_pSerializer->startElementNS( XML_pic, XML_nvPicPr,
+ FSEND );
+ // TODO the right image description
+ m_pSerializer->startElementNS( XML_pic, XML_cNvPr,
+ XML_id, "0",
+ XML_name, "Picture",
+ XML_descr, "A description...",
+ FSEND );
+ // TODO hyperlink
+ // m_pSerializer->singleElementNS( XML_a, XML_hlinkClick,
+ // FSNS( XML_r, XML_id ), "rId4",
+ // FSEND );
+ m_pSerializer->endElementNS( XML_pic, XML_cNvPr );
+
+ m_pSerializer->startElementNS( XML_pic, XML_cNvPicPr,
+ FSEND );
+ // TODO change aspect?
+ m_pSerializer->singleElementNS( XML_a, XML_picLocks,
+ XML_noChangeAspect, "1", XML_noChangeArrowheads, "1",
+ FSEND );
+ m_pSerializer->endElementNS( XML_pic, XML_cNvPicPr );
+ m_pSerializer->endElementNS( XML_pic, XML_nvPicPr );
+
+ // the actual picture
+ m_pSerializer->startElementNS( XML_pic, XML_blipFill,
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_blip,
+ FSNS( XML_r, nImageType ), aRelId.getStr(),
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_srcRect,
+ FSEND );
+ m_pSerializer->startElementNS( XML_a, XML_stretch,
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_fillRect,
+ FSEND );
+ m_pSerializer->endElementNS( XML_a, XML_stretch );
+ m_pSerializer->endElementNS( XML_pic, XML_blipFill );
+
+ // TODO setup the right values below
+ m_pSerializer->startElementNS( XML_pic, XML_spPr,
+ XML_bwMode, "auto",
+ FSEND );
+ m_pSerializer->startElementNS( XML_a, XML_xfrm,
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_off,
+ XML_x, "0", XML_y, "0",
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_ext,
+ XML_cx, aWidth.getStr(),
+ XML_cy, aHeight.getStr(),
+ FSEND );
+ m_pSerializer->endElementNS( XML_a, XML_xfrm );
+ m_pSerializer->startElementNS( XML_a, XML_prstGeom,
+ XML_prst, "rect",
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_avLst,
+ FSEND );
+ m_pSerializer->endElementNS( XML_a, XML_prstGeom );
+ m_pSerializer->singleElementNS( XML_a, XML_noFill,
+ FSEND );
+ m_pSerializer->startElementNS( XML_a, XML_ln,
+ XML_w, "9525",
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_noFill,
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_miter,
+ XML_lim, "800000",
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_headEnd,
+ FSEND );
+ m_pSerializer->singleElementNS( XML_a, XML_tailEnd,
+ FSEND );
+ m_pSerializer->endElementNS( XML_a, XML_ln );
+ m_pSerializer->endElementNS( XML_pic, XML_spPr );
+
+ m_pSerializer->endElementNS( XML_pic, XML_pic );
+
+ m_pSerializer->endElementNS( XML_a, XML_graphicData );
+ m_pSerializer->endElementNS( XML_a, XML_graphic );
+ m_pSerializer->endElementNS( XML_wp, isAnchor ? XML_anchor : XML_inline );
+
+ m_pSerializer->endElementNS( XML_w, XML_drawing );
+}
+
+void DocxAttributeOutput::WriteOLE2Obj( const SdrObject* pSdrObj, const Size& rSize )
+{
+ uno::Reference< chart2::XChartDocument > xChartDoc;
+ uno::Reference< drawing::XShape > xShape( ((SdrObject*)pSdrObj)->getUnoShape(), uno::UNO_QUERY );
+ if( xShape.is() )
+ {
+ uno::Reference< beans::XPropertySet > xPropSet( xShape, uno::UNO_QUERY );
+ if( xPropSet.is() )
+ xChartDoc.set( xPropSet->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Model")) ), uno::UNO_QUERY );
+ }
+
+ if( xChartDoc.is() )
+ {
+ OSL_TRACE("DocxAttributeOutput::WriteOLE2Obj: export chart ");
+ m_pSerializer->startElementNS( XML_w, XML_drawing,
+ FSEND );
+ m_pSerializer->startElementNS( XML_wp, XML_inline,
+ XML_distT, "0", XML_distB, "0", XML_distL, "0", XML_distR, "0",
+ FSEND );
+
+ OString aWidth( OString::valueOf( TwipsToEMU( rSize.Width() ) ) );
+ OString aHeight( OString::valueOf( TwipsToEMU( rSize.Height() ) ) );
+ m_pSerializer->singleElementNS( XML_wp, XML_extent,
+ XML_cx, aWidth.getStr(),
+ XML_cy, aHeight.getStr(),
+ FSEND );
+ // TODO - the right effectExtent, extent including the effect
+ m_pSerializer->singleElementNS( XML_wp, XML_effectExtent,
+ XML_l, "0", XML_t, "0", XML_r, "0", XML_b, "0",
+ FSEND );
+
+ // should get the unique id
+ sal_Int32 nID = 1;
+ OUString sName(RTL_CONSTASCII_USTRINGPARAM("Object 1"));
+ uno::Reference< container::XNamed > xNamed( xShape, uno::UNO_QUERY );
+ if( xNamed.is() )
+ sName = xNamed->getName();
+
+ m_pSerializer->singleElementNS( XML_wp, XML_docPr,
+ XML_id, I32S( nID ),
+ XML_name, USS( sName ),
+ FSEND );
+
+ m_pSerializer->singleElementNS( XML_wp, XML_cNvGraphicFramePr,
+ FSEND );
+
+ m_pSerializer->startElementNS( XML_a, XML_graphic,
+ FSNS( XML_xmlns, XML_a ), "http://schemas.openxmlformats.org/drawingml/2006/main",
+ FSEND );
+
+ m_pSerializer->startElementNS( XML_a, XML_graphicData,
+ XML_uri, "http://schemas.openxmlformats.org/drawingml/2006/chart",
+ FSEND );
+
+ OString aRelId;
+ static sal_Int32 nChartCount = 0;
+ nChartCount++;
+ uno::Reference< frame::XModel > xModel( xChartDoc, uno::UNO_QUERY );
+ aRelId = m_rExport.OutputChart( xModel, nChartCount );
+
+ m_pSerializer->singleElementNS( XML_c, XML_chart,
+ FSNS( XML_xmlns, XML_c ), "http://schemas.openxmlformats.org/drawingml/2006/chart",
+ FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships",
+ FSNS( XML_r, XML_id ), aRelId.getStr(),
+ FSEND );
+
+ m_pSerializer->endElementNS( XML_a, XML_graphicData );
+ m_pSerializer->endElementNS( XML_a, XML_graphic );
+ m_pSerializer->endElementNS( XML_wp, XML_inline );
+ m_pSerializer->endElementNS( XML_w, XML_drawing );
+ }
+}
+
+void DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame &rFrame, const Point& /*rNdTopLeft*/ )
+{
+ m_pSerializer->mark();
+
+ switch ( rFrame.GetWriterType() )
+ {
+ case sw::Frame::eGraphic:
+ {
+ const SwNode *pNode = rFrame.GetContent();
+ const SwGrfNode *pGrfNode = pNode ? pNode->GetGrfNode() : 0;
+ if ( pGrfNode )
+ FlyFrameGraphic( *pGrfNode, rFrame.GetLayoutSize() );
+ }
+ break;
+ case sw::Frame::eDrawing:
+ {
+ const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
+ if ( pSdrObj )
+ {
+ bool bSwapInPage = false;
+ if ( !pSdrObj->GetPage() )
+ {
+ if ( SdrModel* pModel = m_rExport.pDoc->GetDrawModel() )
+ {
+ if ( SdrPage *pPage = pModel->GetPage( 0 ) )
+ {
+ bSwapInPage = true;
+ const_cast< SdrObject* >( pSdrObj )->SetPage( pPage );
+ }
+ }
+ }
+
+ m_pSerializer->startElementNS( XML_w, XML_pict,
+ FSEND );
+
+ m_rExport.VMLExporter().AddSdrObject( *pSdrObj );
+
+ m_pSerializer->endElementNS( XML_w, XML_pict );
+
+ if ( bSwapInPage )
+ const_cast< SdrObject* >( pSdrObj )->SetPage( 0 );
+ }
+ }
+ break;
+ case sw::Frame::eTxtBox:
+ {
+ // The frame output is postponed at the end of the anchor paragraph
+ m_pParentFrame = &rFrame;
+ }
+ break;
+ case sw::Frame::eOle:
+ {
+ const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
+ if ( pSdrObj )
+ WriteOLE2Obj( pSdrObj, rFrame.GetLayoutSize() );
+ }
+ break;
+ default:
+ OSL_TRACE( "TODO DocxAttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFrame, const Point& rNdTopLeft ) - frame type '%s'\n",
+ rFrame.GetWriterType() == sw::Frame::eTxtBox? "eTxtBox":
+ ( rFrame.GetWriterType() == sw::Frame::eOle? "eOle":
+ ( rFrame.GetWriterType() == sw::Frame::eFormControl? "eFormControl": "???" ) ) );
+ break;
+ }
+
+ m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_POSTPONE );
+}
+
+void DocxAttributeOutput::StartStyle( const String& rName, bool bPapFmt,
+ sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 /*nWwId*/, sal_uInt16 nId, bool bAutoUpdate )
+{
+ OString aStyle( "style" );
+
+ m_pSerializer->startElementNS( XML_w, XML_style,
+ FSNS( XML_w, XML_type ), bPapFmt? "paragraph": "character", // FIXME is this correct?
+ FSNS( XML_w, XML_styleId ), ( aStyle + OString::valueOf( sal_Int32( nId ) ) ).getStr(),
+ FSEND );
+
+ m_pSerializer->singleElementNS( XML_w, XML_name,
+ FSNS( XML_w, XML_val ), OUStringToOString( OUString( rName ), RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+
+ if ( nBase != 0x0FFF )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_basedOn,
+ FSNS( XML_w, XML_val ), ( aStyle + OString::valueOf( sal_Int32( nBase ) ) ).getStr(),
+ FSEND );
+ }
+
+ m_pSerializer->singleElementNS( XML_w, XML_next,
+ FSNS( XML_w, XML_val ), ( aStyle + OString::valueOf( sal_Int32( nNext ) ) ).getStr(),
+ FSEND );
+
+ if ( bAutoUpdate )
+ m_pSerializer->singleElementNS( XML_w, XML_autoRedefine, FSEND );
+}
+
+void DocxAttributeOutput::EndStyle()
+{
+ m_pSerializer->endElementNS( XML_w, XML_style );
+}
+
+void DocxAttributeOutput::StartStyleProperties( bool bParProp, sal_uInt16 /*nStyle*/ )
+{
+ if ( bParProp )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
+ InitCollectedParagraphProperties();
+ }
+ else
+ {
+ m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
+ InitCollectedRunProperties();
+ }
+}
+
+void DocxAttributeOutput::EndStyleProperties( bool bParProp )
+{
+ if ( bParProp )
+ {
+ WriteCollectedParagraphProperties();
+ m_pSerializer->endElementNS( XML_w, XML_pPr );
+ }
+ else
+ {
+ WriteCollectedRunProperties();
+ m_pSerializer->endElementNS( XML_w, XML_rPr );
+ }
+}
+
+void DocxAttributeOutput::OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt& /*rNFmt*/, const SwFmt& /*rFmt*/ )
+{
+ if ( nLvl >= WW8ListManager::nMaxLevel )
+ nLvl = WW8ListManager::nMaxLevel - 1;
+
+ m_pSerializer->singleElementNS( XML_w, XML_outlineLvl,
+ FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nLvl ) ).getStr( ),
+ FSEND );
+}
+
+void DocxAttributeOutput::PageBreakBefore( bool bBreak )
+{
+ if ( bBreak )
+ m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_pageBreakBefore,
+ FSNS( XML_w, XML_val ), "false",
+ FSEND );
+}
+
+void DocxAttributeOutput::SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo )
+{
+ switch ( nC )
+ {
+ case msword::ColumnBreak:
+ // The column break should be output in the next paragraph...
+ m_nColBreakStatus = COLBRK_POSTPONE;
+ break;
+ case msword::PageBreak:
+ if ( pSectionInfo )
+ {
+ if ( !m_bParagraphOpened )
+ {
+ // Create a dummy paragraph if needed
+ m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
+
+ m_rExport.SectionProperties( *pSectionInfo );
+
+ m_pSerializer->endElementNS( XML_w, XML_pPr );
+ m_pSerializer->endElementNS( XML_w, XML_p );
+ }
+ else
+ {
+ // postpone the output of this; it has to be done inside the
+ // paragraph properties, so remember it until then
+ m_pSectionInfo = pSectionInfo;
+ }
+ }
+ else
+ {
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_br,
+ FSNS( XML_w, XML_type ), "page", FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ }
+ break;
+ default:
+ OSL_TRACE( "Unknown section break to write: %d\n", nC );
+ break;
+ }
+}
+
+void DocxAttributeOutput::StartSection()
+{
+ m_pSerializer->startElementNS( XML_w, XML_sectPr, FSEND );
+ m_bOpenedSectPr = true;
+
+ // Write the elements in the spec order
+ static const sal_Int32 aOrder[] =
+ {
+ FSNS( XML_w, XML_headerReference ),
+ FSNS( XML_w, XML_footerReference ),
+ FSNS( XML_w, XML_footnotePr ),
+ FSNS( XML_w, XML_endnotePr ),
+ FSNS( XML_w, XML_type ),
+ FSNS( XML_w, XML_pgSz ),
+ FSNS( XML_w, XML_pgMar ),
+ FSNS( XML_w, XML_paperSrc ),
+ FSNS( XML_w, XML_pgBorders ),
+ FSNS( XML_w, XML_lnNumType ),
+ FSNS( XML_w, XML_pgNumType ),
+ FSNS( XML_w, XML_cols ),
+ FSNS( XML_w, XML_formProt ),
+ FSNS( XML_w, XML_vAlign ),
+ FSNS( XML_w, XML_noEndnote ),
+ FSNS( XML_w, XML_titlePg ),
+ FSNS( XML_w, XML_textDirection ),
+ FSNS( XML_w, XML_bidi ),
+ FSNS( XML_w, XML_rtlGutter ),
+ FSNS( XML_w, XML_docGrid ),
+ FSNS( XML_w, XML_printerSettings ),
+ FSNS( XML_w, XML_sectPrChange )
+ };
+
+ // postpone the output so that we can later [in EndParagraphProperties()]
+ // prepend the properties before the run
+ sal_Int32 len = sizeof ( aOrder ) / sizeof( sal_Int32 );
+ uno::Sequence< sal_Int32 > aSeqOrder( len );
+ for ( sal_Int32 i = 0; i < len; i++ )
+ aSeqOrder[i] = aOrder[i];
+
+ m_pSerializer->mark( aSeqOrder );
+}
+
+void DocxAttributeOutput::EndSection()
+{
+ // Write the section properties
+ if ( m_pSectionSpacingAttrList )
+ {
+ XFastAttributeListRef xAttrList( m_pSectionSpacingAttrList );
+ m_pSectionSpacingAttrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_pgMar, xAttrList );
+ }
+
+ // Order the elements
+ m_pSerializer->mergeTopMarks( );
+
+ m_pSerializer->endElementNS( XML_w, XML_sectPr );
+ m_bOpenedSectPr = false;
+}
+
+void DocxAttributeOutput::SectionFormProtection( bool bProtected )
+{
+ if ( bProtected )
+ m_pSerializer->singleElementNS( XML_w, XML_formProt, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_formProt,
+ FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo )
+{
+ FastAttributeList* pAttr = m_pSerializer->createAttrList();
+ pAttr->add( FSNS( XML_w, XML_countBy ), OString::valueOf(static_cast<sal_Int32>(rLnNumInfo.GetCountBy())).getStr());
+ pAttr->add( FSNS( XML_w, XML_restart ), rLnNumInfo.IsRestartEachPage() ? "newPage" : "continuous" );
+ if( rLnNumInfo.GetPosFromLeft())
+ pAttr->add( FSNS( XML_w, XML_distance ), OString::valueOf(static_cast<sal_Int32>(rLnNumInfo.GetPosFromLeft())).getStr());
+ if( nRestartNo )
+ pAttr->add( FSNS( XML_w, XML_start ), OString::valueOf( long( nRestartNo )).getStr());
+ XFastAttributeListRef xAttrs( pAttr );
+ m_pSerializer->singleElementNS( XML_w, XML_lnNumType, xAttrs );
+}
+
+void DocxAttributeOutput::SectionTitlePage()
+{
+ m_pSerializer->singleElementNS( XML_w, XML_titlePg, FSEND );
+}
+
+void DocxAttributeOutput::SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* /*pFirstPageFmt*/ )
+{
+ // Output the margins
+
+ const SvxBoxItem& rBox = pFmt->GetBox( );
+
+ const SvxBorderLine* pBottom = rBox.GetBottom( );
+ const SvxBorderLine* pTop = rBox.GetTop( );
+ const SvxBorderLine* pLeft = rBox.GetLeft( );
+ const SvxBorderLine* pRight = rBox.GetRight( );
+
+ if ( pBottom || pTop || pLeft || pRight )
+ {
+ // All distances are relative to the text margins
+ m_pSerializer->startElementNS( XML_w, XML_pgBorders,
+ FSNS( XML_w, XML_display ), "allPages",
+ FSNS( XML_w, XML_offsetFrom ), "text",
+ FSEND );
+
+ m_pSerializer->mark();
+
+ m_pSerializer->endElementNS( XML_w, XML_pgBorders );
+ m_pSerializer->mark();
+ }
+}
+
+void DocxAttributeOutput::SectionBiDi( bool bBiDi )
+{
+ if ( bBiDi )
+ m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
+}
+
+static OString impl_NumberingType( sal_uInt16 nNumberingType )
+{
+ OString aType;
+
+ switch ( nNumberingType )
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ case SVX_NUM_CHARS_UPPER_LETTER_N: aType = "upperLetter"; break;
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ case SVX_NUM_CHARS_LOWER_LETTER_N: aType = "lowerLetter"; break;
+ case SVX_NUM_ROMAN_UPPER: aType = "upperRoman"; break;
+ case SVX_NUM_ROMAN_LOWER: aType = "lowerRoman"; break;
+
+ case SVX_NUM_ARABIC: aType = "decimal"; break;
+
+ case SVX_NUM_BITMAP:
+ case SVX_NUM_CHAR_SPECIAL: aType = "bullet"; break;
+
+ default: aType = "none"; break;
+ }
+
+ return aType;
+}
+
+void DocxAttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber )
+{
+ // FIXME Not called properly with page styles like "First Page"
+
+ FastAttributeList* pAttr = m_pSerializer->createAttrList();
+
+ // 0 means no restart: then don't output that attribute if 0
+ if ( nPageRestartNumber > 0 )
+ pAttr->add( FSNS( XML_w, XML_start ), OString::valueOf( sal_Int32( nPageRestartNumber ) ) );
+
+ // nNumType corresponds to w:fmt. See WW8Export::GetNumId() for more precisions
+ OString aFmt( impl_NumberingType( nNumType ) );
+ if ( aFmt.getLength() )
+ pAttr->add( FSNS( XML_w, XML_fmt ), aFmt.getStr() );
+
+ XFastAttributeListRef xAttrs( pAttr );
+ m_pSerializer->singleElementNS( XML_w, XML_pgNumType, xAttrs );
+
+ // see 2.6.12 pgNumType (Page Numbering Settings)
+ OSL_TRACE( "TODO DocxAttributeOutput::SectionPageNumbering()\n" );
+}
+
+void DocxAttributeOutput::SectionType( sal_uInt8 nBreakCode )
+{
+ /* break code: 0 No break, 1 New column
+ 2 New page, 3 Even page, 4 Odd page
+ */
+ const char* pType = NULL;
+ switch ( nBreakCode )
+ {
+ case 1: pType = "nextColumn"; break;
+ case 2: pType = "nextPage"; break;
+ case 3: pType = "evenPage"; break;
+ case 4: pType = "oddPage"; break;
+ default: pType = "continuous"; break;
+ }
+
+ if ( pType )
+ m_pSerializer->singleElementNS( XML_w, XML_type,
+ FSNS( XML_w, XML_val ), pType,
+ FSEND );
+}
+
+void DocxAttributeOutput::StartFont( const String& rFamilyName ) const
+{
+ m_pSerializer->startElementNS( XML_w, XML_font,
+ FSNS( XML_w, XML_name ), OUStringToOString( OUString( rFamilyName ), RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+}
+
+void DocxAttributeOutput::EndFont() const
+{
+ m_pSerializer->endElementNS( XML_w, XML_font );
+}
+
+void DocxAttributeOutput::FontAlternateName( const String& rName ) const
+{
+ m_pSerializer->singleElementNS( XML_w, XML_altName,
+ FSNS( XML_w, XML_val ), OUStringToOString( OUString( rName ), RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+}
+
+void DocxAttributeOutput::FontCharset( sal_uInt8 nCharSet, rtl_TextEncoding nEncoding ) const
+{
+ FastAttributeList* pAttr = m_pSerializer->createAttrList();
+
+ OString aCharSet( OString::valueOf( sal_Int32( nCharSet ), 16 ) );
+ if ( aCharSet.getLength() == 1 )
+ aCharSet = OString( "0" ) + aCharSet;
+ pAttr->add( FSNS( XML_w, XML_val ), aCharSet.getStr());
+
+ if( GetExport().GetFilter().getVersion( ) != oox::core::ECMA_DIALECT )
+ {
+ if( const char* charset = rtl_getMimeCharsetFromTextEncoding( nEncoding ))
+ pAttr->add( FSNS( XML_w, XML_characterSet ), charset );
+ }
+
+ m_pSerializer->singleElementNS( XML_w, XML_charset, XFastAttributeListRef( pAttr ));
+}
+
+void DocxAttributeOutput::FontFamilyType( FontFamily eFamily ) const
+{
+ const char *pFamily = NULL;
+ switch ( eFamily )
+ {
+ case FAMILY_ROMAN: pFamily = "roman"; break;
+ case FAMILY_SWISS: pFamily = "swiss"; break;
+ case FAMILY_MODERN: pFamily = "modern"; break;
+ case FAMILY_SCRIPT: pFamily = "script"; break;
+ case FAMILY_DECORATIVE: pFamily = "decorative"; break;
+ default: pFamily = "auto"; break; // no font family
+ }
+
+ if ( pFamily )
+ m_pSerializer->singleElementNS( XML_w, XML_family,
+ FSNS( XML_w, XML_val ), pFamily,
+ FSEND );
+}
+
+void DocxAttributeOutput::FontPitchType( FontPitch ePitch ) const
+{
+ const char *pPitch = NULL;
+ switch ( ePitch )
+ {
+ case PITCH_VARIABLE: pPitch = "variable"; break;
+ case PITCH_FIXED: pPitch = "fixed"; break;
+ default: pPitch = "default"; break; // no info about the pitch
+ }
+
+ if ( pPitch )
+ m_pSerializer->singleElementNS( XML_w, XML_pitch,
+ FSNS( XML_w, XML_val ), pPitch,
+ FSEND );
+}
+
+void DocxAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
+{
+ // nId is the same both for abstract numbering definition as well as the
+ // numbering definition itself
+ // TODO check that this is actually true & fix if not ;-)
+ OString aId( OString::valueOf( sal_Int32( nId ) ) );
+
+ m_pSerializer->startElementNS( XML_w, XML_num,
+ FSNS( XML_w, XML_numId ), aId.getStr(),
+ FSEND );
+
+ m_pSerializer->singleElementNS( XML_w, XML_abstractNumId,
+ FSNS( XML_w, XML_val ), aId.getStr(),
+ FSEND );
+
+#if OSL_DEBUG_LEVEL > 1
+ // TODO ww8 version writes this, anything to do about it here?
+ if ( rRule.IsContinusNum() )
+ OSL_TRACE( "TODO DocxAttributeOutput::NumberingDefinition()\n" );
+#else
+ (void) rRule; // to quiet the warning...
+#endif
+
+ m_pSerializer->endElementNS( XML_w, XML_num );
+}
+
+void DocxAttributeOutput::StartAbstractNumbering( sal_uInt16 nId )
+{
+ m_pSerializer->startElementNS( XML_w, XML_abstractNum,
+ FSNS( XML_w, XML_abstractNumId ), OString::valueOf( sal_Int32( nId ) ).getStr(),
+ FSEND );
+}
+
+void DocxAttributeOutput::EndAbstractNumbering()
+{
+ m_pSerializer->endElementNS( XML_w, XML_abstractNum );
+}
+
+void DocxAttributeOutput::NumberingLevel( sal_uInt8 nLevel,
+ sal_uInt16 nStart,
+ sal_uInt16 nNumberingType,
+ SvxAdjust eAdjust,
+ const sal_uInt8 * /*pNumLvlPos*/,
+ sal_uInt8 nFollow,
+ const wwFont *pFont,
+ const SfxItemSet *pOutSet,
+ sal_Int16 nIndentAt,
+ sal_Int16 nFirstLineIndex,
+ sal_Int16 nListTabPos,
+ const String &rNumberingString )
+{
+ m_pSerializer->startElementNS( XML_w, XML_lvl,
+ FSNS( XML_w, XML_ilvl ), OString::valueOf( sal_Int32( nLevel ) ).getStr(),
+ FSEND );
+
+ // start with the nStart value
+ m_pSerializer->singleElementNS( XML_w, XML_start,
+ FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nStart ) ).getStr(),
+ FSEND );
+
+ // format
+ OString aFmt( impl_NumberingType( nNumberingType ) );
+
+ if ( aFmt.getLength() )
+ m_pSerializer->singleElementNS( XML_w, XML_numFmt,
+ FSNS( XML_w, XML_val ), aFmt.getStr(),
+ FSEND );
+
+ // suffix
+ const char *pSuffix = NULL;
+ switch ( nFollow )
+ {
+ case 1: pSuffix = "space"; break;
+ case 2: pSuffix = "nothing"; break;
+ default: /*pSuffix = "tab";*/ break;
+ }
+ if ( pSuffix )
+ m_pSerializer->singleElementNS( XML_w, XML_suff,
+ FSNS( XML_w, XML_val ), pSuffix,
+ FSEND );
+
+ // text
+ OUString aText( rNumberingString );
+ OUStringBuffer aBuffer( aText.getLength() + WW8ListManager::nMaxLevel );
+
+ const sal_Unicode *pPrev = aText.getStr();
+ const sal_Unicode *pIt = aText.getStr();
+ while ( pIt < aText.getStr() + aText.getLength() )
+ {
+ // convert the level values to %NUMBER form
+ // (we don't use pNumLvlPos at all)
+ // FIXME so far we support the ww8 limit of levels only
+ if ( *pIt < sal_Unicode( WW8ListManager::nMaxLevel ) )
+ {
+ aBuffer.append( pPrev, pIt - pPrev );
+ aBuffer.appendAscii( "%" );
+ aBuffer.append( OUString::valueOf( sal_Int32( *pIt ) + 1 ) );
+
+ pPrev = pIt + 1;
+ }
+ ++pIt;
+ }
+ if ( pPrev < pIt )
+ aBuffer.append( pPrev, pIt - pPrev );
+
+ m_pSerializer->singleElementNS( XML_w, XML_lvlText,
+ FSNS( XML_w, XML_val ), OUStringToOString( aBuffer.makeStringAndClear(), RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+
+ // justification
+ const char *pJc;
+ bool ecmaDialect = ( m_rExport.GetFilter().getVersion() == oox::core::ECMA_DIALECT );
+ switch ( eAdjust )
+ {
+ case SVX_ADJUST_CENTER: pJc = "center"; break;
+ case SVX_ADJUST_RIGHT: pJc = !ecmaDialect ? "end" : "right"; break;
+ default: pJc = !ecmaDialect ? "start" : "left"; break;
+ }
+ m_pSerializer->singleElementNS( XML_w, XML_lvlJc,
+ FSNS( XML_w, XML_val ), pJc,
+ FSEND );
+
+ // indentation
+ m_pSerializer->startElementNS( XML_w, XML_pPr, FSEND );
+ if( nListTabPos != 0 )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_tabs, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_tab,
+ FSNS( XML_w, XML_val ), "num",
+ FSNS( XML_w, XML_pos ), OString::valueOf( static_cast<sal_Int32>(nListTabPos) ).getStr(),
+ FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_tabs );
+ }
+
+ sal_Int32 nToken = ecmaDialect ? XML_left : XML_start;
+ m_pSerializer->singleElementNS( XML_w, XML_ind,
+ FSNS( XML_w, nToken ), OString::valueOf( sal_Int32( nIndentAt ) ).getStr(),
+ FSNS( XML_w, XML_hanging ), OString::valueOf( sal_Int32( -nFirstLineIndex ) ).getStr(),
+ FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_pPr );
+
+ // font
+ if ( pOutSet )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_rPr, FSEND );
+
+ if ( pFont )
+ {
+ GetExport().GetId( *pFont ); // ensure font info is written to fontTable.xml
+ OString aFamilyName( OUStringToOString( OUString( pFont->GetFamilyName() ), RTL_TEXTENCODING_UTF8 ) );
+ m_pSerializer->singleElementNS( XML_w, XML_rFonts,
+ FSNS( XML_w, XML_ascii ), aFamilyName.getStr(),
+ FSNS( XML_w, XML_hAnsi ), aFamilyName.getStr(),
+ FSNS( XML_w, XML_cs ), aFamilyName.getStr(),
+ FSNS( XML_w, XML_hint ), "default",
+ FSEND );
+ }
+ m_rExport.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rExport.mbExportModeRTF );
+
+ m_pSerializer->endElementNS( XML_w, XML_rPr );
+ }
+
+ // TODO anything to do about nListTabPos?
+
+ m_pSerializer->endElementNS( XML_w, XML_lvl );
+}
+
+void DocxAttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )
+{
+ switch ( rCaseMap.GetValue() )
+ {
+ case SVX_CASEMAP_KAPITAELCHEN:
+ m_pSerializer->singleElementNS( XML_w, XML_smallCaps, FSEND );
+ break;
+ case SVX_CASEMAP_VERSALIEN:
+ m_pSerializer->singleElementNS( XML_w, XML_caps, FSEND );
+ break;
+ default: // Something that ooxml does not support
+ m_pSerializer->singleElementNS( XML_w, XML_smallCaps, FSNS( XML_w, XML_val ), "false", FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_caps, FSNS( XML_w, XML_val ), "false", FSEND );
+ break;
+ }
+}
+
+void DocxAttributeOutput::CharColor( const SvxColorItem& rColor )
+{
+ const Color aColor( rColor.GetValue() );
+ OString aColorString;
+
+ aColorString = impl_ConvertColor( aColor );
+
+ m_pSerializer->singleElementNS( XML_w, XML_color,
+ FSNS( XML_w, XML_val ), aColorString.getStr(), FSEND );
+}
+
+void DocxAttributeOutput::CharContour( const SvxContourItem& rContour )
+{
+ if ( rContour.GetValue() )
+ m_pSerializer->singleElementNS( XML_w, XML_outline, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_outline, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossedOut )
+{
+ switch ( rCrossedOut.GetStrikeout() )
+ {
+ case STRIKEOUT_DOUBLE:
+ m_pSerializer->singleElementNS( XML_w, XML_dstrike, FSEND );
+ break;
+ case STRIKEOUT_NONE:
+ m_pSerializer->singleElementNS( XML_w, XML_dstrike, FSNS( XML_w, XML_val ), "false", FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_strike, FSNS( XML_w, XML_val ), "false", FSEND );
+ break;
+ default:
+ m_pSerializer->singleElementNS( XML_w, XML_strike, FSEND );
+ break;
+ }
+}
+
+void DocxAttributeOutput::CharEscapement( const SvxEscapementItem& rEscapement )
+{
+ OString sIss;
+ short nEsc = rEscapement.GetEsc(), nProp = rEscapement.GetProp();
+ if ( !nEsc )
+ {
+ sIss = OString( "baseline" );
+ nEsc = 0;
+ nProp = 100;
+ }
+ else if ( DFLT_ESC_PROP == nProp )
+ {
+ if ( DFLT_ESC_SUB == nEsc || DFLT_ESC_AUTO_SUB == nEsc )
+ sIss = OString( "subscript" );
+ else if ( DFLT_ESC_SUPER == nEsc || DFLT_ESC_AUTO_SUPER == nEsc )
+ sIss = OString( "superscript" );
+ }
+
+ if ( sIss.getLength( ) > 0 )
+ m_pSerializer->singleElementNS( XML_w, XML_vertAlign,
+ FSNS( XML_w, XML_val ), sIss.getStr(), FSEND );
+
+ if ( sIss.getLength() == 0 || sIss.match( OString( "baseline" ) ) )
+ {
+ long nHeight = ((SvxFontHeightItem&)m_rExport.GetItem(
+ RES_CHRATR_FONTSIZE )).GetHeight();
+ OString sPos = OString::valueOf( ( nHeight * nEsc + 500 ) / 1000 );
+ m_pSerializer->singleElementNS( XML_w, XML_position,
+ FSNS( XML_w, XML_val ), sPos.getStr( ), FSEND );
+
+ if( 100 != nProp || sIss.match( OString( "baseline" ) ) )
+ {
+ OString sSize = OString::valueOf( ( nHeight * nProp + 500 ) / 1000 );
+ m_pSerializer->singleElementNS( XML_w, XML_sz,
+ FSNS( XML_w, XML_val ), sSize.getStr( ), FSEND );
+ }
+ }
+}
+
+void DocxAttributeOutput::CharFont( const SvxFontItem& rFont)
+{
+ if (!m_pFontsAttrList)
+ m_pFontsAttrList = m_pSerializer->createAttrList();
+ OUString sFontName(rFont.GetFamilyName());
+ OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
+ m_pFontsAttrList->add(FSNS(XML_w, XML_ascii), sFontNameUtf8);
+ m_pFontsAttrList->add(FSNS(XML_w, XML_hAnsi), sFontNameUtf8);
+}
+
+void DocxAttributeOutput::CharFontSize( const SvxFontHeightItem& rFontSize)
+{
+ OString fontSize = OString::valueOf( sal_Int32( ( rFontSize.GetHeight() + 5 ) / 10 ) );
+
+ switch ( rFontSize.Which() )
+ {
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_CJK_FONTSIZE:
+ m_pSerializer->singleElementNS( XML_w, XML_sz, FSNS( XML_w, XML_val ), fontSize.getStr(), FSEND );
+ break;
+ case RES_CHRATR_CTL_FONTSIZE:
+ m_pSerializer->singleElementNS( XML_w, XML_szCs, FSNS( XML_w, XML_val ), fontSize.getStr(), FSEND );
+ break;
+ }
+}
+
+void DocxAttributeOutput::CharKerning( const SvxKerningItem& rKerning )
+{
+ OString aKerning = OString::valueOf( ( sal_Int32 ) rKerning.GetValue() );
+ m_pSerializer->singleElementNS( XML_w, XML_spacing, FSNS(XML_w, XML_val), aKerning.getStr(), FSEND );
+}
+
+void DocxAttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )
+{
+ if (!m_pCharLangAttrList)
+ m_pCharLangAttrList = m_pSerializer->createAttrList();
+
+ ::com::sun::star::lang::Locale xLocale= MsLangId::convertLanguageToLocale( rLanguage.GetLanguage( ) );
+ OString sLanguage = OUStringToOString(xLocale.Language, RTL_TEXTENCODING_UTF8);
+ OString sCountry = OUStringToOString(xLocale.Country, RTL_TEXTENCODING_UTF8);
+
+ OString aLanguageCode = sLanguage + "-" + sCountry;
+
+ switch ( rLanguage.Which() )
+ {
+ case RES_CHRATR_LANGUAGE:
+ m_pCharLangAttrList->add(FSNS(XML_w, XML_val), aLanguageCode);
+ break;
+ case RES_CHRATR_CJK_LANGUAGE:
+ m_pCharLangAttrList->add(FSNS(XML_w, XML_eastAsia), aLanguageCode);
+ break;
+ case RES_CHRATR_CTL_LANGUAGE:
+ m_pCharLangAttrList->add(FSNS(XML_w, XML_bidi), aLanguageCode);
+ break;
+ }
+}
+
+void DocxAttributeOutput::CharPosture( const SvxPostureItem& rPosture )
+{
+ if ( rPosture.GetPosture() != ITALIC_NONE )
+ m_pSerializer->singleElementNS( XML_w, XML_i, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_i, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharShadow( const SvxShadowedItem& rShadow )
+{
+ if ( rShadow.GetValue() )
+ m_pSerializer->singleElementNS( XML_w, XML_shadow, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_shadow, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )
+{
+ const char *pUnderline;
+
+ switch ( rUnderline.GetLineStyle() )
+ {
+ case UNDERLINE_SINGLE: pUnderline = "single"; break;
+ case UNDERLINE_BOLD: pUnderline = "thick"; break;
+ case UNDERLINE_DOUBLE: pUnderline = "double"; break;
+ case UNDERLINE_DOTTED: pUnderline = "dotted"; break;
+ case UNDERLINE_DASH: pUnderline = "dash"; break;
+ case UNDERLINE_DASHDOT: pUnderline = "dotDash"; break;
+ case UNDERLINE_DASHDOTDOT: pUnderline = "dotDotDash"; break;
+ case UNDERLINE_WAVE: pUnderline = "wave"; break;
+ case UNDERLINE_BOLDDOTTED: pUnderline = "dottedHeavy"; break;
+ case UNDERLINE_BOLDDASH: pUnderline = "dashedHeavy"; break;
+ case UNDERLINE_LONGDASH: pUnderline = "dashLongHeavy"; break;
+ case UNDERLINE_BOLDLONGDASH: pUnderline = "dashLongHeavy"; break;
+ case UNDERLINE_BOLDDASHDOT: pUnderline = "dashDotHeavy"; break;
+ case UNDERLINE_BOLDDASHDOTDOT: pUnderline = "dashDotDotHeavy"; break;
+ case UNDERLINE_BOLDWAVE: pUnderline = "wavyHeavy"; break;
+ case UNDERLINE_DOUBLEWAVE: pUnderline = "wavyDouble"; break;
+ case UNDERLINE_NONE: // fall through
+ default: pUnderline = "none"; break;
+ }
+
+ m_pSerializer->singleElementNS( XML_w, XML_u, FSNS( XML_w, XML_val ), pUnderline, FSEND );
+}
+
+void DocxAttributeOutput::CharWeight( const SvxWeightItem& rWeight )
+{
+ if ( rWeight.GetWeight() == WEIGHT_BOLD )
+ m_pSerializer->singleElementNS( XML_w, XML_b, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_b, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharAutoKern( const SvxAutoKernItem& )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::CharAutoKern()\n" );
+}
+
+void DocxAttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )
+{
+ if ( rBlink.GetValue() )
+ m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS( XML_w, XML_val ), "blinkBackground", FSEND );
+ else
+ m_pSerializer->singleElementNS(XML_w, XML_effect, FSNS( XML_w, XML_val ), "none", FSEND );
+}
+
+void DocxAttributeOutput::CharBackground( const SvxBrushItem& rBrush )
+{
+ m_pSerializer->singleElementNS( XML_w, XML_shd,
+ FSNS( XML_w, XML_fill ), impl_ConvertColor( rBrush.GetColor() ).getStr(),
+ FSNS( XML_w, XML_val ), "clear",
+ FSEND );
+}
+
+void DocxAttributeOutput::CharFontCJK( const SvxFontItem& rFont )
+{
+ if (!m_pFontsAttrList)
+ m_pFontsAttrList = m_pSerializer->createAttrList();
+ OUString sFontName(rFont.GetFamilyName());
+ OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
+ m_pFontsAttrList->add(FSNS(XML_w, XML_eastAsia), sFontNameUtf8);
+}
+
+void DocxAttributeOutput::CharPostureCJK( const SvxPostureItem& rPosture )
+{
+ if ( rPosture.GetPosture() != ITALIC_NONE )
+ m_pSerializer->singleElementNS( XML_w, XML_i, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_i, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharWeightCJK( const SvxWeightItem& rWeight )
+{
+ if ( rWeight.GetWeight() == WEIGHT_BOLD )
+ m_pSerializer->singleElementNS( XML_w, XML_b, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_b, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharFontCTL( const SvxFontItem& rFont )
+{
+ if (!m_pFontsAttrList)
+ m_pFontsAttrList = m_pSerializer->createAttrList();
+ OUString sFontName(rFont.GetFamilyName());
+ OString sFontNameUtf8 = OUStringToOString(sFontName, RTL_TEXTENCODING_UTF8);
+ m_pFontsAttrList->add(FSNS(XML_w, XML_cs), sFontNameUtf8);
+
+}
+
+void DocxAttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture)
+{
+ if ( rPosture.GetPosture() != ITALIC_NONE )
+ m_pSerializer->singleElementNS( XML_w, XML_iCs, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_iCs, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )
+{
+ if ( rWeight.GetWeight() == WEIGHT_BOLD )
+ m_pSerializer->singleElementNS( XML_w, XML_bCs, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_bCs, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::CharRotate( const SvxCharRotateItem& rRotate)
+{
+ if ( !rRotate.GetValue() )
+ return;
+
+ if (!m_pEastAsianLayoutAttrList)
+ m_pEastAsianLayoutAttrList = m_pSerializer->createAttrList();
+ OString sTrue((sal_Char *)"true");
+ m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_vert), sTrue);
+
+ if (rRotate.IsFitToLine())
+ m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_vertCompress), sTrue);
+}
+
+void DocxAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
+{
+ const char *pEmphasis;
+
+ switch ( rEmphasisMark.GetValue() )
+ {
+ case EMPHASISMARK_NONE: pEmphasis = "none"; break;
+ case EMPHASISMARK_SIDE_DOTS: pEmphasis = "dot"; break;
+ case EMPHASISMARK_CIRCLE_ABOVE: pEmphasis = "circle"; break;
+ case EMPHASISMARK_DOTS_BELOW: pEmphasis = "underDot"; break;
+ default: pEmphasis = "comma"; break;
+ }
+
+ m_pSerializer->singleElementNS( XML_w, XML_em, FSNS( XML_w, XML_val ), pEmphasis, FSEND );
+}
+
+void DocxAttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
+{
+ if ( !rTwoLines.GetValue() )
+ return;
+
+ if (!m_pEastAsianLayoutAttrList)
+ m_pEastAsianLayoutAttrList = m_pSerializer->createAttrList();
+ OString sTrue((sal_Char *)"true");
+ m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_combine), sTrue);
+
+ sal_Unicode cStart = rTwoLines.GetStartBracket();
+ sal_Unicode cEnd = rTwoLines.GetEndBracket();
+
+ if (!cStart && !cEnd)
+ return;
+
+ OString sBracket;
+ if ((cStart == '{') || (cEnd == '}'))
+ sBracket = (sal_Char *)"curly";
+ else if ((cStart == '<') || (cEnd == '>'))
+ sBracket = (sal_Char *)"angle";
+ else if ((cStart == '[') || (cEnd == ']'))
+ sBracket = (sal_Char *)"square";
+ else
+ sBracket = (sal_Char *)"round";
+ m_pEastAsianLayoutAttrList->add(FSNS(XML_w, XML_combineBrackets), sBracket);
+}
+
+void DocxAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
+{
+ m_pSerializer->singleElementNS( XML_w, XML_w,
+ FSNS( XML_w, XML_val ), rtl::OString::valueOf( sal_Int32( rScaleWidth.GetValue() ) ).getStr(), FSEND );
+}
+
+void DocxAttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
+{
+ switch ( rRelief.GetValue() )
+ {
+ case RELIEF_EMBOSSED:
+ m_pSerializer->singleElementNS( XML_w, XML_emboss, FSEND );
+ break;
+ case RELIEF_ENGRAVED:
+ m_pSerializer->singleElementNS( XML_w, XML_imprint, FSEND );
+ break;
+ default:
+ m_pSerializer->singleElementNS( XML_w, XML_emboss, FSNS( XML_w, XML_val ), "false", FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_imprint, FSNS( XML_w, XML_val ), "false", FSEND );
+ break;
+ }
+}
+
+void DocxAttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
+{
+ if ( rHidden.GetValue() )
+ m_pSerializer->singleElementNS( XML_w, XML_vanish, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_vanish, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+void DocxAttributeOutput::TextINetFormat( const SwFmtINetFmt& rLink )
+{
+ const SwTxtINetFmt* pINetFmt = rLink.GetTxtINetFmt();
+ const SwCharFmt* pCharFmt = pINetFmt->GetCharFmt();
+
+ OString aStyleId( "style" );
+ aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *pCharFmt ) ) );
+
+ m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
+}
+
+void DocxAttributeOutput::TextCharFormat( const SwFmtCharFmt& rCharFmt )
+{
+ OString aStyleId( "style" );
+ aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *rCharFmt.GetCharFmt() ) ) );
+
+ m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
+}
+
+void DocxAttributeOutput::RefField( const SwField& rFld, const String& rRef )
+{
+ sal_uInt16 nType = rFld.GetTyp( )->Which( );
+ if ( nType == RES_GETEXPFLD )
+ {
+ String sCmd = FieldString( ww::eREF );
+ sCmd.APPEND_CONST_ASC( "\"" );
+ sCmd += rRef;
+ sCmd.APPEND_CONST_ASC( "\" " );
+
+ m_rExport.OutputField( &rFld, ww::eREF, sCmd );
+ }
+
+ // There is nothing to do here for the set fields
+}
+
+void DocxAttributeOutput::HiddenField( const SwField& /*rFld*/ )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::HiddenField()\n" );
+}
+
+void DocxAttributeOutput::PostitField( const SwField* /* pFld*/ )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::PostitField()\n" );
+}
+
+bool DocxAttributeOutput::DropdownField( const SwField* pFld )
+{
+ bool bExpand = false;
+
+ ww::eField eType = ww::eFORMDROPDOWN;
+ String sCmd = FieldString( eType );
+ GetExport( ).OutputField( pFld, eType, sCmd );
+
+ return bExpand;
+}
+
+void DocxAttributeOutput::SetField( const SwField& rFld, ww::eField eType, const String& rCmd )
+{
+ // field bookmarks are handled in the EndRun method
+ GetExport().OutputField(&rFld, eType, rCmd );
+}
+
+void DocxAttributeOutput::WriteExpand( const SwField* pFld )
+{
+ // Will be written in the next End Run
+ String sCmd;
+ m_rExport.OutputField( pFld, ww::eUNKNOWN, sCmd );
+}
+
+void DocxAttributeOutput::WriteField_Impl( const SwField* pFld, ww::eField eType, const String& rFldCmd, sal_uInt8 nMode )
+{
+ struct FieldInfos infos;
+ infos.pField = pFld;
+ infos.sCmd = rFldCmd;
+ infos.eType = eType;
+ infos.bClose = WRITEFIELD_CLOSE & nMode;
+ infos.bOpen = WRITEFIELD_START & nMode;
+ m_Fields.push_back( infos );
+
+ if ( pFld )
+ {
+ sal_uInt16 nType = pFld->GetTyp( )->Which( );
+ sal_uInt16 nSubType = pFld->GetSubType();
+
+ // TODO Any other field types here ?
+ if ( ( nType == RES_SETEXPFLD ) && ( nSubType & nsSwGetSetExpType::GSE_STRING ) )
+ {
+ const SwSetExpField *pSet = ( const SwSetExpField* )( pFld );
+ m_sFieldBkm = pSet->GetPar1( );
+ }
+ else if ( nType == RES_DROPDOWN )
+ {
+ const SwDropDownField* pDropDown = ( const SwDropDownField* )( pFld );
+ m_sFieldBkm = pDropDown->GetName( );
+ }
+ }
+}
+
+void DocxAttributeOutput::WriteFormData_Impl( const ::sw::mark::IFieldmark& rFieldmark )
+{
+ if ( !m_Fields.empty() )
+ m_Fields.begin()->pFieldmark = &rFieldmark;
+}
+
+void DocxAttributeOutput::WriteBookmarks_Impl( std::vector< OUString >& rStarts,
+ std::vector< OUString >& rEnds )
+{
+ for ( std::vector< OUString >::const_iterator it = rStarts.begin(), end = rStarts.end(); it < end; ++it )
+ {
+ OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
+ m_rMarksStart.push_back( rName );
+ }
+ rStarts.clear();
+
+ for ( std::vector< OUString >::const_iterator it = rEnds.begin(), end = rEnds.end(); it < end; ++it )
+ {
+ OString rName = OUStringToOString( *it, RTL_TEXTENCODING_UTF8 ).getStr( );
+ m_rMarksEnd.push_back( rName );
+ }
+ rEnds.clear();
+}
+
+void DocxAttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFootnote )
+{
+ const SwEndNoteInfo& rInfo = rFootnote.IsEndNote()?
+ m_rExport.pDoc->GetEndNoteInfo(): m_rExport.pDoc->GetFtnInfo();
+
+ // footnote/endnote run properties
+ const SwCharFmt* pCharFmt = rInfo.GetAnchorCharFmt( *m_rExport.pDoc );
+
+ OString aStyleId( "style" );
+ aStyleId += OString::valueOf( sal_Int32( m_rExport.GetId( *pCharFmt ) ) );
+
+ m_pSerializer->singleElementNS( XML_w, XML_rStyle, FSNS( XML_w, XML_val ), aStyleId.getStr(), FSEND );
+
+ // remember the footnote/endnote to
+ // 1) write the footnoteReference/endnoteReference in EndRunProperties()
+ // 2) be able to dump them all to footnotes.xml/endnotes.xml
+ if ( !rFootnote.IsEndNote() )
+ m_pFootnotesList->add( rFootnote );
+ else
+ m_pEndnotesList->add( rFootnote );
+}
+
+void DocxAttributeOutput::FootnoteEndnoteReference()
+{
+ sal_Int32 nId;
+ const SwFmtFtn *pFootnote = m_pFootnotesList->getCurrent( nId );
+
+ // both cannot be set at the same time - if they are, it's a bug
+ if ( !pFootnote )
+ pFootnote = m_pEndnotesList->getCurrent( nId );
+
+ if ( !pFootnote )
+ return;
+
+ sal_Int32 nToken = pFootnote->IsEndNote()? XML_endnoteReference: XML_footnoteReference;
+
+ // write it
+ if ( pFootnote->GetNumStr().Len() == 0 )
+ {
+ // autonumbered
+ m_pSerializer->singleElementNS( XML_w, nToken,
+ FSNS( XML_w, XML_id ), ::rtl::OString::valueOf( nId ).getStr(),
+ FSEND );
+ }
+ else
+ {
+ // not autonumbered
+ m_pSerializer->singleElementNS( XML_w, nToken,
+ FSNS( XML_w, XML_customMarkFollows ), "1",
+ FSNS( XML_w, XML_id ), ::rtl::OString::valueOf( nId ).getStr(),
+ FSEND );
+
+ RunText( pFootnote->GetNumStr() );
+ }
+}
+
+void DocxAttributeOutput::FootnotesEndnotes( bool bFootnotes )
+{
+ const FootnotesVector& rVector = bFootnotes? m_pFootnotesList->getVector(): m_pEndnotesList->getVector();
+
+ sal_Int32 nBody = bFootnotes? XML_footnotes: XML_endnotes;
+ sal_Int32 nItem = bFootnotes? XML_footnote: XML_endnote;
+
+ m_pSerializer->startElementNS( XML_w, nBody,
+ FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
+ FSEND );
+
+ sal_Int32 nIndex = 0;
+
+ // separator
+ m_pSerializer->startElementNS( XML_w, nItem,
+ FSNS( XML_w, XML_id ), OString::valueOf( nIndex++ ).getStr(),
+ FSNS( XML_w, XML_type ), "separator",
+ FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_separator, FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ m_pSerializer->endElementNS( XML_w, XML_p );
+ m_pSerializer->endElementNS( XML_w, nItem );
+
+ // separator
+ m_pSerializer->startElementNS( XML_w, nItem,
+ FSNS( XML_w, XML_id ), OString::valueOf( nIndex++ ).getStr(),
+ FSNS( XML_w, XML_type ), "continuationSeparator",
+ FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_p, FSEND );
+ m_pSerializer->startElementNS( XML_w, XML_r, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_continuationSeparator, FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_r );
+ m_pSerializer->endElementNS( XML_w, XML_p );
+ m_pSerializer->endElementNS( XML_w, nItem );
+
+ // footnotes/endnotes themselves
+ for ( FootnotesVector::const_iterator i = rVector.begin(); i != rVector.end(); ++i, ++nIndex )
+ {
+ m_pSerializer->startElementNS( XML_w, nItem,
+ FSNS( XML_w, XML_id ), OString::valueOf( nIndex ).getStr(),
+ FSEND );
+
+ const SwNodeIndex* pIndex = (*i)->GetTxtFtn()->GetStartNode();
+ // tag required at the start of each footnote/endnote
+ m_footnoteEndnoteRefTag = bFootnotes ? XML_footnoteRef : XML_endnoteRef;
+
+ m_rExport.WriteSpecialText( pIndex->GetIndex() + 1,
+ pIndex->GetNode().EndOfSectionIndex(),
+ bFootnotes? TXT_FTN: TXT_EDN );
+
+ m_pSerializer->endElementNS( XML_w, nItem );
+ }
+
+ m_pSerializer->endElementNS( XML_w, nBody );
+
+}
+
+void DocxAttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
+{
+ if ( !m_pParagraphSpacingAttrList )
+ m_pParagraphSpacingAttrList = m_pSerializer->createAttrList();
+
+ if ( nSpace < 0 )
+ {
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "exact" );
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( -nSpace ) ) );
+ }
+ else if( nMulti )
+ {
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "auto" );
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( nSpace ) ) );
+ }
+ else if ( nSpace > 0 )
+ {
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "atLeast" );
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_line ), OString::valueOf( sal_Int32( nSpace ) ) );
+ }
+ else
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_lineRule ), "auto" );
+}
+
+void DocxAttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
+{
+ const char *pAdjustString;
+
+ bool bEcma = GetExport().GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
+
+ const SfxItemSet* pItems = GetExport().GetCurItemSet();
+ const SvxFrameDirectionItem* rFrameDir = static_cast< const SvxFrameDirectionItem* >( pItems->GetItem( RES_FRAMEDIR ) );
+
+ bool bRtl = false;
+ short nDir = rFrameDir->GetValue();
+ bRtl = ( nDir == FRMDIR_HORI_RIGHT_TOP );
+
+ if ( nDir == FRMDIR_ENVIRONMENT )
+ nDir = GetExport( ).GetDefaultFrameDirection( );
+
+ switch ( rAdjust.GetAdjust() )
+ {
+ case SVX_ADJUST_LEFT:
+ if ( bEcma )
+ pAdjustString = "left";
+ else if ( bRtl )
+ pAdjustString = "end";
+ else
+ pAdjustString = "start";
+ break;
+ case SVX_ADJUST_RIGHT:
+ if ( bEcma )
+ pAdjustString = "right";
+ else if ( bRtl )
+ pAdjustString = "start";
+ else
+ pAdjustString = "end";
+ break;
+ case SVX_ADJUST_BLOCKLINE:
+ case SVX_ADJUST_BLOCK:
+ pAdjustString = "both";
+ break;
+ case SVX_ADJUST_CENTER:
+ pAdjustString = "center";
+ break;
+ default:
+ return; // not supported attribute
+ }
+ m_pSerializer->singleElementNS( XML_w, XML_jc, FSNS( XML_w, XML_val ), pAdjustString, FSEND );
+}
+
+void DocxAttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
+{
+ if (rSplit.GetValue())
+ m_pSerializer->singleElementNS( XML_w, XML_keepLines, FSNS( XML_w, XML_val ), "false", FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_keepLines, FSEND );
+}
+
+void DocxAttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
+{
+ if (rWidows.GetValue())
+ m_pSerializer->singleElementNS( XML_w, XML_widowControl, FSEND );
+ else
+ m_pSerializer->singleElementNS( XML_w, XML_widowControl, FSNS( XML_w, XML_val ), "false", FSEND );
+}
+
+static void impl_WriteTabElement( FSHelperPtr pSerializer,
+ const SvxTabStop& rTab, long nCurrentLeft )
+{
+ FastAttributeList *pTabElementAttrList = pSerializer->createAttrList();
+
+ switch (rTab.GetAdjustment())
+ {
+ case SVX_TAB_ADJUST_RIGHT:
+ pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"right") );
+ break;
+ case SVX_TAB_ADJUST_DECIMAL:
+ pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"decimal") );
+ break;
+ case SVX_TAB_ADJUST_CENTER:
+ pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"center") );
+ break;
+ case SVX_TAB_ADJUST_DEFAULT:
+ case SVX_TAB_ADJUST_LEFT:
+ default:
+ pTabElementAttrList->add( FSNS( XML_w, XML_val ), OString( (sal_Char *)"left") );
+ break;
+ }
+
+ pTabElementAttrList->add( FSNS( XML_w, XML_pos ), OString::valueOf( rTab.GetTabPos() + nCurrentLeft ) );
+
+ sal_Unicode cFillChar = rTab.GetFill();
+
+ if (sal_Unicode('.') == cFillChar )
+ pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "dot" ) );
+ else if ( sal_Unicode('-') == cFillChar )
+ pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "hyphen" ) );
+ else if ( sal_Unicode(0xB7) == cFillChar ) // middle dot
+ pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "middleDot" ) );
+ else if ( sal_Unicode('_') == cFillChar )
+ pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "underscore" ) );
+ else
+ pTabElementAttrList->add( FSNS( XML_w, XML_leader ), OString( (sal_Char *) "none" ) );
+
+ pSerializer->singleElementNS( XML_w, XML_tab, pTabElementAttrList );
+}
+
+void DocxAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )
+{
+ const SfxPoolItem* pLR = m_rExport.HasItem( RES_LR_SPACE );
+ long nCurrentLeft = pLR ? ((const SvxLRSpaceItem*)pLR)->GetTxtLeft() : 0;
+
+ m_pSerializer->startElementNS( XML_w, XML_tabs, FSEND );
+
+ sal_uInt16 nCount = rTabStop.Count();
+ for (sal_uInt16 i = 0; i < nCount; i++ )
+ impl_WriteTabElement( m_pSerializer, rTabStop[i], nCurrentLeft );
+
+ m_pSerializer->endElementNS( XML_w, XML_tabs );
+}
+
+void DocxAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
+{
+ m_pSerializer->singleElementNS( XML_w, XML_suppressAutoHyphens,
+ FSNS( XML_w, XML_val ), rHyphenZone.IsHyphen( ) ? "false" : "true" ,
+ FSEND );
+}
+
+void DocxAttributeOutput::ParaNumRule_Impl( const SwTxtNode* /*pTxtNd*/, sal_Int32 nLvl, sal_Int32 nNumId )
+{
+ if ( USHRT_MAX != nNumId && 0 != nNumId )
+ {
+ m_pSerializer->startElementNS( XML_w, XML_numPr, FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_ilvl, FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nLvl )).getStr(), FSEND );
+ m_pSerializer->singleElementNS( XML_w, XML_numId, FSNS( XML_w, XML_val ), OString::valueOf( sal_Int32( nNumId )).getStr(), FSEND );
+ m_pSerializer->endElementNS( XML_w, XML_numPr );
+ }
+}
+
+void DocxAttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
+{
+ sal_uInt16 nXmlElement = 0;
+
+ switch ( rScriptSpace.Which( ) )
+ {
+ case RES_PARATR_SCRIPTSPACE:
+ nXmlElement = XML_autoSpaceDE;
+ break;
+ case RES_PARATR_HANGINGPUNCTUATION:
+ nXmlElement = XML_overflowPunct;
+ break;
+ case RES_PARATR_FORBIDDEN_RULES:
+ nXmlElement = XML_kinsoku;
+ break;
+ }
+
+ if ( nXmlElement )
+ {
+ m_pSerializer->singleElementNS( XML_w, nXmlElement,
+ FSNS( XML_w, XML_val ), rScriptSpace.GetValue( ) ? "true": "false",
+ FSEND );
+ }
+}
+
+void DocxAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
+{
+ const char *pAlignString;
+
+ switch ( rAlign.GetValue() )
+ {
+ case SvxParaVertAlignItem::BASELINE:
+ pAlignString = "baseline";
+ break;
+ case SvxParaVertAlignItem::TOP:
+ pAlignString = "top";
+ break;
+ case SvxParaVertAlignItem::CENTER:
+ pAlignString = "center";
+ break;
+ case SvxParaVertAlignItem::BOTTOM:
+ pAlignString = "bottom";
+ break;
+ case SvxParaVertAlignItem::AUTOMATIC:
+ pAlignString = "auto";
+ break;
+ default:
+ return; // not supported attribute
+ }
+ m_pSerializer->singleElementNS( XML_w, XML_textAlignment, FSNS( XML_w, XML_val ), pAlignString, FSEND );
+}
+
+void DocxAttributeOutput::ParaSnapToGrid( const SvxParaGridItem& rGrid )
+{
+ m_pSerializer->singleElementNS( XML_w, XML_snapToGrid,
+ FSNS( XML_w, XML_val ), rGrid.GetValue( ) ? "true": "false",
+ FSEND );
+}
+
+void DocxAttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
+{
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList( );
+
+ if ( rSize.GetWidth() && rSize.GetWidthSizeType() == ATT_FIX_SIZE )
+ {
+ m_pFlyAttrList->add( FSNS( XML_w, XML_w ), OString::valueOf( rSize.GetWidth( ) ) );
+ }
+
+ if ( rSize.GetHeight() )
+ {
+ OString sRule( "exact" );
+ if ( rSize.GetHeightSizeType() == ATT_MIN_SIZE )
+ sRule = OString( "atLeast" );
+ m_pFlyAttrList->add( FSNS( XML_w, XML_hRule ), sRule );
+ m_pFlyAttrList->add( FSNS( XML_w, XML_h ), OString::valueOf( rSize.GetHeight( ) ) );
+ }
+ }
+ else if ( m_rExport.bOutPageDescs )
+ {
+ FastAttributeList *attrList = m_pSerializer->createAttrList( );
+ if ( m_rExport.pAktPageDesc->GetLandscape( ) )
+ attrList->add( FSNS( XML_w, XML_orient ), "landscape" );
+
+ attrList->add( FSNS( XML_w, XML_w ), OString::valueOf( rSize.GetWidth( ) ) );
+ attrList->add( FSNS( XML_w, XML_h ), OString::valueOf( rSize.GetHeight( ) ) );
+
+ XFastAttributeListRef xAttrList( attrList );
+ attrList = NULL;
+
+ m_pSerializer->singleElementNS( XML_w, XML_pgSz, xAttrList );
+ }
+}
+
+void DocxAttributeOutput::FormatPaperBin( const SvxPaperBinItem& )
+{
+ OSL_TRACE( "TODO DocxAttributeOutput::FormatPaperBin()\n" );
+}
+
+void DocxAttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLRSpace )
+{
+ bool bEcma = m_rExport.GetFilter().getVersion( ) == oox::core::ECMA_DIALECT;
+
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList();
+
+ m_pFlyAttrList->add( FSNS( XML_w, XML_hSpace ),
+ OString::valueOf(
+ sal_Int32( ( rLRSpace.GetLeft() + rLRSpace.GetRight() ) / 2 ) ) );
+ }
+ else if ( m_rExport.bOutPageDescs )
+ {
+ if ( !m_pSectionSpacingAttrList )
+ m_pSectionSpacingAttrList = m_pSerializer->createAttrList();
+
+ sal_uInt16 nLDist, nRDist;
+ const SfxPoolItem* pItem = m_rExport.HasItem( RES_BOX );
+ if ( pItem )
+ {
+ nRDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_LEFT );
+ nLDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_RIGHT );
+ }
+ else
+ nLDist = nRDist = 0;
+ nLDist = nLDist + (sal_uInt16)rLRSpace.GetLeft();
+ nRDist = nRDist + (sal_uInt16)rLRSpace.GetRight();
+
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_left ), OString::valueOf( sal_Int32( nLDist ) ) );
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_right ), OString::valueOf( sal_Int32( nRDist ) ) );
+ }
+ else
+ {
+ FastAttributeList *pLRSpaceAttrList = m_pSerializer->createAttrList();
+
+ pLRSpaceAttrList->add( FSNS( XML_w, ( bEcma ? XML_left : XML_start ) ), OString::valueOf( (sal_Int32) rLRSpace.GetTxtLeft() ) );
+ pLRSpaceAttrList->add( FSNS( XML_w, ( bEcma ? XML_right : XML_end ) ), OString::valueOf( (sal_Int32) rLRSpace.GetRight() ) );
+
+ sal_Int32 nFirstLineAdjustment = rLRSpace.GetTxtFirstLineOfst();
+ if (nFirstLineAdjustment > 0)
+ pLRSpaceAttrList->add( FSNS( XML_w, XML_firstLine ), OString::valueOf( nFirstLineAdjustment ) );
+ else
+ pLRSpaceAttrList->add( FSNS( XML_w, XML_hanging ), OString::valueOf( - nFirstLineAdjustment ) );
+ m_pSerializer->singleElementNS( XML_w, XML_ind, pLRSpaceAttrList );
+ }
+}
+
+void DocxAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
+{
+
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList();
+
+ m_pFlyAttrList->add( FSNS( XML_w, XML_vSpace ),
+ OString::valueOf(
+ sal_Int32( ( rULSpace.GetLower() + rULSpace.GetUpper() ) / 2 ) ) );
+ }
+ else if (m_rExport.bOutPageDescs )
+ {
+ OSL_ENSURE( m_rExport.GetCurItemSet(), "Impossible" );
+ if ( !m_rExport.GetCurItemSet() )
+ return;
+
+ if ( !m_pSectionSpacingAttrList )
+ m_pSectionSpacingAttrList = m_pSerializer->createAttrList();
+
+ HdFtDistanceGlue aDistances( *m_rExport.GetCurItemSet() );
+
+ sal_Int32 nHeader = 0;
+ if ( aDistances.HasHeader() )
+ nHeader = sal_Int32( aDistances.dyaHdrTop );
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_header ), OString::valueOf( nHeader ) );
+
+ // Page top
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_top ),
+ OString::valueOf( sal_Int32( aDistances.dyaTop ) ) );
+
+ sal_Int32 nFooter = 0;
+ if ( aDistances.HasFooter() )
+ nFooter = sal_Int32( aDistances.dyaHdrBottom );
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_footer ), OString::valueOf( nFooter ) );
+
+ // Page Bottom
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_bottom ),
+ OString::valueOf( sal_Int32( aDistances.dyaBottom ) ) );
+
+ // FIXME Page Gutter is not handled ATM, setting to 0 as it's mandatory for OOXML
+ m_pSectionSpacingAttrList->add( FSNS( XML_w, XML_gutter ),
+ OString::valueOf( sal_Int32( 0 ) ) );
+
+ }
+ else
+ {
+ if ( !m_pParagraphSpacingAttrList )
+ m_pParagraphSpacingAttrList = m_pSerializer->createAttrList();
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_before ),
+ OString::valueOf( (sal_Int32)rULSpace.GetUpper() ) );
+ m_pParagraphSpacingAttrList->add( FSNS( XML_w, XML_after ),
+ OString::valueOf( (sal_Int32)rULSpace.GetLower() ) );
+ }
+}
+
+void DocxAttributeOutput::FormatSurround( const SwFmtSurround& rSurround )
+{
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList();
+
+ OString sWrap( "auto" );
+ switch ( rSurround.GetSurround( ) )
+ {
+ case SURROUND_NONE:
+ sWrap = OString( "none" );
+ break;
+ case SURROUND_THROUGHT:
+ sWrap = OString( "through" );
+ break;
+ case SURROUND_IDEAL:
+ case SURROUND_PARALLEL:
+ case SURROUND_LEFT:
+ case SURROUND_RIGHT:
+ default:
+ sWrap = OString( "around" );
+ }
+
+ m_pFlyAttrList->add( FSNS( XML_w, XML_wrap ), sWrap );
+ }
+}
+
+void DocxAttributeOutput::FormatVertOrientation( const SwFmtVertOrient& rFlyVert )
+{
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList();
+
+ OString sAlign;
+ switch( rFlyVert.GetVertOrient() )
+ {
+ case text::VertOrientation::NONE:
+ break;
+ case text::VertOrientation::CENTER:
+ case text::VertOrientation::LINE_CENTER:
+ sAlign = OString( "center" );
+ break;
+ case text::VertOrientation::BOTTOM:
+ case text::VertOrientation::LINE_BOTTOM:
+ sAlign = OString( "bottom" );
+ break;
+ case text::VertOrientation::TOP:
+ case text::VertOrientation::LINE_TOP:
+ default:
+ sAlign = OString( "top" );
+ break;
+ }
+
+ if ( sAlign.getLength() > 0 )
+ m_pFlyAttrList->add( FSNS( XML_w, XML_yAlign ), sAlign );
+ else
+ m_pFlyAttrList->add( FSNS( XML_w, XML_y ),
+ OString::valueOf( sal_Int32( rFlyVert.GetPos() ) ) );
+
+ OString sVAnchor( "page" );
+ switch ( rFlyVert.GetRelationOrient( ) )
+ {
+ case text::RelOrientation::CHAR:
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::TEXT_LINE:
+ sVAnchor = OString( "column" );
+ break;
+ case text::RelOrientation::FRAME:
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_RIGHT:
+ case text::RelOrientation::FRAME_LEFT:
+ case text::RelOrientation::FRAME_RIGHT:
+ sVAnchor = OString( "margin" );
+ break;
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ default:
+ break;
+ }
+
+ m_pFlyAttrList->add( FSNS( XML_w, XML_vAnchor ), sVAnchor );
+ }
+}
+
+void DocxAttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& rFlyHori )
+{
+ if ( m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( !m_pFlyAttrList )
+ m_pFlyAttrList = m_pSerializer->createAttrList();
+
+ OString sAlign;
+ switch( rFlyHori.GetHoriOrient() )
+ {
+ case text::HoriOrientation::NONE:
+ break;
+ case text::HoriOrientation::LEFT:
+ sAlign = OString( rFlyHori.IsPosToggle( ) ? "inside" : "left" );
+ break;
+ case text::HoriOrientation::RIGHT:
+ sAlign = OString( rFlyHori.IsPosToggle( ) ? "outside" : "right" );
+ break;
+ case text::HoriOrientation::CENTER:
+ case text::HoriOrientation::FULL: // FULL only for tables
+ default:
+ sAlign = OString( "center" );
+ break;
+ }
+
+ if ( sAlign.getLength() > 0 )
+ m_pFlyAttrList->add( FSNS( XML_w, XML_xAlign ), sAlign );
+ else
+ m_pFlyAttrList->add( FSNS( XML_w, XML_x ),
+ OString::valueOf( sal_Int32( rFlyHori.GetPos() ) ) );
+
+ OString sHAnchor( "page" );
+ switch ( rFlyHori.GetRelationOrient( ) )
+ {
+ case text::RelOrientation::CHAR:
+ case text::RelOrientation::PRINT_AREA:
+ sHAnchor = OString( "text" );
+ break;
+ case text::RelOrientation::FRAME:
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_RIGHT:
+ case text::RelOrientation::FRAME_LEFT:
+ case text::RelOrientation::FRAME_RIGHT:
+ sHAnchor = OString( "margin" );
+ break;
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ default:
+ break;
+ }
+
+ m_pFlyAttrList->add( FSNS( XML_w, XML_hAnchor ), sHAnchor );
+ }
+}
+
+void DocxAttributeOutput::FormatAnchor( const SwFmtAnchor& )
+{
+ // Fly frames: anchors here aren't matching the anchors in docx
+}
+
+void DocxAttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
+{
+ if ( !m_rExport.bOutPageDescs )
+ {
+ OString sColor = impl_ConvertColor( rBrush.GetColor( ) );
+ m_pSerializer->singleElementNS( XML_w, XML_shd,
+ FSNS( XML_w, XML_fill ), sColor.getStr( ),
+ FSNS( XML_w, XML_val ), "clear",
+ FSEND );
+ }
+}
+
+void DocxAttributeOutput::FormatBox( const SvxBoxItem& rBox )
+{
+
+ if ( !m_bOpenedSectPr )
+ {
+ // Normally open the borders tag for paragraphs
+ m_pSerializer->startElementNS( XML_w, XML_pBdr, FSEND );
+ }
+
+ impl_pageBorders( m_pSerializer, rBox );
+
+ if ( m_bOpenedSectPr )
+ {
+ // Special handling for pgBorder
+ m_pSerializer->mergeTopMarks( sax_fastparser::MERGE_MARKS_PREPEND );
+ m_pSerializer->mergeTopMarks( );
+ }
+ else
+ {
+ // Normally close the borders tag for paragraphs
+ m_pSerializer->endElementNS( XML_w, XML_pBdr );
+ }
+}
+
+void DocxAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol& rCol, bool bEven, SwTwips nPageSize )
+{
+ // Get the columns attributes
+ FastAttributeList *pColsAttrList = m_pSerializer->createAttrList();
+
+ pColsAttrList->add( FSNS( XML_w, XML_num ),
+ OString::valueOf( sal_Int32( nCols ) ). getStr( ) );
+
+ const char* pEquals = "false";
+ if ( bEven )
+ {
+ sal_uInt16 nWidth = rCol.GetGutterWidth( true );
+ pColsAttrList->add( FSNS( XML_w, XML_space ),
+ OString::valueOf( sal_Int32( nWidth ) ).getStr( ) );
+
+ pEquals = "true";
+ }
+
+ pColsAttrList->add( FSNS( XML_w, XML_equalWidth ), pEquals );
+
+ bool bHasSep = COLADJ_NONE == rCol.GetLineAdj( );
+ pColsAttrList->add( FSNS( XML_w, XML_sep ), bHasSep ? "true" : "false" );
+
+ // Write the element
+ m_pSerializer->startElementNS( XML_w, XML_cols, pColsAttrList );
+
+ // Write the columns width if non-equals
+ const SwColumns & rColumns = rCol.GetColumns( );
+ if ( !bEven )
+ {
+ for ( sal_uInt16 n = 0; n < nCols; ++n )
+ {
+ FastAttributeList *pColAttrList = m_pSerializer->createAttrList();
+ sal_uInt16 nWidth = rCol.CalcPrtColWidth( n, ( sal_uInt16 ) nPageSize );
+ pColAttrList->add( FSNS( XML_w, XML_w ),
+ OString::valueOf( sal_Int32( nWidth ) ).getStr( ) );
+
+ if ( n + 1 != nCols )
+ {
+ sal_uInt16 nSpacing = rColumns[n]->GetRight( ) + rColumns[n + 1]->GetLeft( );
+ pColAttrList->add( FSNS( XML_w, XML_space ),
+ OString::valueOf( sal_Int32( nSpacing ) ).getStr( ) );
+ }
+
+ m_pSerializer->singleElementNS( XML_w, XML_col, pColAttrList );
+ }
+ }
+
+ m_pSerializer->endElementNS( XML_w, XML_cols );
+}
+
+void DocxAttributeOutput::FormatKeep( const SvxFmtKeepItem& )
+{
+ m_pSerializer->singleElementNS( XML_w, XML_keepNext, FSEND );
+}
+
+void DocxAttributeOutput::FormatTextGrid( const SwTextGridItem& rGrid )
+{
+ FastAttributeList *pGridAttrList = m_pSerializer->createAttrList();
+
+ OString sGridType;
+ switch ( rGrid.GetGridType( ) )
+ {
+ default:
+ case GRID_NONE:
+ sGridType = OString( "default" );
+ break;
+ case GRID_LINES_ONLY:
+ sGridType = OString( "lines" );
+ break;
+ case GRID_LINES_CHARS:
+ if ( rGrid.IsSnapToChars( ) )
+ sGridType = OString( "snapToChars" );
+ else
+ sGridType = OString( "linesAndChars" );
+ break;
+ }
+ pGridAttrList->add( FSNS( XML_w, XML_type ), sGridType.getStr( ) );
+
+ sal_uInt16 nHeight = rGrid.GetBaseHeight() + rGrid.GetRubyHeight();
+ pGridAttrList->add( FSNS( XML_w, XML_linePitch ),
+ OString::valueOf( sal_Int32( nHeight ) ).getStr( ) );
+
+ MSWordStyles * pStyles = m_rExport.pStyles;
+ SwFmt * pSwFmt = pStyles->GetSwFmt();
+
+ sal_uInt32 nPageCharSize = 0;
+
+ if (pSwFmt != NULL)
+ {
+ nPageCharSize = ItemGet<SvxFontHeightItem>
+ (*pSwFmt, RES_CHRATR_FONTSIZE).GetHeight();
+ }
+
+ sal_uInt16 nPitch = rGrid.IsSquaredMode() ? rGrid.GetBaseHeight() :
+ rGrid.GetBaseWidth( );
+ sal_Int32 nCharSpace = ( nPitch - nPageCharSize ) * 4096 / 20;
+
+ pGridAttrList->add( FSNS( XML_w, XML_charSpace ),
+ OString::valueOf( sal_Int32( nCharSpace ) ).getStr( ) );
+
+ m_pSerializer->singleElementNS( XML_w, XML_docGrid, pGridAttrList );
+}
+
+void DocxAttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
+{
+ if ( !rNumbering.IsCount( ) )
+ m_pSerializer->singleElementNS( XML_w, XML_suppressLineNumbers, FSEND );
+}
+
+void DocxAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
+{
+ OString sTextFlow;
+ bool bBiDi = false;
+ short nDir = rDirection.GetValue();
+
+ if ( nDir == FRMDIR_ENVIRONMENT )
+ nDir = GetExport( ).GetDefaultFrameDirection( );
+
+ switch ( nDir )
+ {
+ default:
+ case FRMDIR_HORI_LEFT_TOP:
+ sTextFlow = OString( "lrTb" );
+ break;
+ case FRMDIR_HORI_RIGHT_TOP:
+ sTextFlow = OString( "lrTb" );
+ bBiDi = true;
+ break;
+ case FRMDIR_VERT_TOP_LEFT: // many things but not this one
+ case FRMDIR_VERT_TOP_RIGHT:
+ sTextFlow = OString( "tbRl" );
+ break;
+ }
+
+ if ( m_rExport.bOutPageDescs )
+ {
+ m_pSerializer->singleElementNS( XML_w, XML_textDirection,
+ FSNS( XML_w, XML_val ), sTextFlow.getStr( ),
+ FSEND );
+ if ( bBiDi )
+ m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
+ }
+ else if ( !m_rExport.bOutFlyFrmAttrs )
+ {
+ if ( bBiDi )
+ m_pSerializer->singleElementNS( XML_w, XML_bidi, FSEND );
+ }
+}
+
+DocxAttributeOutput::DocxAttributeOutput( DocxExport &rExport, FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML )
+ : m_rExport( rExport ),
+ m_pSerializer( pSerializer ),
+ m_rDrawingML( *pDrawingML ),
+ m_pFontsAttrList( NULL ),
+ m_pEastAsianLayoutAttrList( NULL ),
+ m_pCharLangAttrList( NULL ),
+ m_pSectionSpacingAttrList( NULL ),
+ m_pParagraphSpacingAttrList( NULL ),
+ m_pHyperlinkAttrList( NULL ),
+ m_pFlyAttrList( NULL ),
+ m_pFootnotesList( new ::docx::FootnotesList() ),
+ m_pEndnotesList( new ::docx::FootnotesList() ),
+ m_footnoteEndnoteRefTag( 0 ),
+ m_pSectionInfo( NULL ),
+ m_pRedlineData( NULL ),
+ m_nRedlineId( 0 ),
+ m_bOpenedSectPr( false ),
+ m_sFieldBkm( ),
+ m_nNextMarkId( 0 ),
+ m_pTableWrt( NULL ),
+ m_bTableCellOpen( false ),
+ m_nTableDepth( 0 ),
+ m_bParagraphOpened( false ),
+ m_nColBreakStatus( COLBRK_NONE ),
+ m_pParentFrame( NULL )
+{
+}
+
+DocxAttributeOutput::~DocxAttributeOutput()
+{
+ delete m_pFontsAttrList, m_pFontsAttrList = NULL;
+ delete m_pEastAsianLayoutAttrList, m_pEastAsianLayoutAttrList = NULL;
+ delete m_pCharLangAttrList, m_pCharLangAttrList = NULL;
+ delete m_pSectionSpacingAttrList, m_pSectionSpacingAttrList = NULL;
+ delete m_pParagraphSpacingAttrList, m_pParagraphSpacingAttrList = NULL;
+ delete m_pHyperlinkAttrList, m_pHyperlinkAttrList = NULL;
+ delete m_pFlyAttrList, m_pFlyAttrList = NULL;
+
+ delete m_pFootnotesList, m_pFootnotesList = NULL;
+ delete m_pEndnotesList, m_pEndnotesList = NULL;
+
+ delete m_pTableWrt, m_pTableWrt = NULL;
+ m_pParentFrame = NULL;
+}
+
+DocxExport& DocxAttributeOutput::GetExport()
+{
+ return m_rExport;
+}
+
+bool DocxAttributeOutput::HasFootnotes()
+{
+ return !m_pFootnotesList->isEmpty();
+}
+
+bool DocxAttributeOutput::HasEndnotes()
+{
+ return !m_pEndnotesList->isEmpty();
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxattributeoutput.hxx b/sw/source/filter/ww8/docxattributeoutput.hxx
new file mode 100644
index 000000000000..8eee66c51ad6
--- /dev/null
+++ b/sw/source/filter/ww8/docxattributeoutput.hxx
@@ -0,0 +1,609 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DOCXATTRIBUTEOUTPUT_HXX_
+#define _DOCXATTRIBUTEOUTPUT_HXX_
+
+#include "attributeoutputbase.hxx"
+#include "fields.hxx"
+#include "IMark.hxx"
+#include "docxexport.hxx"
+
+#include <sax/fshelper.hxx>
+#include <sax/fastattribs.hxx>
+#include <vcl/vclenum.hxx>
+
+#include <fldbas.hxx>
+
+#include <vector>
+
+class SwGrfNode;
+class SdrObject;
+
+namespace docx { class FootnotesList; }
+namespace oox { namespace drawingml { class DrawingML; } }
+
+struct FieldInfos
+{
+ const SwField* pField;
+ const ::sw::mark::IFieldmark* pFieldmark;
+ ww::eField eType;
+ bool bOpen;
+ bool bClose;
+ String sCmd;
+ FieldInfos() : pField(NULL), pFieldmark(NULL), eType(ww::eUNKNOWN), bOpen(false), bClose(false){}
+};
+
+enum DocxColBreakStatus
+{
+ COLBRK_NONE,
+ COLBRK_POSTPONE,
+ COLBRK_WRITE
+};
+
+/// The class that has handlers for various resource types when exporting as DOCX.
+class DocxAttributeOutput : public AttributeOutputBase
+{
+public:
+ /// Export the state of RTL/CJK.
+ virtual void RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript );
+
+ /// Start of the paragraph.
+ virtual void StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo );
+
+ /// End of the paragraph.
+ virtual void EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner );
+
+ /// Empty paragraph.
+ virtual void EmptyParagraph();
+
+ /// Called before we start outputting the attributes.
+ virtual void StartParagraphProperties( const SwTxtNode& rNode );
+
+ /// Called after we end outputting the attributes.
+ virtual void EndParagraphProperties();
+
+ /// Start of the text run.
+ virtual void StartRun( const SwRedlineData* pRedlineData );
+
+ /// End of the text run.
+ virtual void EndRun();
+
+ /// Called before we start outputting the attributes.
+ virtual void StartRunProperties();
+
+ /// Called after we end outputting the attributes.
+ virtual void EndRunProperties( const SwRedlineData* pRedlineData );
+
+ virtual void FootnoteEndnoteRefTag();
+
+ /// Output text (inside a run).
+ virtual void RunText( const String& rText, rtl_TextEncoding eCharSet = RTL_TEXTENCODING_UTF8 );
+
+ /// Output text (without markup).
+ virtual void RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet );
+
+ /// Output ruby start.
+ virtual void StartRuby( const SwTxtNode& rNode, xub_StrLen nPos, const SwFmtRuby& rRuby );
+
+ /// Output ruby end.
+ virtual void EndRuby();
+
+ /// Output URL start.
+ virtual bool StartURL( const String& rUrl, const String& rTarget );
+
+ /// Output URL end.
+ virtual bool EndURL();
+
+ virtual void FieldVanish( const String& rTxt, ww::eField eType );
+
+ /// Output redlining.
+ ///
+ /// The common attribute that can be among the run properties.
+ virtual void Redline( const SwRedlineData* pRedline );
+
+ /// Output redlining.
+ ///
+ /// Start of the tag that encloses the run, fills the info according to
+ /// the value of m_pRedlineData.
+ void StartRedline( const SwRedlineData* pRedlineData );
+
+ /// Output redlining.
+ ///
+ /// End of the tag that encloses the run.
+ void EndRedline();
+
+ virtual void FormatDrop( const SwTxtNode& rNode, const SwFmtDrop& rSwFmtDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner );
+
+ /// Output style.
+ virtual void ParagraphStyle( sal_uInt16 nStyle );
+
+ virtual void TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo );
+ virtual void TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner );
+ virtual void TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableRowEnd( sal_uInt32 nDepth = 1 );
+
+ /// Start of the styles table.
+ virtual void StartStyles();
+
+ /// End of the styles table.
+ virtual void EndStyles( sal_uInt16 nNumberOfStyles );
+
+ /// Write default style.
+ virtual void DefaultStyle( sal_uInt16 nStyle );
+
+ /// Start of a style in the styles table.
+ virtual void StartStyle( const String& rName, bool bPapFmt,
+ sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 nWwId, sal_uInt16 nId,
+ bool bAutoUpdate );
+
+ /// End of a style in the styles table.
+ virtual void EndStyle();
+
+ /// Start of (paragraph or run) properties of a style.
+ virtual void StartStyleProperties( bool bParProp, sal_uInt16 nStyle );
+
+ /// End of (paragraph or run) properties of a style.
+ virtual void EndStyleProperties( bool bParProp );
+
+ /// Numbering rule and Id.
+ virtual void OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt &rNFmt, const SwFmt &rFmt );
+
+ /// Page break
+ /// As a paragraph property - the paragraph should be on the next page.
+ virtual void PageBreakBefore( bool bBreak );
+
+ /// Write a section break
+ /// msword::ColumnBreak or msword::PageBreak
+ virtual void SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo = NULL );
+
+ /// Start of the section properties.
+ virtual void StartSection();
+
+ /// End of the section properties.
+ virtual void EndSection();
+
+ /// Protection of forms.
+ virtual void SectionFormProtection( bool bProtected );
+
+ /// Numbering of the lines in the document.
+ virtual void SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo );
+
+ /// Has different headers/footers for the title page.
+ virtual void SectionTitlePage();
+
+ /// Description of the page borders.
+ virtual void SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* pFirstPageFmt );
+
+ /// Columns populated from right/numbers on the right side?
+ virtual void SectionBiDi( bool bBiDi );
+
+ /// The style of the page numbers.
+ ///
+ /// nPageRestartNumberr being 0 means no restart.
+ virtual void SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber );
+
+ /// The type of breaking.
+ virtual void SectionType( sal_uInt8 nBreakCode );
+
+ /// Start the font.
+ void StartFont( const String& rFamilyName ) const;
+
+ /// End the font.
+ void EndFont() const;
+
+ /// Alternate name for the font.
+ void FontAlternateName( const String& rName ) const;
+
+ /// Font charset.
+ void FontCharset( sal_uInt8 nCharSet, rtl_TextEncoding nEncoding ) const;
+
+ /// Font family.
+ void FontFamilyType( FontFamily eFamily ) const;
+
+ /// Font pitch.
+ void FontPitchType( FontPitch ePitch ) const;
+
+ /// Definition of a numbering instance.
+ virtual void NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule );
+
+ /// Start of the abstract numbering definition instance.
+ virtual void StartAbstractNumbering( sal_uInt16 nId );
+
+ /// End of the abstract numbering definition instance.
+ virtual void EndAbstractNumbering();
+
+ /// All the numbering level information.
+ virtual void NumberingLevel( sal_uInt8 nLevel,
+ sal_uInt16 nStart,
+ sal_uInt16 nNumberingType,
+ SvxAdjust eAdjust,
+ const sal_uInt8 *pNumLvlPos,
+ sal_uInt8 nFollow,
+ const wwFont *pFont,
+ const SfxItemSet *pOutSet,
+ sal_Int16 nIndentAt,
+ sal_Int16 nFirstLineIndex,
+ sal_Int16 nListTabPos,
+ const String &rNumberingString );
+
+ void WriteField_Impl( const SwField* pFld, ww::eField eType, const String& rFldCmd, sal_uInt8 nMode );
+ void WriteFormData_Impl( const ::sw::mark::IFieldmark& rFieldmark );
+
+ void WriteBookmarks_Impl( std::vector< rtl::OUString >& rStarts, std::vector< rtl::OUString >& rEnds );
+
+private:
+ /// Initialize the structures where we are going to collect some of the paragraph properties.
+ ///
+ /// Some of the properties have to be collected from more sources, and are
+ /// actually not written between StartParagraphProperties and
+ /// EndParagraphProperties. They are output in this method, which is
+ /// supposed to be called just before outputting </rPr> whenever it is done.
+ void InitCollectedParagraphProperties();
+
+ /// Output what we collected during the run properties output.
+ ///
+ /// @see WriteCollectedParagrapProperties().
+ void WriteCollectedParagraphProperties();
+
+ /// Initialize the structures where we are going to collect some of the run properties.
+ ///
+ /// This is an equivalent of InitCollectedParagraphProperties(), resp.
+ /// WriteCollectectedParagraphProperties().
+ ///
+ /// @see InitCollectedParagraphProperties().
+ void InitCollectedRunProperties();
+
+ /// Output what we collected during the run properties output.
+ ///
+ /// @see InitCollectedRunProperies(), WriteCollectedParagraphProperties()
+ void WriteCollectedRunProperties();
+
+ /// Output graphic fly frames.
+ void FlyFrameGraphic( const SwGrfNode& rGrfNode, const Size& rSize );
+ void WriteOLE2Obj( const SdrObject* pSdrObj, const Size& rSize );
+
+ void InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ void StartTable( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ void StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ void StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ void TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ void EndTableCell( );
+ void EndTableRow( );
+ void EndTable();
+
+ /// End cell, row, and even the entire table if necessary.
+ void FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph = false );
+
+ void WriteFFData( const FieldInfos& rInfos );
+protected:
+
+ /// Output frames - the implementation.
+ virtual void OutputFlyFrame_Impl( const sw::Frame& rFmt, const Point& rNdTopLeft );
+
+ /// Sfx item Sfx item RES_CHRATR_CASEMAP
+ virtual void CharCaseMap( const SvxCaseMapItem& rCaseMap );
+
+ /// Sfx item Sfx item RES_CHRATR_COLOR
+ virtual void CharColor( const SvxColorItem& rColor);
+
+ /// Sfx item Sfx item RES_CHRATR_CONTOUR
+ virtual void CharContour( const SvxContourItem& rContour );
+
+ /// Sfx item RES_CHRATR_CROSSEDOUT
+ virtual void CharCrossedOut( const SvxCrossedOutItem& rCrossedOut );
+
+ /// Sfx item RES_CHRATR_ESCAPEMENT
+ virtual void CharEscapement( const SvxEscapementItem& rEscapement );
+
+ /// Sfx item RES_CHRATR_FONT
+ virtual void CharFont( const SvxFontItem& rFont );
+
+ /// Sfx item RES_CHRATR_FONTSIZE
+ virtual void CharFontSize( const SvxFontHeightItem& rFontSize );
+
+ /// Sfx item RES_CHRATR_KERNING
+ virtual void CharKerning( const SvxKerningItem& rKerning );
+
+ /// Sfx item RES_CHRATR_LANGUAGE
+ virtual void CharLanguage( const SvxLanguageItem& rLanguage );
+
+ /// Sfx item RES_CHRATR_POSTURE
+ virtual void CharPosture( const SvxPostureItem& rPosture );
+
+ /// Sfx item RES_CHRATR_SHADOWED
+ virtual void CharShadow( const SvxShadowedItem& rShadow );
+
+ /// Sfx item RES_CHRATR_UNDERLINE
+ virtual void CharUnderline( const SvxUnderlineItem& rUnderline );
+
+ /// Sfx item RES_CHRATR_WEIGHT
+ virtual void CharWeight( const SvxWeightItem& rWeight );
+
+ /// Sfx item RES_CHRATR_AUTOKERN
+ virtual void CharAutoKern( const SvxAutoKernItem& );
+
+ /// Sfx item RES_CHRATR_BLINK
+ virtual void CharAnimatedText( const SvxBlinkItem& rBlink );
+
+ /// Sfx item RES_CHRATR_BACKGROUND
+ virtual void CharBackground( const SvxBrushItem& rBrush );
+
+ /// Sfx item RES_CHRATR_CJK_FONT
+ virtual void CharFontCJK( const SvxFontItem& rFont );
+
+ /// Sfx item RES_CHRATR_CJK_FONTSIZE
+ virtual void CharFontSizeCJK( const SvxFontHeightItem& rFontSize ) { CharFontSize( rFontSize ); }
+
+ /// Sfx item RES_CHRATR_CJK_LANGUAGE
+ virtual void CharLanguageCJK( const SvxLanguageItem& rLanguageItem ) { CharLanguage( rLanguageItem ); }
+
+ /// Sfx item RES_CHRATR_CJK_POSTURE
+ virtual void CharPostureCJK( const SvxPostureItem& rPosture );
+
+ /// Sfx item RES_CHRATR_CJK_WEIGHT
+ virtual void CharWeightCJK( const SvxWeightItem& rWeight );
+
+ /// Sfx item RES_CHRATR_CTL_FONT
+ virtual void CharFontCTL( const SvxFontItem& rFont );
+
+ /// Sfx item RES_CHRATR_CTL_FONTSIZE
+ virtual void CharFontSizeCTL( const SvxFontHeightItem& rFontSize ) { CharFontSize( rFontSize ); }
+
+ /// Sfx item RES_CHRATR_CTL_LANGUAGE
+ virtual void CharLanguageCTL( const SvxLanguageItem& rLanguageItem ) { CharLanguage( rLanguageItem); }
+
+ /// Sfx item RES_CHRATR_CTL_POSTURE
+ virtual void CharPostureCTL( const SvxPostureItem& rWeight );
+
+ /// Sfx item RES_CHRATR_CTL_WEIGHT
+ virtual void CharWeightCTL( const SvxWeightItem& rWeight );
+
+ /// Sfx item RES_CHRATR_ROTATE
+ virtual void CharRotate( const SvxCharRotateItem& rRotate );
+
+ /// Sfx item RES_CHRATR_EMPHASIS_MARK
+ virtual void CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark );
+
+ /// Sfx item RES_CHRATR_TWO_LINES
+ virtual void CharTwoLines( const SvxTwoLinesItem& rTwoLines );
+
+ /// Sfx item RES_CHRATR_SCALEW
+ virtual void CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth );
+
+ /// Sfx item RES_CHRATR_RELIEF
+ virtual void CharRelief( const SvxCharReliefItem& rRelief);
+
+ /// Sfx item RES_CHRATR_HIDDEN
+ virtual void CharHidden( const SvxCharHiddenItem& rHidden );
+
+ /// Sfx item RES_TXTATR_INETFMT
+ virtual void TextINetFormat( const SwFmtINetFmt& );
+
+ /// Sfx item RES_TXTATR_CHARFMT
+ virtual void TextCharFormat( const SwFmtCharFmt& );
+
+ /// Sfx item RES_TXTATR_FTN
+ virtual void TextFootnote_Impl( const SwFmtFtn& );
+
+ /// Output the footnote/endnote reference (if there's one to output).
+ void FootnoteEndnoteReference();
+
+ /// Sfx item RES_PARATR_LINESPACING
+ virtual void ParaLineSpacing_Impl( short nSpace, short nMulti );
+
+ /// Sfx item RES_PARATR_ADJUST
+ virtual void ParaAdjust( const SvxAdjustItem& rAdjust );
+
+ /// Sfx item RES_PARATR_SPLIT
+ virtual void ParaSplit( const SvxFmtSplitItem& rSplit );
+
+ /// Sfx item RES_PARATR_WIDOWS
+ virtual void ParaWidows( const SvxWidowsItem& rWidows );
+
+ /// Sfx item RES_PARATR_TABSTOP
+ virtual void ParaTabStop( const SvxTabStopItem& rTabStop );
+
+ /// Sfx item RES_PARATR_HYPHENZONE
+ virtual void ParaHyphenZone( const SvxHyphenZoneItem& );
+
+ /// Sfx item RES_PARATR_NUMRULE
+ virtual void ParaNumRule_Impl( const SwTxtNode *pTxtNd, sal_Int32 nLvl, sal_Int32 nNumId );
+
+ /// Sfx item RES_PARATR_SCRIPTSPACE
+ virtual void ParaScriptSpace( const SfxBoolItem& );
+
+ /// Sfx item RES_PARATR_VERTALIGN
+ virtual void ParaVerticalAlign( const SvxParaVertAlignItem& rAlign );
+
+ /// Sfx item RES_PARATR_SNAPTOGRID
+ virtual void ParaSnapToGrid( const SvxParaGridItem& );
+
+ /// Sfx item RES_FRM_SIZE
+ virtual void FormatFrameSize( const SwFmtFrmSize& );
+
+ /// Sfx item RES_PAPER_BIN
+ virtual void FormatPaperBin( const SvxPaperBinItem& );
+
+ /// Sfx item RES_LR_SPACE
+ virtual void FormatLRSpace( const SvxLRSpaceItem& rLRSpace );
+
+ /// Sfx item RES_UL_SPACE
+ virtual void FormatULSpace( const SvxULSpaceItem& rULSpace );
+
+ /// Sfx item RES_SURROUND
+ virtual void FormatSurround( const SwFmtSurround& );
+
+ /// Sfx item RES_VERT_ORIENT
+ virtual void FormatVertOrientation( const SwFmtVertOrient& );
+
+ /// Sfx item RES_HORI_ORIENT
+ virtual void FormatHorizOrientation( const SwFmtHoriOrient& );
+
+ /// Sfx item RES_ANCHOR
+ virtual void FormatAnchor( const SwFmtAnchor& );
+
+ /// Sfx item RES_BACKGROUND
+ virtual void FormatBackground( const SvxBrushItem& );
+
+ /// Sfx item RES_BOX
+ virtual void FormatBox( const SvxBoxItem& );
+
+ /// Sfx item RES_COL
+ virtual void FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol & rCol, bool bEven, SwTwips nPageSize );
+
+ /// Sfx item RES_KEEP
+ virtual void FormatKeep( const SvxFmtKeepItem& );
+
+ /// Sfx item RES_TEXTGRID
+ virtual void FormatTextGrid( const SwTextGridItem& );
+
+ /// Sfx item RES_LINENUMBER
+ virtual void FormatLineNumbering( const SwFmtLineNumber& );
+
+ /// Sfx item RES_FRAMEDIR
+ virtual void FormatFrameDirection( const SvxFrameDirectionItem& );
+
+ /// Write the expanded field
+ virtual void WriteExpand( const SwField* pFld );
+
+ virtual void RefField( const SwField& rFld, const String& rRef );
+ virtual void HiddenField( const SwField& rFld );
+ virtual void SetField( const SwField& rFld, ww::eField eType, const String& rCmd );
+ virtual void PostitField( const SwField* pFld );
+ virtual bool DropdownField( const SwField* pFld );
+
+ virtual bool AnalyzeURL( const String& rURL, const String& rTarget, String* pLinkURL, String* pMark );
+
+ /// Reference to the export, where to get the data from
+ DocxExport &m_rExport;
+
+ /// Fast serializer to output the data
+ ::sax_fastparser::FSHelperPtr m_pSerializer;
+
+ /// DrawingML access
+ oox::drawingml::DrawingML &m_rDrawingML;
+
+private:
+
+ void DoWriteBookmarks( );
+
+ void StartField_Impl( FieldInfos& rInfos, sal_Bool bWriteRun = sal_False );
+ void DoWriteCmd( String& rCmd );
+ void CmdField_Impl( FieldInfos& rInfos );
+ void EndField_Impl( FieldInfos& rInfos );
+
+ ::sax_fastparser::FastAttributeList *m_pFontsAttrList, *m_pEastAsianLayoutAttrList;
+ ::sax_fastparser::FastAttributeList *m_pCharLangAttrList;
+ ::sax_fastparser::FastAttributeList *m_pSectionSpacingAttrList;
+ ::sax_fastparser::FastAttributeList *m_pParagraphSpacingAttrList;
+ ::sax_fastparser::FastAttributeList *m_pHyperlinkAttrList;
+ ::sax_fastparser::FastAttributeList *m_pFlyAttrList;
+
+ ::docx::FootnotesList *m_pFootnotesList;
+ ::docx::FootnotesList *m_pEndnotesList;
+ int m_footnoteEndnoteRefTag;
+
+ const WW8_SepInfo *m_pSectionInfo;
+
+ /// Redline data to remember in the text run.
+ const SwRedlineData *m_pRedlineData;
+
+ /// Id of the redline
+ sal_Int32 m_nRedlineId;
+
+ /// Flag indicating that the section properties are being written
+ sal_Bool m_bOpenedSectPr;
+
+ /// Field data to remember in the text run
+ std::vector< FieldInfos > m_Fields;
+ String m_sFieldBkm;
+ sal_Int32 m_nNextMarkId;
+
+ /// Bookmarks to output
+ std::vector<rtl::OString> m_rMarksStart;
+ std::vector<rtl::OString> m_rMarksEnd;
+
+ /// Maps of the bookmarks ids
+ std::map<rtl::OString, sal_uInt16> m_rOpenedMarksIds;
+
+ /// The current table helper
+ SwWriteTable *m_pTableWrt;
+
+ /// Remember if we are in an open cell, or not.
+ bool m_bTableCellOpen;
+
+ /// Remember the current table depth.
+ sal_uInt32 m_nTableDepth;
+
+ bool m_bParagraphOpened;
+
+ // Remember that a column break has to be opened at the
+ // beginning of the next paragraph
+ DocxColBreakStatus m_nColBreakStatus;
+
+ const sw::Frame *m_pParentFrame;
+
+public:
+ DocxAttributeOutput( DocxExport &rExport, ::sax_fastparser::FSHelperPtr pSerializer, oox::drawingml::DrawingML* pDrawingML );
+
+ virtual ~DocxAttributeOutput();
+
+ /// Return the right export class.
+ virtual DocxExport& GetExport();
+ const DocxExport& GetExport() const { return const_cast< DocxAttributeOutput* >( this )->GetExport(); }
+
+ /// For eg. the output of the styles, we need to switch the serializer to enother one.
+ void SetSerializer( ::sax_fastparser::FSHelperPtr pSerializer ) { m_pSerializer = pSerializer; }
+
+ /// Occasionnaly need to use this serializer from the outside
+ ::sax_fastparser::FSHelperPtr GetSerializer( ) { return m_pSerializer; }
+
+ /// Do we have any footnotes?
+ bool HasFootnotes();
+
+ /// Do we have any endnotes?
+ bool HasEndnotes();
+
+ /// Output the content of the footnotes.xml resp. endnotes.xml
+ void FootnotesEndnotes( bool bFootnotes );
+};
+
+#endif // _DOCXATTRIBUTEOUTPUT_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxexport.cxx b/sw/source/filter/ww8/docxexport.cxx
new file mode 100644
index 000000000000..9f0489716fc0
--- /dev/null
+++ b/sw/source/filter/ww8/docxexport.cxx
@@ -0,0 +1,768 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "docxexport.hxx"
+#include "docxexportfilter.hxx"
+#include "docxattributeoutput.hxx"
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <com/sun/star/frame/XModel.hpp>
+
+#include <oox/token/tokens.hxx>
+#include <oox/export/drawingml.hxx>
+#include <oox/export/vmlexport.hxx>
+#include <oox/export/chartexport.hxx>
+
+#include <map>
+#include <algorithm>
+
+#include <IMark.hxx>
+#include <docsh.hxx>
+#include <ndtxt.hxx>
+#include <wrtww8.hxx>
+#include <fltini.hxx>
+#include <fmtline.hxx>
+#include <fmtpdsc.hxx>
+#include <frmfmt.hxx>
+#include <section.hxx>
+
+#include <docary.hxx>
+#include <numrule.hxx>
+#include <charfmt.hxx>
+
+#include "ww8par.hxx"
+#include "ww8scan.hxx"
+
+#include <comphelper/string.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <vcl/font.hxx>
+
+using namespace sax_fastparser;
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using namespace ::oox;
+
+using oox::vml::VMLExport;
+
+using rtl::OUString;
+using rtl::OUStringBuffer;
+
+using sw::mark::IMark;
+
+#define S( x ) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
+
+AttributeOutputBase& DocxExport::AttrOutput() const
+{
+ return *m_pAttrOutput;
+}
+
+MSWordSections& DocxExport::Sections() const
+{
+ return *m_pSections;
+}
+
+bool DocxExport::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich )
+{
+ // TODO FIXME is this actually true for docx? - this is ~copied from WW8
+ if ( nScript == i18n::ScriptType::ASIAN )
+ {
+ // for asian in ww8, there is only one fontsize
+ // and one fontstyle (posture/weight)
+ switch ( nWhich )
+ {
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_POSTURE:
+ case RES_CHRATR_WEIGHT:
+ return false;
+ default:
+ break;
+ }
+ }
+ else if ( nScript != i18n::ScriptType::COMPLEX )
+ {
+ // for western in ww8, there is only one fontsize
+ // and one fontstyle (posture/weight)
+ switch ( nWhich )
+ {
+ case RES_CHRATR_CJK_FONTSIZE:
+ case RES_CHRATR_CJK_POSTURE:
+ case RES_CHRATR_CJK_WEIGHT:
+ return false;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+void DocxExport::AppendBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen )
+{
+ std::vector< OUString > aStarts;
+ std::vector< OUString > aEnds;
+
+ IMarkVector aMarks;
+ if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarks ) )
+ {
+ for ( IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end();
+ it < end; ++it )
+ {
+ IMark* pMark = (*it);
+
+ xub_StrLen nStart = pMark->GetMarkStart().nContent.GetIndex();
+ xub_StrLen nEnd = pMark->GetMarkEnd().nContent.GetIndex();
+
+ if ( nStart == nAktPos )
+ aStarts.push_back( pMark->GetName() );
+
+ if ( nEnd == nAktPos )
+ aEnds.push_back( pMark->GetName() );
+ }
+ }
+
+ m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
+}
+
+void DocxExport::AppendBookmark( const OUString& rName, bool /*bSkip*/ )
+{
+ std::vector< OUString > aStarts;
+ std::vector< OUString > aEnds;
+
+ aStarts.push_back( rName );
+ aEnds.push_back( rName );
+
+ m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
+}
+
+::rtl::OString DocxExport::AddRelation( const OUString& rType, const OUString& rTarget, const OUString& rMode )
+{
+ OUString sId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+ rType, rTarget, rMode );
+
+ return ::rtl::OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
+}
+
+bool DocxExport::DisallowInheritingOutlineNumbering( const SwFmt& rFmt )
+{
+ bool bRet( false );
+
+ if (SFX_ITEM_SET != rFmt.GetItemState(RES_PARATR_NUMRULE, false))
+ {
+ if (const SwFmt *pParent = rFmt.DerivedFrom())
+ {
+ if (((const SwTxtFmtColl*)pParent)->IsAssignedToListLevelOfOutlineStyle())
+ {
+ ::sax_fastparser::FSHelperPtr pSerializer = m_pAttrOutput->GetSerializer( );
+ // Level 9 disables the outline
+ pSerializer->singleElementNS( XML_w, XML_outlineLvl,
+ FSNS( XML_w, XML_val ), "9" ,
+ FSEND );
+
+ bRet = true;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+void DocxExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
+ const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 /*nBreakCode*/ )
+{
+ // headers
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN )
+ WriteHeaderFooter( rLeftFmt, true, "even" );
+
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD )
+ WriteHeaderFooter( rFmt, true, "default" );
+
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_FIRST )
+ WriteHeaderFooter( rFirstPageFmt, true, "first" );
+
+ // footers
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN )
+ WriteHeaderFooter( rLeftFmt, false, "even" );
+
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD )
+ WriteHeaderFooter( rFmt, false, "default" );
+
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_FIRST )
+ WriteHeaderFooter( rFirstPageFmt, false, "first" );
+
+ if ( nHeadFootFlags & ( nsHdFtFlags::WW8_FOOTER_EVEN | nsHdFtFlags::WW8_HEADER_EVEN ))
+ settings.evenAndOddHeaders = true;
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "DocxExport::WriteHeadersFooters() - nBreakCode introduced, but ignored\n" );
+#endif
+}
+
+void DocxExport::OutputField( const SwField* pFld, ww::eField eFldType, const String& rFldCmd, sal_uInt8 nMode )
+{
+ m_pAttrOutput->WriteField_Impl( pFld, eFldType, rFldCmd, nMode );
+}
+
+void DocxExport::WriteFormData( const ::sw::mark::IFieldmark& rFieldmark )
+{
+ m_pAttrOutput->WriteFormData_Impl( rFieldmark );
+}
+
+void DocxExport::WriteHyperlinkData( const ::sw::mark::IFieldmark& /*rFieldmark*/ )
+{
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "TODO DocxExport::WriteHyperlinkData()\n" );
+#endif
+}
+
+void DocxExport::DoComboBox(const rtl::OUString& rName,
+ const rtl::OUString& rHelp,
+ const rtl::OUString& rToolTip,
+ const rtl::OUString& rSelected,
+ uno::Sequence<rtl::OUString>& rListItems)
+{
+ m_pDocumentFS->startElementNS( XML_w, XML_ffData, FSEND );
+
+ m_pDocumentFS->singleElementNS( XML_w, XML_name,
+ FSNS( XML_w, XML_val ), OUStringToOString( rName, RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+
+ m_pDocumentFS->singleElementNS( XML_w, XML_enabled, FSEND );
+
+ if ( rHelp.getLength( ) > 0 )
+ m_pDocumentFS->singleElementNS( XML_w, XML_helpText,
+ FSNS( XML_w, XML_val ), OUStringToOString( rHelp, RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+
+ if ( rToolTip.getLength( ) > 0 )
+ m_pDocumentFS->singleElementNS( XML_w, XML_statusText,
+ FSNS( XML_w, XML_val ), OUStringToOString( rToolTip, RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+
+ m_pDocumentFS->startElementNS( XML_w, XML_ddList, FSEND );
+
+ // Output the 0-based index of the selected value
+ sal_uInt32 nListItems = rListItems.getLength();
+ sal_Int32 nId = 0;
+ sal_uInt32 nI = 0;
+ while ( ( nI < nListItems ) && ( nId == 0 ) )
+ {
+ if ( rListItems[nI] == rSelected )
+ nId = nI;
+ nI++;
+ }
+
+ m_pDocumentFS->singleElementNS( XML_w, XML_result,
+ FSNS( XML_w, XML_val ), rtl::OString::valueOf( nId ).getStr( ),
+ FSEND );
+
+ // Loop over the entries
+
+ for (sal_uInt32 i = 0; i < nListItems; i++)
+ {
+ m_pDocumentFS->singleElementNS( XML_w, XML_listEntry,
+ FSNS( XML_w, XML_val ), OUStringToOString( rListItems[i], RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+ }
+
+ m_pDocumentFS->endElementNS( XML_w, XML_ddList );
+
+ m_pDocumentFS->endElementNS( XML_w, XML_ffData );
+}
+
+void DocxExport::DoFormText(const SwInputField* /*pFld*/)
+{
+ OSL_TRACE( "TODO DocxExport::ForFormText()\n" );
+}
+
+rtl::OString DocxExport::OutputChart( uno::Reference< frame::XModel >& xModel, sal_Int32 nCount )
+{
+ rtl::OUString aFileName = rtl::OUStringBuffer()
+ .appendAscii("charts/chart")
+ .append(nCount)
+ .appendAscii( ".xml" )
+ .makeStringAndClear();
+
+ OUString sId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/chart" ),
+ aFileName );
+
+ aFileName = rtl::OUStringBuffer()
+ .appendAscii("word/charts/chart")
+ .append(nCount)
+ .appendAscii( ".xml" )
+ .makeStringAndClear();
+
+ ::sax_fastparser::FSHelperPtr pChartFS =
+ m_pFilter->openFragmentStreamWithSerializer( aFileName,
+ S( "application/vnd.openxmlformats-officedocument.drawingml.chart" ) );
+
+ oox::drawingml::ChartExport aChartExport( XML_w, pChartFS, xModel, m_pFilter, oox::drawingml::DrawingML::DOCUMENT_DOCX );
+ aChartExport.ExportContent();
+ return ::rtl::OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
+}
+
+void DocxExport::ExportDocument_Impl()
+{
+ InitStyles();
+
+ // init sections
+ m_pSections = new MSWordSections( *this );
+
+ WriteMainText();
+
+ WriteFootnotesEndnotes();
+
+ WriteNumbering();
+
+ WriteFonts();
+
+ WriteSettings();
+
+ delete pStyles, pStyles = NULL;
+ delete m_pSections, m_pSections = NULL;
+}
+
+void DocxExport::OutputPageSectionBreaks( const SwTxtNode& )
+{
+ OSL_TRACE( "TODO DocxExport::OutputPageSectionBreaks( const SwTxtNode& )\n" );
+}
+
+
+void DocxExport::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum )
+{
+ AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
+ m_pSections->AppendSection( pPageDesc, pFmt, nLnNum );
+}
+
+void DocxExport::OutputEndNode( const SwEndNode& rEndNode )
+{
+ MSWordExportBase::OutputEndNode( rEndNode );
+
+ if ( TXT_MAINTEXT == nTxtTyp && rEndNode.StartOfSectionNode()->IsSectionNode() )
+ {
+ // this originally comes from WW8Export::WriteText(), and looks like it
+ // could have some code common with SectionNode()...
+
+ const SwSection& rSect = rEndNode.StartOfSectionNode()->GetSectionNode()->GetSection();
+ if ( bStartTOX && TOX_CONTENT_SECTION == rSect.GetType() )
+ bStartTOX = false;
+
+ SwNodeIndex aIdx( rEndNode, 1 );
+ const SwNode& rNd = aIdx.GetNode();
+ if ( rNd.IsEndNode() && rNd.StartOfSectionNode()->IsSectionNode() )
+ return;
+
+ if ( !rNd.IsSectionNode() && !bIsInTable ) // No sections in table
+ {
+ const SwSectionFmt* pParentFmt = rSect.GetFmt()->GetParent();
+ if( !pParentFmt )
+ pParentFmt = (SwSectionFmt*)0xFFFFFFFF;
+
+ sal_uLong nRstLnNum;
+ if( rNd.IsCntntNode() )
+ nRstLnNum = const_cast< SwCntntNode* >( rNd.GetCntntNode() )->GetSwAttrSet().GetLineNumber().GetStartValue();
+ else
+ nRstLnNum = 0;
+
+ AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo( ) );
+ m_pSections->AppendSection( pAktPageDesc, pParentFmt, nRstLnNum );
+ }
+ }
+}
+
+void DocxExport::OutputTableNode( const SwTableNode& )
+{
+ OSL_TRACE( "TODO DocxExport::OutputTableNode( const SwTableNode& )\n" );
+}
+
+void DocxExport::OutputGrfNode( const SwGrfNode& )
+{
+ OSL_TRACE( "TODO DocxExport::OutputGrfNode( const SwGrfNode& )\n" );
+}
+
+void DocxExport::OutputOLENode( const SwOLENode& )
+{
+ OSL_TRACE( "TODO DocxExport::OutputOLENode( const SwOLENode& )\n" );
+}
+
+void DocxExport::OutputLinkedOLE( const OUString& )
+{
+ // Nothing to implement here: WW8 only
+}
+
+sal_uLong DocxExport::ReplaceCr( sal_uInt8 )
+{
+ // Completely unused for Docx export... only here for code sharing
+ // purpose with binary export
+ return 0;
+}
+
+void DocxExport::PrepareNewPageDesc( const SfxItemSet* pSet,
+ const SwNode& rNd, const SwFmtPageDesc* pNewPgDescFmt,
+ const SwPageDesc* pNewPgDesc )
+{
+ // tell the attribute output that we are ready to write the section
+ // break [has to be output inside paragraph properties]
+ AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
+
+ const SwSectionFmt* pFmt = GetSectionFormat( rNd );
+ const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );
+
+ OSL_ENSURE( pNewPgDescFmt || pNewPgDesc, "Neither page desc format nor page desc provided." );
+
+ if ( pNewPgDescFmt )
+ {
+ m_pSections->AppendSection( *pNewPgDescFmt, rNd, pFmt, nLnNm );
+ }
+ else if ( pNewPgDesc )
+ {
+ m_pSections->AppendSection( pNewPgDesc, rNd, pFmt, nLnNm );
+ }
+
+}
+
+void DocxExport::InitStyles()
+{
+ pStyles = new MSWordStyles( *this );
+
+ // setup word/styles.xml and the relations + content type
+ m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles" ),
+ S( "styles.xml" ) );
+
+ ::sax_fastparser::FSHelperPtr pStylesFS =
+ m_pFilter->openFragmentStreamWithSerializer( S( "word/styles.xml" ),
+ S( "application/vnd.openxmlformats-officedocument.wordprocessingml.styles+xml" ) );
+
+ // switch the serializer to redirect the output to word/styles.xml
+ m_pAttrOutput->SetSerializer( pStylesFS );
+
+ // do the work
+ pStyles->OutputStylesTable();
+
+ // switch the serializer back
+ m_pAttrOutput->SetSerializer( m_pDocumentFS );
+}
+
+void DocxExport::WriteFootnotesEndnotes()
+{
+ if ( m_pAttrOutput->HasFootnotes() )
+ {
+ // setup word/styles.xml and the relations + content type
+ m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes" ),
+ S( "footnotes.xml" ) );
+
+ ::sax_fastparser::FSHelperPtr pFootnotesFS =
+ m_pFilter->openFragmentStreamWithSerializer( S( "word/footnotes.xml" ),
+ S( "application/vnd.openxmlformats-officedocument.wordprocessingml.footnotes+xml" ) );
+
+ // switch the serializer to redirect the output to word/footnotes.xml
+ m_pAttrOutput->SetSerializer( pFootnotesFS );
+
+ // do the work
+ m_pAttrOutput->FootnotesEndnotes( true );
+
+ // switch the serializer back
+ m_pAttrOutput->SetSerializer( m_pDocumentFS );
+ }
+
+ if ( m_pAttrOutput->HasEndnotes() )
+ {
+ // setup word/styles.xml and the relations + content type
+ m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/endnotes" ),
+ S( "endnotes.xml" ) );
+
+ ::sax_fastparser::FSHelperPtr pEndnotesFS =
+ m_pFilter->openFragmentStreamWithSerializer( S( "word/endnotes.xml" ),
+ S( "application/vnd.openxmlformats-officedocument.wordprocessingml.endnotes+xml" ) );
+
+ // switch the serializer to redirect the output to word/endnotes.xml
+ m_pAttrOutput->SetSerializer( pEndnotesFS );
+
+ // do the work
+ m_pAttrOutput->FootnotesEndnotes( false );
+
+ // switch the serializer back
+ m_pAttrOutput->SetSerializer( m_pDocumentFS );
+ }
+}
+
+void DocxExport::WriteNumbering()
+{
+ if ( !pUsedNumTbl )
+ return; // no numbering is used
+
+ m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering" ),
+ S( "numbering.xml" ) );
+
+ ::sax_fastparser::FSHelperPtr pNumberingFS = m_pFilter->openFragmentStreamWithSerializer( S( "word/numbering.xml" ),
+ S( "application/vnd.openxmlformats-officedocument.wordprocessingml.numbering+xml" ) );
+
+ // switch the serializer to redirect the output to word/nubering.xml
+ m_pAttrOutput->SetSerializer( pNumberingFS );
+
+ pNumberingFS->startElementNS( XML_w, XML_numbering,
+ FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
+ FSEND );
+
+ AbstractNumberingDefinitions();
+
+ NumberingDefinitions();
+
+ pNumberingFS->endElementNS( XML_w, XML_numbering );
+
+ // switch the serializer back
+ m_pAttrOutput->SetSerializer( m_pDocumentFS );
+}
+
+void DocxExport::WriteHeaderFooter( const SwFmt& rFmt, bool bHeader, const char* pType )
+{
+ // setup the xml stream
+ OUString aRelId;
+ ::sax_fastparser::FSHelperPtr pFS;
+ if ( bHeader )
+ {
+ OUString aName( OUStringBuffer().appendAscii( "header" ).append( ++m_nHeaders ).appendAscii( ".xml" ).makeStringAndClear() );
+
+ aRelId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header" ),
+ aName );
+
+ pFS = m_pFilter->openFragmentStreamWithSerializer( OUStringBuffer().appendAscii( "word/" ).append( aName ).makeStringAndClear(),
+ S( "application/vnd.openxmlformats-officedocument.wordprocessingml.header+xml" ) );
+
+ pFS->startElementNS( XML_w, XML_hdr, MainXmlNamespaces( pFS ));
+ }
+ else
+ {
+ OUString aName( OUStringBuffer().appendAscii( "footer" ).append( ++m_nFooters ).appendAscii( ".xml" ).makeStringAndClear() );
+
+ aRelId = m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer" ),
+ aName );
+
+ pFS = m_pFilter->openFragmentStreamWithSerializer( OUStringBuffer().appendAscii( "word/" ).append( aName ).makeStringAndClear(),
+ S( "application/vnd.openxmlformats-officedocument.wordprocessingml.footer+xml" ) );
+
+ pFS->startElementNS( XML_w, XML_ftr, MainXmlNamespaces( pFS ));
+ }
+
+ // switch the serializer to redirect the output to word/styles.xml
+ m_pAttrOutput->SetSerializer( pFS );
+
+ // do the work
+ WriteHeaderFooterText( rFmt, bHeader );
+
+ // switch the serializer back
+ m_pAttrOutput->SetSerializer( m_pDocumentFS );
+
+ // close the tag
+ sal_Int32 nReference;
+ if ( bHeader )
+ {
+ pFS->endElementNS( XML_w, XML_hdr );
+ nReference = XML_headerReference;
+ }
+ else
+ {
+ pFS->endElementNS( XML_w, XML_ftr );
+ nReference = XML_footerReference;
+ }
+
+ // and write the reference
+ m_pDocumentFS->singleElementNS( XML_w, nReference,
+ FSNS( XML_w, XML_type ), pType,
+ FSNS( XML_r, XML_id ), rtl::OUStringToOString( aRelId, RTL_TEXTENCODING_UTF8 ).getStr(),
+ FSEND );
+}
+
+void DocxExport::WriteFonts()
+{
+ m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable" ),
+ S( "fontTable.xml" ) );
+
+ ::sax_fastparser::FSHelperPtr pFS = m_pFilter->openFragmentStreamWithSerializer(
+ S( "word/fontTable.xml" ),
+ S( "application/vnd.openxmlformats-officedocument.wordprocessingml.fontTable+xml" ) );
+
+ pFS->startElementNS( XML_w, XML_fonts,
+ FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
+ FSEND );
+
+ // switch the serializer to redirect the output to word/styles.xml
+ m_pAttrOutput->SetSerializer( pFS );
+
+ // do the work
+ maFontHelper.WriteFontTable( *m_pAttrOutput );
+
+ // switch the serializer back
+ m_pAttrOutput->SetSerializer( m_pDocumentFS );
+
+ pFS->endElementNS( XML_w, XML_fonts );
+}
+
+
+void DocxExport::WriteProperties( )
+{
+ // Write the core properties
+ SwDocShell* pDocShell( pDoc->GetDocShell( ) );
+ uno::Reference<document::XDocumentProperties> xDocProps;
+ if ( pDocShell )
+ {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel( ), uno::UNO_QUERY );
+ xDocProps = xDPS->getDocumentProperties();
+ }
+
+ m_pFilter->exportDocumentProperties( xDocProps );
+}
+
+void DocxExport::WriteSettings()
+{
+ if( !settings.hasData())
+ return;
+ m_pFilter->addRelation( m_pDocumentFS->getOutputStream(),
+ S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings" ),
+ S( "settings.xml" ) );
+
+ ::sax_fastparser::FSHelperPtr pFS = m_pFilter->openFragmentStreamWithSerializer(
+ S( "word/settings.xml" ),
+ S( "application/vnd.openxmlformats-officedocument.wordprocessingml.settings+xml" ) );
+
+ pFS->startElementNS( XML_w, XML_settings,
+ FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main",
+ FSEND );
+
+ if( settings.evenAndOddHeaders )
+ pFS->singleElementNS( XML_w, XML_evenAndOddHeaders, FSEND );
+
+ pFS->endElementNS( XML_w, XML_settings );
+}
+
+VMLExport& DocxExport::VMLExporter()
+{
+ return *m_pVMLExport;
+}
+
+void DocxExport::WriteMainText()
+{
+ // setup the namespaces
+ m_pDocumentFS->startElementNS( XML_w, XML_document, MainXmlNamespaces( m_pDocumentFS ));
+
+ // body
+ m_pDocumentFS->startElementNS( XML_w, XML_body, FSEND );
+
+ pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
+
+ // the text
+ WriteText();
+
+ // the last section info
+ const WW8_SepInfo *pSectionInfo = m_pSections? m_pSections->CurrentSectionInfo(): NULL;
+ if ( pSectionInfo )
+ SectionProperties( *pSectionInfo );
+
+ // finish body and document
+ m_pDocumentFS->endElementNS( XML_w, XML_body );
+ m_pDocumentFS->endElementNS( XML_w, XML_document );
+}
+
+XFastAttributeListRef DocxExport::MainXmlNamespaces( FSHelperPtr serializer )
+{
+ FastAttributeList* pAttr = serializer->createAttrList();
+ pAttr->add( FSNS( XML_xmlns, XML_o ), "urn:schemas-microsoft-com:office:office" );
+ pAttr->add( FSNS( XML_xmlns, XML_r ), "http://schemas.openxmlformats.org/officeDocument/2006/relationships" );
+ pAttr->add( FSNS( XML_xmlns, XML_v ), "urn:schemas-microsoft-com:vml" );
+ pAttr->add( FSNS( XML_xmlns, XML_w ), "http://schemas.openxmlformats.org/wordprocessingml/2006/main" );
+ pAttr->add( FSNS( XML_xmlns, XML_w10 ), "urn:schemas-microsoft-com:office:word" );
+ pAttr->add( FSNS( XML_xmlns, XML_wp ), "http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" );
+ return XFastAttributeListRef( pAttr );
+}
+
+bool DocxExport::ignoreAttributeForStyles( sal_uInt16 nWhich ) const
+{
+ if( nWhich == RES_TEXTGRID )
+ return true; // w:docGrid is written only to document.xml, not to styles.xml
+ return MSWordExportBase::ignoreAttributeForStyles( nWhich );
+}
+
+DocxExport::DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam )
+ : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
+ m_pFilter( pFilter ),
+ m_pAttrOutput( NULL ),
+ m_pSections( NULL ),
+ m_nHeaders( 0 ),
+ m_nFooters( 0 ),
+ m_pVMLExport( NULL )
+{
+ // Write the document properies
+ WriteProperties( );
+
+ // relations for the document
+ m_pFilter->addRelation( S( "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" ),
+ S( "word/document.xml" ) );
+
+ // the actual document
+ m_pDocumentFS = m_pFilter->openFragmentStreamWithSerializer( S( "word/document.xml" ),
+ S( "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml" ) );
+
+ // the DrawingML access
+ m_pDrawingML = new oox::drawingml::DrawingML( m_pDocumentFS, m_pFilter, oox::drawingml::DrawingML::DOCUMENT_DOCX );
+
+ // the attribute output for the document
+ m_pAttrOutput = new DocxAttributeOutput( *this, m_pDocumentFS, m_pDrawingML );
+
+ // the related VMLExport
+ m_pVMLExport = new VMLExport( m_pDocumentFS );
+}
+
+DocxExport::~DocxExport()
+{
+ delete m_pVMLExport, m_pVMLExport = NULL;
+ delete m_pAttrOutput, m_pAttrOutput = NULL;
+ delete m_pDrawingML, m_pDrawingML = NULL;
+}
+
+DocxSettingsData::DocxSettingsData()
+: evenAndOddHeaders( false )
+{
+}
+
+bool DocxSettingsData::hasData() const
+{
+ if( evenAndOddHeaders )
+ return true;
+ return false;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxexport.hxx b/sw/source/filter/ww8/docxexport.hxx
new file mode 100644
index 000000000000..ee84dcd33b42
--- /dev/null
+++ b/sw/source/filter/ww8/docxexport.hxx
@@ -0,0 +1,239 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DOCXEXPORT_HXX_
+#define _DOCXEXPORT_HXX_
+
+#include "wrtww8.hxx"
+
+#include <sax/fshelper.hxx>
+#include <sax/fastattribs.hxx>
+#include <rtl/ustring.hxx>
+
+#include <cstdio>
+#include <vector>
+
+class DocxAttributeOutput;
+class DocxExportFilter;
+class SwNode;
+class SwEndNode;
+class SwTableNode;
+class SwTxtNode;
+class SwGrfNode;
+class SwOLENode;
+class SwSectionNode;
+class SwNumRuleTbl;
+
+namespace oox {
+ namespace drawingml { class DrawingML; }
+ namespace vml { class VMLExport; }
+}
+
+namespace com { namespace sun { namespace star {
+ namespace frame { class XModel; }
+} } }
+
+/// Data to be written in the document settings part of the document
+struct DocxSettingsData
+{
+ DocxSettingsData();
+ bool hasData() const; /// returns true if there are any non-default settings (i.e. something to write)
+ bool evenAndOddHeaders;
+};
+
+/// The class that does all the actual DOCX export-related work.
+class DocxExport : public MSWordExportBase
+{
+ /// Pointer to the filter that owns us.
+ DocxExportFilter *m_pFilter;
+
+ /// Fast serializer for the document output.
+ ::sax_fastparser::FSHelperPtr m_pDocumentFS;
+
+ /// Access to the DrawingML writer.
+ oox::drawingml::DrawingML *m_pDrawingML;
+
+ /// Attribute output for document.
+ DocxAttributeOutput *m_pAttrOutput;
+
+ /// Sections/headers/footers
+ MSWordSections *m_pSections;
+
+ /// Header counter.
+ sal_Int32 m_nHeaders;
+
+ /// Footer counter.
+ sal_Int32 m_nFooters;
+
+ /// Exporter of the VML shapes.
+ oox::vml::VMLExport *m_pVMLExport;
+
+ DocxSettingsData settings;
+
+public:
+
+ DocxExportFilter& GetFilter() { return *m_pFilter; };
+ const DocxExportFilter& GetFilter() const { return *m_pFilter; };
+
+ /// Access to the attribute output class.
+ virtual AttributeOutputBase& AttrOutput() const;
+
+ /// Access to the sections/headers/footres.
+ virtual MSWordSections& Sections() const;
+
+ /// Determines if the format is expected to support unicode.
+ virtual bool SupportsUnicode() const { return true; }
+
+ virtual bool ignoreAttributeForStyles( sal_uInt16 nWhich ) const;
+
+ /// Guess the script (asian/western).
+ virtual bool CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich );
+
+ virtual void AppendBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen );
+
+ virtual void AppendBookmark( const rtl::OUString& rName, bool bSkip = false );
+
+ /// Returns the relationd id
+ rtl::OString AddRelation( const rtl::OUString& rType, const rtl::OUString& rTarget, const rtl::OUString& rMode );
+
+ virtual void WriteCR( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner = ww8::WW8TableNodeInfoInner::Pointer_t()*/ ) { /* FIXME no-op for docx, most probably should not even be in MSWordExportBase */ }
+ virtual void WriteChar( sal_Unicode ) { /* FIXME */ fprintf( stderr, "HACK! WriteChar() has nothing to do for docx.\n" ); }
+
+ /// Return value indicates if an inherited outline numbering is suppressed.
+ virtual bool DisallowInheritingOutlineNumbering( const SwFmt &rFmt );
+
+ /// Output the actual headers and footers.
+ virtual void WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
+ const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 nBreakCode );
+
+ /// Write the field
+ virtual void OutputField( const SwField* pFld, ww::eField eFldType,
+ const String& rFldCmd, sal_uInt8 nMode = nsFieldFlags::WRITEFIELD_ALL );
+
+ /// Write the data of the form field
+ virtual void WriteFormData( const ::sw::mark::IFieldmark& rFieldmark );
+ virtual void WriteHyperlinkData( const ::sw::mark::IFieldmark& rFieldmark );
+
+ virtual void DoComboBox(const rtl::OUString &rName,
+ const rtl::OUString &rHelp,
+ const rtl::OUString &ToolTip,
+ const rtl::OUString &rSelected,
+ com::sun::star::uno::Sequence<rtl::OUString> &rListItems);
+
+ virtual void DoFormText(const SwInputField * pFld);
+
+ virtual sal_uLong ReplaceCr( sal_uInt8 nChar );
+
+ /// Returns the relationd id
+ rtl::OString OutputChart( com::sun::star::uno::Reference< com::sun::star::frame::XModel >& xModel, sal_Int32 nCount );
+
+protected:
+ /// Format-dependant part of the actual export.
+ virtual void ExportDocument_Impl();
+
+ /// Output page/section breaks
+ virtual void OutputPageSectionBreaks( const SwTxtNode& );
+
+ /// Output SwEndNode
+ virtual void OutputEndNode( const SwEndNode& );
+
+ /// Output SwTableNode
+ virtual void OutputTableNode( const SwTableNode& );
+
+ /// Output SwGrfNode
+ virtual void OutputGrfNode( const SwGrfNode& );
+
+ /// Output SwOLENode
+ virtual void OutputOLENode( const SwOLENode& );
+
+ virtual void OutputLinkedOLE( const rtl::OUString& );
+
+ virtual void AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum );
+
+ virtual void SectionBreaksAndFrames( const SwTxtNode& /*rNode*/ ) {}
+
+ /// Get ready for a new section.
+ virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
+ const SwNode& rNd,
+ const SwFmtPageDesc* pNewPgDescFmt = 0,
+ const SwPageDesc* pNewPgDesc = 0 );
+
+private:
+ /// Setup pStyles and write styles.xml
+ void InitStyles();
+
+ /// Write footnotes.xml and endnotes.xml.
+ void WriteFootnotesEndnotes();
+
+ /// Write the numbering table.
+ virtual void WriteNumbering();
+
+ /// Write reference to a header/foorter + the actual xml containing the text.
+ void WriteHeaderFooter( const SwFmt& rFmt, bool bHeader, const char* pType );
+
+ /// Write word/fontTable.xml.
+ void WriteFonts();
+
+ /// Write docProps/core.xml
+ void WriteProperties();
+
+ /// Write word/settings.xml
+ void WriteSettings();
+
+ /// All xml namespaces to be used at the top of any text .xml file (main doc, headers, footers,...)
+ sax_fastparser::XFastAttributeListRef MainXmlNamespaces( sax_fastparser::FSHelperPtr serializer );
+
+public:
+ /// FIXME this is temporary, remotely reminding the method of the same
+ /// name in WW8Export.
+ void WriteMainText();
+
+ /// Pass the pDocument, pCurrentPam and pOriginalPam to the base class.
+ DocxExport( DocxExportFilter *pFilter, SwDoc *pDocument,
+ SwPaM *pCurrentPam, SwPaM *pOriginalPam );
+
+ /// Destructor.
+ virtual ~DocxExport();
+
+ /// Reference to the VMLExport instance for the main document.
+ oox::vml::VMLExport& VMLExporter();
+
+ /// Data to be exported in the settings part of the document
+ DocxSettingsData& settingsData();
+
+private:
+ /// No copying.
+ DocxExport( const DocxExport& );
+
+ /// No copying.
+ DocxExport& operator=( const DocxExport& );
+};
+
+#endif // _DOCXEXPORT_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxexportfilter.cxx b/sw/source/filter/ww8/docxexportfilter.cxx
new file mode 100644
index 000000000000..b784e8404b8f
--- /dev/null
+++ b/sw/source/filter/ww8/docxexportfilter.cxx
@@ -0,0 +1,162 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "docxexportfilter.hxx"
+#include "rtfexportfilter.hxx"
+#include "rtfimportfilter.hxx"
+#include "docxexport.hxx"
+
+#include <docsh.hxx>
+#include <pam.hxx>
+#include <unotxdoc.hxx>
+
+#include <cppuhelper/implementationentry.hxx>
+
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+#define S( x ) OUString( RTL_CONSTASCII_USTRINGPARAM( x ) )
+
+DocxExportFilter::DocxExportFilter( const uno::Reference< uno::XComponentContext >& xContext )
+ : oox::core::XmlFilterBase( xContext )
+{
+}
+
+bool DocxExportFilter::exportDocument()
+{
+ OSL_TRACE( "DocxExportFilter::exportDocument()\n" ); // DEBUG remove me
+
+ // get SwDoc*
+ uno::Reference< uno::XInterface > xIfc( getModel(), uno::UNO_QUERY );
+ SwXTextDocument *pTxtDoc = dynamic_cast< SwXTextDocument * >( xIfc.get() );
+ if ( !pTxtDoc )
+ return false;
+
+ SwDoc *pDoc = pTxtDoc->GetDocShell()->GetDoc();
+ if ( !pDoc )
+ return false;
+
+ // get SwPaM*
+ // FIXME so far we get SwPaM for the entire document; probably we should
+ // be able to output just the selection as well - though no idea how to
+ // get the correct SwPaM* then...
+ SwPaM aPam( pDoc->GetNodes().GetEndOfContent() );
+ aPam.SetMark();
+ aPam.Move( fnMoveBackward, fnGoDoc );
+
+ SwPaM *pCurPam = new SwPaM( *aPam.End(), *aPam.Start() );
+
+ // export the document
+ // (in a separate block so that it's destructed before the commit)
+ {
+ DocxExport aExport( this, pDoc, pCurPam, &aPam );
+ aExport.ExportDocument( true ); // FIXME support exporting selection only
+ }
+
+ commitStorage();
+
+ // delete the pCurPam
+ if ( pCurPam )
+ {
+ while ( pCurPam->GetNext() != pCurPam )
+ delete pCurPam->GetNext();
+ delete pCurPam;
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// UNO stuff so that the filter is registered
+//////////////////////////////////////////////////////////////////////////
+
+#define IMPL_NAME "com.sun.star.comp.Writer.DocxExport"
+
+OUString DocxExport_getImplementationName()
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPL_NAME ) );
+}
+
+OUString DocxExportFilter::implGetImplementationName() const
+{
+ return DocxExport_getImplementationName();
+}
+
+uno::Sequence< OUString > SAL_CALL DocxExport_getSupportedServiceNames() throw()
+{
+ const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.ExportFilter" ) );
+ const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
+ return aSeq;
+}
+
+uno::Reference< uno::XInterface > SAL_CALL DocxExport_createInstance(const uno::Reference< uno::XComponentContext > & xCtx ) throw( uno::Exception )
+{
+ return (cppu::OWeakObject*) new DocxExportFilter( xCtx );
+}
+
+extern "C"
+{
+
+SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ )
+{
+ *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
+}
+
+// ------------------------
+// - component_getFactory -
+// ------------------------
+
+::cppu::ImplementationEntry entries [] =
+{
+ {
+ DocxExport_createInstance, DocxExport_getImplementationName,
+ DocxExport_getSupportedServiceNames, ::cppu::createSingleComponentFactory,
+ 0, 0
+ },
+ {
+ RtfExport_createInstance, RtfExport_getImplementationName,
+ RtfExport_getSupportedServiceNames, ::cppu::createSingleComponentFactory,
+ 0, 0
+ },
+ {
+ RtfImport_createInstance, RtfImport_getImplementationName,
+ RtfImport_getSupportedServiceNames, ::cppu::createSingleComponentFactory,
+ 0, 0
+ },
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( const sal_Char* pImplName, void* pServiceManager, void* pRegistryKey )
+{
+ return ::cppu::component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey, entries );
+}
+
+} // extern "C"
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxexportfilter.hxx b/sw/source/filter/ww8/docxexportfilter.hxx
new file mode 100644
index 000000000000..68c11242ea0b
--- /dev/null
+++ b/sw/source/filter/ww8/docxexportfilter.hxx
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DOCXEXPORTFILTER_HXX_
+#define _DOCXEXPORTFILTER_HXX_
+
+#include <oox/core/xmlfilterbase.hxx>
+#include <oox/drawingml/chart/chartconverter.hxx>
+#include <oox/vml/vmldrawing.hxx>
+
+#include <com/sun/star/beans/PropertyValue.hpp>
+
+/// The physical access to the DOCX document (for writing).
+class DocxExportFilter : public oox::core::XmlFilterBase
+{
+public:
+ DocxExportFilter( const com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& xContext );
+
+ // FIXME these should not even exist for the export-only filter!
+ // For now, let's just do empty implementations of those.
+ virtual bool importDocument() { return false; }
+ virtual const ::oox::drawingml::Theme* getCurrentTheme() const { return NULL; }
+ virtual sal_Int32 getSchemeClr( sal_Int32 ) const { return 0; }
+ virtual ::oox::vml::Drawing* getVmlDrawing() { return NULL; }
+ virtual ::oox::drawingml::chart::ChartConverter& getChartConverter() { static ::oox::drawingml::chart::ChartConverter aConverter; return aConverter; }
+ virtual const ::oox::drawingml::table::TableStyleListPtr getTableStyles() { return ::oox::drawingml::table::TableStyleListPtr(); }
+
+ // Actual export of the DOCX document
+ virtual bool exportDocument();
+
+private:
+
+ /// Implementatio of the filter abstract method.
+ virtual ::rtl::OUString implGetImplementationName() const;
+
+ virtual ::oox::ole::VbaProject* implCreateVbaProject() const
+ {
+ return NULL; // FIXME: implement me !
+ }
+};
+
+#endif // _DOCXEXPORTFILTER_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/docxfootnotes.hxx b/sw/source/filter/ww8/docxfootnotes.hxx
new file mode 100644
index 000000000000..300f50b34da8
--- /dev/null
+++ b/sw/source/filter/ww8/docxfootnotes.hxx
@@ -0,0 +1,102 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _DOCXFOOTNOTES_HXX_
+#define _DOCXFOOTNOTES_HXX_
+
+#include <fmtftn.hxx>
+
+#include <rtl/string.hxx>
+#include <rtl/ustring.hxx>
+#include <sax/fshelper.hxx>
+
+#include <vector>
+
+namespace docx {
+
+typedef ::std::vector< const SwFmtFtn* > FootnotesVector;
+
+/** Remember footnotes/endnotes so that we can dump them in one go.
+
+ Also rememeber the last added footnote Id to be able to write it in the
+ DocxAttributeOutput::EndRunProperties() method.
+*/
+class FootnotesList {
+ /// The current footnote, that was not written yet.
+ sal_Int32 m_nCurrent;
+
+ /// List of the footnotes.
+ FootnotesVector m_aFootnotes;
+
+public:
+ FootnotesList() : m_nCurrent( -1 ) {}
+
+ void add( const SwFmtFtn& rFootnote )
+ {
+ m_aFootnotes.push_back( &rFootnote );
+ m_nCurrent = m_aFootnotes.size() - 1;
+ }
+
+ /// Return the current footnote/endnote and clear the 'current' state.
+ const SwFmtFtn* getCurrent( sal_Int32& rId )
+ {
+ // skip ids 0 and 1 - they are reserved for separator and
+ // continuationSeparator
+ rId = m_nCurrent + 2;
+
+ // anything to write at all?
+ if ( m_nCurrent < 0 )
+ {
+ rId = -1;
+ return NULL;
+ }
+
+ const SwFmtFtn *pFootnote = m_aFootnotes[m_nCurrent];
+ m_nCurrent = -1;
+
+ return pFootnote;
+ }
+
+ /// Return all the footnotes/endnotes.
+ const FootnotesVector& getVector() const
+ {
+ return m_aFootnotes;
+ }
+
+ /// Do we have any footnotes/endnotes at all?
+ bool isEmpty() const
+ {
+ return m_aFootnotes.empty();
+ }
+};
+
+} // namespace docx
+
+#endif // _DOCXFOOTNOTES_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/escher.hxx b/sw/source/filter/ww8/escher.hxx
new file mode 100644
index 000000000000..55de32d362b2
--- /dev/null
+++ b/sw/source/filter/ww8/escher.hxx
@@ -0,0 +1,184 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _ESCHER_HXX
+#define _ESCHER_HXX
+
+#include <filter/msfilter/escherex.hxx>
+
+const sal_uInt32 nInlineHack = 0x00010001;
+class SwFrmFmt;
+// #i30669#
+class SwFmtHoriOrient;
+class SwFmtVertOrient;
+// <--
+
+class WinwordAnchoring : public EscherExClientRecord_Base
+{
+public:
+ void WriteData(EscherEx& rEx) const;
+ void SetAnchoring(const SwFrmFmt& rFmt);
+
+ /** method to perform conversion of positioning attributes with the help
+ of corresponding layout information
+
+ #i30669#
+ Because most of the Writer object positions doesn't correspond to the
+ object positions in WW8, this method converts the positioning
+ attributes. For this conversion the corresponding layout information
+ is needed. If no layout information exists - e.g. no layout exists - no
+ conversion is performed.
+ No conversion is performed for as-character anchored objects. Whose
+ object positions are already treated special in method <WriteData(..)>.
+ Usage of method: Used by method <SetAnchoring(..)>, nothing else
+
+ @param _iorHoriOri
+ input/output parameter - containing the current horizontal position
+ attributes, which are converted by this method.
+
+ @param _iorVertOri
+ input/output parameter - containing the current vertical position
+ attributes, which are converted by this method.
+
+ @param _rFrmFmt
+ input parameter - frame format of the anchored object
+
+ @return boolean, indicating, if a conversion has been performed.
+ */
+ static bool ConvertPosition( SwFmtHoriOrient& _iorHoriOri,
+ SwFmtVertOrient& _iorVertOri,
+ const SwFrmFmt& _rFrmFmt );
+
+private:
+ bool mbInline;
+ sal_uInt32 mnXAlign;
+ sal_uInt32 mnYAlign;
+ sal_uInt32 mnXRelTo;
+ sal_uInt32 mnYRelTo;
+
+};
+
+class SwEscherExGlobal : public EscherExGlobal
+{
+public:
+ explicit SwEscherExGlobal();
+ virtual ~SwEscherExGlobal();
+
+private:
+ /** Overloaded to create a new memory stream for picture data. */
+ virtual SvStream* ImplQueryPictureStream();
+
+private:
+ ::std::auto_ptr< SvStream > mxPicStrm;
+};
+
+class SwBasicEscherEx : public EscherEx
+{
+private:
+ void Init();
+protected:
+ WW8Export& rWrt;
+ SvStream* pEscherStrm;
+ long mnEmuMul, mnEmuDiv;
+
+ virtual sal_Int32 WriteFlyFrameAttr(const SwFrmFmt& rFmt, MSO_SPT eShapeType,
+ EscherPropertyContainer& rPropOpt);
+ void WriteBrushAttr(const SvxBrushItem &rBrush,
+ EscherPropertyContainer& rPropOpt);
+ void WriteOLEPicture(EscherPropertyContainer &rPropOpt,
+ sal_uInt32 nShapeFlags, const Graphic &rGraphic, const SdrObject &rObj,
+ sal_uInt32 nShapeId, const com::sun::star::awt::Rectangle* pVisArea );
+ void WriteGrfAttr(const SwNoTxtNode& rNd,EscherPropertyContainer& rPropOpt);
+
+ sal_Int32 DrawModelToEmu(sal_Int32 nVal) const
+ { return BigMulDiv(nVal, mnEmuMul, mnEmuDiv); }
+
+ sal_Int32 ToFract16(sal_Int32 nVal, sal_uInt32 nMax) const;
+
+ virtual void SetPicId(const SdrObject &, sal_uInt32, EscherPropertyContainer &);
+ SdrLayerID GetInvisibleHellId() const;
+
+public:
+ SwBasicEscherEx(SvStream* pStrm, WW8Export& rWrt);
+ sal_Int32 WriteGrfFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId);
+ sal_Int32 WriteOLEFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId);
+ void WriteEmptyFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId);
+ virtual void WriteFrmExtraData(const SwFrmFmt&);
+ virtual void WritePictures();
+ virtual ~SwBasicEscherEx();
+private:
+ //No copying
+ SwBasicEscherEx(const SwBasicEscherEx&);
+ SwBasicEscherEx& operator=(const SwBasicEscherEx&);
+};
+
+class SwEscherEx : public SwBasicEscherEx
+{
+private:
+ SvULongs aFollowShpIds;
+ EscherExHostAppData aHostData;
+ WinwordAnchoring aWinwordAnchoring;
+ WW8_WrPlcTxtBoxes *pTxtBxs;
+
+ sal_uInt32 GetFlyShapeId(const SwFrmFmt& rFmt,
+ unsigned int nHdFtIndex, DrawObjPointerVector &rPVec);
+ void MakeZOrderArrAndFollowIds(std::vector<DrawObj>& rSrcArr,
+ DrawObjPointerVector& rDstArr);
+
+ sal_Int32 WriteFlyFrm(const DrawObj &rObj, sal_uInt32 &rShapeId,
+ DrawObjPointerVector &rPVec);
+ sal_Int32 WriteTxtFlyFrame(const DrawObj &rObj, sal_uInt32 nShapeId,
+ sal_uInt32 nTxtBox, DrawObjPointerVector &rPVec);
+ void WriteOCXControl(const SwFrmFmt& rFmt,sal_uInt32 nShapeId);
+ virtual sal_Int32 WriteFlyFrameAttr(const SwFrmFmt& rFmt, MSO_SPT eShapeType,
+ EscherPropertyContainer& rPropOpt);
+
+ virtual sal_uInt32 QueryTextID(
+ const com::sun::star::uno::Reference<
+ com::sun::star::drawing::XShape > &,sal_uInt32);
+ virtual void SetPicId(const SdrObject &rSdrObj, sal_uInt32 nShapeId,
+ EscherPropertyContainer &rPropOpt);
+public:
+ SwEscherEx( SvStream* pStrm, WW8Export& rWW8Wrt );
+ virtual ~SwEscherEx();
+ void FinishEscher();
+ virtual void WritePictures();
+
+ virtual void WriteFrmExtraData(const SwFrmFmt& rFmt);
+
+ EscherExHostAppData* StartShape(const com::sun::star::uno::Reference<
+ com::sun::star::drawing::XShape > &, const Rectangle*) {return &aHostData;}
+private:
+ //No copying
+ SwEscherEx(const SwEscherEx&);
+ SwEscherEx &operator=(const SwEscherEx&);
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/fields.cxx b/sw/source/filter/ww8/fields.cxx
new file mode 100644
index 000000000000..7b84c26f4c42
--- /dev/null
+++ b/sw/source/filter/ww8/fields.cxx
@@ -0,0 +1,151 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "fields.hxx"
+#include <osl/diagnose.h>
+#include <sal/macros.h>
+#include <stddef.h>
+
+namespace ww
+{
+ const char *GetEnglishFieldName(eField eIndex) throw()
+ {
+ //0 Signifies the field names I can't find.
+ // #i43956# - field <eFOOTREF> = 5 should be mapped to "REF"
+ static const char *aFieldNames[] =
+ {
+ /* 0*/ 0,
+ /* 1*/ 0,
+ /* 2*/ 0,
+ /* 3*/ "REF",
+ /* 4*/ "XE",
+ /* 5*/ "REF",
+ /* 6*/ "SET",
+ /* 7*/ "IF",
+ /* 8*/ "INDEX",
+ /* 9*/ "TC",
+ /*10*/ "STYLEREF",
+ /*11*/ "RD",
+ /*12*/ "SEQ",
+ /*13*/ "TOC",
+ /*14*/ "INFO",
+ /*15*/ "TITLE",
+ /*16*/ "SUBJECT",
+ /*17*/ "AUTHOR",
+ /*18*/ "KEYWORDS",
+ /*19*/ "COMMENTS",
+ /*20*/ "LASTSAVEDBY",
+ /*21*/ "CREATEDATE",
+ /*22*/ "SAVEDATE",
+ /*23*/ "PRINTDATE",
+ /*24*/ "REVNUM",
+ /*25*/ "EDITTIME",
+ /*26*/ "NUMPAGES",
+ /*27*/ "NUMWORDS",
+ /*28*/ "NUMCHARS",
+ /*29*/ "FILENAME",
+ /*30*/ "TEMPLATE",
+ /*31*/ "DATE",
+ /*32*/ "TIME",
+ /*33*/ "PAGE",
+ /*34*/ "=",
+ /*35*/ "QUOTE",
+ /*36*/ 0,
+ /*37*/ "PAGEREF",
+ /*38*/ "ASK",
+ /*39*/ "FILLIN",
+ /*40*/ 0,
+ /*41*/ "NEXT",
+ /*42*/ "NEXTIF",
+ /*43*/ "SKIPIF",
+ /*44*/ "MERGEREC",
+ /*45*/ 0,
+ /*46*/ 0,
+ /*47*/ 0,
+ /*48*/ "PRINT",
+ /*49*/ "EQ",
+ /*50*/ "GOTOBUTTON",
+ /*51*/ "MACROBUTTON",
+ /*52*/ "AUTONUMOUT",
+ /*53*/ "AUTONUMLGL",
+ /*54*/ "AUTONUM",
+ /*55*/ 0,
+ /*56*/ "LINK",
+ /*57*/ "SYMBOL",
+ /*58*/ "EMBED",
+ /*59*/ "MERGEFIELD",
+ /*60*/ "USERNAME",
+ /*61*/ "USERINITIALS",
+ /*62*/ "USERADDRESS",
+ /*63*/ "BARCODE",
+ /*64*/ "DOCVARIABLE",
+ /*65*/ "SECTION",
+ /*66*/ "SECTIONPAGES",
+ /*67*/ "INCLUDEPICTURE",
+ /*68*/ "INCLUDETEXT",
+ /*69*/ "FILESIZE",
+ /*70*/ "FORMTEXT",
+ /*71*/ "FORMCHECKBOX",
+ /*72*/ "NOTEREF",
+ /*73*/ "TOA",
+ /*74*/ "TA",
+ /*75*/ "MERGESEQ",
+ /*76*/ 0,
+ /*77*/ "PRIVATE",
+ /*78*/ "DATABASE",
+ /*79*/ "AUTOTEXT",
+ /*80*/ "COMPARE",
+ /*81*/ 0,
+ /*82*/ 0,
+ /*83*/ "FORMDROPDOWN",
+ /*84*/ "ADVANCE",
+ /*85*/ "DOCPROPERTY",
+ /*86*/ 0,
+ /*87*/ "CONTROL",
+ /*88*/ "HYPERLINK",
+ /*89*/ "AUTOTEXTLIST",
+ /*90*/ "LISTNUM",
+ /*91*/ 0,
+ /*92*/ "BIDIOUTLINE",
+ /*93*/ "ADDRESSBLOCK",
+ /*94*/ "GREETINGLINE",
+ /*95*/ "SHAPE"
+ };
+
+ size_t nIndex = static_cast<size_t>(eIndex);
+ if (nIndex >= SAL_N_ELEMENTS(aFieldNames))
+ eIndex = eNONE;
+ OSL_ENSURE(eIndex != eNONE, "Unknown WinWord Field, let cmc know");
+ return aFieldNames[eIndex];
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/fields.hxx b/sw/source/filter/ww8/fields.hxx
new file mode 100644
index 000000000000..a491109c0b7d
--- /dev/null
+++ b/sw/source/filter/ww8/fields.hxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+/// @HTML
+#ifndef WW_FIELDS_HXX
+#define WW_FIELDS_HXX
+
+namespace ww
+{
+ enum eField
+ {
+ eNONE = 0,
+ eUNKNOWN = 1,
+ ePOSSIBLEBOOKMARK = 2,
+ eREF = 3,
+ eXE = 4,
+ eFOOTREF = 5,
+ eSET = 6,
+ eIF = 7,
+ eINDEX = 8,
+ eTC = 9,
+ eSTYLEREF = 10,
+ eRD = 11,
+ eSEQ = 12,
+ eTOC = 13,
+ eINFO = 14,
+ eTITLE = 15,
+ eSUBJECT = 16,
+ eAUTHOR = 17,
+ eKEYWORDS = 18,
+ eCOMMENTS = 19,
+ eLASTSAVEDBY = 20,
+ eCREATEDATE = 21,
+ eSAVEDATE = 22,
+ ePRINTDATE = 23,
+ eREVNUM = 24,
+ eEDITTIME = 25,
+ eNUMPAGE = 26,
+ eNUMWORDS = 27,
+ eNUMCHARS = 28,
+ eFILENAME = 29,
+ eTEMPLATE = 30,
+ eDATE = 31,
+ eTIME = 32,
+ ePAGE = 33,
+ eEquals = 34,
+ eQUOTE = 35,
+ eMERGEINC = 36,
+ ePAGEREF = 37,
+ eASK = 38,
+ eFILLIN = 39,
+ eMERGEDATA = 40,
+ eNEXT = 41,
+ eNEXTIF = 42,
+ eSKIPIF = 43,
+ eMERGEREC = 44,
+ eDDEREF = 45,
+ eDDEAUTOREF = 46,
+ eGLOSSREF = 47,
+ ePRINT = 48,
+ eEQ = 49,
+ eGOTOBUTTON = 50,
+ eMACROBUTTON = 51,
+ eAUTONUMOUT = 52,
+ eAUTONUMLGL = 53,
+ eAUTONUM = 54,
+ eINCLUDETIFF = 55,
+ eLINK = 56,
+ eSYMBOL = 57,
+ eEMBED = 58,
+ eMERGEFIELD = 59,
+ eUSERNAME = 60,
+ eUSERINITIALS = 61,
+ eUSERADDRESS = 62,
+ eBARCODE = 63,
+ eDOCVARIABLE = 64,
+ eSECTION = 65,
+ eSECTIONPAGES = 66,
+ eINCLUDEPICTURE = 67,
+ eINCLUDETEXT = 68,
+ eFILESIZE = 69,
+ eFORMTEXT = 70,
+ eFORMCHECKBOX = 71,
+ eNOTEREF = 72,
+ eTOA = 73,
+ eTA = 74,
+ eMERGESEQ = 75,
+ eMACRO = 76,
+ ePRIVATE = 77,
+ eDATABASE = 78,
+ eAUTOTEXT = 79,
+ eCOMPARE = 80,
+ ePLUGIN = 81,
+ eSUBSCRIBER = 82,
+ eFORMDROPDOWN = 83,
+ eADVANCE = 84,
+ eDOCPROPERTY = 85,
+ eUNKNOWN2 = 86,
+ eCONTROL = 87,
+ eHYPERLINK = 88,
+ eAUTOTEXTLIST = 89,
+ eLISTNUM = 90,
+ eHTMLCONTROL = 91,
+ eBIDIOUTLINE = 92,
+ eADDRESSBLOCK = 93,
+ eGREETINGLINE = 94,
+ eSHAPE = 95
+ };
+
+ /** Find the English Field Name from a winword index
+
+ See OpenOffice.org issue 12831
+ (http://www.openoffice.org/issues/show_bug.cgi?id=12831) and MS
+ Knowledge Base article 268717
+ (http://support.microsoft.com/default.aspx?scid=kb;en-us;268717) for
+ details of why to use english field names and not localized ones since
+ Word 2000.
+
+ @param
+ nIndex the index to search for
+
+ @return 0 if not found, otherwise the fieldname as a C style ASCII
+ string
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ const char *GetEnglishFieldName(eField eIndex) throw();
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/hash_wrap.hxx b/sw/source/filter/ww8/hash_wrap.hxx
new file mode 100644
index 000000000000..e89392f22cbf
--- /dev/null
+++ b/sw/source/filter/ww8/hash_wrap.hxx
@@ -0,0 +1,122 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+//this is a shameless rip from sortedarray.hxx but changed to boost::unordered_set
+
+#ifndef WW_HASH_WRAP_HXX
+#define WW_HASH_WRAP_HXX
+
+#include <boost/unordered_set.hpp>
+#include <tools/debug.hxx>
+
+//simple wrapper around boost::unordered_set to behave like sorted array
+namespace ww
+{
+ /** simple template that manages a hash
+
+
+ @author
+ <a href="mailto:mikeleib@openoffice.org">Michael Leibowitz</a>
+ */
+ template<class C, class HashFcn = boost::hash<C> > class WrappedHash
+ {
+ private:
+ boost::unordered_set<C, HashFcn> mHashSet;
+
+ //No copying
+ WrappedHash(const WrappedHash&);
+ WrappedHash& operator=(const WrappedHash&);
+ public:
+ //Find an entry, return its address if found and 0 if not
+ const C* search(C aSrch) const
+ {
+ typename boost::unordered_set<C, HashFcn>::const_iterator it;
+ it= mHashSet.find(aSrch);
+ if (it != mHashSet.end())
+ return &(*it);
+ else
+ return 0;
+ }
+
+ WrappedHash(const C *pWwSprmTab, const size_t nNoElems)
+ {
+ OSL_ENSURE(nNoElems && pWwSprmTab, "WW8: empty Array: Don't do that");
+ const C *pIter = pWwSprmTab;
+ const C *pEnd = pWwSprmTab + nNoElems;
+ while (pIter < pEnd)
+ {
+ mHashSet.insert(*pIter);
+ pIter++;
+ }
+#if OSL_DEBUG_LEVEL > 1
+ bool bBroken=false;
+ rtl::OUString sError;
+ pIter = pWwSprmTab;
+ const C *pBeforeEnd = pWwSprmTab + nNoElems - 1;
+ while (pIter < pBeforeEnd)
+ {
+ if (*pIter == *(pIter+1))
+ {
+ if (!bBroken)
+ {
+ sError = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "WW8: Duplicate in list, almost certainly don't "
+ "want that!\n"
+ "(You will not see this message again unless you "
+ "restart)\n"
+ "Extra entries are...\n"));
+ bBroken=true;
+ }
+
+ size_t nSize = sizeof(C);
+ const sal_uInt8 *pHack =
+ reinterpret_cast<const sal_uInt8 *>(&(*pIter));
+ for (size_t i=0; i < nSize; ++i)
+ {
+ sError += rtl::OUString::valueOf(
+ static_cast<sal_Int32>(pHack[i]), 16);
+ sError += rtl::OUString::valueOf(sal_Unicode(' '));
+ }
+ sError += rtl::OUString::valueOf(sal_Unicode('\n'));
+ while (*pIter == *(pIter+1) && pIter < pBeforeEnd)
+ ++pIter;
+ }
+ else
+ ++pIter;
+ }
+ if (bBroken)
+ {
+ OSL_FAIL( rtl::OUStringToOString( sError, RTL_TEXTENCODING_ASCII_US ).getStr() );
+ }
+#endif
+ }
+ };
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/needed_cast.hxx b/sw/source/filter/ww8/needed_cast.hxx
new file mode 100644
index 000000000000..d2d6af415b97
--- /dev/null
+++ b/sw/source/filter/ww8/needed_cast.hxx
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef WW_NEEDED_CAST_HXX
+#define WW_NEEDED_CAST_HXX
+
+#include <tools/debug.hxx>
+#include "staticassert.hxx"
+
+namespace ww
+{
+ template<typename Ret, typename Param> Ret checking_cast(Param in, Ret)
+ {
+ return static_cast<Ret>(in);
+ }
+
+ template<typename Ret> Ret checking_cast(Ret in, Ret)
+ {
+ DBG_ASSERT( false, "UnnecessaryCast" );
+ return in;
+ }
+
+ /*
+ needed_cast is the same as static_cast except that there will be a compile
+ time assert when NDEBUG is not defined and the in and out types are the
+ same. i.e. needed_cast catches unneccessary casts
+ */
+ template<typename Ret, typename Param> Ret needed_cast(Param in)
+ {
+ /*
+ Massage a single argument and a ret value into two arguments to allow
+ a determination if the dest type is the same as the sourct type
+ */
+ return checking_cast(in, Ret());
+ }
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfattributeoutput.cxx b/sw/source/filter/ww8/rtfattributeoutput.cxx
new file mode 100644
index 000000000000..e3e02f32f6d3
--- /dev/null
+++ b/sw/source/filter/ww8/rtfattributeoutput.cxx
@@ -0,0 +1,3464 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * Copyright 2010 Miklos Vajna.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "rtfattributeoutput.hxx"
+#include "rtfexport.hxx"
+#include "rtfsdrexport.hxx"
+#include "writerwordglue.hxx"
+#include "wrtww8.hxx"
+#include "ww8par.hxx"
+#include "fmtcntnt.hxx"
+#include "fmtsrnd.hxx"
+#include "fchrfmt.hxx"
+#include "tgrditem.hxx"
+#include "fmtruby.hxx"
+#include "charfmt.hxx"
+#include "breakit.hxx"
+
+#include <i18npool/mslangid.hxx>
+
+#include <hintids.hxx>
+
+#include <svl/poolitem.hxx>
+#include <svtools/rtfkeywd.hxx>
+
+#include <editeng/fontitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/hyznitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/paravertalignitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/blnkitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/fmglob.hxx>
+#include <svx/svdouno.hxx>
+#include <filter/msfilter/msoleexp.hxx>
+
+#include <docufld.hxx>
+#include <flddropdown.hxx>
+#include <format.hxx>
+#include <fmtclds.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtfld.hxx>
+#include <fmtfsize.hxx>
+#include <fmtftn.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmtline.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <frmatr.hxx>
+#include <ftninfo.hxx>
+#include <htmltbl.hxx>
+#include <ndgrf.hxx>
+#include <ndtxt.hxx>
+#include <node.hxx>
+#include <pagedesc.hxx>
+#include <paratr.hxx>
+#include <swmodule.hxx>
+#include <swtable.hxx>
+#include <txtftn.hxx>
+#include <txtinet.hxx>
+#include <numrule.hxx>
+#include <grfatr.hxx>
+#include <ndole.hxx>
+#include <lineinfo.hxx>
+#include <rtf.hxx>
+
+#include <rtl/strbuf.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <rtl/ustring.hxx>
+
+#include <tools/color.hxx>
+
+#include <vcl/cvtgrf.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/chart2/XChartDocument.hpp>
+#include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/container/XNamed.hpp>
+
+#include <osl/diagnose.h>
+
+using ::editeng::SvxBorderLine;
+using rtl::OString;
+using rtl::OStringBuffer;
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using rtl::OUStringToOString;
+
+using namespace nsSwDocInfoSubType;
+using namespace nsFieldFlags;
+using namespace sw::util;
+using namespace ::com::sun::star;
+
+static OString OutTBLBorderLine(RtfExport &rExport, const SvxBorderLine* pLine, const sal_Char* pStr)
+{
+ OStringBuffer aRet;
+ if ( !pLine->isEmpty() )
+ {
+ aRet.append(pStr);
+ // single line
+ switch ( pLine->GetStyle( ) )
+ {
+ case ::editeng::SOLID:
+ {
+ if( DEF_LINE_WIDTH_0 == pLine->GetWidth() )
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRHAIR);
+ else
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRS);
+ }
+ break;
+ case ::editeng::DOTTED:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRDOT);
+ break;
+ case ::editeng::DASHED:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRDASH);
+ break;
+ case ::editeng::DOUBLE:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRDB);
+ break;
+ case ::editeng::THINTHICK_SMALLGAP:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHSG);
+ break;
+ case ::editeng::THINTHICK_MEDIUMGAP:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHMG);
+ break;
+ case ::editeng::THINTHICK_LARGEGAP:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRTNTHLG);
+ break;
+ case ::editeng::THICKTHIN_SMALLGAP:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNSG);
+ break;
+ case ::editeng::THICKTHIN_MEDIUMGAP:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNMG);
+ break;
+ case ::editeng::THICKTHIN_LARGEGAP:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRTHTNLG);
+ break;
+ case ::editeng::EMBOSSED:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDREMBOSS);
+ break;
+ case ::editeng::ENGRAVED:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRENGRAVE);
+ break;
+ case ::editeng::OUTSET:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDROUTSET);
+ break;
+ case ::editeng::INSET:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRINSET);
+ break;
+ case ::editeng::NO_STYLE:
+ default:
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRNONE);
+ break;
+ }
+
+ if ( 255 >= pLine->GetWidth() ) // That value comes from RTF specs
+ {
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRW).append((sal_Int32)pLine->GetWidth());
+ }
+ else
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRTH OOO_STRING_SVTOOLS_RTF_BRDRW).append((sal_Int32)pLine->GetWidth() / 2);
+
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRDRCF);
+ aRet.append((sal_Int32)rExport.GetColor(pLine->GetColor()));
+ }
+ return aRet.makeStringAndClear();
+}
+
+static OString OutBorderLine(RtfExport &rExport, const SvxBorderLine* pLine,
+ const sal_Char* pStr, sal_uInt16 nDist)
+{
+ OStringBuffer aRet;
+ aRet.append(OutTBLBorderLine(rExport, pLine, pStr));
+ aRet.append(OOO_STRING_SVTOOLS_RTF_BRSP);
+ aRet.append((sal_Int32)nDist);
+ return aRet.makeStringAndClear();
+}
+
+void RtfAttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ /*
+ You would have thought that
+ m_rExport.Strm() << (bIsRTL ? OOO_STRING_SVTOOLS_RTF_RTLCH : OOO_STRING_SVTOOLS_RTF_LTRCH); would be sufficent here ,
+ but looks like word needs to see the other directional token to be
+ satisified that all is kosher, otherwise it seems in ver 2003 to go and
+ semi-randomlyly stick strike through about the place. Perhaps
+ strikethrough is some ms developers "something is wrong signal" debugging
+ code that we're triggering ?
+ */
+ if (bIsRTL) {
+ m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LTRCH);
+ m_aStylesEnd.append(' ');
+ m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_RTLCH);
+ } else {
+ m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_RTLCH);
+ m_aStylesEnd.append(' ');
+ m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LTRCH);
+ }
+
+ switch (nScript) {
+ case i18n::ScriptType::LATIN:
+ m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LOCH);
+ break;
+ case i18n::ScriptType::ASIAN:
+ m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_DBCH);
+ break;
+ case i18n::ScriptType::COMPLEX:
+ /* noop */
+ break;
+ default:
+ /* should not happen? */
+ break;
+ }
+}
+
+void RtfAttributeOutput::StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // Output table/table row/table cell starts if needed
+ if ( pTextNodeInfo.get() )
+ {
+ sal_uInt32 nRow = pTextNodeInfo->getRow();
+ sal_uInt32 nCell = pTextNodeInfo->getCell();
+
+ // New cell/row?
+ if ( m_nTableDepth > 0 && !m_bTableCellOpen )
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t pDeepInner( pTextNodeInfo->getInnerForDepth( m_nTableDepth ) );
+ OSL_ENSURE( pDeepInner, "TableNodeInfoInner not found");
+ if ( pDeepInner && pDeepInner->getCell() == 0 )
+ StartTableRow( pDeepInner );
+
+ StartTableCell( pDeepInner );
+ }
+
+ if ( nRow == 0 && nCell == 0 )
+ {
+ // Do we have to start the table?
+ // [If we are at the rigth depth already, it means that we
+ // continue the table cell]
+ sal_uInt32 nCurrentDepth = pTextNodeInfo->getDepth();
+
+ if ( nCurrentDepth > m_nTableDepth )
+ {
+ // Start all the tables that begin here
+ for ( sal_uInt32 nDepth = m_nTableDepth + 1; nDepth <= pTextNodeInfo->getDepth(); ++nDepth )
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t pInner( pTextNodeInfo->getInnerForDepth( nDepth ) );
+
+ m_bLastTable = (nDepth == pTextNodeInfo->getDepth());
+ StartTable( pInner );
+ StartTableRow( pInner );
+ StartTableCell( pInner );
+ }
+
+ m_nTableDepth = nCurrentDepth;
+ }
+ }
+ }
+
+ OSL_ENSURE(m_aRun.getLength() == 0, "m_aRun is not empty");
+}
+
+void RtfAttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ FinishTableRowCell( pTextNodeInfoInner );
+
+ OStringBuffer aParagraph;
+
+ aParagraph.append(m_aRun.makeStringAndClear());
+ aParagraph.append(m_aAfterRuns.makeStringAndClear());
+ if (m_bTblAfterCell)
+ m_bTblAfterCell = false;
+ else
+ {
+ aParagraph.append(m_rExport.sNewLine);
+ aParagraph.append(OOO_STRING_SVTOOLS_RTF_PAR);
+ aParagraph.append(' ');
+ }
+ if (m_nColBreakNeeded)
+ {
+ aParagraph.append(OOO_STRING_SVTOOLS_RTF_COLUMN);
+ m_nColBreakNeeded = false;
+ }
+
+ if (!m_bBufferSectionHeaders)
+ m_rExport.Strm() << aParagraph.makeStringAndClear();
+ else
+ m_aSectionHeaders.append(aParagraph.makeStringAndClear());
+}
+
+void RtfAttributeOutput::EmptyParagraph()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << m_rExport.sNewLine << OOO_STRING_SVTOOLS_RTF_PAR << ' ';
+}
+
+void RtfAttributeOutput::StartParagraphProperties( const SwTxtNode& rNode )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ OSL_ENSURE(m_aStyles.getLength() == 0, "m_aStyles is not empty");
+
+ // output page/section breaks
+ SwNodeIndex aNextIndex( rNode, 1 );
+ m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
+ m_bBufferSectionBreaks = true;
+
+ // output section headers / footers
+ if (!m_bBufferSectionHeaders)
+ m_rExport.Strm() << m_aSectionHeaders.makeStringAndClear();
+
+ if ( aNextIndex.GetNode().IsTxtNode() )
+ {
+ const SwTxtNode* pTxtNode = static_cast< SwTxtNode* >( &aNextIndex.GetNode() );
+ m_rExport.OutputSectionBreaks( pTxtNode->GetpSwAttrSet(), *pTxtNode );
+ }
+ else if ( aNextIndex.GetNode().IsTableNode() )
+ {
+ const SwTableNode* pTableNode = static_cast< SwTableNode* >( &aNextIndex.GetNode() );
+ const SwFrmFmt *pFmt = pTableNode->GetTable().GetFrmFmt();
+ m_rExport.OutputSectionBreaks( &(pFmt->GetAttrSet()), *pTableNode );
+ }
+ m_bBufferSectionBreaks = false;
+
+ OStringBuffer aPar;
+ if (!m_rExport.bRTFFlySyntax)
+ {
+ aPar.append(OOO_STRING_SVTOOLS_RTF_PARD);
+ aPar.append(OOO_STRING_SVTOOLS_RTF_PLAIN);
+ aPar.append(' ');
+ }
+ if (!m_bBufferSectionHeaders)
+ m_rExport.Strm() << aPar.makeStringAndClear();
+ else
+ m_aSectionHeaders.append(aPar.makeStringAndClear());
+}
+
+void RtfAttributeOutput::EndParagraphProperties()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ m_aStyles.append(m_aStylesEnd.makeStringAndClear());
+ m_rExport.Strm() << m_aStyles.makeStringAndClear();
+}
+
+void RtfAttributeOutput::StartRun( const SwRedlineData* pRedlineData )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aRun.append('{');
+
+ // if there is some redlining in the document, output it
+ Redline( pRedlineData );
+
+ OSL_ENSURE(m_aRunText.getLength() == 0, "m_aRunText is not empty");
+}
+
+void RtfAttributeOutput::EndRun()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ m_aRun.append(m_rExport.sNewLine);
+ m_aRun.append(m_aRunText.makeStringAndClear());
+ m_aRun.append('}');
+}
+
+void RtfAttributeOutput::StartRunProperties()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ OSL_ENSURE(m_aStyles.getLength() == 0, "m_aStyles is not empty");
+}
+
+void RtfAttributeOutput::EndRunProperties( const SwRedlineData* /*pRedlineData*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ m_aStyles.append(m_aStylesEnd.makeStringAndClear());
+ m_aRun.append(m_aStyles.makeStringAndClear());
+}
+
+void RtfAttributeOutput::RunText( const String& rText, rtl_TextEncoding eCharSet )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ RawText( rText, 0, eCharSet );
+}
+
+OStringBuffer& RtfAttributeOutput::RunText()
+{
+ return m_aRunText;
+}
+
+OStringBuffer& RtfAttributeOutput::Styles()
+{
+ return m_aStyles;
+}
+
+void RtfAttributeOutput::RawText( const String& rText, bool /*bForceUnicode*/, rtl_TextEncoding eCharSet )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ m_aRunText.append(m_rExport.OutString(rText, eCharSet));
+}
+
+void RtfAttributeOutput::StartRuby( const SwTxtNode& /*rNode*/, xub_StrLen /*nPos*/, const SwFmtRuby& /*rRuby*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::EndRuby()
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+bool RtfAttributeOutput::StartURL( const String& rUrl, const String& rTarget )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append('{');
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FIELD);
+ m_aStyles.append('{');
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FLDINST);
+ m_aStyles.append(" HYPERLINK ");
+
+ String sURL( rUrl );
+ if( sURL.Len() )
+ {
+ m_aStyles.append("\"");
+ m_aStyles.append(m_rExport.OutString( sURL, m_rExport.eCurrentEncoding));
+ m_aStyles.append("\" ");
+ }
+
+ if( rTarget.Len() )
+ {
+ m_aStyles.append("\\\\t \"");
+ m_aStyles.append(m_rExport.OutString( rTarget, m_rExport.eCurrentEncoding));
+ m_aStyles.append("\" ");
+ }
+
+ m_aStyles.append("}");
+ return true;
+}
+
+bool RtfAttributeOutput::EndURL()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // close the fldrslt group
+ m_aRunText.append('}');
+ // close the field group
+ m_aRunText.append('}');
+ return true;
+}
+
+void RtfAttributeOutput::FieldVanish( const String& /*rTxt*/, ww::eField /*eType*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::Redline( const SwRedlineData* pRedline )
+{
+ if (!pRedline)
+ return;
+
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if (pRedline->GetType() == nsRedlineType_t::REDLINE_INSERT)
+ {
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_REVISED);
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_REVAUTH);
+ m_aRun.append((sal_Int32)m_rExport.GetRedline(SW_MOD()->GetRedlineAuthor(pRedline->GetAuthor())));
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_REVDTTM);
+ }
+ else if(pRedline->GetType() == nsRedlineType_t::REDLINE_DELETE)
+ {
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_DELETED);
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_REVAUTHDEL);
+ m_aRun.append((sal_Int32)m_rExport.GetRedline(SW_MOD()->GetRedlineAuthor(pRedline->GetAuthor())));
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_REVDTTMDEL);
+ }
+ m_aRun.append((sal_Int32)sw::ms::DateTime2DTTM(pRedline->GetTimeStamp()));
+ m_aRun.append(' ');
+}
+
+void RtfAttributeOutput::FormatDrop( const SwTxtNode& /*rNode*/, const SwFmtDrop& /*rSwFmtDrop*/, sal_uInt16 /*nStyle*/, ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/, ww8::WW8TableNodeInfoInner::Pointer_t /*pTextNodeInfoInner*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::ParagraphStyle( sal_uInt16 nStyle )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ OString *pStyle = m_rExport.GetStyle(nStyle);
+ OStringBuffer aStyle;
+ aStyle.append(OOO_STRING_SVTOOLS_RTF_S);
+ aStyle.append((sal_Int32)nStyle);
+ if (pStyle)
+ aStyle.append(pStyle->getStr());
+ if (!m_bBufferSectionHeaders)
+ m_rExport.Strm() << aStyle.makeStringAndClear();
+ else
+ m_aSectionHeaders.append(aStyle.makeStringAndClear());
+}
+
+void RtfAttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_INTBL);
+ if ( m_nTableDepth > 1 )
+ {
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ITAP);
+ m_aStyles.append((sal_Int32)m_nTableDepth);
+ }
+ m_bWroteCellInfo = true;
+}
+
+void RtfAttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfo*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /* noop */
+}
+
+void RtfAttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( !m_pTableWrt )
+ InitTableHelper( pTableTextNodeInfoInner );
+
+ const SwTable *pTbl = pTableTextNodeInfoInner->getTable();
+ SwFrmFmt *pFmt = pTbl->GetFrmFmt( );
+
+ m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_TROWD);
+ TableOrientation( pTableTextNodeInfoInner );
+ TableBidi( pTableTextNodeInfoInner );
+ TableHeight( pTableTextNodeInfoInner );
+ TableCanSplit( pTableTextNodeInfoInner );
+
+ // Cell margins
+ const SvxBoxItem& rBox = pFmt->GetBox( );
+ static const sal_uInt16 aBorders[] =
+ {
+ BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
+ };
+
+ static const char* aRowPadNames[] =
+ {
+ OOO_STRING_SVTOOLS_RTF_TRPADDT, OOO_STRING_SVTOOLS_RTF_TRPADDL, OOO_STRING_SVTOOLS_RTF_TRPADDB, OOO_STRING_SVTOOLS_RTF_TRPADDR
+ };
+
+ static const char* aRowPadUnits[] =
+ {
+ OOO_STRING_SVTOOLS_RTF_TRPADDFT, OOO_STRING_SVTOOLS_RTF_TRPADDFL, OOO_STRING_SVTOOLS_RTF_TRPADDFB, OOO_STRING_SVTOOLS_RTF_TRPADDFR
+ };
+
+ for (int i = 0; i < 4; ++i)
+ {
+ m_aRowDefs.append(aRowPadUnits[i]);
+ m_aRowDefs.append((sal_Int32)3);
+ m_aRowDefs.append(aRowPadNames[i]);
+ m_aRowDefs.append((sal_Int32)rBox.GetDistance(aBorders[i]));
+ }
+
+ // The cell-dependent properties
+ const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
+ SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
+ SwTwips nSz = 0;
+ Point aPt;
+ SwRect aRect( pFmt->FindLayoutRect( false, &aPt ));
+ SwTwips nPageSize = aRect.Width();
+
+ // Handle the page size when not rendered
+ if( 0 == nPageSize )
+ {
+ const SwNode* pNode = pTableTextNodeInfoInner->getNode();
+ const SwFrmFmt* pFrmFmt = GetExport().mpParentFrame ? &GetExport().mpParentFrame->GetFrmFmt() :
+ const_cast<const SwDoc *>(GetExport().pDoc)
+ ->GetPageDesc(0).GetPageFmtOfNode(*pNode, false);
+
+ const SvxLRSpaceItem& rLR = pFrmFmt->GetLRSpace();
+ nPageSize = pFrmFmt->GetFrmSize().GetWidth() -
+ rLR.GetLeft() - rLR.GetRight();
+ }
+ SwTwips nTblSz = pFmt->GetFrmSize().GetWidth();
+ for( sal_uInt16 i = 0; i < pRow->GetCells().Count(); i++ )
+ {
+ SwWriteTableCell *pCell = pRow->GetCells( )[ i ];
+ const SwFrmFmt *pCellFmt = pCell->GetBox()->GetFrmFmt();
+
+ pTableTextNodeInfoInner->setCell( i );
+ TableCellProperties(pTableTextNodeInfoInner);
+
+ // Right boundary: this can't be in TableCellProperties as the old
+ // value of nSz is needed.
+ nSz += pCellFmt->GetFrmSize().GetWidth();
+ m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CELLX);
+ SwTwips nCalc = nSz;
+ nCalc *= nPageSize;
+ nCalc /= nTblSz;
+ m_aRowDefs.append( (sal_Int32)(pFmt->GetLRSpace().GetLeft() + nCalc) );
+ }
+}
+
+void RtfAttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /*
+ * The function name is a bit misleading: given that we write borders
+ * before each row, we just have borders, not default ones. Additionally,
+ * this function actually writes borders for a specific cell only and is
+ * called for each cell.
+ */
+
+ const SwTableBox *pTblBox = pTableTextNodeInfoInner->getTableBox( );
+ SwFrmFmt *pFmt = pTblBox->GetFrmFmt( );
+ const SvxBoxItem& rDefault = pFmt->GetBox( );
+ const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
+ SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
+ SwWriteTableCell *pCell = pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
+ const SwFrmFmt *pCellFmt = pCell->GetBox()->GetFrmFmt();
+ const SfxPoolItem* pItem;
+ if (SFX_ITEM_SET == pCellFmt->GetAttrSet().GetItemState(RES_BOX, sal_True, &pItem))
+ {
+ const SvxBoxItem& rBox = (SvxBoxItem&)*pItem;
+ static const sal_uInt16 aBorders[] =
+ {
+ BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
+ };
+ static const char* aBorderNames[] =
+ {
+ OOO_STRING_SVTOOLS_RTF_CLBRDRT, OOO_STRING_SVTOOLS_RTF_CLBRDRL, OOO_STRING_SVTOOLS_RTF_CLBRDRB, OOO_STRING_SVTOOLS_RTF_CLBRDRR
+ };
+ //Yes left and top are swapped with eachother for cell padding! Because
+ //that's what the thunderingly annoying rtf export/import word xp does.
+ static const char* aCellPadNames[] =
+ {
+ OOO_STRING_SVTOOLS_RTF_CLPADL, OOO_STRING_SVTOOLS_RTF_CLPADT, OOO_STRING_SVTOOLS_RTF_CLPADB, OOO_STRING_SVTOOLS_RTF_CLPADR
+ };
+ static const char* aCellPadUnits[] =
+ {
+ OOO_STRING_SVTOOLS_RTF_CLPADFL, OOO_STRING_SVTOOLS_RTF_CLPADFT, OOO_STRING_SVTOOLS_RTF_CLPADFB, OOO_STRING_SVTOOLS_RTF_CLPADFR
+ };
+ for (int i = 0; i < 4; ++i)
+ {
+ if (const SvxBorderLine* pLn = rBox.GetLine(aBorders[i]))
+ m_aRowDefs.append(OutTBLBorderLine(m_rExport, pLn, aBorderNames[i]));
+ if (rDefault.GetDistance(aBorders[i]) !=
+ rBox.GetDistance(aBorders[i]))
+ {
+ m_aRowDefs.append(aCellPadUnits[i]);
+ m_aRowDefs.append((sal_Int32)3);
+ m_aRowDefs.append(aCellPadNames[i]);
+ m_aRowDefs.append((sal_Int32)rBox.GetDistance(aBorders[i]));
+ }
+ }
+ }
+}
+
+void RtfAttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
+ SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
+ SwWriteTableCell *pCell = pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
+ const SwFrmFmt *pCellFmt = pCell->GetBox()->GetFrmFmt();
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == pCellFmt->GetAttrSet().GetItemState(
+ RES_BACKGROUND, sal_True, &pItem ))
+ {
+ const SvxBrushItem& rBack = (SvxBrushItem&)*pItem;
+ if( !rBack.GetColor().GetTransparency() )
+ {
+ m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLCBPAT);
+ m_aRowDefs.append((sal_Int32)m_rExport.GetColor(rBack.GetColor()));
+ }
+ }
+}
+
+void RtfAttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
+ const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
+
+ if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
+ {
+ sal_Int32 nHeight = 0;
+
+ switch ( rLSz.GetHeightSizeType() )
+ {
+ case ATT_FIX_SIZE: nHeight = -rLSz.GetHeight(); break;
+ case ATT_MIN_SIZE: nHeight = rLSz.GetHeight(); break;
+ default: break;
+ }
+
+ if ( nHeight )
+ {
+ m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_TRRH);
+ m_aRowDefs.append(nHeight);
+ }
+ }
+}
+
+void RtfAttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
+ const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit( );
+
+ // The rtf default is to allow a row to break
+ if (rSplittable.GetValue() == 0)
+ m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_TRKEEP);
+}
+
+void RtfAttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const SwTable * pTable = pTableTextNodeInfoInner->getTable();
+ const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
+
+ if ( m_rExport.TrueFrameDirection( *pFrmFmt ) != FRMDIR_HORI_RIGHT_TOP )
+ m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_LTRROW);
+ else
+ m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_RTLROW);
+}
+
+void RtfAttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const SwWriteTableRows& aRows = m_pTableWrt->GetRows( );
+ SwWriteTableRow *pRow = aRows[ pTableTextNodeInfoInner->getRow( ) ];
+ SwWriteTableCell *pCell = pRow->GetCells( )[ pTableTextNodeInfoInner->getCell( ) ];
+ const SwFrmFmt *pCellFmt = pCell->GetBox()->GetFrmFmt();
+ const SfxPoolItem* pItem;
+
+ // vertical merges
+ if (pCell->GetRowSpan() > 1)
+ m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVMGF);
+ else if (pCell->GetRowSpan() == 0)
+ m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVMRG);
+
+ // vertical alignment
+ if( SFX_ITEM_SET == pCellFmt->GetAttrSet().GetItemState(
+ RES_VERT_ORIENT, sal_True, &pItem ) )
+ switch( ((SwFmtVertOrient*)pItem)->GetVertOrient() )
+ {
+ case text::VertOrientation::CENTER: m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVERTALC); break;
+ case text::VertOrientation::BOTTOM: m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVERTALB); break;
+ default: m_aRowDefs.append(OOO_STRING_SVTOOLS_RTF_CLVERTALT); break;
+ }
+}
+
+void RtfAttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t /*pNodeInfo*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /* noop */
+}
+
+void RtfAttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // This is called when the nested table ends in a cell, and there's no
+ // paragraph benhind that; so we must check for the ends of cell, rows,
+ // and tables
+ // ['true' to write an empty paragraph, MS Word insists on that]
+ FinishTableRowCell( pNodeInfoInner, true );
+}
+
+void RtfAttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const SwTable *pTable = pTableTextNodeInfoInner->getTable();
+ SwFrmFmt *pFmt = pTable->GetFrmFmt( );
+
+ OStringBuffer aTblAdjust( OOO_STRING_SVTOOLS_RTF_TRQL );
+ switch (pFmt->GetHoriOrient().GetHoriOrient())
+ {
+ case text::HoriOrientation::CENTER:
+ aTblAdjust.setLength(0);
+ aTblAdjust.append(OOO_STRING_SVTOOLS_RTF_TRQC);
+ break;
+ case text::HoriOrientation::RIGHT:
+ aTblAdjust.setLength(0);
+ aTblAdjust.append(OOO_STRING_SVTOOLS_RTF_TRQR);
+ break;
+ case text::HoriOrientation::NONE:
+ case text::HoriOrientation::LEFT_AND_WIDTH:
+ aTblAdjust.append(OOO_STRING_SVTOOLS_RTF_TRLEFT);
+ aTblAdjust.append((sal_Int32)pFmt->GetLRSpace().GetLeft());
+ break;
+ default:
+ break;
+ }
+
+ m_aRowDefs.append(aTblAdjust.makeStringAndClear());
+}
+
+void RtfAttributeOutput::TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::TableRowEnd( sal_uInt32 /*nDepth*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /* noop, see EndTableRow() */
+}
+
+/*
+ * Our private table methods.
+ */
+
+void RtfAttributeOutput::InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ sal_uInt32 nPageSize = 0;
+ bool bRelBoxSize = false;
+
+ // Create the SwWriteTable instance to use col spans
+ GetTablePageSize( pTableTextNodeInfoInner.get(), nPageSize, bRelBoxSize );
+
+ const SwTable* pTable = pTableTextNodeInfoInner->getTable( );
+ const SwFrmFmt *pFmt = pTable->GetFrmFmt( );
+ SwTwips nTblSz = pFmt->GetFrmSize( ).GetWidth( );
+
+ const SwHTMLTableLayout *pLayout = pTable->GetHTMLTableLayout();
+ if( pLayout && pLayout->IsExportable() )
+ m_pTableWrt = new SwWriteTable( pLayout );
+ else
+ m_pTableWrt = new SwWriteTable( pTable->GetTabLines(), (sal_uInt16)nPageSize,
+ (sal_uInt16)nTblSz, false);
+}
+
+void RtfAttributeOutput::StartTable( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // To trigger calling InitTableHelper()
+ delete m_pTableWrt, m_pTableWrt = NULL;
+}
+
+void RtfAttributeOutput::StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ sal_uInt32 nCurrentDepth = pTableTextNodeInfoInner->getDepth();
+ OSL_TRACE("%s, (depth is %d)", OSL_THIS_FUNC, (int)nCurrentDepth);
+
+ TableDefinition(pTableTextNodeInfoInner);
+
+ if (!m_bLastTable)
+ m_aTables.push_back(m_aRowDefs.makeStringAndClear());
+
+ // We'll write the table definition for nested tables later
+ if ( nCurrentDepth > 1 )
+ return;
+ m_rExport.Strm() << m_aRowDefs.makeStringAndClear();
+}
+
+void RtfAttributeOutput::StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_bTableCellOpen = true;
+}
+
+void RtfAttributeOutput::TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ TableDefaultBorders(pTableTextNodeInfoInner);
+ TableBackgrounds(pTableTextNodeInfoInner);
+ TableVerticalCell(pTableTextNodeInfoInner);
+}
+
+void RtfAttributeOutput::EndTableCell( )
+{
+ OSL_TRACE("%s, (depth is %d)", OSL_THIS_FUNC, (int)m_nTableDepth);
+
+ if (!m_bWroteCellInfo)
+ {
+ m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_INTBL);
+ m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_ITAP);
+ m_aAfterRuns.append((sal_Int32)m_nTableDepth);
+ }
+ if ( m_nTableDepth > 1 )
+ m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_NESTCELL);
+ else
+ m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_CELL);
+
+ m_bTableCellOpen = false;
+ m_bTblAfterCell = true;
+ m_bWroteCellInfo = false;
+}
+
+void RtfAttributeOutput::EndTableRow( )
+{
+ OSL_TRACE("%s, (depth is %d)", OSL_THIS_FUNC, (int)m_nTableDepth);
+
+ if ( m_nTableDepth > 1 )
+ {
+ m_aAfterRuns.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_NESTTABLEPROPRS);
+ if (m_aRowDefs.getLength() > 0)
+ m_aAfterRuns.append(m_aRowDefs.makeStringAndClear());
+ else if (m_aTables.size() > 0)
+ {
+ m_aAfterRuns.append(m_aTables.back());
+ m_aTables.pop_back();
+ }
+ m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_NESTROW "}" "{" OOO_STRING_SVTOOLS_RTF_NONESTTABLES OOO_STRING_SVTOOLS_RTF_PAR "}");
+ }
+ else
+ {
+ if (m_aTables.size() > 0)
+ {
+ m_aAfterRuns.append(m_aTables.back());
+ m_aTables.pop_back();
+ }
+ m_aAfterRuns.append(OOO_STRING_SVTOOLS_RTF_ROW).append(OOO_STRING_SVTOOLS_RTF_PARD);
+ }
+}
+
+void RtfAttributeOutput::EndTable()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( m_nTableDepth > 0 ) {
+ m_nTableDepth--;
+ delete m_pTableWrt, m_pTableWrt = NULL;
+ }
+
+ // We closed the table; if it is a nested table, the cell that contains it
+ // still continues
+ m_bTableCellOpen = true;
+
+ // Cleans the table helper
+ delete m_pTableWrt, m_pTableWrt = NULL;
+}
+
+void RtfAttributeOutput::FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool /*bForceEmptyParagraph*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( pInner.get() )
+ {
+ // Where are we in the table
+ sal_uInt32 nRow = pInner->getRow( );
+
+ const SwTable *pTable = pInner->getTable( );
+ const SwTableLines& rLines = pTable->GetTabLines( );
+ sal_uInt16 nLinesCount = rLines.Count( );
+
+ if ( pInner->isEndOfCell() )
+ EndTableCell();
+
+ // This is a line end
+ if ( pInner->isEndOfLine() )
+ EndTableRow();
+
+ // This is the end of the table
+ if ( pInner->isEndOfLine( ) && ( nRow + 1 ) == nLinesCount )
+ EndTable();
+ }
+}
+
+void RtfAttributeOutput::StartStyles()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ m_rExport.Strm() << m_rExport.sNewLine << '{' << OOO_STRING_SVTOOLS_RTF_COLORTBL;
+ m_rExport.OutColorTable();
+ OSL_ENSURE(m_aStylesheet.getLength() == 0, "m_aStylesheet is not empty");
+ m_aStylesheet.append(m_rExport.sNewLine);
+ m_aStylesheet.append('{');
+ m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_STYLESHEET);
+}
+
+void RtfAttributeOutput::EndStyles( sal_uInt16 /*nNumberOfStyles*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ m_rExport.Strm() << '}';
+ m_rExport.Strm() << m_aStylesheet.makeStringAndClear();
+ m_rExport.Strm() << '}';
+}
+
+void RtfAttributeOutput::DefaultStyle( sal_uInt16 /*nStyle*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /* noop, the default style is always 0 in RTF */
+}
+
+void RtfAttributeOutput::StartStyle( const String& rName, bool bPapFmt,
+ sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 /*nWwId*/, sal_uInt16 nId,
+ bool /* bAutoUpdate */ )
+{
+ OSL_TRACE("%s, rName = '%s'", OSL_THIS_FUNC,
+ OUStringToOString( OUString( rName ), m_rExport.eCurrentEncoding ).getStr());
+
+ m_aStylesheet.append('{');
+ if (bPapFmt)
+ m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_S);
+ else
+ m_aStylesheet.append( OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_CS);
+ m_aStylesheet.append( (sal_Int32)nId );
+
+ if ( nBase != 0x0FFF )
+ {
+ m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_SBASEDON);
+ m_aStylesheet.append((sal_Int32)nBase);
+ }
+
+ m_aStylesheet.append(OOO_STRING_SVTOOLS_RTF_SNEXT);
+ m_aStylesheet.append((sal_Int32)nNext);
+
+ m_rStyleName = rName;
+ m_nStyleId = nId;
+}
+
+void RtfAttributeOutput::EndStyle()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ m_aStyles.append(m_aStylesEnd.makeStringAndClear());
+ OString aStyles = m_aStyles.makeStringAndClear();
+ m_rExport.InsStyle(m_nStyleId, aStyles);
+ m_aStylesheet.append(aStyles);
+ m_aStylesheet.append(' ');
+ m_aStylesheet.append(m_rExport.OutString(m_rStyleName, m_rExport.eCurrentEncoding));
+ m_aStylesheet.append(";}");
+ m_aStylesheet.append(m_rExport.sNewLine);
+}
+
+void RtfAttributeOutput::StartStyleProperties( bool /*bParProp*/, sal_uInt16 /*nStyle*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ /* noop */
+}
+
+void RtfAttributeOutput::EndStyleProperties( bool /*bParProp*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ /* noop */
+}
+
+void RtfAttributeOutput::OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt& /*rNFmt*/, const SwFmt& /*rFmt*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( nLvl >= WW8ListManager::nMaxLevel )
+ nLvl = WW8ListManager::nMaxLevel - 1;
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ILVL);
+ m_aStyles.append((sal_Int32)nLvl);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_OUTLINELEVEL);
+ m_aStyles.append((sal_Int32)nLvl);
+}
+
+void RtfAttributeOutput::PageBreakBefore( bool bBreak )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if (bBreak)
+ {
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_PAGEBB;
+ }
+}
+
+void RtfAttributeOutput::SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ switch (nC)
+ {
+ case msword::ColumnBreak:
+ m_nColBreakNeeded = true;
+ break;
+ case msword::PageBreak:
+ if ( pSectionInfo )
+ m_rExport.SectionProperties( *pSectionInfo );
+ break;
+ }
+}
+
+void RtfAttributeOutput::StartSection()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_SECT OOO_STRING_SVTOOLS_RTF_SECTD);
+ if (!m_bBufferSectionBreaks)
+ m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
+}
+
+void RtfAttributeOutput::EndSection()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /*
+ * noop, \sect must go to StartSection or Word won't notice multiple
+ * columns...
+ */
+}
+
+void RtfAttributeOutput::SectionFormProtection( bool bProtected )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_SECTUNLOCKED);
+ m_aSectionBreaks.append((sal_Int32)!bProtected);
+}
+
+void RtfAttributeOutput::SectionLineNumbering( sal_uLong /*nRestartNo*/, const SwLineNumberInfo& rLnNumInfo )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LINEMOD;
+ m_rExport.OutLong(rLnNumInfo.GetCountBy());
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LINEX;
+ m_rExport.OutLong(rLnNumInfo.GetPosFromLeft());
+ if (!rLnNumInfo.IsRestartEachPage())
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LINECONT;
+}
+
+void RtfAttributeOutput::SectionTitlePage()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /*
+ * noop, handled in RtfExport::WriteHeaderFooter()
+ */
+}
+
+void RtfAttributeOutput::SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* /*pFirstPageFmt*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const SvxBoxItem& rBox = pFmt->GetBox();
+ const SvxBorderLine *pLine = rBox.GetTop();
+ if(pLine)
+ m_aSectionBreaks.append(OutBorderLine( m_rExport, pLine,
+ OOO_STRING_SVTOOLS_RTF_PGBRDRT,
+ rBox.GetDistance(BOX_LINE_TOP) ));
+ pLine = rBox.GetBottom();
+ if(pLine)
+ m_aSectionBreaks.append(OutBorderLine( m_rExport, pLine,
+ OOO_STRING_SVTOOLS_RTF_PGBRDRB,
+ rBox.GetDistance(BOX_LINE_BOTTOM) ));
+ pLine = rBox.GetLeft();
+ if(pLine)
+ m_aSectionBreaks.append(OutBorderLine( m_rExport, pLine,
+ OOO_STRING_SVTOOLS_RTF_PGBRDRL,
+ rBox.GetDistance(BOX_LINE_LEFT) ));
+ pLine = rBox.GetRight();
+ if(pLine)
+ m_aSectionBreaks.append(OutBorderLine( m_rExport, pLine,
+ OOO_STRING_SVTOOLS_RTF_PGBRDRR,
+ rBox.GetDistance(BOX_LINE_RIGHT) ));
+}
+
+void RtfAttributeOutput::SectionBiDi( bool bBiDi )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << (bBiDi ? OOO_STRING_SVTOOLS_RTF_RTLSECT : OOO_STRING_SVTOOLS_RTF_LTRSECT);
+}
+
+void RtfAttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if (nPageRestartNumber > 0)
+ {
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGNSTARTS);
+ m_aSectionBreaks.append((sal_Int32)nPageRestartNumber);
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGNRESTART);
+ }
+
+ const char* pStr = 0;
+ switch ( nNumType )
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ case SVX_NUM_CHARS_UPPER_LETTER_N: pStr = OOO_STRING_SVTOOLS_RTF_PGNUCLTR; break;
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ case SVX_NUM_CHARS_LOWER_LETTER_N: pStr = OOO_STRING_SVTOOLS_RTF_PGNLCLTR; break;
+ case SVX_NUM_ROMAN_UPPER: pStr = OOO_STRING_SVTOOLS_RTF_PGNUCRM; break;
+ case SVX_NUM_ROMAN_LOWER: pStr = OOO_STRING_SVTOOLS_RTF_PGNLCRM; break;
+
+ case SVX_NUM_ARABIC: pStr = OOO_STRING_SVTOOLS_RTF_PGNDEC; break;
+ }
+ if (pStr)
+ m_aSectionBreaks.append(pStr);
+}
+
+void RtfAttributeOutput::SectionType( sal_uInt8 nBreakCode )
+{
+ OSL_TRACE("%s, nBreakCode = %d", OSL_THIS_FUNC, nBreakCode);
+
+ /*
+ * break code: 0 No break, 1 New column
+ * 2 New page, 3 Even page, 4 Odd page
+ */
+ const char* sType = NULL;
+ switch ( nBreakCode )
+ {
+ case 1: sType = OOO_STRING_SVTOOLS_RTF_SBKCOL; break;
+ case 2: sType = OOO_STRING_SVTOOLS_RTF_SBKPAGE; break;
+ case 3: sType = OOO_STRING_SVTOOLS_RTF_SBKEVEN; break;
+ case 4: sType = OOO_STRING_SVTOOLS_RTF_SBKODD; break;
+ default: sType = OOO_STRING_SVTOOLS_RTF_SBKNONE; break;
+ }
+ m_aSectionBreaks.append(sType);
+ if (!m_bBufferSectionBreaks)
+ m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
+}
+
+void RtfAttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &/*rRule*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTOVERRIDE;
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LISTID;
+ m_rExport.OutULong(nId);
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LISTOVERRIDECOUNT << '0';
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LS;
+ m_rExport.OutULong(nId) << '}';
+}
+
+void RtfAttributeOutput::StartAbstractNumbering( sal_uInt16 nId )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LIST << OOO_STRING_SVTOOLS_RTF_LISTTEMPLATEID;
+ m_rExport.OutULong( nId );
+ m_nListId = nId;
+}
+
+void RtfAttributeOutput::EndAbstractNumbering()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LISTID;
+ m_rExport.OutULong( m_nListId ) << '}' << m_rExport.sNewLine;
+}
+
+void RtfAttributeOutput::NumberingLevel( sal_uInt8 nLevel,
+ sal_uInt16 nStart,
+ sal_uInt16 nNumberingType,
+ SvxAdjust eAdjust,
+ const sal_uInt8 * pNumLvlPos,
+ sal_uInt8 /*nFollow*/,
+ const wwFont * pFont,
+ const SfxItemSet * pOutSet,
+ sal_Int16 nIndentAt,
+ sal_Int16 nFirstLineIndex,
+ sal_Int16 /*nListTabPos*/,
+ const String &rNumberingString )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << m_rExport.sNewLine;
+ if( nLevel > 8 ) // RTF knows only 9 levels
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_SOUTLVL;
+
+ m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTLEVEL;
+
+ sal_uInt16 nVal = 0;
+ switch( nNumberingType )
+ {
+ case SVX_NUM_ROMAN_UPPER: nVal = 1; break;
+ case SVX_NUM_ROMAN_LOWER: nVal = 2; break;
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ case SVX_NUM_CHARS_UPPER_LETTER_N: nVal = 3; break;
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ case SVX_NUM_CHARS_LOWER_LETTER_N: nVal = 4; break;
+
+ case SVX_NUM_BITMAP:
+ case SVX_NUM_CHAR_SPECIAL: nVal = 23; break;
+ }
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELNFC;
+ m_rExport.OutULong( nVal );
+
+ switch( eAdjust )
+ {
+ case SVX_ADJUST_CENTER: nVal = 1; break;
+ case SVX_ADJUST_RIGHT: nVal = 2; break;
+ default: nVal = 0; break;
+ }
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELJC;
+ m_rExport.OutULong( nVal );
+
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELSTARTAT;
+ m_rExport.OutULong( nStart );
+
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_LEVELFOLLOW << "0";
+
+ // leveltext group
+ m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LEVELTEXT << ' ';
+
+ if( SVX_NUM_CHAR_SPECIAL == nNumberingType ||
+ SVX_NUM_BITMAP == nNumberingType )
+ {
+ m_rExport.Strm() << "\\'01";
+ sal_Unicode cChar = rNumberingString.GetChar(0);
+ m_rExport.Strm() << "\\u";
+ m_rExport.OutULong(cChar);
+ m_rExport.Strm() << " ?";
+ }
+ else
+ {
+ m_rExport.Strm() << "\\'" << m_rExport.OutHex( rNumberingString.Len(), 2 );
+ m_rExport.Strm() << m_rExport.OutString( rNumberingString, m_rExport.eDefaultEncoding );
+ }
+
+ m_rExport.Strm() << ";}";
+
+ // write the levelnumbers
+ m_rExport.Strm() << "{" << OOO_STRING_SVTOOLS_RTF_LEVELNUMBERS;
+ for( sal_uInt8 i = 0; i <= nLevel && pNumLvlPos[ i ]; ++i )
+ {
+ m_rExport.Strm() << "\\'" << m_rExport.OutHex(pNumLvlPos[ i ], 2).getStr();
+ }
+ m_rExport.Strm() << ";}";
+
+ if( pOutSet )
+ {
+ if (pFont)
+ {
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_F;
+ m_rExport.OutULong(m_rExport.maFontHelper.GetId(*pFont));
+ }
+ m_rExport.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rExport.mbExportModeRTF );
+ m_rExport.Strm() << m_aStyles.makeStringAndClear();
+ }
+
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FI;
+ m_rExport.OutLong( nFirstLineIndex ) << OOO_STRING_SVTOOLS_RTF_LI;
+ m_rExport.OutLong( nIndentAt );
+
+ m_rExport.Strm() << '}';
+ if( nLevel > 8 )
+ m_rExport.Strm() << '}';
+}
+
+void RtfAttributeOutput::WriteField_Impl( const SwField* pFld, ww::eField /*eType*/, const String& rFldCmd, sal_uInt8 /*nMode*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // NEEDSWORK this has beeen tested only with page numbers
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_FIELD);
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST " ");
+ m_aRunText.append(m_rExport.OutString(rFldCmd, m_rExport.eCurrentEncoding));
+ m_aRunText.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
+ if (pFld)
+ m_aRunText.append(m_rExport.OutString(pFld->ExpandField(true), m_rExport.eDefaultEncoding));
+ m_aRunText.append("}}");
+}
+
+void RtfAttributeOutput::WriteBookmarks_Impl( std::vector< rtl::OUString >& rStarts, std::vector< rtl::OUString >& rEnds )
+{
+ for ( std::vector< OUString >::const_iterator it = rStarts.begin(), end = rStarts.end(); it < end; ++it )
+ {
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKSTART " ");
+ m_aRun.append(m_rExport.OutString(*it, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ }
+ rStarts.clear();
+
+ for ( std::vector< OUString >::const_iterator it = rEnds.begin(), end = rEnds.end(); it < end; ++it )
+ {
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_BKMKEND " ");
+ m_aRun.append(m_rExport.OutString(*it, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ }
+ rEnds.clear();
+}
+
+void RtfAttributeOutput::WriteHeaderFooter_Impl( const SwFrmFmt& rFmt, bool bHeader, const sal_Char* pStr )
+{
+ OStringBuffer aSectionBreaks = m_aSectionBreaks;
+ m_aSectionBreaks.setLength(0);
+ OStringBuffer aRun = m_aRun;
+ m_aRun.setLength(0);
+
+ m_aSectionHeaders.append(bHeader ? OOO_STRING_SVTOOLS_RTF_HEADERY : OOO_STRING_SVTOOLS_RTF_FOOTERY);
+ m_aSectionHeaders.append((sal_Int32)m_rExport.pAktPageDesc->GetMaster().GetULSpace().GetUpper());
+ m_aSectionHeaders.append('{');
+ m_aSectionHeaders.append(pStr);
+ m_bBufferSectionHeaders = true;
+ m_rExport.WriteHeaderFooterText(rFmt, bHeader);
+ m_bBufferSectionHeaders = false;
+ m_aSectionHeaders.append('}');
+
+ m_aSectionBreaks = aSectionBreaks;
+ m_aRun = aRun;
+}
+
+void RtfAttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFrame, const Point& /*rNdTopLeft*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const SwNode *pNode = rFrame.GetContent();
+ const SwGrfNode *pGrfNode = pNode ? pNode->GetGrfNode() : 0;
+
+ switch ( rFrame.GetWriterType() )
+ {
+ case sw::Frame::eTxtBox:
+ OSL_ENSURE(m_aRunText.getLength() == 0, "m_aRunText is not empty");
+ m_rExport.mpParentFrame = &rFrame;
+ m_rExport.bOutFlyFrmAttrs = m_rExport.bRTFFlySyntax = true;
+ m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
+ m_rExport.Strm() << m_aRunText.makeStringAndClear();
+ m_rExport.Strm() << m_aStyles.makeStringAndClear();
+ m_rExport.bOutFlyFrmAttrs = m_rExport.bRTFFlySyntax = false;
+ m_rExport.Strm() << "{" OOO_STRING_SVTOOLS_RTF_IGNORE;
+ m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
+ m_rExport.Strm() << m_aRunText.makeStringAndClear();
+ m_rExport.Strm() << m_aStyles.makeStringAndClear();
+ m_rExport.Strm() << '}';
+
+ {
+ /*
+ * Save m_aRun as we should not loose the opening brace.
+ * OTOH, just drop the contents of m_aRunText in case something
+ * would be there, causing a problem later.
+ */
+ OString aSave = m_aRun.makeStringAndClear();
+ m_rExport.bRTFFlySyntax = true;
+
+ const SwFrmFmt& rFrmFmt = rFrame.GetFrmFmt( );
+ const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
+ sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
+ sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
+ m_rExport.SaveData( nStt, nEnd );
+ m_rExport.mpParentFrame = &rFrame;
+ m_rExport.WriteText( );
+ m_rExport.RestoreData();
+
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_PARD;
+ m_rExport.bRTFFlySyntax = false;
+ m_aRun.append(aSave);
+ m_aRunText.setLength(0);
+ }
+
+ m_rExport.mpParentFrame = NULL;
+ m_rExport.Strm() << RtfExport::sNewLine;
+ break;
+ case sw::Frame::eGraphic:
+ if (!rFrame.IsInline())
+ {
+ m_rExport.mpParentFrame = &rFrame;
+ m_rExport.bRTFFlySyntax = true;
+ m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
+ m_rExport.bRTFFlySyntax = false;
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE);
+ m_rExport.OutputFormat( rFrame.GetFrmFmt(), false, false, true );
+ m_aRunText.append('}');
+ m_rExport.mpParentFrame = NULL;
+ }
+
+ if ( pGrfNode )
+ FlyFrameGraphic( dynamic_cast<const SwFlyFrmFmt*>( &rFrame.GetFrmFmt() ), *pGrfNode );
+ break;
+ case sw::Frame::eDrawing:
+ {
+ const SdrObject* pSdrObj = rFrame.GetFrmFmt().FindRealSdrObject();
+ if ( pSdrObj )
+ {
+ bool bSwapInPage = false;
+ if ( !pSdrObj->GetPage() )
+ {
+ if ( SdrModel* pModel = m_rExport.pDoc->GetDrawModel() )
+ {
+ if ( SdrPage *pPage = pModel->GetPage( 0 ) )
+ {
+ bSwapInPage = true;
+ const_cast< SdrObject* >( pSdrObj )->SetPage( pPage );
+ }
+ }
+ }
+
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_FIELD "{");
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLDINST);
+ m_aRunText.append(" SHAPE ");
+ m_aRunText.append("}" "{" OOO_STRING_SVTOOLS_RTF_FLDRSLT);
+
+ m_rExport.SdrExporter().AddSdrObject( *pSdrObj );
+
+ m_aRunText.append('}');
+ m_aRunText.append('}');
+
+ if ( bSwapInPage )
+ const_cast< SdrObject* >( pSdrObj )->SetPage( 0 );
+ }
+ }
+ break;
+ case sw::Frame::eFormControl:
+ {
+ const SwFrmFmt &rFrmFmt = rFrame.GetFrmFmt();
+ const SdrObject *pObject = rFrmFmt.FindRealSdrObject();
+
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_FIELD);
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST);
+
+ if (pObject && pObject->GetObjInventor() == FmFormInventor)
+ {
+ if (SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObject))
+ {
+ uno::Reference< awt::XControlModel > xControlModel =
+ pFormObj->GetUnoControlModel();
+ uno::Reference< lang::XServiceInfo > xInfo(xControlModel, uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySetInfo> xPropSetInfo = xPropSet->getPropertySetInfo();
+ OUString sName;
+ if (xInfo->supportsService(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.form.component.CheckBox"))))
+ {
+
+ m_aRun.append(OUStringToOString(OUString(FieldString(ww::eFORMCHECKBOX)), m_rExport.eCurrentEncoding));
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD "{");
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFTYPE "1"); // 1 = checkbox
+ // checkbox size in half points, this seems to be always 20, see WW8Export::DoCheckBox()
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFHPS "20");
+
+ OUString aStr;
+ sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name"));
+ if (xPropSetInfo->hasPropertyByName(sName))
+ {
+ xPropSet->getPropertyValue(sName) >>= aStr;
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME " ");
+ m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ }
+
+ sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HelpText"));
+ if (xPropSetInfo->hasPropertyByName(sName))
+ {
+ xPropSet->getPropertyValue(sName) >>= aStr;
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ");
+ m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ }
+
+ sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HelpF1Text"));
+ if (xPropSetInfo->hasPropertyByName(sName))
+ {
+ xPropSet->getPropertyValue(sName) >>= aStr;
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ");
+ m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ }
+
+ sal_Int16 nTemp = 0;
+ xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultState"))) >>= nTemp;
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFDEFRES);
+ m_aRun.append((sal_Int32)nTemp);
+ xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("State"))) >>= nTemp;
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFRES);
+ m_aRun.append((sal_Int32)nTemp);
+
+ m_aRun.append("}}");
+
+ // field result is empty, ffres already contains the form result
+ m_aRun.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
+ }
+ else if (xInfo->supportsService(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.form.component.TextField"))))
+ {
+ OStringBuffer aBuf;
+ OString aStr;
+ OUString aTmp;
+ const sal_Char* pStr;
+
+ m_aRun.append(OUStringToOString(OUString(FieldString(ww::eFORMTEXT)), m_rExport.eCurrentEncoding));
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_DATAFIELD " ");
+ for (int i = 0; i < 8; i++) aBuf.append((sal_Char)0x00);
+ xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name"))) >>= aTmp;
+ aStr = OUStringToOString(aTmp, m_rExport.eCurrentEncoding);
+ aBuf.append((sal_Char)aStr.getLength());
+ aBuf.append(aStr);
+ aBuf.append((sal_Char)0x00);
+ xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultText"))) >>= aTmp;
+ aStr = OUStringToOString(aTmp, m_rExport.eCurrentEncoding);
+ aBuf.append((sal_Char)aStr.getLength());
+ aBuf.append(aStr);
+ for (int i = 0; i < 11; i++) aBuf.append((sal_Char)0x00);
+ aStr = aBuf.makeStringAndClear();
+ pStr = aStr.getStr();
+ for (int i = 0; i < aStr.getLength(); i++, pStr++)
+ m_aRun.append(m_rExport.OutHex(*pStr, 2));
+ m_aRun.append('}');
+ m_aRun.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
+ xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Text"))) >>= aTmp;
+ m_aRun.append(OUStringToOString(aTmp, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD "{");
+ sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HelpText"));
+ if (xPropSetInfo->hasPropertyByName(sName))
+ {
+ xPropSet->getPropertyValue(sName) >>= aTmp;
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ");
+ m_aRun.append(OUStringToOString(aTmp, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ }
+
+ sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HelpF1Text"));
+ if (xPropSetInfo->hasPropertyByName(sName))
+ {
+ xPropSet->getPropertyValue(sName) >>= aTmp;
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ");
+ m_aRun.append(OUStringToOString(aTmp, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ }
+ m_aRun.append("}");
+ }
+ else if (xInfo->supportsService(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.form.component.ListBox"))))
+ {
+ OUString aStr;
+ uno::Sequence<sal_Int16> aIntSeq;
+ uno::Sequence<OUString> aStrSeq;
+
+ m_aRun.append(OUStringToOString(OUString(FieldString(ww::eFORMDROPDOWN)), m_rExport.eCurrentEncoding));
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD "{");
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFTYPE "2"); // 2 = list
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFHASLISTBOX);
+
+ xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DefaultSelection"))) >>= aIntSeq;
+ if( aIntSeq.getLength() )
+ {
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFDEFRES);
+ // a dropdown list can have only one 'selected item by default'
+ m_aRun.append((sal_Int32)aIntSeq[0]);
+ }
+
+ xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SelectedItems"))) >>= aIntSeq;
+ if( aIntSeq.getLength() )
+ {
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFRES);
+ // a dropdown list can have only one 'currently selected item'
+ m_aRun.append((sal_Int32)aIntSeq[0]);
+ }
+
+ sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name"));
+ if (xPropSetInfo->hasPropertyByName(sName))
+ {
+ xPropSet->getPropertyValue(sName) >>= aStr;
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME " ");
+ m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ }
+
+ sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HelpText"));
+ if (xPropSetInfo->hasPropertyByName(sName))
+ {
+ xPropSet->getPropertyValue(sName) >>= aStr;
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNHELP);
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ");
+ m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ }
+
+ sName = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HelpF1Text"));
+ if (xPropSetInfo->hasPropertyByName(sName))
+ {
+ xPropSet->getPropertyValue(sName) >>= aStr;
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FFOWNSTAT);
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ");
+ m_aRun.append(OUStringToOString(aStr, m_rExport.eCurrentEncoding));
+ m_aRun.append('}');
+ }
+
+
+ xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("StringItemList"))) >>= aStrSeq;
+ sal_uInt32 nListItems = aStrSeq.getLength();
+ for (sal_uInt32 i = 0; i < nListItems; i++)
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFL " ")
+ .append(OUStringToOString(aStrSeq[i], m_rExport.eCurrentEncoding)).append('}');
+
+ m_aRun.append("}}");
+
+ // field result is empty, ffres already contains the form result
+ m_aRun.append("}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
+ }
+ else
+ OSL_TRACE("%s unhandled form control: '%s'", OSL_THIS_FUNC,
+ OUStringToOString(xInfo->getImplementationName(), m_rExport.eCurrentEncoding).getStr());
+ m_aRun.append('}');
+ }
+ }
+
+ m_aRun.append('}');
+ }
+ break;
+ case sw::Frame::eOle:
+ {
+ const SwFrmFmt &rFrmFmt = rFrame.GetFrmFmt();
+ const SdrObject *pSdrObj = rFrmFmt.FindRealSdrObject();
+ if ( pSdrObj )
+ {
+ SwNodeIndex aIdx(*rFrmFmt.GetCntnt().GetCntntIdx(), 1);
+ SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
+ FlyFrameOLE(dynamic_cast<const SwFlyFrmFmt*>( &rFrmFmt ), rOLENd, rFrame.GetLayoutSize());
+ }
+ }
+ break;
+ default:
+ OSL_TRACE("%s: unknown type (%d)", OSL_THIS_FUNC, rFrame.GetWriterType());
+ break;
+ }
+}
+
+void RtfAttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ switch ( rCaseMap.GetValue() )
+ {
+ case SVX_CASEMAP_KAPITAELCHEN:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SCAPS);
+ break;
+ case SVX_CASEMAP_VERSALIEN:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CAPS);
+ break;
+ default: // Something that rtf does not support
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SCAPS);
+ m_aStyles.append((sal_Int32)0);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CAPS);
+ m_aStyles.append((sal_Int32)0);
+ break;
+ }
+}
+
+void RtfAttributeOutput::CharColor( const SvxColorItem& rColor )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const Color aColor( rColor.GetValue() );
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CF);
+ m_aStyles.append( (sal_Int32)m_rExport.GetColor( aColor ));
+}
+
+void RtfAttributeOutput::CharContour( const SvxContourItem& rContour )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_OUTL);
+ if ( !rContour.GetValue() )
+ m_aStyles.append((sal_Int32)0);
+}
+
+void RtfAttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossedOut )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ switch ( rCrossedOut.GetStrikeout() )
+ {
+ case STRIKEOUT_NONE:
+ if (!m_bStrikeDouble)
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKE);
+ else
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKED);
+ m_aStyles.append((sal_Int32)0);
+ break;
+ case STRIKEOUT_DOUBLE:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKED);
+ m_aStyles.append((sal_Int32)1);
+ break;
+ default:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_STRIKE);
+ break;
+ }
+}
+
+void RtfAttributeOutput::CharEscapement( const SvxEscapementItem& rEsc )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const char * pUpDn;
+
+ SwTwips nH = ((SvxFontHeightItem&)m_rExport.GetItem( RES_CHRATR_FONTSIZE )).GetHeight();
+
+ if( 0 < rEsc.GetEsc() )
+ pUpDn = OOO_STRING_SVTOOLS_RTF_UP;
+ else if( 0 > rEsc.GetEsc() )
+ {
+ pUpDn = OOO_STRING_SVTOOLS_RTF_DN;
+ nH = -nH;
+ }
+ else
+ return;
+
+ short nEsc = rEsc.GetEsc();
+ short nProp = rEsc.GetProp() * 100;
+ if( DFLT_ESC_AUTO_SUPER == nEsc )
+ {
+ nEsc = 100 - rEsc.GetProp();
+ ++nProp;
+ }
+ else if( DFLT_ESC_AUTO_SUB == nEsc )
+ {
+ nEsc = - 100 + rEsc.GetProp();
+ ++nProp;
+ }
+
+ m_aStyles.append('{');
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_UPDNPROP);
+ m_aStyles.append( (sal_Int32)nProp );
+ m_aStyles.append('}');
+ m_aStyles.append(pUpDn);
+
+ /*
+ * Calculate the act. FontSize and the percentage of the displacement;
+ * RTF file expects half points, while internally it's in twips.
+ * Formally : (FontSize * 1/20 ) pts x * 2
+ * ----------------------- = ------------
+ * 100% Escapement
+ */
+
+ m_aStyles.append( (sal_Int32) ( (long( nEsc ) * nH) + 500L ) / 1000L );
+ // 500L to round !!
+}
+
+void RtfAttributeOutput::CharFont( const SvxFontItem& rFont)
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LOCH);
+ m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_F);
+ m_aStylesEnd.append((sal_Int32)m_rExport.maFontHelper.GetId(rFont));
+ m_rExport.eCurrentEncoding = rtl_getTextEncodingFromWindowsCharset(sw::ms::rtl_TextEncodingToWinCharset(rFont.GetCharSet()));
+}
+
+void RtfAttributeOutput::CharFontSize( const SvxFontHeightItem& rFontSize)
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ switch ( rFontSize.Which() )
+ {
+ case RES_CHRATR_FONTSIZE:
+ m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_FS);
+ m_aStylesEnd.append((sal_Int32)(rFontSize.GetHeight() / 10 ));
+ break;
+ case RES_CHRATR_CJK_FONTSIZE:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FS);
+ m_aStyles.append((sal_Int32)(rFontSize.GetHeight() / 10 ));
+ break;
+ case RES_CHRATR_CTL_FONTSIZE:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AFS);
+ m_aStyles.append((sal_Int32)(rFontSize.GetHeight() / 10 ));
+ break;
+ }
+}
+
+void RtfAttributeOutput::CharKerning( const SvxKerningItem& rKerning )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // in quater points then in twips
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_EXPND);
+ m_aStyles.append((sal_Int32)(rKerning.GetValue() / 5));
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_EXPNDTW);
+ m_aStyles.append((sal_Int32)(rKerning.GetValue()));
+}
+
+void RtfAttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ switch (rLanguage.Which())
+ {
+ case RES_CHRATR_LANGUAGE:
+ m_aStylesEnd.append(OOO_STRING_SVTOOLS_RTF_LANG);
+ m_aStylesEnd.append((sal_Int32)rLanguage.GetLanguage());
+ break;
+ case RES_CHRATR_CJK_LANGUAGE:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LANGFE);
+ m_aStyles.append((sal_Int32)rLanguage.GetLanguage());
+ break;
+ case RES_CHRATR_CTL_LANGUAGE:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LANG);
+ m_aStyles.append((sal_Int32)rLanguage.GetLanguage());
+ break;
+ }
+}
+
+void RtfAttributeOutput::CharPosture( const SvxPostureItem& rPosture )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_I);
+ if ( rPosture.GetPosture() == ITALIC_NONE )
+ m_aStyles.append((sal_Int32)0);
+}
+
+void RtfAttributeOutput::CharShadow( const SvxShadowedItem& rShadow )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SHAD);
+ if ( !rShadow.GetValue() )
+ m_aStyles.append((sal_Int32)0);
+}
+
+void RtfAttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const char* pStr = 0;
+ const SfxPoolItem* pItem = m_rExport.HasItem( RES_CHRATR_WORDLINEMODE );
+ bool bWord = false;
+ if (pItem)
+ bWord = ((const SvxWordLineModeItem*)pItem)->GetValue() ? true : false;
+ switch(rUnderline.GetLineStyle() )
+ {
+ case UNDERLINE_SINGLE:
+ pStr = bWord ? OOO_STRING_SVTOOLS_RTF_ULW : OOO_STRING_SVTOOLS_RTF_UL;
+ break;
+ case UNDERLINE_DOUBLE:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULDB;
+ break;
+ case UNDERLINE_NONE:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULNONE;
+ break;
+ case UNDERLINE_DOTTED:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULD;
+ break;
+ case UNDERLINE_DASH:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULDASH;
+ break;
+ case UNDERLINE_DASHDOT:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULDASHD;
+ break;
+ case UNDERLINE_DASHDOTDOT:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULDASHDD;
+ break;
+ case UNDERLINE_BOLD:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULTH;
+ break;
+ case UNDERLINE_WAVE:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULWAVE;
+ break;
+ case UNDERLINE_BOLDDOTTED:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULTHD;
+ break;
+ case UNDERLINE_BOLDDASH:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULTHDASH;
+ break;
+ case UNDERLINE_LONGDASH:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULLDASH;
+ break;
+ case UNDERLINE_BOLDLONGDASH:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULTHLDASH;
+ break;
+ case UNDERLINE_BOLDDASHDOT:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULTHDASHD;
+ break;
+ case UNDERLINE_BOLDDASHDOTDOT:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULTHDASHDD;
+ break;
+ case UNDERLINE_BOLDWAVE:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULHWAVE;
+ break;
+ case UNDERLINE_DOUBLEWAVE:
+ pStr = OOO_STRING_SVTOOLS_RTF_ULULDBWAVE;
+ break;
+ default:
+ break;
+ }
+
+ if( pStr )
+ {
+ m_aStyles.append(pStr);
+ // NEEDSWORK looks like here rUnderline.GetColor() is always black,
+ // even if the color in the odt is for example green...
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ULC);
+ m_aStyles.append( (sal_Int32)m_rExport.GetColor(rUnderline.GetColor()) );
+ }
+}
+
+void RtfAttributeOutput::CharWeight( const SvxWeightItem& rWeight )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_B);
+ if ( rWeight.GetWeight() != WEIGHT_BOLD )
+ m_aStyles.append((sal_Int32)0);
+}
+
+void RtfAttributeOutput::CharAutoKern( const SvxAutoKernItem& rAutoKern)
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KERNING);
+ m_aStyles.append((sal_Int32) (rAutoKern.GetValue() ? 1 : 0));
+}
+
+void RtfAttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ANIMTEXT);
+ m_aStyles.append((sal_Int32) (rBlink.GetValue() ? 2 : 0));
+}
+
+void RtfAttributeOutput::CharBackground( const SvxBrushItem& rBrush )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if( !rBrush.GetColor().GetTransparency() )
+ {
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CHCBPAT);
+ m_aStyles.append((sal_Int32)m_rExport.GetColor(rBrush.GetColor()));
+ }
+}
+
+void RtfAttributeOutput::CharFontCJK( const SvxFontItem& rFont )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HICH);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AF);
+ m_aStyles.append((sal_Int32)m_rExport.maFontHelper.GetId(rFont));
+}
+
+void RtfAttributeOutput::CharFontSizeCJK( const SvxFontHeightItem& rFontSize )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ CharFontSize( rFontSize );
+}
+
+void RtfAttributeOutput::CharLanguageCJK( const SvxLanguageItem& rLanguageItem )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ CharLanguage( rLanguageItem );
+}
+
+void RtfAttributeOutput::CharPostureCJK( const SvxPostureItem& rPosture )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_I);
+ if ( rPosture.GetPosture() == ITALIC_NONE )
+ m_aStyles.append((sal_Int32)0);
+}
+
+void RtfAttributeOutput::CharWeightCJK( const SvxWeightItem& rWeight )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_B);
+ if ( rWeight.GetWeight() != WEIGHT_BOLD )
+ m_aStyles.append((sal_Int32)0);
+}
+
+void RtfAttributeOutput::CharFontCTL( const SvxFontItem& rFont )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_DBCH);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AF);
+ m_aStyles.append((sal_Int32)m_rExport.maFontHelper.GetId(rFont));
+}
+
+void RtfAttributeOutput::CharFontSizeCTL( const SvxFontHeightItem& rFontSize )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ CharFontSize( rFontSize );
+}
+
+void RtfAttributeOutput::CharLanguageCTL( const SvxLanguageItem& rLanguageItem )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ CharLanguage( rLanguageItem );
+}
+
+void RtfAttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture)
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AI);
+ if ( rPosture.GetPosture() == ITALIC_NONE )
+ m_aStyles.append((sal_Int32)0);
+}
+
+void RtfAttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_AB);
+ if ( rWeight.GetWeight() != WEIGHT_BOLD )
+ m_aStyles.append((sal_Int32)0);
+}
+
+void RtfAttributeOutput::CharRotate( const SvxCharRotateItem& rRotate)
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HORZVERT);
+ m_aStyles.append((sal_Int32)(rRotate.IsFitToLine() ? 1 : 0));
+}
+
+void RtfAttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const sal_Char* pStr;
+ switch( rEmphasisMark.GetEmphasisMark())
+ {
+ case EMPHASISMARK_NONE: pStr = OOO_STRING_SVTOOLS_RTF_ACCNONE; break;
+ case EMPHASISMARK_SIDE_DOTS: pStr = OOO_STRING_SVTOOLS_RTF_ACCCOMMA; break;
+ default: pStr = OOO_STRING_SVTOOLS_RTF_ACCDOT; break;
+ }
+ m_aStyles.append(pStr);
+}
+
+void RtfAttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if( rTwoLines.GetValue() )
+ {
+ sal_Unicode cStart = rTwoLines.GetStartBracket();
+ sal_Unicode cEnd = rTwoLines.GetEndBracket();
+
+ sal_uInt16 nType;
+ if( !cStart && !cEnd )
+ nType = 0;
+ else if( '{' == cStart || '}' == cEnd )
+ nType = 4;
+ else if( '<' == cStart || '>' == cEnd )
+ nType = 3;
+ else if( '[' == cStart || ']' == cEnd )
+ nType = 2;
+ else // all other kind of brackets
+ nType = 1;
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TWOINONE);
+ m_aStyles.append((sal_Int32)nType);
+ }
+}
+
+void RtfAttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CHARSCALEX);
+ m_aStyles.append((sal_Int32)rScaleWidth.GetValue());
+}
+
+void RtfAttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const sal_Char* pStr;
+ switch (rRelief.GetValue())
+ {
+ case RELIEF_EMBOSSED:
+ pStr = OOO_STRING_SVTOOLS_RTF_EMBO;
+ break;
+ case RELIEF_ENGRAVED:
+ pStr = OOO_STRING_SVTOOLS_RTF_IMPR;
+ break;
+ default:
+ pStr = 0;
+ break;
+ }
+
+ if (pStr)
+ m_aStyles.append(pStr);
+}
+
+void RtfAttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_V);
+ if ( !rHidden.GetValue() )
+ m_aStyles.append((sal_Int32)0);
+}
+
+void RtfAttributeOutput::TextINetFormat( const SwFmtINetFmt& rURL )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if( rURL.GetValue().Len() )
+ {
+ const SwCharFmt* pFmt;
+ const SwTxtINetFmt* pTxtAtr = rURL.GetTxtINetFmt();
+
+ m_aStyles.append("{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " ");
+ if( pTxtAtr && 0 != ( pFmt = pTxtAtr->GetCharFmt() ))
+ {
+ sal_uInt16 nStyle = m_rExport.GetId( *pFmt );
+ OString* pString = m_rExport.GetStyle(nStyle);
+ if (pString)
+ m_aStyles.append(*pString);
+ }
+ }
+}
+
+void RtfAttributeOutput::TextCharFormat( const SwFmtCharFmt& rCharFmt )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ sal_uInt16 nStyle = m_rExport.GetId( *rCharFmt.GetCharFmt() );
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_CS);
+ m_aStyles.append((sal_Int32)nStyle);
+ OString* pString = m_rExport.GetStyle(nStyle);
+ if (pString)
+ m_aStyles.append(*pString);
+}
+
+void RtfAttributeOutput::WriteTextFootnoteNumStr(const SwFmtFtn& rFootnote)
+{
+ if (!rFootnote.GetNumStr().Len())
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_CHFTN);
+ else
+ m_aRun.append(m_rExport.OutString(rFootnote.GetNumStr(), m_rExport.eCurrentEncoding));
+}
+
+void RtfAttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFootnote )
+{
+ OSL_TRACE("%s start", OSL_THIS_FUNC);
+
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_SUPER " ");
+ WriteTextFootnoteNumStr(rFootnote);
+ m_aRun.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FOOTNOTE);
+ if( rFootnote.IsEndNote() )
+ m_aRun.append(OOO_STRING_SVTOOLS_RTF_FTNALT);
+ m_aRun.append(' ');
+ WriteTextFootnoteNumStr(rFootnote);
+
+ /*
+ * The footnote contains a whole paragraph, so we have to:
+ * 1) Reset, then later restore the contents of our run buffer.
+ * 2) Buffer the output of the whole paragraph, as we do so for section headers already.
+ */
+ const SwNodeIndex* pIndex = rFootnote.GetTxtFtn()->GetStartNode();
+ OStringBuffer aRun = m_aRun;
+ m_aRun.setLength(0);
+ m_bBufferSectionHeaders = true;
+ m_rExport.WriteSpecialText( pIndex->GetIndex() + 1,
+ pIndex->GetNode().EndOfSectionIndex(),
+ !rFootnote.IsEndNote() ? TXT_FTN : TXT_EDN);
+ m_bBufferSectionHeaders = false;
+ m_aRun = aRun;
+ m_aRun.append(m_aSectionHeaders.makeStringAndClear());
+
+ m_aRun.append("}");
+ m_aRun.append("}");
+
+ OSL_TRACE("%s end", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SL);
+ m_aStyles.append((sal_Int32)nSpace);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SLMULT);
+ m_aStyles.append((sal_Int32)nMulti);
+
+}
+
+void RtfAttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ switch ( rAdjust.GetAdjust() )
+ {
+ case SVX_ADJUST_LEFT:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QL);
+ break;
+ case SVX_ADJUST_RIGHT:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QR);
+ break;
+ case SVX_ADJUST_BLOCKLINE:
+ case SVX_ADJUST_BLOCK:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QJ);
+ break;
+ case SVX_ADJUST_CENTER:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_QC);
+ break;
+ default:
+ break;
+ }
+}
+
+void RtfAttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if( !rSplit.GetValue() )
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KEEP);
+}
+
+void RtfAttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if (rWidows.GetValue())
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_WIDCTLPAR);
+ else
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOWIDCTLPAR);
+}
+
+void RtfAttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStop )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ long nOffset = ((SvxLRSpaceItem&)m_rExport.GetItem( RES_LR_SPACE )).GetTxtLeft();
+ for( sal_uInt16 n = 0; n < rTabStop.Count(); n++ )
+ {
+ const SvxTabStop & rTS = rTabStop[ n ];
+ if( SVX_TAB_ADJUST_DEFAULT != rTS.GetAdjustment() )
+ {
+ const char* pFill = 0;
+ switch( rTS.GetFill() )
+ {
+ case cDfltFillChar:
+ break;
+
+ case '.': pFill = OOO_STRING_SVTOOLS_RTF_TLDOT; break;
+ case '_': pFill = OOO_STRING_SVTOOLS_RTF_TLUL; break;
+ case '-': pFill = OOO_STRING_SVTOOLS_RTF_TLTH; break;
+ case '=': pFill = OOO_STRING_SVTOOLS_RTF_TLEQ; break;
+ default:
+ break;
+ }
+ if( pFill )
+ m_aStyles.append(pFill);
+
+ const sal_Char* pAdjStr = 0;
+ switch (rTS.GetAdjustment())
+ {
+ case SVX_TAB_ADJUST_RIGHT:
+ pAdjStr = OOO_STRING_SVTOOLS_RTF_TQR;
+ break;
+ case SVX_TAB_ADJUST_DECIMAL:
+ pAdjStr = OOO_STRING_SVTOOLS_RTF_TQDEC;
+ break;
+ case SVX_TAB_ADJUST_CENTER:
+ pAdjStr = OOO_STRING_SVTOOLS_RTF_TQC;
+ break;
+ default:
+ break;
+ }
+ if (pAdjStr)
+ m_aStyles.append(pAdjStr);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TX);
+ m_aStyles.append((sal_Int32)(rTS.GetTabPos() + nOffset));
+ }
+ else
+ {
+ m_aTabStop.append( OOO_STRING_SVTOOLS_RTF_DEFTAB );
+ m_aTabStop.append( (sal_Int32)rTabStop[0].GetTabPos() );
+ }
+ }
+}
+
+void RtfAttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ sal_Int32 nFlags = rHyphenZone.IsHyphen() ? 1 : 0;
+ if( rHyphenZone.IsPageEnd() )
+ nFlags += 2;
+ m_aStyles.append('{');
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_IGNORE);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHEN);
+ m_aStyles.append((sal_Int32)nFlags);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHLEAD);
+ m_aStyles.append((sal_Int32)rHyphenZone.GetMinLead());
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHTRAIL);
+ m_aStyles.append((sal_Int32)rHyphenZone.GetMinTrail());
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_HYPHMAX);
+ m_aStyles.append((sal_Int32)rHyphenZone.GetMaxHyphens());
+ m_aStyles.append('}');
+}
+
+void RtfAttributeOutput::ParaNumRule_Impl( const SwTxtNode* pTxtNd, sal_Int32 nLvl, sal_Int32 nNumId )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( USHRT_MAX == nNumId || 0 == nNumId || 0 == pTxtNd)
+ return;
+
+ const SwNumRule* pRule = pTxtNd->GetNumRule();
+
+ if( pRule && pTxtNd->IsInList() )
+ {
+ OSL_ENSURE( pTxtNd->GetActualListLevel() >= 0 && pTxtNd->GetActualListLevel() < MAXLEVEL,
+ "<SwRTFWriter::OutListNum(..)> - text node does not have valid list level. Serious defect -> please inform OD" );
+
+ const bool bExportNumRule = USHRT_MAX != nNumId;
+ const SwNumFmt* pFmt = pRule->GetNumFmt( nLvl );
+ if( !pFmt )
+ pFmt = &pRule->Get( nLvl );
+
+ const SfxItemSet& rNdSet = pTxtNd->GetSwAttrSet();
+
+ if ( bExportNumRule ) {
+ m_aStyles.append('{');
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LISTTEXT);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_PARD);
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_PLAIN);
+ m_aStyles.append(' ');
+ }
+
+ SvxLRSpaceItem aLR( (SvxLRSpaceItem&)rNdSet.Get( RES_LR_SPACE ) );
+ aLR.SetTxtLeft( aLR.GetTxtLeft() + pFmt->GetIndentAt() );
+ aLR.SetTxtFirstLineOfst( pFmt->GetFirstLineOffset() );
+
+ sal_uInt16 nStyle = m_rExport.GetId( *pFmt->GetCharFmt() );
+ OString* pString = m_rExport.GetStyle(nStyle);
+ if (pString)
+ m_aStyles.append(*pString);
+
+ {
+ String sTxt;
+ if( SVX_NUM_CHAR_SPECIAL == pFmt->GetNumberingType() || SVX_NUM_BITMAP == pFmt->GetNumberingType() )
+ sTxt = pFmt->GetBulletChar();
+ else
+ sTxt = pTxtNd->GetNumString();
+
+ m_aStyles.append(' ');
+
+ if (sTxt.Len())
+ {
+ m_aStyles.append(m_rExport.OutString(sTxt, m_rExport.eDefaultEncoding));
+ }
+
+ if( bExportNumRule )
+ {
+ if( OUTLINE_RULE != pRule->GetRuleType() )
+ {
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB);
+ m_aStyles.append('}');
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ILVL);
+ if( nLvl > 8 ) // RTF knows only 9 levels
+ {
+ m_aStyles.append((sal_Int32)8);
+ m_aStyles.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SOUTLVL);
+ m_aStyles.append((sal_Int32)nLvl);
+ m_aStyles.append('}');
+ }
+ else
+ m_aStyles.append((sal_Int32)nLvl);
+ }
+ else
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB "}");
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LS);
+ m_aStyles.append((sal_Int32)m_rExport.GetId(*pRule)+1);
+ m_aStyles.append(' ');
+ }
+ else if( sTxt.Len() )
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_TAB);
+ }
+ FormatLRSpace(aLR);
+ }
+}
+
+void RtfAttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if (!rScriptSpace.GetValue( ))
+ return;
+ switch ( rScriptSpace.Which( ) )
+ {
+ case RES_PARATR_SCRIPTSPACE:
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_ASPALPHA);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void RtfAttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const char* pStr;
+ switch ( rAlign.GetValue() )
+ {
+ case SvxParaVertAlignItem::TOP: pStr = OOO_STRING_SVTOOLS_RTF_FAHANG; break;
+ case SvxParaVertAlignItem::BOTTOM: pStr = OOO_STRING_SVTOOLS_RTF_FAVAR; break;
+ case SvxParaVertAlignItem::CENTER: pStr = OOO_STRING_SVTOOLS_RTF_FACENTER; break;
+ case SvxParaVertAlignItem::BASELINE: pStr = OOO_STRING_SVTOOLS_RTF_FAROMAN; break;
+
+ default: pStr = OOO_STRING_SVTOOLS_RTF_FAAUTO; break;
+ }
+ m_aStyles.append(pStr);
+}
+
+void RtfAttributeOutput::ParaSnapToGrid( const SvxParaGridItem& /*rGrid*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
+ {
+ if( rSize.GetWidth() )
+ {
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_ABSW);
+ m_aRunText.append((sal_Int32)rSize.GetWidth());
+ }
+
+ if( rSize.GetHeight() )
+ {
+ long nH = rSize.GetHeight();
+ if( ATT_FIX_SIZE == rSize.GetHeightSizeType() )
+ nH = -nH;
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_ABSH);
+ m_aRunText.append((sal_Int32)nH);
+ }
+ }
+ else if (m_rExport.bOutPageDescs)
+ {
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGWSXN);
+ m_aSectionBreaks.append((sal_Int32)rSize.GetWidth());
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_PGHSXN);
+ m_aSectionBreaks.append((sal_Int32)rSize.GetHeight());
+ if (!m_bBufferSectionBreaks)
+ m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
+ }
+}
+
+void RtfAttributeOutput::FormatPaperBin( const SvxPaperBinItem& )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLRSpace )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( !m_rExport.bOutFlyFrmAttrs )
+ {
+ if( m_rExport.bOutPageDescs )
+ {
+ if( rLRSpace.GetLeft() )
+ {
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGLSXN);
+ m_aSectionBreaks.append((sal_Int32)rLRSpace.GetLeft());
+ }
+ if( rLRSpace.GetRight() )
+ {
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGRSXN);
+ m_aSectionBreaks.append((sal_Int32)rLRSpace.GetRight());
+ }
+ if (!m_bBufferSectionBreaks)
+ m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
+ }
+ else
+ {
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LI);
+ m_aStyles.append( (sal_Int32) rLRSpace.GetTxtLeft() );
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RI);
+ m_aStyles.append( (sal_Int32) rLRSpace.GetRight() );
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LIN);
+ m_aStyles.append( (sal_Int32) rLRSpace.GetTxtLeft() );
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RIN);
+ m_aStyles.append( (sal_Int32) rLRSpace.GetRight() );
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_FI);
+ m_aStyles.append( (sal_Int32) rLRSpace.GetTxtFirstLineOfst() );
+ }
+ }
+ else if (rLRSpace.GetLeft() == rLRSpace.GetRight() && m_rExport.bRTFFlySyntax)
+ {
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_DFRMTXTX;
+ m_rExport.OutLong( rLRSpace.GetLeft() );
+ }
+}
+
+void RtfAttributeOutput::FormatULSpace( const SvxULSpaceItem& rULSpace )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( !m_rExport.bOutFlyFrmAttrs )
+ {
+ if( m_rExport.bOutPageDescs )
+ {
+ OSL_ENSURE( m_rExport.GetCurItemSet(), "Impossible" );
+ if ( !m_rExport.GetCurItemSet() )
+ return;
+
+ HdFtDistanceGlue aDistances( *m_rExport.GetCurItemSet() );
+
+ if ( aDistances.HasHeader() )
+ {
+ if( aDistances.dyaTop )
+ {
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGTSXN);
+ m_aSectionBreaks.append((sal_Int32)aDistances.dyaTop);
+ }
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_HEADERY);
+ m_aSectionBreaks.append((sal_Int32)aDistances.dyaHdrTop);
+ }
+
+ if( aDistances.HasFooter() )
+ {
+ if( aDistances.dyaBottom )
+ {
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_MARGBSXN);
+ m_aSectionBreaks.append((sal_Int32)aDistances.dyaBottom);
+ }
+ m_aSectionBreaks.append(OOO_STRING_SVTOOLS_RTF_FOOTERY);
+ m_aSectionBreaks.append((sal_Int32)aDistances.dyaHdrBottom);
+ }
+ if (!m_bBufferSectionBreaks)
+ m_rExport.Strm() << m_aSectionBreaks.makeStringAndClear();
+ }
+ else
+ {
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SB);
+ m_aStyles.append( (sal_Int32) rULSpace.GetUpper() );
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_SA);
+ m_aStyles.append( (sal_Int32) rULSpace.GetLower() );
+ }
+ }
+ else if (rULSpace.GetUpper() == rULSpace.GetLower() && m_rExport.bRTFFlySyntax)
+ {
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_DFRMTXTY;
+ m_rExport.OutLong( rULSpace.GetLower() );
+ }
+}
+
+void RtfAttributeOutput::FormatSurround( const SwFmtSurround& rSurround )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( m_rExport.bOutFlyFrmAttrs && !m_rExport.bRTFFlySyntax )
+ {
+ SwSurround eSurround = rSurround.GetSurround();
+ sal_Bool bGold = SURROUND_IDEAL == eSurround;
+ if( bGold )
+ eSurround = SURROUND_PARALLEL;
+ RTFSurround aMC( bGold, static_cast< sal_uInt8 >(eSurround) );
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYMAINCNT);
+ m_aRunText.append( (sal_Int32) aMC.GetValue() );
+ }
+}
+
+void RtfAttributeOutput::FormatVertOrientation( const SwFmtVertOrient& rFlyVert )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
+ {
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_PVPARA);
+
+ switch (rFlyVert.GetVertOrient())
+ {
+ case text::VertOrientation::TOP:
+ case text::VertOrientation::LINE_TOP:
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYT);
+ break;
+ case text::VertOrientation::BOTTOM:
+ case text::VertOrientation::LINE_BOTTOM:
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYB);
+ break;
+ case text::VertOrientation::CENTER:
+ case text::VertOrientation::LINE_CENTER:
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSYC);
+ break;
+ case text::VertOrientation::NONE:
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSY);
+ m_aRunText.append((sal_Int32)rFlyVert.GetPos());
+ break;
+ default:
+ break;
+ }
+ }
+ else if ( !m_rExport.bRTFFlySyntax )
+ {
+ RTFVertOrient aVO( static_cast< sal_uInt16 >(rFlyVert.GetVertOrient()), static_cast< sal_uInt16 >(rFlyVert.GetRelationOrient()) );
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYVERT);
+ m_aRunText.append((sal_Int32)aVO.GetValue());
+ }
+}
+
+void RtfAttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& rFlyHori )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( m_rExport.bOutFlyFrmAttrs && m_rExport.bRTFFlySyntax )
+ {
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_PHCOL);
+
+ const char* pS = 0;
+ switch(rFlyHori.GetHoriOrient())
+ {
+ case text::HoriOrientation::RIGHT:
+ pS = rFlyHori.IsPosToggle() ? OOO_STRING_SVTOOLS_RTF_POSXO : OOO_STRING_SVTOOLS_RTF_POSXR;
+ break;
+ case text::HoriOrientation::LEFT:
+ pS = rFlyHori.IsPosToggle() ? OOO_STRING_SVTOOLS_RTF_POSXI : OOO_STRING_SVTOOLS_RTF_POSXL;
+ break;
+ case text::HoriOrientation::CENTER:
+ pS = OOO_STRING_SVTOOLS_RTF_POSXC;
+ break;
+ case text::HoriOrientation::NONE:
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_POSX);
+ m_aRunText.append((sal_Int32)rFlyHori.GetPos());
+ break;
+ default:
+ break;
+ }
+ if (pS)
+ m_aRunText.append(pS);
+ } else if ( !m_rExport.bRTFFlySyntax )
+ {
+ RTFHoriOrient aHO( static_cast< sal_uInt16 >(rFlyHori.GetHoriOrient()),
+ static_cast< sal_uInt16 >(rFlyHori.GetRelationOrient()) );
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYHORZ);
+ m_aRunText.append((sal_Int32)aHO.GetValue());
+ }
+}
+
+void RtfAttributeOutput::FormatAnchor( const SwFmtAnchor& rAnchor )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( !m_rExport.bRTFFlySyntax )
+ {
+ sal_uInt16 nId = static_cast< sal_uInt16 >(rAnchor.GetAnchorId());
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYANCHOR);
+ m_aRunText.append((sal_Int32)nId);
+ switch( nId )
+ {
+ case FLY_AT_PAGE:
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYPAGE);
+ m_aRunText.append((sal_Int32)rAnchor.GetPageNum());
+ break;
+ case FLY_AT_PARA:
+ case FLY_AS_CHAR:
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_FLYCNTNT);
+ break;
+ }
+ }
+}
+
+void RtfAttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if( !rBrush.GetColor().GetTransparency() )
+ {
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_CBPAT);
+ m_aStyles.append((sal_Int32)m_rExport.GetColor(rBrush.GetColor()));
+ }
+}
+
+void RtfAttributeOutput::FormatBox( const SvxBoxItem& rBox )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ static sal_uInt16 aBorders[] = {
+ BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT };
+ static const sal_Char* aBorderNames[] = {
+ OOO_STRING_SVTOOLS_RTF_BRDRT, OOO_STRING_SVTOOLS_RTF_BRDRL, OOO_STRING_SVTOOLS_RTF_BRDRB, OOO_STRING_SVTOOLS_RTF_BRDRR };
+
+ sal_uInt16 nDist = rBox.GetDistance();
+
+ if ( m_rExport.bRTFFlySyntax )
+ return;
+
+ if( rBox.GetTop() && rBox.GetBottom() &&
+ rBox.GetLeft() && rBox.GetRight() &&
+ *rBox.GetTop() == *rBox.GetBottom() &&
+ *rBox.GetTop() == *rBox.GetLeft() &&
+ *rBox.GetTop() == *rBox.GetRight() &&
+ nDist == rBox.GetDistance( BOX_LINE_TOP ) &&
+ nDist == rBox.GetDistance( BOX_LINE_LEFT ) &&
+ nDist == rBox.GetDistance( BOX_LINE_BOTTOM ) &&
+ nDist == rBox.GetDistance( BOX_LINE_RIGHT ))
+ m_aSectionBreaks.append(OutBorderLine( m_rExport, rBox.GetTop(), OOO_STRING_SVTOOLS_RTF_BOX, nDist ));
+ else
+ {
+ const sal_uInt16* pBrd = aBorders;
+ const sal_Char** pBrdNms = (const sal_Char**)aBorderNames;
+ for(int i = 0; i < 4; ++i, ++pBrd, ++pBrdNms)
+ {
+ if (const SvxBorderLine* pLn = rBox.GetLine(*pBrd))
+ {
+ m_aSectionBreaks.append(OutBorderLine(m_rExport, pLn, *pBrdNms,
+ rBox.GetDistance(*pBrd)));
+ }
+ }
+ }
+
+ if (!m_bBufferSectionBreaks)
+ m_aStyles.append(m_aSectionBreaks.makeStringAndClear());
+}
+
+void RtfAttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol& rCol, bool bEven, SwTwips nPageSize )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLS;
+ m_rExport.OutLong( nCols );
+
+ if( bEven )
+ {
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLSX;
+ m_rExport.OutLong( rCol.GetGutterWidth( sal_True ) );
+ }
+ else
+ {
+ const SwColumns & rColumns = rCol.GetColumns( );
+ for( sal_uInt16 n = 0; n < nCols; )
+ {
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLNO;
+ m_rExport.OutLong( n+1 );
+
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLW;
+ m_rExport.OutLong( rCol.CalcPrtColWidth( n, nPageSize ) );
+
+ if( ++n != nCols )
+ {
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_COLSR;
+ m_rExport.OutLong( rColumns[ n-1 ]->GetRight() +
+ rColumns[ n ]->GetLeft() );
+ }
+ }
+ }
+}
+
+void RtfAttributeOutput::FormatKeep( const SvxFmtKeepItem& rItem )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if( rItem.GetValue() )
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_KEEPN);
+}
+
+void RtfAttributeOutput::FormatTextGrid( const SwTextGridItem& /*rGrid*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( !rNumbering.IsCount( ) )
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_NOLINE);
+}
+
+void RtfAttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if (!m_rExport.bOutPageDescs)
+ {
+ if (rDirection.GetValue() == FRMDIR_HORI_RIGHT_TOP)
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_RTLPAR);
+ else
+ m_aStyles.append(OOO_STRING_SVTOOLS_RTF_LTRPAR);
+ }
+}
+
+void RtfAttributeOutput::WriteExpand( const SwField* /*pFld*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::RefField( const SwField& /*rFld*/, const String& /*rRef*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::HiddenField( const SwField& /*rFld*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::SetField( const SwField& /*rFld*/, ww::eField /*eType*/, const String& /*rCmd*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfAttributeOutput::PostitField( const SwField* pFld )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ const SwPostItField& rPFld = *(SwPostItField*)pFld;
+
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNID " ");
+ m_aRunText.append(OUStringToOString(OUString(rPFld.GetPar1()), m_rExport.eCurrentEncoding));
+ m_aRunText.append("}");
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNAUTHOR " ");
+ m_aRunText.append(OUStringToOString(OUString(rPFld.GetPar1()), m_rExport.eCurrentEncoding));
+ m_aRunText.append("}");
+ m_aRunText.append(OOO_STRING_SVTOOLS_RTF_CHATN);
+
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ANNOTATION);
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_ATNDATE " ");
+ m_aRunText.append((sal_Int32)sw::ms::DateTime2DTTM(rPFld.GetDate()));
+ m_aRunText.append('}');
+ m_aRunText.append(OUStringToOString(OUString(rPFld.GetTxt()), m_rExport.eCurrentEncoding));
+ m_aRunText.append('}');
+}
+
+bool RtfAttributeOutput::DropdownField( const SwField* /*pFld*/ )
+{
+ // this is handled in OutputFlyFrame_Impl()
+ return true;
+}
+
+RtfAttributeOutput::RtfAttributeOutput( RtfExport &rExport )
+ : m_rExport( rExport ),
+ m_bStrikeDouble( false ),
+ m_pTableWrt( NULL ),
+ m_bTableCellOpen( false ),
+ m_nTableDepth( 0 ),
+ m_bTblAfterCell( false ),
+ m_nColBreakNeeded( false ),
+ m_bBufferSectionBreaks( false ),
+ m_bBufferSectionHeaders( false ),
+ m_bLastTable( true ),
+ m_bWroteCellInfo( false )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+}
+
+RtfAttributeOutput::~RtfAttributeOutput()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+}
+
+MSWordExportBase& RtfAttributeOutput::GetExport()
+{
+ return m_rExport;
+}
+
+// These are used by wwFont::WriteRtf()
+
+/// Start the font.
+void RtfAttributeOutput::StartFont( const String& rFamilyName ) const
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << OUStringToOString( OUString( rFamilyName ), m_rExport.eCurrentEncoding ).getStr();
+}
+
+/// End the font.
+void RtfAttributeOutput::EndFont() const
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << ";}";
+}
+
+/// Alternate name for the font.
+void RtfAttributeOutput::FontAlternateName( const String& rName ) const
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_FALT << ' ';
+ m_rExport.Strm() << OUStringToOString( OUString( rName ), m_rExport.eCurrentEncoding ) << '}';
+}
+
+/// Font charset.
+void RtfAttributeOutput::FontCharset( sal_uInt8 nCharSet ) const
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FCHARSET;
+ m_rExport.OutULong( nCharSet );
+ m_rExport.Strm() << ' ';
+}
+
+/// Font family.
+void RtfAttributeOutput::FontFamilyType( FontFamily eFamily, const wwFont &rFont ) const
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << '{' << OOO_STRING_SVTOOLS_RTF_F;
+
+ const char* pStr = OOO_STRING_SVTOOLS_RTF_FNIL;
+ switch (eFamily)
+ {
+ case FAMILY_ROMAN:
+ pStr = OOO_STRING_SVTOOLS_RTF_FROMAN;
+ break;
+ case FAMILY_SWISS:
+ pStr = OOO_STRING_SVTOOLS_RTF_FSWISS;
+ break;
+ case FAMILY_MODERN:
+ pStr = OOO_STRING_SVTOOLS_RTF_FMODERN;
+ break;
+ case FAMILY_SCRIPT:
+ pStr = OOO_STRING_SVTOOLS_RTF_FSCRIPT;
+ break;
+ case FAMILY_DECORATIVE:
+ pStr = OOO_STRING_SVTOOLS_RTF_FDECOR;
+ break;
+ default:
+ break;
+ }
+ m_rExport.OutULong(m_rExport.maFontHelper.GetId(rFont)) << pStr;
+}
+
+/// Font pitch.
+void RtfAttributeOutput::FontPitchType( FontPitch ePitch ) const
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_rExport.Strm() << OOO_STRING_SVTOOLS_RTF_FPRQ;
+
+ sal_uInt16 nVal = 0;
+ switch (ePitch)
+ {
+ case PITCH_FIXED:
+ nVal = 1;
+ break;
+ case PITCH_VARIABLE:
+ nVal = 2;
+ break;
+ default:
+ break;
+ }
+ m_rExport.OutULong(nVal);
+}
+
+static bool IsEMF(const sal_uInt8 *pGraphicAry, unsigned long nSize)
+{
+ if (pGraphicAry && (nSize > 0x2c ))
+ {
+ // check the magic number
+ if (
+ (pGraphicAry[0x28] == 0x20 ) && (pGraphicAry[0x29] == 0x45) &&
+ (pGraphicAry[0x2a] == 0x4d ) && (pGraphicAry[0x2b] == 0x46)
+ )
+ {
+ //emf detected
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool StripMetafileHeader(const sal_uInt8 *&rpGraphicAry, unsigned long &rSize)
+{
+ if (rpGraphicAry && (rSize > 0x22))
+ {
+ if (
+ (rpGraphicAry[0] == 0xd7) && (rpGraphicAry[1] == 0xcd) &&
+ (rpGraphicAry[2] == 0xc6) && (rpGraphicAry[3] == 0x9a)
+ )
+ { // we have to get rid of the metafileheader
+ rpGraphicAry += 22;
+ rSize -= 22;
+ return true;
+ }
+ }
+ return false;
+}
+
+static OString WriteHex(const sal_uInt8* pData, sal_uInt32 nSize, sal_uInt32 nLimit = 64)
+{
+ OStringBuffer aRet;
+
+ sal_uInt32 nBreak = 0;
+ for (sal_uInt32 i = 0; i < nSize; i++)
+ {
+ OString sNo = OString::valueOf(sal_Int32(pData[i]), 16);
+ if (sNo.getLength() < 2)
+ aRet.append('0');
+ aRet.append(sNo);
+ if (++nBreak == nLimit)
+ {
+ aRet.append(RtfExport::sNewLine);
+ nBreak = 0;
+ }
+ }
+
+ return aRet.makeStringAndClear();
+}
+
+static OString WriteHex(sal_Int32 nNum)
+{
+ return WriteHex((sal_uInt8*)&nNum, sizeof(sal_Int32));
+}
+
+static OString WriteHex(OString sString)
+{
+ OStringBuffer aRet;
+
+ aRet.append(WriteHex(sString.getLength()+1));
+ aRet.append(WriteHex((sal_uInt8*)sString.getStr(), sString.getLength()+1));
+
+ return aRet.makeStringAndClear();
+}
+
+void lcl_AppendSP( OStringBuffer& rBuffer,
+ const char cName[],
+ const ::rtl::OUString& rValue,
+ const RtfExport& rExport )
+{
+ rBuffer.append( "{" OOO_STRING_SVTOOLS_RTF_SP "{" ); // "{\sp{"
+ rBuffer.append( OOO_STRING_SVTOOLS_RTF_SN " " );//" \sn "
+ rBuffer.append( cName ); //"PropName"
+ rBuffer.append( "}{" OOO_STRING_SVTOOLS_RTF_SV " " );
+// "}{ \sv "
+ rBuffer.append( rExport.OutString( rValue, rExport.eCurrentEncoding ) );
+ rBuffer.append( "}}" );
+}
+
+static OString ExportPICT( const SwFlyFrmFmt* pFlyFrmFmt, const Size &rOrig, const Size &rRendered, const Size &rMapped,
+ const SwCropGrf &rCr, const char *pBLIPType, const sal_uInt8 *pGraphicAry,
+ unsigned long nSize, const RtfExport& rExport )
+{
+ OStringBuffer aRet;
+ bool bIsWMF = (const char *)pBLIPType == (const char *)OOO_STRING_SVTOOLS_RTF_WMETAFILE ? true : false;
+ if (pBLIPType && nSize && pGraphicAry)
+ {
+ aRet.append("{" OOO_STRING_SVTOOLS_RTF_PICT);
+
+ if( pFlyFrmFmt )
+ {
+ String sDescription = pFlyFrmFmt->GetObjDescription();
+ //write picture properties - wzDescription at first
+ //looks like: "{\*\picprop{\sp{\sn PropertyName}{\sv PropertyValue}}}"
+ aRet.append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_PICPROP );//"{\*\picprop
+ lcl_AppendSP( aRet, "wzDescription", sDescription, rExport );
+ String sName = pFlyFrmFmt->GetObjTitle();
+ lcl_AppendSP( aRet, "wzName", sName, rExport );
+ aRet.append( "}" ); //"}"
+ }
+
+ long nXCroppedSize = rOrig.Width()-(rCr.GetLeft() + rCr.GetRight());
+ long nYCroppedSize = rOrig.Height()-(rCr.GetTop() + rCr.GetBottom());
+ /* Graphic with a zero height or width, typically copied from webpages, caused crashes. */
+ if( !nXCroppedSize )
+ nXCroppedSize = 100;
+ if( !nYCroppedSize )
+ nYCroppedSize = 100;
+
+ //Given the original size and taking cropping into account
+ //first, how much has the original been scaled to get the
+ //final rendered size
+ aRet.append(OOO_STRING_SVTOOLS_RTF_PICSCALEX);
+ aRet.append((sal_Int32)((100 * rRendered.Width()) / nXCroppedSize));
+ aRet.append(OOO_STRING_SVTOOLS_RTF_PICSCALEY);
+ aRet.append((sal_Int32)((100 * rRendered.Height()) / nYCroppedSize));
+
+ aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPL);
+ aRet.append((sal_Int32)rCr.GetLeft());
+ aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPR);
+ aRet.append((sal_Int32)rCr.GetRight());
+ aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPT);
+ aRet.append((sal_Int32)rCr.GetTop());
+ aRet.append(OOO_STRING_SVTOOLS_RTF_PICCROPB);
+ aRet.append((sal_Int32)rCr.GetBottom());
+
+ aRet.append(OOO_STRING_SVTOOLS_RTF_PICW);
+ aRet.append((sal_Int32)rMapped.Width());
+ aRet.append(OOO_STRING_SVTOOLS_RTF_PICH);
+ aRet.append((sal_Int32)rMapped.Height());
+
+ aRet.append(OOO_STRING_SVTOOLS_RTF_PICWGOAL);
+ aRet.append((sal_Int32)rOrig.Width());
+ aRet.append(OOO_STRING_SVTOOLS_RTF_PICHGOAL);
+ aRet.append((sal_Int32)rOrig.Height());
+
+ aRet.append(pBLIPType);
+ if (bIsWMF)
+ {
+ aRet.append((sal_Int32)8);
+ StripMetafileHeader(pGraphicAry, nSize);
+ }
+ aRet.append(RtfExport::sNewLine);
+ aRet.append(WriteHex(pGraphicAry, nSize));
+ aRet.append('}');
+ }
+ return aRet.makeStringAndClear();
+}
+
+void RtfAttributeOutput::FlyFrameOLEData( SwOLENode& rOLENode )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
+ sal_Int64 nAspect = rOLENode.GetAspect();
+ svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
+ SvGlobalName aObjName(aObjRef->getClassID());
+
+ if (SotExchange::IsMath(aObjName))
+ {
+ // ObjectHeader
+ m_aRunText.append(WriteHex(0x00000501)); // OLEVersion
+ m_aRunText.append(WriteHex(0x00000002)); // FormatID
+ m_aRunText.append(WriteHex(OString("Equation.3"))); // ClassName
+ m_aRunText.append(WriteHex(0x00000000)); // TopicName
+ m_aRunText.append(WriteHex(0x00000000)); // ItemName
+
+ // NativeData
+ SvMemoryStream *pStream = new SvMemoryStream;
+ SvStorage* pStorage = new SvStorage(*pStream);
+ m_rExport.pOLEExp->ExportOLEObject( aObjRef, *pStorage );
+ pStream->Seek(STREAM_SEEK_TO_END);
+ sal_uInt32 nNativeDataSize = pStream->Tell();
+ const sal_uInt8* pNativeData = (sal_uInt8*)pStream->GetData();
+ m_aRunText.append(WriteHex(nNativeDataSize));
+ m_aRunText.append(RtfExport::sNewLine);
+ m_aRunText.append(WriteHex(pNativeData, nNativeDataSize, 126));
+ m_aRunText.append(RtfExport::sNewLine);
+ delete pStream;
+
+ // MetaFilePresentationObject
+ pStream = new SvMemoryStream;
+ Graphic* pGraphic = rOLENode.GetGraphic();
+ if (GraphicConverter::Export(*pStream, *pGraphic, CVT_WMF) != ERRCODE_NONE)
+ OSL_FAIL("failed to export the presentation data");
+ pStream->Seek(STREAM_SEEK_TO_END);
+ sal_uInt32 nPresentationDataSize = pStream->Tell();
+ const sal_uInt8* pPresentationData = (sal_uInt8*)pStream->GetData();
+ m_aRunText.append(WriteHex(pPresentationData, nPresentationDataSize, 126));
+ }
+}
+
+void RtfAttributeOutput::FlyFrameOLE( const SwFlyFrmFmt* pFlyFrmFmt, SwOLENode& rOLENode, const Size& rSize )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ SvMemoryStream aStream;
+ const sal_uInt8* pGraphicAry = 0;
+ sal_uInt32 nSize = 0;
+ Graphic* pGraphic = rOLENode.GetGraphic();
+
+ Size aSize(sw::util::GetSwappedInSize(rOLENode));
+ Size aRendered(aSize);
+ aRendered.Width() = rSize.Width();
+ aRendered.Height() = rSize.Height();
+ Size aMapped(pGraphic->GetPrefSize());
+ const SwCropGrf &rCr = (const SwCropGrf &)rOLENode.GetAttr(RES_GRFATR_CROPGRF);
+ const sal_Char* pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
+
+ if (GraphicConverter::Export(aStream, *pGraphic, CVT_WMF) != ERRCODE_NONE)
+ OSL_FAIL("failed to export the graphic");
+ aStream.Seek(STREAM_SEEK_TO_END);
+ nSize = aStream.Tell();
+ pGraphicAry = (sal_uInt8*)aStream.GetData();
+
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_OBJECT OOO_STRING_SVTOOLS_RTF_OBJEMB);
+
+ // export the object data in the appropriate format; RTF requires the usage of the OLE 1.0 format
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_OBJDATA " ");
+ FlyFrameOLEData(rOLENode);
+ m_aRunText.append("}{" OOO_STRING_SVTOOLS_RTF_RESULT);
+
+ SwTwips nHeight = aSize.Height();
+ nHeight/=20; //nHeight was in twips, want it in half points, but then half of total height.
+ long nFontHeight = ((const SvxFontHeightItem&)m_rExport.GetItem(RES_CHRATR_FONTSIZE)).GetHeight();
+ nHeight-=nFontHeight/20;
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_DN).append(nHeight);
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT);
+ m_aRunText.append(ExportPICT( pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
+ m_aRunText.append("}}}}");
+}
+
+void RtfAttributeOutput::FlyFrameGraphic( const SwFlyFrmFmt* pFlyFrmFmt, const SwGrfNode& rGrfNode)
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ SvMemoryStream aStream;
+ const sal_uInt8* pGraphicAry = 0;
+ sal_uInt32 nSize = 0;
+
+ Graphic aGraphic(rGrfNode.GetGrf());
+
+ // If there is no graphic there is not much point in parsing it
+ if(aGraphic.GetType()==GRAPHIC_NONE)
+ return;
+
+ GfxLink aGraphicLink;
+ const sal_Char* pBLIPType = 0;
+ if (aGraphic.IsLink())
+ {
+ aGraphicLink = aGraphic.GetLink();
+ nSize = aGraphicLink.GetDataSize();
+ pGraphicAry = aGraphicLink.GetData();
+ switch (aGraphicLink.GetType())
+ {
+ case GFX_LINK_TYPE_NATIVE_JPG:
+ pBLIPType = OOO_STRING_SVTOOLS_RTF_JPEGBLIP;
+ break;
+ case GFX_LINK_TYPE_NATIVE_PNG:
+ pBLIPType = OOO_STRING_SVTOOLS_RTF_PNGBLIP;
+ break;
+ case GFX_LINK_TYPE_NATIVE_WMF:
+ pBLIPType =
+ IsEMF(pGraphicAry, nSize) ? OOO_STRING_SVTOOLS_RTF_EMFBLIP : OOO_STRING_SVTOOLS_RTF_WMETAFILE;
+ break;
+ default:
+ break;
+ }
+ }
+
+ GraphicType eGraphicType = aGraphic.GetType();
+ if (!pGraphicAry)
+ {
+ if (ERRCODE_NONE == GraphicConverter::Export(aStream, aGraphic,
+ (eGraphicType == GRAPHIC_BITMAP) ? CVT_PNG : CVT_WMF))
+ {
+ pBLIPType = (eGraphicType == GRAPHIC_BITMAP) ?
+ OOO_STRING_SVTOOLS_RTF_PNGBLIP : OOO_STRING_SVTOOLS_RTF_WMETAFILE;
+ aStream.Seek(STREAM_SEEK_TO_END);
+ nSize = aStream.Tell();
+ pGraphicAry = (sal_uInt8*)aStream.GetData();
+ }
+ }
+
+ Size aMapped(eGraphicType == GRAPHIC_BITMAP ? aGraphic.GetSizePixel() : aGraphic.GetPrefSize());
+
+ const SwCropGrf &rCr = (const SwCropGrf &)rGrfNode.GetAttr(RES_GRFATR_CROPGRF);
+
+ //Get original size in twips
+ Size aSize(sw::util::GetSwappedInSize(rGrfNode));
+ Size aRendered(aSize);
+ if (pFlyFrmFmt)
+ {
+ const SwFmtFrmSize& rS = pFlyFrmFmt->GetFrmSize();
+ aRendered.Width() = rS.GetWidth();
+ aRendered.Height() = rS.GetHeight();
+ }
+
+ /*
+ If the graphic is not of type WMF then we will have to store two
+ graphics, one in the native format wrapped in shppict, and the other in
+ the wmf format wrapped in nonshppict, so as to keep wordpad happy. If its
+ a wmf already then we don't need any such wrapping
+ */
+ bool bIsWMF = (const sal_Char*)pBLIPType == (const sal_Char*)OOO_STRING_SVTOOLS_RTF_WMETAFILE ? true : false;
+ if (!bIsWMF)
+ m_aRunText.append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_SHPPICT);
+
+ if (pBLIPType)
+ m_aRunText.append(ExportPICT( pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport));
+ else
+ {
+ aStream.Seek(0);
+ GraphicConverter::Export(aStream, aGraphic, CVT_WMF);
+ pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
+ aStream.Seek(STREAM_SEEK_TO_END);
+ nSize = aStream.Tell();
+ pGraphicAry = (sal_uInt8*)aStream.GetData();
+
+ m_aRunText.append(ExportPICT(pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
+ }
+
+ if (!bIsWMF)
+ {
+ m_aRunText.append("}" "{" OOO_STRING_SVTOOLS_RTF_NONSHPPICT);
+
+ aStream.Seek(0);
+ GraphicConverter::Export(aStream, aGraphic, CVT_WMF);
+ pBLIPType = OOO_STRING_SVTOOLS_RTF_WMETAFILE;
+ aStream.Seek(STREAM_SEEK_TO_END);
+ nSize = aStream.Tell();
+ pGraphicAry = (sal_uInt8*)aStream.GetData();
+
+ m_aRunText.append(ExportPICT(pFlyFrmFmt, aSize, aRendered, aMapped, rCr, pBLIPType, pGraphicAry, nSize, m_rExport ));
+
+ m_aRunText.append('}');
+ }
+
+ m_aRunText.append(m_rExport.sNewLine);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfattributeoutput.hxx b/sw/source/filter/ww8/rtfattributeoutput.hxx
new file mode 100644
index 000000000000..fcf43b765543
--- /dev/null
+++ b/sw/source/filter/ww8/rtfattributeoutput.hxx
@@ -0,0 +1,572 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * Copyright 2010 Miklos Vajna.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _RTFATTRIBUTEOUTPUT_HXX_
+#define _RTFATTRIBUTEOUTPUT_HXX_
+
+#include <set>
+#include "attributeoutputbase.hxx"
+#include "fields.hxx"
+#include "rtfexport.hxx"
+
+#include <vcl/vclenum.hxx>
+
+#include <fldbas.hxx>
+#include <rtl/strbuf.hxx>
+
+#include <vector>
+
+
+class SwGrfNode;
+class SwOLENode;
+class SdrObject;
+class SwFlyFrmFmt;
+
+/// The class that has handlers for various resource types when exporting as RTF
+class RtfAttributeOutput : public AttributeOutputBase
+{
+public:
+ /// Export the state of RTL/CJK.
+ virtual void RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript );
+
+ /// Start of the paragraph.
+ virtual void StartParagraph( ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo );
+
+ /// End of the paragraph.
+ virtual void EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner );
+
+ /// Empty paragraph.
+ virtual void EmptyParagraph();
+
+ /// Called before we start outputting the attributes.
+ virtual void StartParagraphProperties( const SwTxtNode& rNode );
+
+ /// Called after we end outputting the attributes.
+ virtual void EndParagraphProperties();
+
+ /// Start of the text run.
+ virtual void StartRun( const SwRedlineData* pRedlineData );
+
+ /// End of the text run.
+ virtual void EndRun();
+
+ /// Called before we start outputting the attributes.
+ virtual void StartRunProperties();
+
+ /// Called after we end outputting the attributes.
+ virtual void EndRunProperties( const SwRedlineData* pRedlineData );
+
+ /// Output text (inside a run).
+ virtual void RunText( const String& rText, rtl_TextEncoding eCharSet = RTL_TEXTENCODING_UTF8 );
+
+ // Access to (anyway) private buffers, used by the sdr exporter
+ rtl::OStringBuffer& RunText();
+ rtl::OStringBuffer& Styles();
+
+ /// Output text (without markup).
+ virtual void RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet );
+
+ /// Output ruby start.
+ virtual void StartRuby( const SwTxtNode& rNode, xub_StrLen nPos, const SwFmtRuby& rRuby );
+
+ /// Output ruby end.
+ virtual void EndRuby();
+
+ /// Output URL start.
+ virtual bool StartURL( const String& rUrl, const String& rTarget );
+
+ /// Output URL end.
+ virtual bool EndURL();
+
+ virtual void FieldVanish( const String& rTxt, ww::eField eType );
+
+ /// Output redlining.
+ ///
+ /// The common attribute that can be among the run properties.
+ virtual void Redline( const SwRedlineData* pRedline );
+
+ virtual void FormatDrop( const SwTxtNode& rNode, const SwFmtDrop& rSwFmtDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner );
+
+ /// Output style.
+ virtual void ParagraphStyle( sal_uInt16 nStyle );
+
+ virtual void TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo );
+ virtual void TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner );
+ virtual void TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableRowEnd( sal_uInt32 nDepth );
+
+ /// Start of the styles table.
+ virtual void StartStyles();
+
+ /// End of the styles table.
+ virtual void EndStyles( sal_uInt16 nNumberOfStyles );
+
+ /// Write default style.
+ virtual void DefaultStyle( sal_uInt16 nStyle );
+
+ /// Start of a style in the styles table.
+ virtual void StartStyle( const String& rName, bool bPapFmt,
+ sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 nWwId, sal_uInt16 nId,
+ bool bAutoUpdate );
+
+ /// End of a style in the styles table.
+ virtual void EndStyle();
+
+ /// Start of (paragraph or run) properties of a style.
+ virtual void StartStyleProperties( bool bParProp, sal_uInt16 nStyle );
+
+ /// End of (paragraph or run) properties of a style.
+ virtual void EndStyleProperties( bool bParProp );
+
+ /// Numbering rule and Id.
+ virtual void OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt &rNFmt, const SwFmt &rFmt );
+
+ /// Page break
+ /// As a paragraph property - the paragraph should be on the next page.
+ virtual void PageBreakBefore( bool bBreak );
+
+ /// Write a section break
+ /// msword::ColumnBreak or msword::PageBreak
+ virtual void SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo = NULL );
+
+ /// Start of the section properties.
+ virtual void StartSection();
+
+ /// End of the section properties.
+ virtual void EndSection();
+
+ /// Protection of forms.
+ virtual void SectionFormProtection( bool bProtected );
+
+ /// Numbering of the lines in the document.
+ virtual void SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo );
+
+ /// Has different headers/footers for the title page.
+ virtual void SectionTitlePage();
+
+ /// Description of the page borders.
+ virtual void SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* pFirstPageFmt );
+
+ /// Columns populated from right/numbers on the right side?
+ virtual void SectionBiDi( bool bBiDi );
+
+ /// The style of the page numbers.
+ ///
+ /// nPageRestartNumberr being 0 means no restart.
+ virtual void SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber );
+
+ /// The type of breaking.
+ virtual void SectionType( sal_uInt8 nBreakCode );
+
+ /// Definition of a numbering instance.
+ virtual void NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule );
+
+ /// Start of the abstract numbering definition instance.
+ virtual void StartAbstractNumbering( sal_uInt16 nId );
+
+ /// End of the abstract numbering definition instance.
+ virtual void EndAbstractNumbering();
+
+ /// All the numbering level information.
+ virtual void NumberingLevel( sal_uInt8 nLevel,
+ sal_uInt16 nStart,
+ sal_uInt16 nNumberingType,
+ SvxAdjust eAdjust,
+ const sal_uInt8 *pNumLvlPos,
+ sal_uInt8 nFollow,
+ const wwFont *pFont,
+ const SfxItemSet *pOutSet,
+ sal_Int16 nIndentAt,
+ sal_Int16 nFirstLineIndex,
+ sal_Int16 nListTabPos,
+ const String &rNumberingString );
+
+ void WriteField_Impl( const SwField* pFld, ww::eField eType, const String& rFldCmd, sal_uInt8 nMode );
+ void WriteBookmarks_Impl( std::vector< rtl::OUString >& rStarts, std::vector< rtl::OUString >& rEnds );
+ void WriteHeaderFooter_Impl( const SwFrmFmt& rFmt, bool bHeader, const sal_Char* pStr );
+
+protected:
+ /// Output frames - the implementation.
+ virtual void OutputFlyFrame_Impl( const sw::Frame& rFmt, const Point& rNdTopLeft );
+
+ /// Sfx item Sfx item RES_CHRATR_CASEMAP
+ virtual void CharCaseMap( const SvxCaseMapItem& rCaseMap );
+
+ /// Sfx item Sfx item RES_CHRATR_COLOR
+ virtual void CharColor( const SvxColorItem& rColor);
+
+ /// Sfx item Sfx item RES_CHRATR_CONTOUR
+ virtual void CharContour( const SvxContourItem& rContour );
+
+ /// Sfx item RES_CHRATR_CROSSEDOUT
+ virtual void CharCrossedOut( const SvxCrossedOutItem& rCrossedOut );
+
+ /// Sfx item RES_CHRATR_ESCAPEMENT
+ virtual void CharEscapement( const SvxEscapementItem& rEscapement );
+
+ /// Sfx item RES_CHRATR_FONT
+ virtual void CharFont( const SvxFontItem& rFont );
+
+ /// Sfx item RES_CHRATR_FONTSIZE
+ virtual void CharFontSize( const SvxFontHeightItem& rFontSize );
+
+ /// Sfx item RES_CHRATR_KERNING
+ virtual void CharKerning( const SvxKerningItem& rKerning );
+
+ /// Sfx item RES_CHRATR_LANGUAGE
+ virtual void CharLanguage( const SvxLanguageItem& rLanguage );
+
+ /// Sfx item RES_CHRATR_POSTURE
+ virtual void CharPosture( const SvxPostureItem& rPosture );
+
+ /// Sfx item RES_CHRATR_SHADOWED
+ virtual void CharShadow( const SvxShadowedItem& rShadow );
+
+ /// Sfx item RES_CHRATR_UNDERLINE
+ virtual void CharUnderline( const SvxUnderlineItem& rUnderline );
+
+ /// Sfx item RES_CHRATR_WEIGHT
+ virtual void CharWeight( const SvxWeightItem& rWeight );
+
+ /// Sfx item RES_CHRATR_AUTOKERN
+ virtual void CharAutoKern( const SvxAutoKernItem& );
+
+ /// Sfx item RES_CHRATR_BLINK
+ virtual void CharAnimatedText( const SvxBlinkItem& rBlink );
+
+ /// Sfx item RES_CHRATR_BACKGROUND
+ virtual void CharBackground( const SvxBrushItem& rBrush );
+
+ /// Sfx item RES_CHRATR_CJK_FONT
+ virtual void CharFontCJK( const SvxFontItem& rFont );
+
+ /// Sfx item RES_CHRATR_CJK_FONTSIZE
+ virtual void CharFontSizeCJK( const SvxFontHeightItem& rFontSize );
+
+ /// Sfx item RES_CHRATR_CJK_LANGUAGE
+ virtual void CharLanguageCJK( const SvxLanguageItem& rLanguageItem );
+
+ /// Sfx item RES_CHRATR_CJK_POSTURE
+ virtual void CharPostureCJK( const SvxPostureItem& rPosture );
+
+ /// Sfx item RES_CHRATR_CJK_WEIGHT
+ virtual void CharWeightCJK( const SvxWeightItem& rWeight );
+
+ /// Sfx item RES_CHRATR_CTL_FONT
+ virtual void CharFontCTL( const SvxFontItem& rFont );
+
+ /// Sfx item RES_CHRATR_CTL_FONTSIZE
+ virtual void CharFontSizeCTL( const SvxFontHeightItem& rFontSize );
+
+ /// Sfx item RES_CHRATR_CTL_LANGUAGE
+ virtual void CharLanguageCTL( const SvxLanguageItem& rLanguageItem );
+
+ /// Sfx item RES_CHRATR_CTL_POSTURE
+ virtual void CharPostureCTL( const SvxPostureItem& rWeight );
+
+ /// Sfx item RES_CHRATR_CTL_WEIGHT
+ virtual void CharWeightCTL( const SvxWeightItem& rWeight );
+
+ /// Sfx item RES_CHRATR_ROTATE
+ virtual void CharRotate( const SvxCharRotateItem& rRotate );
+
+ /// Sfx item RES_CHRATR_EMPHASIS_MARK
+ virtual void CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark );
+
+ /// Sfx item RES_CHRATR_TWO_LINES
+ virtual void CharTwoLines( const SvxTwoLinesItem& rTwoLines );
+
+ /// Sfx item RES_CHRATR_SCALEW
+ virtual void CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth );
+
+ /// Sfx item RES_CHRATR_RELIEF
+ virtual void CharRelief( const SvxCharReliefItem& rRelief);
+
+ /// Sfx item RES_CHRATR_HIDDEN
+ virtual void CharHidden( const SvxCharHiddenItem& rHidden );
+
+ /// Sfx item RES_TXTATR_INETFMT
+ virtual void TextINetFormat( const SwFmtINetFmt& );
+
+ /// Sfx item RES_TXTATR_CHARFMT
+ virtual void TextCharFormat( const SwFmtCharFmt& );
+
+ /// Sfx item RES_TXTATR_FTN
+ virtual void TextFootnote_Impl( const SwFmtFtn& );
+
+ /// Sfx item RES_PARATR_LINESPACING
+ virtual void ParaLineSpacing_Impl( short nSpace, short nMulti );
+
+ /// Sfx item RES_PARATR_ADJUST
+ virtual void ParaAdjust( const SvxAdjustItem& rAdjust );
+
+ /// Sfx item RES_PARATR_SPLIT
+ virtual void ParaSplit( const SvxFmtSplitItem& rSplit );
+
+ /// Sfx item RES_PARATR_WIDOWS
+ virtual void ParaWidows( const SvxWidowsItem& rWidows );
+
+ /// Sfx item RES_PARATR_TABSTOP
+ virtual void ParaTabStop( const SvxTabStopItem& rTabStop );
+
+ /// Sfx item RES_PARATR_HYPHENZONE
+ virtual void ParaHyphenZone( const SvxHyphenZoneItem& );
+
+ /// Sfx item RES_PARATR_NUMRULE
+ virtual void ParaNumRule_Impl( const SwTxtNode *pTxtNd, sal_Int32 nLvl, sal_Int32 nNumId );
+
+ /// Sfx item RES_PARATR_SCRIPTSPACE
+ virtual void ParaScriptSpace( const SfxBoolItem& );
+
+ /// Sfx item RES_PARATR_VERTALIGN
+ virtual void ParaVerticalAlign( const SvxParaVertAlignItem& rAlign );
+
+ /// Sfx item RES_PARATR_SNAPTOGRID
+ virtual void ParaSnapToGrid( const SvxParaGridItem& );
+
+ /// Sfx item RES_FRM_SIZE
+ virtual void FormatFrameSize( const SwFmtFrmSize& );
+
+ /// Sfx item RES_PAPER_BIN
+ virtual void FormatPaperBin( const SvxPaperBinItem& );
+
+ /// Sfx item RES_LR_SPACE
+ virtual void FormatLRSpace( const SvxLRSpaceItem& rLRSpace );
+
+ /// Sfx item RES_UL_SPACE
+ virtual void FormatULSpace( const SvxULSpaceItem& rULSpace );
+
+ /// Sfx item RES_SURROUND
+ virtual void FormatSurround( const SwFmtSurround& );
+
+ /// Sfx item RES_VERT_ORIENT
+ virtual void FormatVertOrientation( const SwFmtVertOrient& );
+
+ /// Sfx item RES_HORI_ORIENT
+ virtual void FormatHorizOrientation( const SwFmtHoriOrient& );
+
+ /// Sfx item RES_ANCHOR
+ virtual void FormatAnchor( const SwFmtAnchor& );
+
+ /// Sfx item RES_BACKGROUND
+ virtual void FormatBackground( const SvxBrushItem& );
+
+ /// Sfx item RES_BOX
+ virtual void FormatBox( const SvxBoxItem& );
+
+ /// Sfx item RES_COL
+ virtual void FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol & rCol, bool bEven, SwTwips nPageSize );
+
+ /// Sfx item RES_KEEP
+ virtual void FormatKeep( const SvxFmtKeepItem& );
+
+ /// Sfx item RES_TEXTGRID
+ virtual void FormatTextGrid( const SwTextGridItem& );
+
+ /// Sfx item RES_LINENUMBER
+ virtual void FormatLineNumbering( const SwFmtLineNumber& );
+
+ /// Sfx item RES_FRAMEDIR
+ virtual void FormatFrameDirection( const SvxFrameDirectionItem& );
+
+ /// Write the expanded field
+ virtual void WriteExpand( const SwField* pFld );
+
+ virtual void RefField( const SwField& rFld, const String& rRef );
+ virtual void HiddenField( const SwField& rFld );
+ virtual void SetField( const SwField& rFld, ww::eField eType, const String& rCmd );
+ virtual void PostitField( const SwField* pFld );
+ virtual bool DropdownField( const SwField* pFld );
+
+ /// Reference to the export, where to get the data from
+ RtfExport &m_rExport;
+
+private:
+
+ /// Output graphic fly frames.
+ void FlyFrameGraphic( const SwFlyFrmFmt* pFlyFrmFmt, const SwGrfNode& rGrfNode );
+ void FlyFrameOLE( const SwFlyFrmFmt* pFlyFrmFmt, SwOLENode& rOLENode, const Size& rSize );
+ void FlyFrameOLEData( SwOLENode& rOLENode );
+
+ /*
+ * Table methods.
+ */
+ void InitTableHelper( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ void StartTable( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ void StartTableRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ void StartTableCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ void TableCellProperties( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ void EndTableCell( );
+ void EndTableRow( );
+ void EndTable();
+
+ /// End cell, row, and even the entire table if necessary.
+ void FinishTableRowCell( ww8::WW8TableNodeInfoInner::Pointer_t pInner, bool bForceEmptyParagraph = false );
+
+ void WriteTextFootnoteNumStr(const SwFmtFtn& rFootnote);
+
+ /*
+ * Current style name and its ID.
+ */
+ String m_rStyleName;
+ sal_uInt16 m_nStyleId;
+ /*
+ * Current list ID.
+ */
+ sal_uInt16 m_nListId;
+ /*
+ * This is needed because the call order is: run text, run properties, paragraph properties.
+ * What we need is the opposite.
+ */
+ rtl::OStringBuffer m_aRun;
+ rtl::OStringBuffer m_aRunText;
+ /*
+ * This is written after runs.
+ */
+ rtl::OStringBuffer m_aAfterRuns;
+ /*
+ * Same for colors and stylesheets: first we just want to output colors,
+ * need to buffer the stylesheet table to output it after the color one.
+ */
+ rtl::OStringBuffer m_aStylesheet;
+ /*
+ * This one just holds the style commands in the current style.
+ */
+ rtl::OStringBuffer m_aStyles;
+ /*
+ * This is the same as m_aStyles but the conents of it is written last.
+ */
+ rtl::OStringBuffer m_aStylesEnd;
+
+ /*
+ * We just get a "end of strike" mark at the end of strike, store here what to finish: single or double strike.
+ */
+ bool m_bStrikeDouble;
+
+ /*
+ * The current table helper.
+ */
+ SwWriteTable *m_pTableWrt;
+
+ /*
+ * Remember if we are in an open cell, or not.
+ */
+ bool m_bTableCellOpen;
+
+ /*
+ * Remember the current table depth.
+ */
+ sal_uInt32 m_nTableDepth;
+
+ /*
+ * Remember if we wrote a \cell or not.
+ */
+ bool m_bTblAfterCell;
+
+ /*
+ * For late output of row definitions.
+ */
+ rtl::OStringBuffer m_aRowDefs;
+
+ /*
+ * Is a column break needed after the next \par?
+ */
+ bool m_nColBreakNeeded;
+
+ /*
+ * If section breaks should be buffered to m_aSectionBreaks
+ */
+ bool m_bBufferSectionBreaks;
+ rtl::OStringBuffer m_aSectionBreaks;
+
+ /*
+ * If section headers (and footers) should be buffered to
+ * m_aSectionHeaders.
+ */
+ bool m_bBufferSectionHeaders;
+ rtl::OStringBuffer m_aSectionHeaders;
+
+ /*
+ * Support for starting multiple tables at the same cell.
+ * If the current table is the last started one.
+ */
+ bool m_bLastTable;
+ /*
+ * List of already started but not yet defined tables (need to be defined
+ * after the nested tables).
+ */
+ std::vector< rtl::OString > m_aTables;
+ /*
+ * If cell info is already output.
+ */
+ bool m_bWroteCellInfo;
+
+public:
+ RtfAttributeOutput( RtfExport &rExport );
+
+ virtual ~RtfAttributeOutput();
+
+ /// Return the right export class.
+ virtual MSWordExportBase& GetExport();
+
+ rtl::OStringBuffer m_aTabStop;
+
+ // These are used by wwFont::WriteRtf()
+ /// Start the font.
+ void StartFont( const String& rFamilyName ) const;
+
+ /// End the font.
+ void EndFont() const;
+
+ /// Alternate name for the font.
+ void FontAlternateName( const String& rName ) const;
+
+ /// Font charset.
+ void FontCharset( sal_uInt8 nCharSet ) const;
+
+ /// Font family.
+ void FontFamilyType( FontFamily eFamily, const wwFont &rFont ) const;
+
+ /// Font pitch.
+ void FontPitchType( FontPitch ePitch ) const;
+};
+
+#endif // _RTFATTRIBUTEOUTPUT_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfexport.cxx b/sw/source/filter/ww8/rtfexport.cxx
new file mode 100644
index 000000000000..453c0a724d4b
--- /dev/null
+++ b/sw/source/filter/ww8/rtfexport.cxx
@@ -0,0 +1,1302 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * Copyright 2010 Miklos Vajna.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "rtfexport.hxx"
+#include "rtfexportfilter.hxx"
+#include "rtfsdrexport.hxx"
+#include "rtfattributeoutput.hxx"
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <com/sun/star/frame/XModel.hpp>
+
+#include <map>
+#include <algorithm>
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+
+#include <IMark.hxx>
+#include <docsh.hxx>
+#include <ndtxt.hxx>
+#include <wrtww8.hxx>
+#include <fltini.hxx>
+#include <fmtline.hxx>
+#include <fmtpdsc.hxx>
+#include <frmfmt.hxx>
+#include <section.hxx>
+#include <pagedesc.hxx>
+#include <swtable.hxx>
+#include <fmtfsize.hxx>
+#include <frmatr.hxx>
+#include <ftninfo.hxx>
+#include <fmthdft.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/paperinf.hxx>
+#include <editeng/protitem.hxx>
+
+#include <docary.hxx>
+#include <numrule.hxx>
+#include <charfmt.hxx>
+#include <lineinfo.hxx>
+#include <swmodule.hxx>
+
+#include "ww8par.hxx"
+#include "ww8scan.hxx"
+
+#include <comphelper/string.hxx>
+#include <rtl/ustrbuf.hxx>
+#include <vcl/font.hxx>
+#include <svtools/rtfkeywd.hxx>
+#include <unotools/configmgr.hxx>
+
+using ::editeng::SvxBorderLine;
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+
+using rtl::OString;
+using rtl::OUString;
+using rtl::OStringBuffer;
+using rtl::OUStringBuffer;
+
+using sw::mark::IMark;
+
+#if defined(UNX)
+const sal_Char RtfExport::sNewLine = '\012';
+#else
+const sal_Char RtfExport::sNewLine[] = "\015\012";
+#endif
+
+// the default text encoding for the export, if it doesn't fit unicode will
+// be used
+#define DEF_ENCODING RTL_TEXTENCODING_ASCII_US
+
+AttributeOutputBase& RtfExport::AttrOutput() const
+{
+ return *m_pAttrOutput;
+}
+
+MSWordSections& RtfExport::Sections() const
+{
+ return *m_pSections;
+}
+
+RtfSdrExport& RtfExport::SdrExporter() const
+{
+ return *m_pSdrExport;
+}
+
+bool RtfExport::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich )
+{
+ // FIXME is this actually true for rtf? - this is copied from DOCX
+ if ( nScript == i18n::ScriptType::ASIAN )
+ {
+ // for asian in ww8, there is only one fontsize
+ // and one fontstyle (posture/weight)
+ switch ( nWhich )
+ {
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_POSTURE:
+ case RES_CHRATR_WEIGHT:
+ return false;
+ default:
+ break;
+ }
+ }
+ else if ( nScript != i18n::ScriptType::COMPLEX )
+ {
+ // for western in ww8, there is only one fontsize
+ // and one fontstyle (posture/weight)
+ switch ( nWhich )
+ {
+ case RES_CHRATR_CJK_FONTSIZE:
+ case RES_CHRATR_CJK_POSTURE:
+ case RES_CHRATR_CJK_WEIGHT:
+ return false;
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
+void RtfExport::AppendBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ std::vector< OUString > aStarts;
+ std::vector< OUString > aEnds;
+
+ IMarkVector aMarks;
+ if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarks ) )
+ {
+ for ( IMarkVector::const_iterator it = aMarks.begin(), end = aMarks.end();
+ it < end; ++it )
+ {
+ IMark* pMark = (*it);
+ xub_StrLen nStart = pMark->GetMarkStart().nContent.GetIndex();
+ xub_StrLen nEnd = pMark->GetMarkEnd().nContent.GetIndex();
+
+ if ( nStart == nAktPos )
+ aStarts.push_back( pMark->GetName() );
+
+ if ( nEnd == nAktPos )
+ aEnds.push_back( pMark->GetName() );
+ }
+ }
+
+ m_pAttrOutput->WriteBookmarks_Impl( aStarts, aEnds );
+}
+
+void RtfExport::AppendBookmark( const OUString& rName, bool /*bSkip*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ std::vector<OUString> aStarts;
+ std::vector<OUString> aEnds;
+
+ aStarts.push_back(rName);
+ aEnds.push_back(rName);
+
+ m_pAttrOutput->WriteBookmarks_Impl(aStarts, aEnds);
+}
+
+void RtfExport::WriteChar( sal_Unicode )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /* WriteChar() has nothing to do for rtf. */
+}
+
+static bool IsExportNumRule( const SwNumRule& rRule, sal_uInt8* pEnd = 0 )
+{
+ sal_uInt8 nEnd = MAXLEVEL;
+ while( nEnd-- && !rRule.GetNumFmt( nEnd ))
+ ;
+ ++nEnd;
+
+ const SwNumFmt* pNFmt;
+ sal_uInt8 nLvl;
+
+ for( nLvl = 0; nLvl < nEnd; ++nLvl )
+ if( SVX_NUM_NUMBER_NONE != ( pNFmt = &rRule.Get( nLvl ))
+ ->GetNumberingType() || pNFmt->GetPrefix().Len() ||
+ (pNFmt->GetSuffix().Len() && pNFmt->GetSuffix() != aDotStr ))
+ break;
+
+ if( pEnd )
+ *pEnd = nEnd;
+ return nLvl != nEnd;
+}
+
+void RtfExport::BuildNumbering()
+{
+ const SwNumRuleTbl& rListTbl = pDoc->GetNumRuleTbl();
+
+ for( sal_uInt16 n = rListTbl.Count()+1; n; )
+ {
+ SwNumRule* pRule;
+ --n;
+ if( n == rListTbl.Count() )
+ pRule = (SwNumRule*)pDoc->GetOutlineNumRule();
+ else
+ {
+ pRule = rListTbl[ n ];
+ if( !pDoc->IsUsed( *pRule ))
+ continue;
+ }
+
+ if( IsExportNumRule( *pRule ))
+ GetId( *pRule );
+ }
+}
+
+void RtfExport::WriteNumbering()
+{
+ OSL_TRACE("%s start", OSL_THIS_FUNC);
+
+ if ( !pUsedNumTbl )
+ return; // no numbering is used
+
+ Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_LISTTABLE;
+ AbstractNumberingDefinitions();
+ Strm() << '}';
+
+ Strm() << '{' << OOO_STRING_SVTOOLS_RTF_LISTOVERRIDETABLE;
+ NumberingDefinitions();
+ Strm() << '}';
+
+ OSL_TRACE("%s end", OSL_THIS_FUNC);
+}
+
+void RtfExport::WriteRevTab()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ int nRevAuthors = pDoc->GetRedlineTbl().Count();
+
+ if (nRevAuthors < 1)
+ return;
+
+ // RTF always seems to use Unknown as the default first entry
+ String sUnknown(RTL_CONSTASCII_USTRINGPARAM("Unknown"));
+ GetRedline(sUnknown);
+
+ for( sal_uInt16 i = 0; i < pDoc->GetRedlineTbl().Count(); ++i )
+ {
+ const SwRedline* pRedl = pDoc->GetRedlineTbl()[ i ];
+
+ GetRedline(SW_MOD()->GetRedlineAuthor(pRedl->GetAuthor()));
+ }
+
+ // Now write the table
+ Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_REVTBL << ' ';
+ for(sal_uInt16 i = 0; i < m_aRedlineTbl.size(); ++i)
+ {
+ const String* pAuthor = GetRedline(i);
+ Strm() << '{';
+ if (pAuthor)
+ Strm() << OutString(*pAuthor, eDefaultEncoding);
+ Strm() << ";}";
+ }
+ Strm() << '}' << sNewLine;
+}
+
+void RtfExport::WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
+ const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 /*nBreakCode*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // headers
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_EVEN )
+ WriteHeaderFooter( rLeftFmt, true, OOO_STRING_SVTOOLS_RTF_HEADERL );
+
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_ODD )
+ WriteHeaderFooter( rFmt, true, OOO_STRING_SVTOOLS_RTF_HEADER );
+
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_HEADER_FIRST )
+ WriteHeaderFooter( rFirstPageFmt, true, OOO_STRING_SVTOOLS_RTF_HEADERF );
+
+ // footers
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_EVEN )
+ WriteHeaderFooter( rLeftFmt, false, OOO_STRING_SVTOOLS_RTF_FOOTERL );
+
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_ODD )
+ WriteHeaderFooter( rFmt, false, OOO_STRING_SVTOOLS_RTF_FOOTER );
+
+ if ( nHeadFootFlags & nsHdFtFlags::WW8_FOOTER_FIRST )
+ WriteHeaderFooter( rFirstPageFmt, false, OOO_STRING_SVTOOLS_RTF_FOOTERF );
+}
+
+void RtfExport::OutputField( const SwField* pFld, ww::eField eFldType, const String& rFldCmd, sal_uInt8 nMode )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_pAttrOutput->WriteField_Impl( pFld, eFldType, rFldCmd, nMode );
+}
+
+void RtfExport::WriteFormData( const ::sw::mark::IFieldmark& /*rFieldmark*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfExport::WriteHyperlinkData( const ::sw::mark::IFieldmark& /*rFieldmark*/ )
+{
+ OSL_TRACE("TODO: %s", OSL_THIS_FUNC);
+}
+
+void RtfExport::DoComboBox(const rtl::OUString& /*rName*/,
+ const rtl::OUString& /*rHelp*/,
+ const rtl::OUString& /*rToolTip*/,
+ const rtl::OUString& /*rSelected*/,
+ uno::Sequence<rtl::OUString>& /*rListItems*/)
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // this is handled in RtfAttributeOutput::OutputFlyFrame_Impl
+}
+
+void RtfExport::DoFormText(const SwInputField* pFld )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ ::rtl::OUString sResult = pFld->ExpandField(pDoc->IsClipBoard());
+ ::rtl::OUString sHelp( pFld->GetHelp() );
+ ::rtl::OUString sName = pFld->GetPar2();
+ ::rtl::OUString sStatus = pFld->GetToolTip();
+ m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_FIELD "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FLDINST "{ FORMTEXT }");
+ m_pAttrOutput->RunText().append("{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FORMFIELD " {" OOO_STRING_SVTOOLS_RTF_FFTYPE "0" );
+ if( sHelp.getLength() )
+ m_pAttrOutput->RunText().append( OOO_STRING_SVTOOLS_RTF_FFOWNHELP );
+ if( sStatus.getLength() )
+ m_pAttrOutput->RunText().append( OOO_STRING_SVTOOLS_RTF_FFOWNSTAT );
+ m_pAttrOutput->RunText().append( OOO_STRING_SVTOOLS_RTF_FFTYPETXT "0" );
+
+ if( sName.getLength() )
+ m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFNAME " ").append( OutString( sName, eDefaultEncoding )).append( "}" );
+ if( sHelp.getLength() )
+ m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFHELPTEXT " ").append( OutString( sHelp, eDefaultEncoding )).append( "}" );
+ m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFDEFTEXT " ").append( OutString( sResult, eDefaultEncoding )).append( "}" );
+ if( sStatus.getLength() )
+ m_pAttrOutput->RunText().append( "{" OOO_STRING_SVTOOLS_RTF_IGNORE OOO_STRING_SVTOOLS_RTF_FFSTATTEXT " ").append( OutString( sStatus, eDefaultEncoding )).append( "}");
+ m_pAttrOutput->RunText().append( "}}}{" OOO_STRING_SVTOOLS_RTF_FLDRSLT " " );
+ m_pAttrOutput->RunText().append( OutString( sResult, eDefaultEncoding )).append( "}}" );
+}
+
+sal_uLong RtfExport::ReplaceCr( sal_uInt8 )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // Completely unused for Rtf export... only here for code sharing
+ // purpose with binary export
+
+ return 0;
+}
+
+void RtfExport::WriteFonts()
+{
+ Strm() << sNewLine << '{' << OOO_STRING_SVTOOLS_RTF_FONTTBL;
+ maFontHelper.WriteFontTable( *m_pAttrOutput );
+ Strm() << '}';
+}
+
+void RtfExport::WriteStyles()
+{
+ OSL_TRACE("%s start", OSL_THIS_FUNC);
+ pStyles->OutputStylesTable();
+ OSL_TRACE("%s end", OSL_THIS_FUNC);
+}
+
+void RtfExport::WriteMainText()
+{
+ OSL_TRACE("%s start", OSL_THIS_FUNC);
+ pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
+ WriteText();
+ OSL_TRACE("%s end", OSL_THIS_FUNC);
+}
+
+void RtfExport::WriteInfo()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ Strm() << '{' << OOO_STRING_SVTOOLS_RTF_INFO;
+
+ SwDocShell *pDocShell(pDoc->GetDocShell());
+ uno::Reference<document::XDocumentProperties> xDocProps;
+ if (pDocShell) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY);
+ xDocProps.set(xDPS->getDocumentProperties());
+ }
+
+ if (xDocProps.is()) {
+ OutUnicode(OOO_STRING_SVTOOLS_RTF_TITLE, xDocProps->getTitle());
+ OutUnicode(OOO_STRING_SVTOOLS_RTF_SUBJECT, xDocProps->getSubject());
+
+ OutUnicode(OOO_STRING_SVTOOLS_RTF_KEYWORDS,
+ ::comphelper::string::convertCommaSeparated(xDocProps->getKeywords()));
+ OutUnicode(OOO_STRING_SVTOOLS_RTF_DOCCOMM, xDocProps->getDescription());
+
+ OutUnicode(OOO_STRING_SVTOOLS_RTF_AUTHOR, xDocProps->getAuthor());
+ OutDateTime(OOO_STRING_SVTOOLS_RTF_CREATIM, xDocProps->getCreationDate());
+
+ OutUnicode(OOO_STRING_SVTOOLS_RTF_AUTHOR,xDocProps->getModifiedBy());
+ OutDateTime(OOO_STRING_SVTOOLS_RTF_REVTIM, xDocProps->getModificationDate());
+
+ OutDateTime(OOO_STRING_SVTOOLS_RTF_PRINTIM, xDocProps->getPrintDate());
+ }
+
+ Strm() << '{' << OOO_STRING_SVTOOLS_RTF_COMMENT << " ";
+ OUString sProduct;
+ utl::ConfigManager::GetDirectConfigProperty(utl::ConfigManager::PRODUCTNAME) >>= sProduct;
+ Strm() << OUStringToOString( sProduct, eCurrentEncoding) << "}{" << OOO_STRING_SVTOOLS_RTF_VERN;
+ OutULong( SUPD*10 ) << '}';
+ Strm() << '}';
+}
+
+void RtfExport::WritePageDescTable()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // Write page descriptions (page styles)
+ sal_uInt16 nSize = pDoc->GetPageDescCnt();
+ if( !nSize )
+ return;
+
+ Strm() << sNewLine; // a separator
+ bOutPageDescs = sal_True;
+ Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_PGDSCTBL;
+ for( sal_uInt16 n = 0; n < nSize; ++n )
+ {
+ const SwPageDesc& rPageDesc =
+ const_cast<const SwDoc*>(pDoc)->GetPageDesc( n );
+
+ Strm() << sNewLine << '{' << OOO_STRING_SVTOOLS_RTF_PGDSC;
+ OutULong( n ) << OOO_STRING_SVTOOLS_RTF_PGDSCUSE;
+ OutULong( rPageDesc.ReadUseOn() );
+
+ OutPageDescription( rPageDesc, sal_False, sal_False );
+
+ // search for the next page description
+ sal_uInt16 i = nSize;
+ while( i )
+ if( rPageDesc.GetFollow() ==
+ &const_cast<const SwDoc *>(pDoc)->GetPageDesc( --i ) )
+ break;
+ Strm() << OOO_STRING_SVTOOLS_RTF_PGDSCNXT;
+ OutULong( i ) << ' ';
+ Strm() << OutString( rPageDesc.GetName(), eDefaultEncoding) << ";}";
+ }
+ Strm() << '}' << sNewLine;
+ bOutPageDescs = sal_False;
+
+ // reset table infos, otherwise the depth of the cells will be incorrect,
+ // in case the page style (header or footer) had tables
+ mpTableInfo = ww8::WW8TableInfo::Pointer_t(new ww8::WW8TableInfo());
+}
+
+void RtfExport::ExportDocument_Impl()
+{
+#ifdef DEBUG
+ // MSWordExportBase::WriteText and others write debug messages to std::clog
+ // which is not interesting while debugging RtfExport
+ std::ostringstream aOss;
+ std::streambuf *pOldBuf = std::clog.rdbuf(aOss.rdbuf());
+#endif
+
+ // Make the header
+ Strm() << '{' << OOO_STRING_SVTOOLS_RTF_RTF << '1'
+ << OOO_STRING_SVTOOLS_RTF_ANSI;
+ Strm() << OOO_STRING_SVTOOLS_RTF_DEFF;
+ OutULong( maFontHelper.GetId( (SvxFontItem&)pDoc->GetAttrPool().GetDefaultItem(
+ RES_CHRATR_FONT ) ));
+ // If this not exist, MS don't understand our ansi characters (0x80-0xff).
+ Strm() << "\\adeflang1025";
+
+ // Font table
+ WriteFonts();
+
+ pStyles = new MSWordStyles( *this );
+ // Color and stylesheet table
+ WriteStyles();
+
+ // List table
+ BuildNumbering();
+ WriteNumbering();
+
+ WriteRevTab();
+
+ WriteInfo();
+ // Default TabSize
+ Strm() << m_pAttrOutput->m_aTabStop.makeStringAndClear() << sNewLine;
+ // Page description
+ WritePageDescTable();
+
+ // Enable form protection by default if needed, as there is no switch to
+ // enable it on a per-section basis. OTOH don't always enable it as it
+ // breaks moving of drawings - so write it only in case there is really a
+ // protected section in the document.
+ {
+ const SfxItemPool& rPool = pDoc->GetAttrPool();
+ sal_uInt32 const nMaxItem = rPool.GetItemCount2(RES_PROTECT);
+ for (sal_uInt32 n = 0; n < nMaxItem; ++n)
+ {
+ const SvxProtectItem* pProtect = (const SvxProtectItem*)rPool.GetItem2(RES_PROTECT, n);
+ if (pProtect && pProtect->IsCntntProtected())
+ {
+ Strm() << OOO_STRING_SVTOOLS_RTF_FORMPROT;
+ break;
+ }
+ }
+ }
+
+ // enable form field shading
+ Strm() << OOO_STRING_SVTOOLS_RTF_FORMSHADE;
+
+ // size and empty margins of the page
+ if( pDoc->GetPageDescCnt() )
+ {
+ // Seeking the first SwFmtPageDesc. If no set, the default is valid
+ const SwFmtPageDesc* pSttPgDsc = 0;
+ {
+ const SwNode& rSttNd = *pDoc->GetNodes()[
+ pDoc->GetNodes().GetEndOfExtras().GetIndex() + 2 ];
+ const SfxItemSet* pSet = 0;
+
+ if( rSttNd.IsCntntNode() )
+ pSet = &rSttNd.GetCntntNode()->GetSwAttrSet();
+ else if( rSttNd.IsTableNode() )
+ pSet = &rSttNd.GetTableNode()->GetTable().
+ GetFrmFmt()->GetAttrSet();
+ else if( rSttNd.IsSectionNode() )
+ pSet = &rSttNd.GetSectionNode()->GetSection().
+ GetFmt()->GetAttrSet();
+
+ if( pSet )
+ {
+ sal_uInt16 nPosInDoc;
+ pSttPgDsc = (SwFmtPageDesc*)&pSet->Get( RES_PAGEDESC );
+ if( !pSttPgDsc->GetPageDesc() )
+ pSttPgDsc = 0;
+ else if( pDoc->FindPageDescByName( pSttPgDsc->
+ GetPageDesc()->GetName(), &nPosInDoc ))
+ {
+ Strm() << '{' << OOO_STRING_SVTOOLS_RTF_IGNORE << OOO_STRING_SVTOOLS_RTF_PGDSCNO;
+ OutULong( nPosInDoc ) << '}';
+ }
+ }
+ }
+ const SwPageDesc& rPageDesc = pSttPgDsc ? *pSttPgDsc->GetPageDesc()
+ : const_cast<const SwDoc *>(pDoc)->GetPageDesc( 0 );
+ const SwFrmFmt &rFmtPage = rPageDesc.GetMaster();
+
+ {
+ if( rPageDesc.GetLandscape() )
+ Strm() << OOO_STRING_SVTOOLS_RTF_LANDSCAPE;
+
+ const SwFmtFrmSize& rSz = rFmtPage.GetFrmSize();
+ // Clipboard document is always created without a printer, then
+ // the size will be always LONG_MAX! Solution then is to use A4
+ if( LONG_MAX == rSz.GetHeight() || LONG_MAX == rSz.GetWidth() )
+ {
+ Strm() << OOO_STRING_SVTOOLS_RTF_PAPERH;
+ Size a4 = SvxPaperInfo::GetPaperSize(PAPER_A4);
+ OutULong( a4.Height() ) << OOO_STRING_SVTOOLS_RTF_PAPERW;
+ OutULong( a4.Width() );
+ }
+ else
+ {
+ Strm() << OOO_STRING_SVTOOLS_RTF_PAPERH;
+ OutULong( rSz.GetHeight() ) << OOO_STRING_SVTOOLS_RTF_PAPERW;
+ OutULong( rSz.GetWidth() );
+ }
+ }
+
+ {
+ const SvxLRSpaceItem& rLR = rFmtPage.GetLRSpace();
+ Strm() << OOO_STRING_SVTOOLS_RTF_MARGL;
+ OutLong( rLR.GetLeft() ) << OOO_STRING_SVTOOLS_RTF_MARGR;
+ OutLong( rLR.GetRight() );
+ }
+
+ {
+ const SvxULSpaceItem& rUL = rFmtPage.GetULSpace();
+ Strm() << OOO_STRING_SVTOOLS_RTF_MARGT;
+ OutLong( rUL.GetUpper() ) << OOO_STRING_SVTOOLS_RTF_MARGB;
+ OutLong( rUL.GetLower() );
+ }
+
+ Strm() << OOO_STRING_SVTOOLS_RTF_SECTD << OOO_STRING_SVTOOLS_RTF_SBKNONE;
+ // All sections are unlocked by default
+ Strm() << OOO_STRING_SVTOOLS_RTF_SECTUNLOCKED;
+ OutLong(1);
+ OutPageDescription( rPageDesc, sal_False, sal_True ); // Changed bCheckForFirstPage to sal_True so headers
+ // following title page are correctly added - i13107
+ if( pSttPgDsc )
+ {
+ pAktPageDesc = &rPageDesc;
+ }
+ }
+
+ // line numbering
+ const SwLineNumberInfo& rLnNumInfo = pDoc->GetLineNumberInfo();
+ if ( rLnNumInfo.IsPaintLineNumbers() )
+ AttrOutput().SectionLineNumbering( 0, rLnNumInfo );
+
+ {
+ // write the footnotes and endnotes-out Info
+ const SwFtnInfo& rFtnInfo = pDoc->GetFtnInfo();
+
+ const char* pOut = FTNPOS_CHAPTER == rFtnInfo.ePos
+ ? OOO_STRING_SVTOOLS_RTF_ENDDOC
+ : OOO_STRING_SVTOOLS_RTF_FTNBJ;
+ Strm() << pOut << OOO_STRING_SVTOOLS_RTF_FTNSTART;
+ OutLong( rFtnInfo.nFtnOffset + 1 );
+
+ switch( rFtnInfo.eNum )
+ {
+ case FTNNUM_PAGE: pOut = OOO_STRING_SVTOOLS_RTF_FTNRSTPG; break;
+ case FTNNUM_DOC: pOut = OOO_STRING_SVTOOLS_RTF_FTNRSTCONT; break;
+ default: pOut = OOO_STRING_SVTOOLS_RTF_FTNRESTART; break;
+ }
+ Strm() << pOut;
+
+ switch( rFtnInfo.aFmt.GetNumberingType() )
+ {
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ case SVX_NUM_CHARS_LOWER_LETTER_N: pOut = OOO_STRING_SVTOOLS_RTF_FTNNALC; break;
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ case SVX_NUM_CHARS_UPPER_LETTER_N: pOut = OOO_STRING_SVTOOLS_RTF_FTNNAUC; break;
+ case SVX_NUM_ROMAN_LOWER: pOut = OOO_STRING_SVTOOLS_RTF_FTNNRLC; break;
+ case SVX_NUM_ROMAN_UPPER: pOut = OOO_STRING_SVTOOLS_RTF_FTNNRUC; break;
+ case SVX_NUM_CHAR_SPECIAL: pOut = OOO_STRING_SVTOOLS_RTF_FTNNCHI; break;
+ default: pOut = OOO_STRING_SVTOOLS_RTF_FTNNAR; break;
+ }
+ Strm() << pOut;
+
+
+ const SwEndNoteInfo& rEndNoteInfo = pDoc->GetEndNoteInfo();
+
+ Strm() << OOO_STRING_SVTOOLS_RTF_AENDDOC << OOO_STRING_SVTOOLS_RTF_AFTNRSTCONT
+ << OOO_STRING_SVTOOLS_RTF_AFTNSTART;
+ OutLong( rEndNoteInfo.nFtnOffset + 1 );
+
+ switch( rEndNoteInfo.aFmt.GetNumberingType() )
+ {
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ case SVX_NUM_CHARS_LOWER_LETTER_N: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNALC; break;
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ case SVX_NUM_CHARS_UPPER_LETTER_N: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNAUC; break;
+ case SVX_NUM_ROMAN_LOWER: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNRLC; break;
+ case SVX_NUM_ROMAN_UPPER: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNRUC; break;
+ case SVX_NUM_CHAR_SPECIAL: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNCHI; break;
+ default: pOut = OOO_STRING_SVTOOLS_RTF_AFTNNAR; break;
+ }
+ Strm() << pOut;
+ }
+
+ Strm() << sNewLine;
+
+ // Init sections
+ m_pSections = new MSWordSections( *this );
+
+ WriteMainText();
+
+ Strm() << '}';
+
+#ifdef DEBUG
+ std::clog.rdbuf(pOldBuf);
+#endif
+}
+
+void RtfExport::PrepareNewPageDesc( const SfxItemSet* pSet,
+ const SwNode& rNd, const SwFmtPageDesc* pNewPgDescFmt,
+ const SwPageDesc* pNewPgDesc )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ const SwSectionFmt* pFmt = GetSectionFormat( rNd );
+ const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );
+
+ OSL_ENSURE( pNewPgDescFmt || pNewPgDesc, "Neither page desc format nor page desc provided." );
+
+ if ( pNewPgDescFmt )
+ m_pSections->AppendSection( *pNewPgDescFmt, rNd, pFmt, nLnNm );
+ else if ( pNewPgDesc )
+ m_pSections->AppendSection( pNewPgDesc, rNd, pFmt, nLnNm );
+
+ AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
+}
+
+bool RtfExport::DisallowInheritingOutlineNumbering( const SwFmt& rFmt )
+{
+ bool bRet( false );
+
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if (SFX_ITEM_SET != rFmt.GetItemState(RES_PARATR_NUMRULE, false))
+ {
+ if (const SwFmt *pParent = rFmt.DerivedFrom())
+ {
+ if (((const SwTxtFmtColl*)pParent)->IsAssignedToListLevelOfOutlineStyle())
+ {
+ // Level 9 disables the outline
+ Strm() << OOO_STRING_SVTOOLS_RTF_LEVEL << 9;
+
+ bRet = true;
+ }
+ }
+ }
+
+ return bRet;
+}
+
+void RtfExport::OutputGrfNode( const SwGrfNode& )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /* noop, see RtfAttributeOutput::FlyFrameGraphic */
+}
+
+void RtfExport::OutputOLENode( const SwOLENode& )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /* noop, see RtfAttributeOutput::FlyFrameOLE */
+}
+
+void RtfExport::OutputLinkedOLE( const rtl::OUString& )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+}
+
+void RtfExport::OutputTextNode( const SwTxtNode& rNode )
+{
+ if ( !m_bOutOutlineOnly || rNode.IsOutline( ) )
+ MSWordExportBase::OutputTextNode( rNode );
+}
+
+void RtfExport::AppendSection( const SwPageDesc* pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_pSections->AppendSection( pPageDesc, pFmt, nLnNum );
+ AttrOutput().SectionBreak( msword::PageBreak, m_pSections->CurrentSectionInfo() );
+}
+
+RtfExport::RtfExport( RtfExportFilter *pFilter, SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam, Writer* pWriter, bool bOutOutlineOnly )
+ : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
+ m_pFilter( pFilter ),
+ m_pWriter( pWriter ),
+ m_pAttrOutput( NULL ),
+ m_pSections( NULL ),
+ m_pSdrExport( NULL ),
+ m_bOutOutlineOnly( bOutOutlineOnly ),
+ eDefaultEncoding(
+ rtl_getTextEncodingFromWindowsCharset(
+ sw::ms::rtl_TextEncodingToWinCharset(DEF_ENCODING))),
+ eCurrentEncoding(eDefaultEncoding),
+ bRTFFlySyntax(false)
+{
+ mbExportModeRTF = true;
+ // the attribute output for the document
+ m_pAttrOutput = new RtfAttributeOutput( *this );
+ // that just causes problems for RTF
+ bSubstituteBullets = false;
+ // needed to have a complete font table
+ maFontHelper.bLoadAllFonts = true;
+ // the related SdrExport
+ m_pSdrExport = new RtfSdrExport( *this );
+
+ if (!m_pWriter)
+ m_pWriter = &m_pFilter->m_aWriter;
+}
+
+RtfExport::~RtfExport()
+{
+ delete m_pAttrOutput, m_pAttrOutput = NULL;
+ delete m_pSdrExport, m_pSdrExport = NULL;
+}
+
+SvStream& RtfExport::Strm()
+{
+ return m_pWriter->Strm();
+}
+
+SvStream& RtfExport::OutULong( sal_uLong nVal )
+{
+ return m_pWriter->OutULong( Strm(), nVal );
+}
+
+SvStream& RtfExport::OutLong( long nVal )
+{
+ return m_pWriter->OutLong( Strm(), nVal );
+}
+
+void RtfExport::OutUnicode(const sal_Char *pToken, const String &rContent)
+{
+ if (rContent.Len())
+ {
+ Strm() << '{' << pToken << ' ';
+ Strm() << OutString( rContent, eCurrentEncoding ).getStr();
+ Strm() << '}';
+ }
+}
+
+OString RtfExport::OutHex(sal_uLong nHex, sal_uInt8 nLen)
+{
+ sal_Char aNToABuf[] = "0000000000000000";
+
+ OSL_ENSURE( nLen < sizeof(aNToABuf), "nLen is too big" );
+ if( nLen >= sizeof(aNToABuf) )
+ nLen = (sizeof(aNToABuf)-1);
+
+ // Set pointer to the buffer end
+ sal_Char* pStr = aNToABuf + (sizeof(aNToABuf)-1);
+ for( sal_uInt8 n = 0; n < nLen; ++n )
+ {
+ *(--pStr) = (sal_Char)(nHex & 0xf ) + 48;
+ if( *pStr > '9' )
+ *pStr += 39;
+ nHex >>= 4;
+ }
+ return OString(pStr);
+}
+
+OString RtfExport::OutChar(sal_Unicode c, int *pUCMode, rtl_TextEncoding eDestEnc)
+{
+ OStringBuffer aBuf;
+ const sal_Char* pStr = 0;
+ // 0x0b instead of \n, etc because of the replacements in SwWW8AttrIter::GetSnippet()
+ switch (c)
+ {
+ case 0x0b:
+ // hard line break
+ pStr = OOO_STRING_SVTOOLS_RTF_LINE;
+ break;
+ case '\t':
+ pStr = OOO_STRING_SVTOOLS_RTF_TAB;
+ break;
+ case '\\':
+ case '}':
+ case '{':
+ aBuf.append('\\');
+ aBuf.append((sal_Char)c);
+ break;
+ case 0xa0:
+ // non-breaking space
+ pStr = "\\~";
+ break;
+ case 0x1e:
+ // non-breaking hyphen
+ pStr = "\\_";
+ break;
+ case 0x1f:
+ // optional hyphen
+ pStr = "\\-";
+ break;
+ default:
+ if (c >= ' ' && c <= '~')
+ aBuf.append((sal_Char)c);
+ else {
+ //If we can't convert to the dest encoding, or if
+ //its an uncommon multibyte sequence which most
+ //readers won't be able to handle correctly, then
+ //If we can't convert to the dest encoding, then
+ //export as unicode
+ OUString sBuf(&c, 1);
+ OString sConverted;
+ sal_uInt32 nFlags =
+ RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
+ RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR;
+ bool bWriteAsUnicode = !(sBuf.convertToString(&sConverted,
+ eDestEnc, nFlags))
+ || (RTL_TEXTENCODING_UTF8==eDestEnc); // #i43933# do not export UTF-8 chars in RTF;
+ if (bWriteAsUnicode)
+ sBuf.convertToString(&sConverted,
+ eDestEnc, OUSTRING_TO_OSTRING_CVTFLAGS);
+ const sal_Int32 nLen = sConverted.getLength();
+
+ if (bWriteAsUnicode && pUCMode)
+ {
+ // then write as unicode - character
+ if (*pUCMode != nLen)
+ {
+ aBuf.append("\\uc");
+ aBuf.append((sal_Int32)nLen);
+ // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.
+ aBuf.append(' ');
+ *pUCMode = nLen;
+ }
+ aBuf.append("\\u");
+ aBuf.append((sal_Int32)c);
+ }
+
+ for (sal_Int32 nI = 0; nI < nLen; ++nI)
+ {
+ aBuf.append("\\'");
+ aBuf.append(OutHex(sConverted.getStr()[nI], 2));
+ }
+ }
+ }
+ if (pStr) {
+ aBuf.append(pStr);
+ aBuf.append(' ');
+ }
+ return aBuf.makeStringAndClear();
+}
+
+OString RtfExport::OutString(const String &rStr, rtl_TextEncoding eDestEnc)
+{
+ OSL_TRACE("%s, rStr = '%s'", OSL_THIS_FUNC,
+ OUStringToOString( OUString( rStr ), eDestEnc ).getStr());
+ OStringBuffer aBuf;
+ int nUCMode = 1;
+ for (xub_StrLen n = 0; n < rStr.Len(); ++n)
+ aBuf.append(OutChar(rStr.GetChar(n), &nUCMode, eDestEnc));
+ if (nUCMode != 1) {
+ aBuf.append(OOO_STRING_SVTOOLS_RTF_UC);
+ aBuf.append((sal_Int32)1);
+ aBuf.append(" "); // #i47831# add an additional whitespace, so that "document whitespaces" are not ignored.;
+ }
+ return aBuf.makeStringAndClear();
+}
+
+void RtfExport::OutDateTime(const sal_Char* pStr, const util::DateTime& rDT )
+{
+ Strm() << '{' << pStr << OOO_STRING_SVTOOLS_RTF_YR;
+ OutULong( rDT.Year ) << OOO_STRING_SVTOOLS_RTF_MO;
+ OutULong( rDT.Month ) << OOO_STRING_SVTOOLS_RTF_DY;
+ OutULong( rDT.Day ) << OOO_STRING_SVTOOLS_RTF_HR;
+ OutULong( rDT.Hours ) << OOO_STRING_SVTOOLS_RTF_MIN;
+ OutULong( rDT.Minutes ) << '}';
+}
+
+sal_uInt16 RtfExport::GetColor( const Color& rColor ) const
+{
+ for (RtfColorTbl::const_iterator it=m_aColTbl.begin() ; it != m_aColTbl.end(); ++it )
+ if ((*it).second == rColor) {
+ OSL_TRACE("%s returning %d (%d,%d,%d)", OSL_THIS_FUNC, (*it).first, rColor.GetRed(), rColor.GetGreen(), rColor.GetBlue());
+ return (*it).first;
+ }
+ OSL_FAIL( "No such Color in m_aColTbl!" );
+ return 0;
+}
+
+void RtfExport::InsColor( const Color& rCol )
+{
+ sal_uInt16 n;
+ bool bContainsAuto = false;
+ for (RtfColorTbl::iterator it=m_aColTbl.begin() ; it != m_aColTbl.end(); ++it )
+ if ((*it).second == rCol)
+ return; // Already in the table
+ else if ((*it).second == COL_AUTO)
+ bContainsAuto = true;
+ if (rCol.GetColor() == COL_AUTO)
+ n = 0;
+ else
+ {
+ n = m_aColTbl.size();
+ // Fix for the case when first a !COL_AUTO gets inserted as #0, then
+ // gets overwritten by COL_AUTO
+ if (!n)
+ n++;
+
+ // Fix the case where the table doesn't contain the COL_AUTO at #0
+ else if (!bContainsAuto)
+ n++;
+ }
+ m_aColTbl.insert(std::pair<sal_uInt16,Color>( n, rCol ));
+}
+
+void RtfExport::InsColorLine( const SvxBoxItem& rBox )
+{
+ const SvxBorderLine* pLine = 0;
+
+ if( rBox.GetTop() )
+ InsColor( (pLine = rBox.GetTop())->GetColor() );
+ if( rBox.GetBottom() && pLine != rBox.GetBottom() )
+ InsColor( (pLine = rBox.GetBottom())->GetColor() );
+ if( rBox.GetLeft() && pLine != rBox.GetLeft() )
+ InsColor( (pLine = rBox.GetLeft())->GetColor() );
+ if( rBox.GetRight() && pLine != rBox.GetRight() )
+ InsColor( rBox.GetRight()->GetColor() );
+}
+void RtfExport::OutColorTable()
+{
+ // Build the table from rPool since the colors provided to
+ // RtfAttributeOutput callbacks are too late.
+ sal_uInt32 nMaxItem;
+ const SfxItemPool& rPool = pDoc->GetAttrPool();
+
+ // char color
+ {
+ const SvxColorItem* pCol = (const SvxColorItem*)GetDfltAttr(
+ RES_CHRATR_COLOR );
+ InsColor( pCol->GetValue() );
+ if( 0 != ( pCol = (const SvxColorItem*)rPool.GetPoolDefaultItem(
+ RES_CHRATR_COLOR ) ))
+ InsColor( pCol->GetValue() );
+ nMaxItem = rPool.GetItemCount2(RES_CHRATR_COLOR);
+ for (sal_uInt32 n = 0; n < nMaxItem; ++n)
+ {
+ if( 0 != (pCol = (const SvxColorItem*)rPool.GetItem2(
+ RES_CHRATR_COLOR, n ) ) )
+ InsColor( pCol->GetValue() );
+ }
+
+ const SvxUnderlineItem* pUnder = (const SvxUnderlineItem*)GetDfltAttr( RES_CHRATR_UNDERLINE );
+ InsColor( pUnder->GetColor() );
+ nMaxItem = rPool.GetItemCount2(RES_CHRATR_UNDERLINE);
+ for (sal_uInt32 n = 0; n < nMaxItem; ++n)
+ {
+ if( 0 != (pUnder = (const SvxUnderlineItem*)rPool.GetItem2( RES_CHRATR_UNDERLINE, n ) ) )
+ InsColor( pUnder->GetColor() );
+
+ }
+
+ const SvxOverlineItem* pOver = (const SvxOverlineItem*)GetDfltAttr( RES_CHRATR_OVERLINE );
+ InsColor( pOver->GetColor() );
+ nMaxItem = rPool.GetItemCount2(RES_CHRATR_OVERLINE);
+ for (sal_uInt32 n = 0; n < nMaxItem; ++n)
+ {
+ if( 0 != (pOver = (const SvxOverlineItem*)rPool.GetItem2( RES_CHRATR_OVERLINE, n ) ) )
+ InsColor( pOver->GetColor() );
+
+ }
+
+ }
+
+ // background color
+ static const sal_uInt16 aBrushIds[] = {
+ RES_BACKGROUND, RES_CHRATR_BACKGROUND, 0 };
+
+ for( const sal_uInt16* pIds = aBrushIds; *pIds; ++pIds )
+ {
+ const SvxBrushItem* pBkgrd = (const SvxBrushItem*)GetDfltAttr( *pIds );
+ InsColor( pBkgrd->GetColor() );
+ if( 0 != ( pBkgrd = (const SvxBrushItem*)rPool.GetPoolDefaultItem(
+ *pIds ) ))
+ {
+ InsColor( pBkgrd->GetColor() );
+ }
+ nMaxItem = rPool.GetItemCount2( *pIds );
+ for (sal_uInt32 n = 0; n < nMaxItem; ++n)
+ {
+ if( 0 != (pBkgrd = (const SvxBrushItem*)rPool.GetItem2(
+ *pIds , n ) ))
+ {
+ InsColor( pBkgrd->GetColor() );
+ }
+ }
+ }
+
+ // shadow color
+ {
+ const SvxShadowItem* pShadow = (const SvxShadowItem*)GetDfltAttr(
+ RES_SHADOW );
+ InsColor( pShadow->GetColor() );
+ if( 0 != ( pShadow = (const SvxShadowItem*)rPool.GetPoolDefaultItem(
+ RES_SHADOW ) ))
+ {
+ InsColor( pShadow->GetColor() );
+ }
+ nMaxItem = rPool.GetItemCount2(RES_SHADOW);
+ for (sal_uInt32 n = 0; n < nMaxItem; ++n)
+ {
+ if( 0 != (pShadow = (const SvxShadowItem*)rPool.GetItem2(
+ RES_SHADOW, n ) ) )
+ {
+ InsColor( pShadow->GetColor() );
+ }
+ }
+ }
+
+ // frame border color
+ {
+ const SvxBoxItem* pBox;
+ if( 0 != ( pBox = (const SvxBoxItem*)rPool.GetPoolDefaultItem(
+ RES_BOX ) ))
+ InsColorLine( *pBox );
+ nMaxItem = rPool.GetItemCount2(RES_BOX);
+ for (sal_uInt32 n = 0; n < nMaxItem; ++n)
+ {
+ if( 0 != (pBox = (const SvxBoxItem*)rPool.GetItem2( RES_BOX, n ) ))
+ InsColorLine( *pBox );
+ }
+ }
+
+ for (size_t n = 0; n < m_aColTbl.size(); ++n)
+ {
+ const Color& rCol = m_aColTbl[ n ];
+ if( n || COL_AUTO != rCol.GetColor() )
+ {
+ Strm() << OOO_STRING_SVTOOLS_RTF_RED;
+ OutULong( rCol.GetRed() ) << OOO_STRING_SVTOOLS_RTF_GREEN;
+ OutULong( rCol.GetGreen() ) << OOO_STRING_SVTOOLS_RTF_BLUE;
+ OutULong( rCol.GetBlue() );
+ }
+ Strm() << ';';
+ }
+}
+
+void RtfExport::InsStyle( sal_uInt16 nId, const OString& rStyle )
+{
+ m_aStyTbl.insert(std::pair<sal_uInt16,OString>(nId, rStyle) );
+}
+
+OString* RtfExport::GetStyle( sal_uInt16 nId )
+{
+ std::map<sal_uInt16,OString>::iterator i = m_aStyTbl.find(nId);
+ if (i != m_aStyTbl.end())
+ return &i->second;
+ return NULL;
+}
+
+sal_uInt16 RtfExport::GetRedline( const String& rAuthor )
+{
+ std::map<String,sal_uInt16>::iterator i = m_aRedlineTbl.find(rAuthor);
+ if (i != m_aRedlineTbl.end())
+ return i->second;
+ else
+ {
+ int nId = m_aRedlineTbl.size();
+ m_aRedlineTbl.insert(std::pair<String,sal_uInt16>(rAuthor,nId));
+ return nId;
+ }
+}
+
+const String* RtfExport::GetRedline( sal_uInt16 nId )
+{
+ for(std::map<String,sal_uInt16>::iterator aIter = m_aRedlineTbl.begin(); aIter != m_aRedlineTbl.end(); ++aIter)
+ if ((*aIter).second == nId)
+ return &(*aIter).first;
+ return NULL;
+}
+
+void RtfExport::OutPageDescription( const SwPageDesc& rPgDsc, sal_Bool bWriteReset, sal_Bool bCheckForFirstPage )
+{
+ OSL_TRACE("%s start", OSL_THIS_FUNC);
+ const SwPageDesc *pSave = pAktPageDesc;
+
+ pAktPageDesc = &rPgDsc;
+ if( bCheckForFirstPage && pAktPageDesc->GetFollow() &&
+ pAktPageDesc->GetFollow() != pAktPageDesc )
+ pAktPageDesc = pAktPageDesc->GetFollow();
+
+ if( bWriteReset )
+ {
+ if( pCurPam->GetPoint()->nNode == pOrigPam->Start()->nNode )
+ Strm() << OOO_STRING_SVTOOLS_RTF_SECTD << OOO_STRING_SVTOOLS_RTF_SBKNONE;
+ else
+ Strm() << OOO_STRING_SVTOOLS_RTF_SECT << OOO_STRING_SVTOOLS_RTF_SECTD;
+ }
+
+ if( pAktPageDesc->GetLandscape() )
+ Strm() << OOO_STRING_SVTOOLS_RTF_LNDSCPSXN;
+
+ const SwFmt *pFmt = &pAktPageDesc->GetMaster(); //GetLeft();
+ bOutPageDescs = true;
+ OutputFormat(*pFmt, true, false);
+ bOutPageDescs = false;
+
+ // normal header / footer (without a style)
+ const SfxPoolItem* pItem;
+ if( pAktPageDesc->GetLeft().GetAttrSet().GetItemState( RES_HEADER, sal_False,
+ &pItem ) == SFX_ITEM_SET)
+ WriteHeaderFooter(*pItem, true);
+ if( pAktPageDesc->GetLeft().GetAttrSet().GetItemState( RES_FOOTER, sal_False,
+ &pItem ) == SFX_ITEM_SET)
+ WriteHeaderFooter(*pItem, false);
+
+ // title page
+ if( pAktPageDesc != &rPgDsc )
+ {
+ pAktPageDesc = &rPgDsc;
+ Strm() << OOO_STRING_SVTOOLS_RTF_TITLEPG;
+ if( pAktPageDesc->GetMaster().GetAttrSet().GetItemState( RES_HEADER,
+ sal_False, &pItem ) == SFX_ITEM_SET )
+ WriteHeaderFooter(*pItem, true);
+ if( pAktPageDesc->GetMaster().GetAttrSet().GetItemState( RES_FOOTER,
+ sal_False, &pItem ) == SFX_ITEM_SET )
+ WriteHeaderFooter(*pItem, false);
+ }
+
+ // numbering type
+ AttrOutput().SectionPageNumbering(pAktPageDesc->GetNumType().GetNumberingType(), 0);
+
+ pAktPageDesc = pSave;
+ OSL_TRACE("%s end", OSL_THIS_FUNC);
+}
+
+void RtfExport::WriteHeaderFooter(const SfxPoolItem& rItem, bool bHeader)
+{
+ if (bHeader)
+ {
+ const SwFmtHeader& rHeader = (const SwFmtHeader&)rItem;
+ if (!rHeader.IsActive())
+ return;
+ }
+ else
+ {
+ const SwFmtFooter& rFooter = (const SwFmtFooter&)rItem;
+ if (!rFooter.IsActive())
+ return;
+ }
+
+ OSL_TRACE("%s start", OSL_THIS_FUNC);
+
+ const sal_Char* pStr = (bHeader ? OOO_STRING_SVTOOLS_RTF_HEADER : OOO_STRING_SVTOOLS_RTF_FOOTER);
+ /* is this a title page? */
+ if( pAktPageDesc->GetFollow() && pAktPageDesc->GetFollow() != pAktPageDesc )
+ {
+ Strm() << OOO_STRING_SVTOOLS_RTF_TITLEPG;
+ pStr = (bHeader ? OOO_STRING_SVTOOLS_RTF_HEADERF : OOO_STRING_SVTOOLS_RTF_FOOTERF);
+ }
+ Strm() << '{' << pStr;
+ WriteHeaderFooterText(pAktPageDesc->GetMaster(), bHeader);
+ Strm() << '}';
+
+ OSL_TRACE("%s end", OSL_THIS_FUNC);
+}
+
+void RtfExport::WriteHeaderFooter(const SwFrmFmt& rFmt, bool bHeader, const sal_Char* pStr)
+{
+ OSL_TRACE("%s start", OSL_THIS_FUNC);
+
+ m_pAttrOutput->WriteHeaderFooter_Impl( rFmt, bHeader, pStr );
+
+ OSL_TRACE("%s end", OSL_THIS_FUNC);
+}
+
+/// Glue class to call RtfExport as an internal filter, needed by copy&paste support.
+class SwRTFWriter : public Writer
+{
+ private:
+ bool m_bOutOutlineOnly;
+
+ public:
+ SwRTFWriter( const String& rFilterName, const String& rBaseURL );
+ virtual ~SwRTFWriter();
+ virtual sal_uLong WriteStream();
+};
+
+SwRTFWriter::SwRTFWriter( const String& rFltName, const String & rBaseURL )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ SetBaseURL( rBaseURL );
+ // export outline nodes, only (send outline to clipboard/presentation)
+ m_bOutOutlineOnly = 'O' == rFltName.GetChar( 0 );
+}
+
+SwRTFWriter::~SwRTFWriter()
+{}
+
+sal_uLong SwRTFWriter::WriteStream()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ RtfExport aExport( NULL, pDoc, new SwPaM( *pCurPam->End(), *pCurPam->Start() ), pCurPam, this, m_bOutOutlineOnly );
+ aExport.ExportDocument( true );
+ return 0;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL ExportRTF( const String& rFltName, const String& rBaseURL, WriterRef& xRet )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+ xRet = new SwRTFWriter( rFltName, rBaseURL );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfexport.hxx b/sw/source/filter/ww8/rtfexport.hxx
new file mode 100644
index 000000000000..60b6c347ae0c
--- /dev/null
+++ b/sw/source/filter/ww8/rtfexport.hxx
@@ -0,0 +1,221 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * Copyright 2010 Miklos Vajna.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _RTFEXPORT_HXX_
+#define _RTFEXPORT_HXX_
+
+#include <set>
+#include "wrtww8.hxx"
+
+#include <rtl/ustring.hxx>
+
+#include <cstdio>
+#include <map>
+
+class RtfAttributeOutput;
+class RtfExportFilter;
+class RtfSdrExport;
+typedef std::map<sal_uInt16,Color> RtfColorTbl;
+typedef std::map<sal_uInt16,rtl::OString> RtfStyleTbl;
+typedef std::map<String,sal_uInt16> RtfRedlineTbl;
+class SwNode;
+class SwEndNode;
+class SwTableNode;
+class SwTxtNode;
+class SwGrfNode;
+class SwOLENode;
+class SwSectionNode;
+class SwNumRuleTbl;
+
+namespace com { namespace sun { namespace star {
+ namespace frame { class XModel; }
+} } }
+
+/// The class that does all the actual RTF export-related work.
+class RtfExport : public MSWordExportBase
+{
+ /// Pointer to the filter that owns us.
+ RtfExportFilter *m_pFilter;
+ Writer* m_pWriter;
+
+ /// Attribute output for document.
+ RtfAttributeOutput *m_pAttrOutput;
+
+ /// Sections/headers/footers
+ MSWordSections *m_pSections;
+
+ RtfSdrExport *m_pSdrExport;
+ bool m_bOutOutlineOnly;
+
+public:
+ /// Access to the attribute output class.
+ virtual AttributeOutputBase& AttrOutput() const;
+
+ /// Access to the sections/headers/footres.
+ virtual MSWordSections& Sections() const;
+
+ /// Access to the Rtf Sdr exporter.
+ virtual RtfSdrExport& SdrExporter() const;
+
+ /// Determines if the format is expected to support unicode.
+ virtual bool SupportsUnicode() const { return true; }
+
+ /// Guess the script (asian/western).
+ virtual bool CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich );
+
+ virtual void AppendBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen );
+
+ virtual void AppendBookmark( const rtl::OUString& rName, bool bSkip = false );
+
+ virtual void WriteCR( ww8::WW8TableNodeInfoInner::Pointer_t /*pTableTextNodeInfoInner = ww8::WW8TableNodeInfoInner::Pointer_t()*/ ) { /* no-op for rtf, most probably should not even be in MSWordExportBase */ }
+ virtual void WriteChar( sal_Unicode );
+
+ /// Write the numbering table.
+ virtual void WriteNumbering();
+
+ /// Write the revision table.
+ virtual void WriteRevTab();
+
+ /// Output the actual headers and footers.
+ virtual void WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
+ const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 nBreakCode );
+
+ /// Write the field
+ virtual void OutputField( const SwField* pFld, ww::eField eFldType,
+ const String& rFldCmd, sal_uInt8 nMode = nsFieldFlags::WRITEFIELD_ALL );
+
+ /// Write the data of the form field
+ virtual void WriteFormData( const ::sw::mark::IFieldmark& rFieldmark );
+ virtual void WriteHyperlinkData( const ::sw::mark::IFieldmark& rFieldmark );
+
+ virtual void DoComboBox(const rtl::OUString &rName,
+ const rtl::OUString &rHelp,
+ const rtl::OUString &ToolTip,
+ const rtl::OUString &rSelected,
+ com::sun::star::uno::Sequence<rtl::OUString> &rListItems);
+
+ virtual void DoFormText(const SwInputField * pFld);
+
+ virtual sal_uLong ReplaceCr( sal_uInt8 nChar );
+
+protected:
+ /// Format-dependant part of the actual export.
+ virtual void ExportDocument_Impl();
+
+ virtual void SectionBreaksAndFrames( const SwTxtNode& /*rNode*/ ) {}
+
+ /// Get ready for a new section.
+ virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
+ const SwNode& rNd,
+ const SwFmtPageDesc* pNewPgDescFmt = 0,
+ const SwPageDesc* pNewPgDesc = 0 );
+
+ /// Return value indicates if an inherited outline numbering is suppressed.
+ virtual bool DisallowInheritingOutlineNumbering(const SwFmt &rFmt);
+
+ /// Output SwTxtNode is depending on outline export mode
+ virtual void OutputTextNode( const SwTxtNode& );
+
+ /// Output SwGrfNode
+ virtual void OutputGrfNode( const SwGrfNode& );
+
+ /// Output SwOLENode
+ virtual void OutputOLENode( const SwOLENode& );
+
+ virtual void OutputLinkedOLE(const rtl::OUString&);
+
+ virtual void AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum );
+
+public:
+ /// Pass the pDocument, pCurrentPam and pOriginalPam to the base class.
+ RtfExport( RtfExportFilter *pFilter, SwDoc *pDocument,
+ SwPaM *pCurrentPam, SwPaM *pOriginalPam, Writer* pWriter,
+ bool bOutOutlineOnly = false );
+
+ /// Destructor.
+ virtual ~RtfExport();
+
+#if defined(UNX)
+ static const sal_Char sNewLine; // \012 or \015
+#else
+ static const sal_Char sNewLine[]; // \015\012
+#endif
+
+ rtl_TextEncoding eDefaultEncoding;
+ rtl_TextEncoding eCurrentEncoding;
+ /// This is used by OutputFlyFrame_Impl() to control the written syntax
+ bool bRTFFlySyntax;
+
+ sal_Bool m_bOutStyleTab : 1;
+ SvStream& Strm();
+ SvStream& OutULong( sal_uLong nVal );
+ SvStream& OutLong( long nVal );
+ void OutUnicode(const sal_Char *pToken, const String &rContent);
+ void OutDateTime(const sal_Char* pStr, const util::DateTime& rDT );
+ static rtl::OString OutChar(sal_Unicode c, int *pUCMode, rtl_TextEncoding eDestEnc);
+ static rtl::OString OutString(const String &rStr, rtl_TextEncoding eDestEnc);
+ static rtl::OString OutHex(sal_uLong nHex, sal_uInt8 nLen);
+ void OutPageDescription( const SwPageDesc& rPgDsc, sal_Bool bWriteReset, sal_Bool bCheckForFirstPage );
+
+ sal_uInt16 GetColor( const Color& rColor ) const;
+ void InsColor( const Color& rCol );
+ void InsColorLine( const SvxBoxItem& rBox );
+ void OutColorTable();
+ sal_uInt16 GetRedline( const String& rAuthor );
+ const String* GetRedline( sal_uInt16 nId );
+
+ void InsStyle( sal_uInt16 nId, const rtl::OString& rStyle );
+ rtl::OString* GetStyle( sal_uInt16 nId );
+
+private:
+ /// No copying.
+ RtfExport( const RtfExport& );
+
+ /// No copying.
+ RtfExport& operator=( const RtfExport& );
+
+ void WriteFonts();
+ void WriteStyles();
+ void WriteMainText();
+ void WriteInfo();
+ /// Writes the writer-specific \pgdsctbl group.
+ void WritePageDescTable();
+ /// This is necessary to have the numbering table ready before the main text is being processed.
+ void BuildNumbering();
+ void WriteHeaderFooter(const SfxPoolItem& rItem, bool bHeader);
+ void WriteHeaderFooter(const SwFrmFmt& rFmt, bool bHeader, const sal_Char* pStr);
+
+ RtfColorTbl m_aColTbl;
+ RtfStyleTbl m_aStyTbl;
+ RtfRedlineTbl m_aRedlineTbl;
+};
+
+#endif // _RTFEXPORT_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfexportfilter.cxx b/sw/source/filter/ww8/rtfexportfilter.cxx
new file mode 100644
index 000000000000..0aedd4add7f8
--- /dev/null
+++ b/sw/source/filter/ww8/rtfexportfilter.cxx
@@ -0,0 +1,138 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * Copyright 2010 Miklos Vajna.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include <rtfexportfilter.hxx>
+#include <rtfexport.hxx>
+#include <rtfimportfilter.hxx>
+
+#include <docsh.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <unotxdoc.hxx>
+
+#include <cppuhelper/factory.hxx>
+#include <comphelper/mediadescriptor.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+
+RtfExportFilter::RtfExportFilter( const uno::Reference< uno::XComponentContext >& xCtx) :
+ m_xCtx( xCtx )
+{
+}
+
+RtfExportFilter::~RtfExportFilter()
+{
+}
+
+sal_Bool RtfExportFilter::filter( const uno::Sequence< beans::PropertyValue >& aDescriptor )
+ throw (uno::RuntimeException)
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ MediaDescriptor aMediaDesc = aDescriptor;
+ ::uno::Reference< io::XStream > xStream =
+ aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_STREAMFOROUTPUT(), uno::Reference< io::XStream >() );
+ m_pStream = utl::UcbStreamHelper::CreateStream( xStream, sal_True );
+ m_aWriter.SetStream(m_pStream);
+
+ // get SwDoc*
+ uno::Reference< uno::XInterface > xIfc( m_xSrcDoc, uno::UNO_QUERY );
+ SwXTextDocument *pTxtDoc = dynamic_cast< SwXTextDocument * >( xIfc.get() );
+ if ( !pTxtDoc ) {
+ return sal_False;
+ }
+
+ SwDoc *pDoc = pTxtDoc->GetDocShell()->GetDoc();
+ if ( !pDoc ) {
+ return sal_False;
+ }
+
+ // get SwPaM*
+ // we get SwPaM for the entire document; copy&paste is handled internally, not via UNO
+ SwPaM aPam( pDoc->GetNodes().GetEndOfContent() );
+ aPam.SetMark();
+ aPam.Move( fnMoveBackward, fnGoDoc );
+
+ SwPaM *pCurPam = new SwPaM( *aPam.End(), *aPam.Start() );
+
+ // export the document
+ // (in a separate block so that it's destructed before the commit)
+ {
+ RtfExport aExport( this, pDoc, pCurPam, &aPam, NULL );
+ aExport.ExportDocument( true );
+ }
+
+ // delete the pCurPam
+ if ( pCurPam )
+ {
+ while ( pCurPam->GetNext() != pCurPam )
+ delete pCurPam->GetNext();
+ delete pCurPam;
+ }
+ delete m_pStream;
+
+ return sal_True;
+}
+
+
+void RtfExportFilter::cancel( ) throw (uno::RuntimeException)
+{
+}
+
+void RtfExportFilter::setSourceDocument( const uno::Reference< lang::XComponent >& xDoc )
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ m_xSrcDoc = xDoc;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// UNO helpers
+//////////////////////////////////////////////////////////////////////////
+
+OUString RtfExport_getImplementationName()
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPL_NAME_RTFEXPORT ) );
+}
+
+uno::Sequence< OUString > SAL_CALL RtfExport_getSupportedServiceNames() throw()
+{
+ const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.ExportFilter" ) );
+ const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
+ return aSeq;
+}
+
+uno::Reference< uno::XInterface > SAL_CALL RtfExport_createInstance(const uno::Reference< uno::XComponentContext > & xCtx ) throw( uno::Exception )
+{
+ return (cppu::OWeakObject*) new RtfExportFilter( xCtx );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfexportfilter.hxx b/sw/source/filter/ww8/rtfexportfilter.hxx
new file mode 100644
index 000000000000..de7c94cf80ac
--- /dev/null
+++ b/sw/source/filter/ww8/rtfexportfilter.hxx
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * Copyright 2010 Miklos Vajna.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _RTFEXPORTFILTER_HXX_
+#define _RTFEXPORTFILTER_HXX_
+
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XExporter.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/implbase2.hxx>
+#include <tools/stream.hxx>
+#include <shellio.hxx>
+
+/// Dummy Writer implementation to be able to use the string format methods of the base class
+class RtfWriter : public Writer
+{
+protected:
+ sal_uLong WriteStream() { return 0; }
+};
+
+/// The physical access to the RTF document (for writing).
+class RtfExportFilter : public cppu::WeakImplHelper2
+<
+ com::sun::star::document::XFilter,
+ com::sun::star::document::XExporter
+>
+{
+protected:
+ ::com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > m_xCtx;
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > m_xSrcDoc;
+ SvStream* m_pStream;
+public:
+ RtfExportFilter( const ::com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& xCtx );
+ virtual ~RtfExportFilter();
+
+ // XFilter
+ virtual sal_Bool SAL_CALL filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL cancel( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XExporter
+ virtual void SAL_CALL setSourceDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc )
+ throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+
+ RtfWriter m_aWriter;
+};
+
+::rtl::OUString RtfExport_getImplementationName();
+::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL RtfExport_getSupportedServiceNames()
+ throw();
+::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL RtfExport_createInstance(
+ const ::com::sun::star::uno::Reference<
+ com::sun::star::uno::XComponentContext > &xCtx)
+ throw( ::com::sun::star::uno::Exception );
+
+#define IMPL_NAME_RTFEXPORT "com.sun.star.comp.Writer.RtfExport"
+
+#endif // _RTFEXPORTFILTER_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfimportfilter.cxx b/sw/source/filter/ww8/rtfimportfilter.cxx
new file mode 100644
index 000000000000..980c96fd8974
--- /dev/null
+++ b/sw/source/filter/ww8/rtfimportfilter.cxx
@@ -0,0 +1,139 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * Copyright 2010 Miklos Vajna.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "rtfimportfilter.hxx"
+#include "../rtf/swparrtf.hxx"
+
+#include <docsh.hxx>
+#include <doc.hxx>
+#include <pam.hxx>
+#include <unotxdoc.hxx>
+#include <swerror.h>
+
+#include <cppuhelper/factory.hxx>
+#include <comphelper/mediadescriptor.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+
+#include <com/sun/star/frame/XDesktop.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <com/sun/star/frame/XComponentLoader.hpp>
+
+using namespace ::comphelper;
+using namespace ::com::sun::star;
+using ::rtl::OUString;
+using rtl::OUStringToOString;
+
+RtfImportFilter::RtfImportFilter( const uno::Reference< uno::XComponentContext > &xCtx ) :
+ m_xCtx( xCtx )
+{
+}
+
+RtfImportFilter::~RtfImportFilter()
+{
+}
+
+sal_Bool RtfImportFilter::filter( const uno::Sequence< beans::PropertyValue >& aDescriptor )
+ throw (uno::RuntimeException)
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ MediaDescriptor aMediaDesc = aDescriptor;
+ ::uno::Reference< io::XInputStream > xInputStream =
+ aMediaDesc.getUnpackedValueOrDefault( MediaDescriptor::PROP_INPUTSTREAM(), uno::Reference< io::XInputStream >() );
+ SvStream* pStream = utl::UcbStreamHelper::CreateStream( xInputStream, sal_True );
+ if (!pStream)
+ return sal_False;
+
+ // get SwDoc*
+ uno::Reference< uno::XInterface > xIfc( m_xDstDoc, uno::UNO_QUERY );
+ SwXTextDocument *pTxtDoc = dynamic_cast< SwXTextDocument * >( xIfc.get() );
+ if (!pTxtDoc)
+ return sal_False;
+ SwDoc *pDoc = pTxtDoc->GetDocShell()->GetDoc();
+ if (!pDoc)
+ return sal_False;
+
+ // get SwPaM*
+ // NEEDSWORK should we care about partial imports? For now we just import
+ // the whole document
+ SwPaM aPam( pDoc->GetNodes().GetEndOfContent() );
+ aPam.SetMark();
+ aPam.Move( fnMoveBackward, fnGoDoc );
+ SwPaM *pCurPam = new SwPaM( *aPam.End(), *aPam.Start() );
+
+ String aURL;
+ OUString sTemp;
+ for ( sal_Int32 i = 0; i < aDescriptor.getLength(); i++ )
+ {
+ if( aDescriptor[i].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("URL")) )
+ {
+ aDescriptor[i].Value >>= sTemp;
+ aURL = sTemp;
+ }
+ }
+
+ RtfReader aReader;
+ sal_Bool bRet = aReader.Read(pStream, *pDoc, aURL, *pCurPam) == 0;
+ delete pStream;
+ return bRet;
+}
+
+
+void RtfImportFilter::cancel( ) throw (uno::RuntimeException)
+{
+}
+
+void RtfImportFilter::setTargetDocument( const uno::Reference< lang::XComponent >& xDoc )
+ throw (lang::IllegalArgumentException, uno::RuntimeException)
+{
+ m_xDstDoc = xDoc;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// UNO helpers
+//////////////////////////////////////////////////////////////////////////
+
+OUString RtfImport_getImplementationName()
+{
+ return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPL_NAME_RTFIMPORT ) );
+}
+
+uno::Sequence< OUString > SAL_CALL RtfImport_getSupportedServiceNames() throw()
+{
+ const OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.ImportFilter" ) );
+ const uno::Sequence< OUString > aSeq( &aServiceName, 1 );
+ return aSeq;
+}
+
+uno::Reference< uno::XInterface > SAL_CALL RtfImport_createInstance(const uno::Reference< uno::XComponentContext > & xCtx ) throw( uno::Exception )
+{
+ return (cppu::OWeakObject*) new RtfImportFilter( xCtx );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfimportfilter.hxx b/sw/source/filter/ww8/rtfimportfilter.hxx
new file mode 100644
index 000000000000..9782dae31300
--- /dev/null
+++ b/sw/source/filter/ww8/rtfimportfilter.hxx
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * Copyright 2010 Miklos Vajna.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _RTFIMPORTFILTER_HXX_
+#define _RTFIMPORTFILTER_HXX_
+
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/uno/XComponentContext.hpp>
+#include <cppuhelper/implbase2.hxx>
+#include <tools/stream.hxx>
+#include <shellio.hxx>
+
+/// The physical access to the RTF document (for reading).
+class RtfImportFilter : public cppu::WeakImplHelper2
+<
+ com::sun::star::document::XFilter,
+ com::sun::star::document::XImporter
+>
+{
+protected:
+ ::com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext > m_xCtx;
+ ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > m_xDstDoc;
+public:
+ RtfImportFilter( const ::com::sun::star::uno::Reference< com::sun::star::uno::XComponentContext >& xCtx );
+ virtual ~RtfImportFilter();
+
+ // XFilter
+ virtual sal_Bool SAL_CALL filter( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aDescriptor )
+ throw (::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL cancel( )
+ throw (::com::sun::star::uno::RuntimeException);
+
+ // XImporter
+ virtual void SAL_CALL setTargetDocument( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent >& xDoc )
+ throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
+};
+
+::rtl::OUString RtfImport_getImplementationName();
+::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL RtfImport_getSupportedServiceNames()
+ throw();
+::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > SAL_CALL RtfImport_createInstance(
+ const ::com::sun::star::uno::Reference<
+ com::sun::star::uno::XComponentContext > &xCtx)
+ throw( ::com::sun::star::uno::Exception );
+
+#define IMPL_NAME_RTFIMPORT "com.sun.star.comp.Writer.RtfImport"
+
+#endif // _RTFIMPORTFILTER_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfsdrexport.cxx b/sw/source/filter/ww8/rtfsdrexport.cxx
new file mode 100644
index 000000000000..99a166196d09
--- /dev/null
+++ b/sw/source/filter/ww8/rtfsdrexport.cxx
@@ -0,0 +1,588 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * Copyright 2010 Miklos Vajna.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#include "rtfsdrexport.hxx"
+#include "rtfexport.hxx"
+#include "writerhelper.hxx"
+#include "rtfattributeoutput.hxx"
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <osl/diagnose.h>
+#include <rtl/strbuf.hxx>
+#include <rtl/ustring.hxx>
+#include <svl/itemiter.hxx>
+#include <svtools/rtfkeywd.hxx>
+#include <editeng/editdata.hxx>
+#include <editeng/editobj.hxx>
+#include <editeng/flditem.hxx>
+#include <editeng/fontitem.hxx>
+#include <svx/svdotext.hxx>
+#include <tools/stream.hxx>
+#include <breakit.hxx>
+
+using rtl::OString;
+using rtl::OStringBuffer;
+using rtl::OUString;
+using rtl::OUStringBuffer;
+using namespace sw::util;
+
+/// Implementation of an empty stream that silently succeeds, but does nothing.
+///
+/// In fact, this is a hack. The right solution is to abstract EscherEx to be
+/// able to work without SvStream; but at the moment it is better to live with
+/// this I guess.
+class SvNullStream : public SvStream
+{
+protected:
+ virtual sal_Size GetData( void* pData, sal_Size nSize ) { memset( pData, 0, nSize ); return nSize; }
+ virtual sal_Size PutData( const void*, sal_Size nSize ) { return nSize; }
+ virtual sal_Size SeekPos( sal_Size nPos ) { return nPos; }
+ virtual void SetSize( sal_Size ) {}
+ virtual void FlushData() {}
+
+public:
+ SvNullStream() : SvStream() {}
+ virtual ~SvNullStream() {}
+};
+
+RtfSdrExport::RtfSdrExport( RtfExport &rExport )
+ : EscherEx( EscherExGlobalRef( new EscherExGlobal ), *( new SvNullStream )),
+ m_rExport( rExport ),
+ m_rAttrOutput( (RtfAttributeOutput&)m_rExport.AttrOutput() ),
+ m_nShapeType( ESCHER_ShpInst_Nil ),
+ m_pShapeStyle( new OStringBuffer( 200 ) ),
+ m_pShapeTypeWritten( new bool[ ESCHER_ShpInst_COUNT ] )
+{
+ mnGroupLevel = 1;
+ memset( m_pShapeTypeWritten, 0, ESCHER_ShpInst_COUNT * sizeof( bool ) );
+}
+
+RtfSdrExport::~RtfSdrExport()
+{
+ delete mpOutStrm, mpOutStrm = NULL;
+ delete m_pShapeStyle, m_pShapeStyle = NULL;
+ delete[] m_pShapeTypeWritten, m_pShapeTypeWritten = NULL;
+}
+
+void RtfSdrExport::OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ EscherEx::OpenContainer( nEscherContainer, nRecInstance );
+
+ if ( nEscherContainer == ESCHER_SpContainer )
+ {
+ m_nShapeType = ESCHER_ShpInst_Nil;
+ if ( m_pShapeStyle->getLength() )
+ m_pShapeStyle->makeStringAndClear();
+ m_pShapeStyle->ensureCapacity( 200 );
+ m_aShapeProps.clear();
+ }
+}
+
+void RtfSdrExport::CloseContainer()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( mRecTypes.back() == ESCHER_SpContainer )
+ {
+ // write the shape now when we have all the info
+ sal_Int32 nShapeElement = StartShape();
+ EndShape( nShapeElement );
+
+ // cleanup
+ m_nShapeType = ESCHER_ShpInst_Nil;
+ }
+
+ EscherEx::CloseContainer();
+}
+
+sal_uInt32 RtfSdrExport::EnterGroup( const String& /*rShapeName*/, const Rectangle* /*pRect*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ return GenerateShapeId();
+}
+
+void RtfSdrExport::LeaveGroup()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /* noop */
+}
+
+void RtfSdrExport::AddShape( sal_uInt32 nShapeType, sal_uInt32 nShapeFlags, sal_uInt32 /*nShapeId*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ m_nShapeType = nShapeType;
+ m_nShapeFlags = nShapeFlags;
+}
+
+inline sal_uInt16 impl_GetUInt16( const sal_uInt8* &pVal )
+{
+ sal_uInt16 nRet = *pVal++;
+ nRet += ( *pVal++ ) << 8;
+ return nRet;
+}
+
+inline sal_Int32 impl_GetPointComponent( const sal_uInt8* &pVal, sal_uInt16 nPointSize )
+{
+ sal_Int32 nRet = 0;
+ if ( ( nPointSize == 0xfff0 ) || ( nPointSize == 4 ) )
+ {
+ sal_uInt16 nUnsigned = *pVal++;
+ nUnsigned += ( *pVal++ ) << 8;
+
+ nRet = sal_Int16( nUnsigned );
+ }
+ else if ( nPointSize == 8 )
+ {
+ sal_uInt32 nUnsigned = *pVal++;
+ nUnsigned += ( *pVal++ ) << 8;
+ nUnsigned += ( *pVal++ ) << 16;
+ nUnsigned += ( *pVal++ ) << 24;
+
+ nRet = nUnsigned;
+ }
+
+ return nRet;
+}
+
+void RtfSdrExport::Commit( EscherPropertyContainer& rProps, const Rectangle& rRect )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( m_nShapeType == ESCHER_ShpInst_Nil )
+ return;
+
+ if ( m_nShapeType == ESCHER_ShpInst_Line )
+ AddLineDimensions( rRect );
+ else
+ AddRectangleDimensions( *m_pShapeStyle, rRect );
+
+ // properties
+ const EscherProperties &rOpts = rProps.GetOpts();
+ for ( EscherProperties::const_iterator it = rOpts.begin(); it != rOpts.end(); ++it )
+ {
+ sal_uInt16 nId = ( it->nPropId & 0x0FFF );
+
+ switch ( nId )
+ {
+ case ESCHER_Prop_WrapText:
+ {
+ int nWrapType = 0;
+ switch ( it->nPropValue )
+ {
+ case ESCHER_WrapSquare: nWrapType = 2; break;
+ case ESCHER_WrapByPoints: nWrapType = 4; break;
+ case ESCHER_WrapNone: nWrapType = 3; break;
+ case ESCHER_WrapTopBottom: nWrapType = 1; break;
+ case ESCHER_WrapThrough: nWrapType = 5; break;
+ }
+ if ( nWrapType )
+ m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPWR).append((sal_Int32)nWrapType);
+ }
+ break;
+ case ESCHER_Prop_fillColor:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("fillColor"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_fillBackColor:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("fillBackColor"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_AnchorText:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("anchorText"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_fNoFillHitTest:
+ if (it->nPropValue)
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("fNoFillHitTest"), OString::valueOf(sal_Int32(1))));
+ break;
+ case ESCHER_Prop_fNoLineDrawDash:
+ // for some reason the value is set to 0x90000 if lines are switched off
+ if( it->nPropValue == 0x90000 )
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("fLine"), OString::valueOf(sal_Int32(0))));
+ break;
+ case ESCHER_Prop_lineColor:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("lineColor"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_lineBackColor:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("lineBackColor"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_lineJoinStyle:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("lineJoinStyle"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_fshadowObscured:
+ if (it->nPropValue)
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("fshadowObscured"), OString::valueOf(sal_Int32(1))));
+ break;
+ case ESCHER_Prop_geoLeft:
+ case ESCHER_Prop_geoTop:
+ {
+ sal_uInt32 nLeft = 0, nTop = 0;
+
+ if ( nId == ESCHER_Prop_geoLeft )
+ {
+ nLeft = it->nPropValue;
+ rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
+ }
+ else
+ {
+ nTop = it->nPropValue;
+ rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
+ }
+
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("geoLeft"),
+ OString::valueOf(sal_Int32(sal_Int32( nLeft )))));
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("geoTop"),
+ OString::valueOf(sal_Int32(sal_Int32( nTop )))));
+ }
+ break;
+
+ case ESCHER_Prop_geoRight:
+ case ESCHER_Prop_geoBottom:
+ {
+ sal_uInt32 nLeft = 0, nRight = 0, nTop = 0, nBottom = 0;
+ rProps.GetOpt( ESCHER_Prop_geoLeft, nLeft );
+ rProps.GetOpt( ESCHER_Prop_geoTop, nTop );
+
+ if ( nId == ESCHER_Prop_geoRight )
+ {
+ nRight = it->nPropValue;
+ rProps.GetOpt( ESCHER_Prop_geoBottom, nBottom );
+ }
+ else
+ {
+ nBottom = it->nPropValue;
+ rProps.GetOpt( ESCHER_Prop_geoRight, nRight );
+ }
+
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("geoRight"),
+ OString::valueOf(sal_Int32(sal_Int32( nRight ) - sal_Int32( nLeft )))));
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("geoBottom"),
+ OString::valueOf(sal_Int32(sal_Int32( nBottom ) - sal_Int32( nTop )))));
+ }
+ break;
+ case ESCHER_Prop_pVertices:
+ case ESCHER_Prop_pSegmentInfo:
+ {
+ EscherPropSortStruct aVertices;
+ EscherPropSortStruct aSegments;
+
+ if ( rProps.GetOpt( ESCHER_Prop_pVertices, aVertices ) &&
+ rProps.GetOpt( ESCHER_Prop_pSegmentInfo, aSegments ) )
+ {
+ const sal_uInt8 *pVerticesIt = aVertices.pBuf + 6;
+ const sal_uInt8 *pSegmentIt = aSegments.pBuf;
+
+ OStringBuffer aSegmentInfo( 512 );
+ OStringBuffer aVerticies( 512 );
+
+ sal_uInt16 nPointSize = aVertices.pBuf[4] + ( aVertices.pBuf[5] << 8 );
+
+ // number of segments
+ sal_uInt16 nSegments = impl_GetUInt16( pSegmentIt );
+ sal_Int32 nVertices = 0;
+ aSegmentInfo.append("2;").append((sal_Int32)nSegments);
+ pSegmentIt += 4;
+
+ for ( ; nSegments; --nSegments )
+ {
+ sal_uInt16 nSeg = impl_GetUInt16( pSegmentIt );
+ aSegmentInfo.append(';').append((sal_Int32)nSeg);
+ switch ( nSeg )
+ {
+ case 0x0001: // lineto
+ case 0x4000: // moveto
+ {
+ sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize );
+ sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize );
+ aVerticies.append( ";(" ).append( nX ).append( "," ).append( nY ).append( ")" );
+ nVertices ++;
+ }
+ break;
+ case 0x2001: // curveto
+ {
+ for (int i = 0; i < 3; i++)
+ {
+ sal_Int32 nX = impl_GetPointComponent( pVerticesIt, nPointSize );
+ sal_Int32 nY = impl_GetPointComponent( pVerticesIt, nPointSize );
+ aVerticies.append( ";(" ).append( nX ).append( "," ).append( nY ).append( ")" );
+ nVertices ++;
+ }
+ }
+ break;
+ case 0xb300:
+ case 0xac00:
+ case 0xaa00: // nofill
+ case 0xab00: // nostroke
+ case 0x6001: // close
+ case 0x8000: // end
+ break;
+ default:
+ OSL_TRACE("%s: unhandled segment '%x' in the path", OSL_THIS_FUNC, nSeg);
+ break;
+ }
+ }
+
+ if (aVerticies.getLength() )
+ {
+ // We know the number of vertices at the end only, so we have to prepend them here.
+ OStringBuffer aBuf;
+ aBuf.append("8;").append((sal_Int32)nVertices);
+ aBuf.append(aVerticies.makeStringAndClear());
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("pVerticies"), aBuf.makeStringAndClear()));
+ }
+ if ( aSegmentInfo.getLength() )
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("pSegmentInfo"), aSegmentInfo.makeStringAndClear()));
+ }
+ else
+ OSL_TRACE("%s: unhandled shape path, missing either pVertices or pSegmentInfo", OSL_THIS_FUNC);
+ }
+ break;
+ case ESCHER_Prop_shapePath:
+ // noop, we use pSegmentInfo instead
+ break;
+ case ESCHER_Prop_fFillOK:
+ if (!it->nPropValue)
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("fFillOK"), OString::valueOf(sal_Int32(0))));
+ break;
+ case ESCHER_Prop_dxTextLeft:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("dxTextLeft"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_dyTextTop:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("dyTextTop"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_dxTextRight:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("dxTextRight"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_dyTextBottom:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("dyTextBottom"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_FitTextToShape:
+ // Size text to fit shape size: not supported by RTF
+ break;
+ case ESCHER_Prop_adjustValue:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("adjustValue"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ case ESCHER_Prop_txflTextFlow:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("txflTextFlow"), OString::valueOf(sal_Int32(it->nPropValue))));
+ break;
+ default:
+ OSL_TRACE("%s: unhandled property: %d (value: %d)", OSL_THIS_FUNC, nId, it->nPropValue);
+ break;
+ }
+ }
+}
+
+void RtfSdrExport::AddLineDimensions( const Rectangle& rRectangle )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // We get the position relative to (the current?) character
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("posrelh"), OString::valueOf(sal_Int32(3))));
+
+ switch ( m_nShapeFlags & 0xC0 )
+ {
+ case 0x40:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("fFlipV"), OString::valueOf(sal_Int32(1))));
+ break;
+ case 0x80:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("fFlipH"), OString::valueOf(sal_Int32(1))));
+ break;
+ case 0xC0:
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("fFlipV"), OString::valueOf(sal_Int32(1))));
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("fFlipH"), OString::valueOf(sal_Int32(1))));
+ break;
+ }
+
+ // the actual dimensions
+ m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPLEFT).append(rRectangle.Left());
+ m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPTOP).append(rRectangle.Top());
+ m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPRIGHT).append(rRectangle.Right());
+ m_pShapeStyle->append(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM).append(rRectangle.Bottom());
+}
+
+void RtfSdrExport::AddRectangleDimensions( rtl::OStringBuffer& rBuffer, const Rectangle& rRectangle )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ // We get the position relative to (the current?) character
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("posrelh"), OString::valueOf(sal_Int32(3))));
+
+ rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPLEFT).append(rRectangle.Left());
+ rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPTOP).append(rRectangle.Top());
+ rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPRIGHT).append(rRectangle.Right());
+ rBuffer.append(OOO_STRING_SVTOOLS_RTF_SHPBOTTOM).append(rRectangle.Bottom());
+}
+
+void RtfSdrExport::AddShapeAttribute( sal_Int32 /*nAttribute*/, const rtl::OString& /*rValue*/ )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ /* noop */
+}
+
+extern const char* pShapeTypes[];
+
+void lcl_AppendSP( ::rtl::OStringBuffer& rRunText, const char cName[], const ::rtl::OString& rValue)
+{
+ rRunText.append('{').append(OOO_STRING_SVTOOLS_RTF_SP)
+ .append('{').append(OOO_STRING_SVTOOLS_RTF_SN " ").append(cName).append('}')
+ .append('{').append(OOO_STRING_SVTOOLS_RTF_SV " ").append(rValue).append('}')
+ .append('}');
+}
+sal_Int32 RtfSdrExport::StartShape()
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( m_nShapeType == ESCHER_ShpInst_Nil )
+ return -1;
+
+ m_aShapeProps.insert(std::pair<OString,OString>(OString("shapeType"), OString::valueOf(sal_Int32(m_nShapeType))));
+
+ m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_SHP);
+ m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_IGNORE).append(OOO_STRING_SVTOOLS_RTF_SHPINST);
+
+ m_rAttrOutput.RunText().append(m_pShapeStyle->makeStringAndClear());
+ // Ignore \shpbxpage, \shpbxmargin, and \shpbxcolumn, in favor of the posrelh property.
+ m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_SHPBXIGNORE);
+ // Ignore \shpbypage, \shpbymargin, and \shpbycolumn, in favor of the posrelh property.
+ m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_SHPBYIGNORE);
+
+ for(std::map<OString,OString>::reverse_iterator i = m_aShapeProps.rbegin(); i != m_aShapeProps.rend(); ++i)
+ lcl_AppendSP(m_rAttrOutput.RunText(), (*i).first, (*i).second );
+
+ lcl_AppendSP(m_rAttrOutput.RunText(), "wzDescription", RtfExport::OutString( m_pSdrObject->GetDescription(), m_rExport.eCurrentEncoding));
+ lcl_AppendSP(m_rAttrOutput.RunText(), "wzName", RtfExport::OutString( m_pSdrObject->GetTitle(), m_rExport.eCurrentEncoding));
+
+ // now check if we have some text
+ const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, m_pSdrObject);
+ if (pTxtObj)
+ {
+ const OutlinerParaObject* pParaObj = 0;
+ bool bOwnParaObj = false;
+
+ /*
+ #i13885#
+ When the object is actively being edited, that text is not set into
+ the objects normal text object, but lives in a seperate object.
+ */
+ if (pTxtObj->IsTextEditActive())
+ {
+ pParaObj = pTxtObj->GetEditOutlinerParaObject();
+ bOwnParaObj = true;
+ }
+ else
+ {
+ pParaObj = pTxtObj->GetOutlinerParaObject();
+ }
+
+ if( pParaObj )
+ {
+ // this is reached only in case some text is attached to the shape
+ WriteOutliner(*pParaObj);
+ if( bOwnParaObj )
+ delete pParaObj;
+ }
+ }
+
+ return m_nShapeType;
+}
+
+void RtfSdrExport::WriteOutliner(const OutlinerParaObject& rParaObj)
+{
+ OSL_TRACE("%s start", OSL_THIS_FUNC);
+
+ const EditTextObject& rEditObj = rParaObj.GetTextObject();
+ MSWord_SdrAttrIter aAttrIter( m_rExport, rEditObj, TXT_HFTXTBOX );
+
+ sal_uInt16 nPara = rEditObj.GetParagraphCount();
+
+ m_rAttrOutput.RunText().append('{').append(OOO_STRING_SVTOOLS_RTF_SHPTXT).append(' ');
+ for (sal_uInt16 n = 0; n < nPara; ++n)
+ {
+ if( n )
+ aAttrIter.NextPara( n );
+
+ rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
+
+ String aStr( rEditObj.GetText( n ));
+ xub_StrLen nAktPos = 0;
+ xub_StrLen nEnd = aStr.Len();
+
+ aAttrIter.OutParaAttr(false);
+ m_rAttrOutput.RunText().append(m_rAttrOutput.Styles().makeStringAndClear());
+
+ do {
+ xub_StrLen nNextAttr = aAttrIter.WhereNext();
+ rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
+
+ if( nNextAttr > nEnd )
+ nNextAttr = nEnd;
+
+ aAttrIter.OutAttr( nAktPos );
+ m_rAttrOutput.RunText().append('{').append(m_rAttrOutput.Styles().makeStringAndClear()).append(m_rExport.sNewLine);
+ bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
+ if( !bTxtAtr )
+ {
+ String aOut( aStr.Copy( nAktPos, nNextAttr - nAktPos ) );
+ m_rAttrOutput.RunText().append( m_rExport.OutString( aOut, eChrSet ) );
+ }
+
+ m_rAttrOutput.RunText().append('}');
+
+ nAktPos = nNextAttr;
+ eChrSet = eNextChrSet;
+ aAttrIter.NextPos();
+ }
+ while( nAktPos < nEnd );
+ }
+ m_rAttrOutput.RunText().append(OOO_STRING_SVTOOLS_RTF_PAR).append('}');
+
+ OSL_TRACE("%s end", OSL_THIS_FUNC);
+}
+
+void RtfSdrExport::EndShape( sal_Int32 nShapeElement )
+{
+ OSL_TRACE("%s", OSL_THIS_FUNC);
+
+ if ( nShapeElement >= 0 )
+ {
+ // end of the shape
+ m_rAttrOutput.RunText().append('}').append('}');
+ }
+}
+
+sal_uInt32 RtfSdrExport::AddSdrObject( const SdrObject& rObj )
+{
+ m_pSdrObject = &rObj;
+ return EscherEx::AddSdrObject(rObj);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/rtfsdrexport.hxx b/sw/source/filter/ww8/rtfsdrexport.hxx
new file mode 100644
index 000000000000..f461357e5c61
--- /dev/null
+++ b/sw/source/filter/ww8/rtfsdrexport.hxx
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ * Copyright 2010 Miklos Vajna.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _RTFSdrEXPORT_HXX_
+#define _RTFSdrEXPORT_HXX_
+
+#include <filter/msfilter/escherex.hxx>
+#include <editeng/outlobj.hxx>
+#include <rtl/strbuf.hxx>
+
+#include <map>
+
+class RtfExport;
+class RtfAttributeOutput;
+
+/// Handles export of drawings using RTF markup
+class RtfSdrExport : public EscherEx
+{
+ RtfExport &m_rExport;
+
+ RtfAttributeOutput &m_rAttrOutput;
+
+ const SdrObject* m_pSdrObject;
+
+ /// Remember the shape type.
+ sal_uInt32 m_nShapeType;
+
+ /// Remember the shape flags.
+ sal_uInt32 m_nShapeFlags;
+
+ /// Remember style, the most important shape attribute ;-)
+ rtl::OStringBuffer *m_pShapeStyle;
+
+ std::map<rtl::OString,rtl::OString> m_aShapeProps;
+
+ /// Remember which shape types we had already written.
+ bool *m_pShapeTypeWritten;
+
+public:
+ RtfSdrExport( RtfExport &rExport );
+ virtual ~RtfSdrExport();
+
+ /// Export the sdr object as Sdr.
+ ///
+ /// Call this when you need to export the object as Sdr in RTF.
+ sal_uInt32 AddSdrObject( const SdrObject& rObj );
+
+protected:
+ /// Add an attribute to the generated shape element.
+ ///
+ /// This should be called from within StartShape() to ensure that the
+ /// added attribute is preserved.
+ void AddShapeAttribute( sal_Int32 nAttribute, const rtl::OString& sValue );
+
+ /// Start the shape for which we just collected the information.
+ ///
+ /// Returns the element's tag number, -1 means we wrote nothing.
+ using EscherEx::StartShape;
+ virtual sal_Int32 StartShape();
+
+ /// End the shape.
+ ///
+ /// The parameter is just what we got from StartShape().
+ using EscherEx::EndShape;
+ virtual void EndShape( sal_Int32 nShapeElement );
+
+ virtual void Commit( EscherPropertyContainer& rProps, const Rectangle& rRect );
+
+private:
+
+ virtual void OpenContainer( sal_uInt16 nEscherContainer, int nRecInstance = 0 );
+ virtual void CloseContainer();
+
+ using EscherEx::EnterGroup;
+ virtual sal_uInt32 EnterGroup( const String& rShapeName, const Rectangle* pBoundRect = 0 );
+ virtual void LeaveGroup();
+
+ virtual void AddShape( sal_uInt32 nShapeType, sal_uInt32 nShapeFlags, sal_uInt32 nShapeId = 0 );
+
+private:
+ /// Add starting and ending point of a line to the m_pShapeAttrList.
+ void AddLineDimensions( const Rectangle& rRectangle );
+
+ /// Add position and size to the OStringBuffer.
+ void AddRectangleDimensions( rtl::OStringBuffer& rBuffer, const Rectangle& rRectangle );
+
+ void WriteOutliner(const OutlinerParaObject& rParaObj);
+};
+
+#endif // _RTFSdrEXPORT_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/sortedarray.hxx b/sw/source/filter/ww8/sortedarray.hxx
new file mode 100644
index 000000000000..2e8d53e21661
--- /dev/null
+++ b/sw/source/filter/ww8/sortedarray.hxx
@@ -0,0 +1,119 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef WW_SORTEDARRAY_HXX
+#define WW_SORTEDARRAY_HXX
+
+#include <algorithm>
+#include <tools/debug.hxx>
+
+//simple template that manages a static [] array by sorting at construction
+
+namespace ww
+{
+ /** simple template that manages a static array
+
+ The template sorts the array at construction in place.
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ template<class C> class SortedArray
+ {
+ private:
+ //The array e.g. of sprms.
+ C *mpWwSprmTab;
+ size_t mnNoElems;
+
+ //No copying
+ SortedArray(const SortedArray&);
+ SortedArray& operator=(const SortedArray&);
+ public:
+ //Find an entry, return its address if found and 0 if not
+ const C *search(C aSrch) const
+ {
+ std::pair<C *, C *> aPair =
+ std::equal_range(mpWwSprmTab, mpWwSprmTab + mnNoElems, aSrch);
+ if (aPair.first != aPair.second)
+ return aPair.first;
+ else
+ return 0;
+ }
+
+ SortedArray(C *pWwSprmTab, size_t nNoElems)
+ : mpWwSprmTab(pWwSprmTab), mnNoElems(nNoElems)
+ {
+ OSL_ENSURE(mnNoElems && pWwSprmTab, "WW8: empty Array: Don't do that");
+ std::sort(mpWwSprmTab, mpWwSprmTab + mnNoElems);
+#if OSL_DEBUG_LEVEL > 1
+ bool bBroken=false;
+ rtl::OUString sError;
+ const C *pIter = mpWwSprmTab;
+ const C *pBeforeEnd = mpWwSprmTab + mnNoElems - 1;
+ while (pIter < pBeforeEnd)
+ {
+ if (*pIter == *(pIter+1))
+ {
+ if (!bBroken)
+ {
+ sError = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(
+ "WW8: Duplicate in list, almost certainly don't "
+ "want that!\n"
+ "(You will not see this message again unless you "
+ "restart)\n"
+ "Extra entries are...\n"));
+ bBroken=true;
+ }
+
+ size_t nSize = sizeof(C);
+ const sal_uInt8 *pHack =
+ reinterpret_cast<const sal_uInt8 *>(&(*pIter));
+ for (size_t i=0; i < nSize; ++i)
+ {
+ sError += rtl::OUString::valueOf(
+ static_cast<sal_Int32>(pHack[i]), 16);
+ sError += rtl::OUString::valueOf(sal_Unicode(' '));
+ }
+ sError += rtl::OUString::valueOf(sal_Unicode('\n'));
+ while (*pIter == *(pIter+1) && pIter < pBeforeEnd)
+ ++pIter;
+ }
+ else
+ ++pIter;
+ }
+ if (bBroken)
+ {
+ OSL_FAIL( rtl::OUStringToOString( sError, RTL_TEXTENCODING_ASCII_US ).getStr() );
+ }
+#endif
+ }
+ };
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/staticassert.hxx b/sw/source/filter/ww8/staticassert.hxx
new file mode 100644
index 000000000000..3d1a3c2bceea
--- /dev/null
+++ b/sw/source/filter/ww8/staticassert.hxx
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef WW_STATICASSERT_HXX
+#define WW_STATICASSERT_HXX
+
+/*
+ Lifted direct from:
+ Modern C++ Design: Generic Programming and Design Patterns Applied
+ Section 2.1
+ by Andrei Alexandrescu
+*/
+namespace ww
+{
+ template<bool> class compile_time_check
+ {
+ public:
+ compile_time_check(...) {}
+ };
+
+ template<> class compile_time_check<false>
+ {
+ };
+}
+
+ /*
+ Similiar to assert, StaticAssert is only in operation when NDEBUG is not
+ defined. It will test its first argument at compile time and on failure
+ report the error message of the second argument, which must be a valid c++
+ classname. i.e. no spaces, punctuation or reserved keywords.
+ */
+#ifndef NDEBUG
+# define StaticAssert(test, errormsg) \
+ do { \
+ struct ERROR_##errormsg {}; \
+ typedef ww::compile_time_check< (test) != 0 > tmplimpl; \
+ tmplimpl aTemp = tmplimpl(ERROR_##errormsg()); \
+ sizeof(aTemp); \
+ } while (0)
+#else
+# define StaticAssert(test, errormsg) \
+ do {} while (0)
+#endif
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/styles.cxx b/sw/source/filter/ww8/styles.cxx
new file mode 100644
index 000000000000..806ee13d9505
--- /dev/null
+++ b/sw/source/filter/ww8/styles.cxx
@@ -0,0 +1,218 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include "../inc/wwstyles.hxx"
+
+#include <functional> //std::unary_function
+#include <algorithm> //std::find_if
+#include <tools/string.hxx> //do we have to...
+
+#include <tools/debug.hxx>
+#include "staticassert.hxx" //StaticAssert
+
+namespace
+{
+ class SameName: public std::unary_function<const sal_Char*, bool>
+ {
+ private:
+ const String &mrName;
+ public:
+ explicit SameName(const String &rName) : mrName(rName) {}
+ bool operator() (const sal_Char *pEntry) const
+ { return mrName.EqualsAscii(pEntry); }
+ };
+
+ const sal_Char **GetStiNames() throw()
+ {
+ static const sal_Char *stiName[] =
+ {
+ "Normal",
+ "Heading 1",
+ "Heading 2",
+ "Heading 3",
+ "Heading 4",
+ "Heading 5",
+ "Heading 6",
+ "Heading 7",
+ "Heading 8",
+ "Heading 9",
+ "Index 1",
+ "Index 2",
+ "Index 3",
+ "Index 4",
+ "Index 5",
+ "Index 6",
+ "Index 7",
+ "Index 8",
+ "Index 9",
+ "TOC 1",
+ "TOC 2",
+ "TOC 3",
+ "TOC 4",
+ "TOC 5",
+ "TOC 6",
+ "TOC 7",
+ "TOC 8",
+ "TOC 9",
+ "Normal Indent",
+ "Footnote Text",
+ "Annotation Text",
+ "Header",
+ "Footer",
+ "Index Heading",
+ "Caption",
+ "Table of Figures",
+ "Envelope Address",
+ "Envelope Return",
+ "Footnote Reference",
+ "Annotation Reference",
+ "Line Number",
+ "Page Number",
+ "Endnote Reference",
+ "Endnote Text",
+ "Table of Authorities",
+ "Macro Text",
+ "TOA Heading",
+ "List",
+ "List 2",
+ "List 3",
+ "List 4",
+ "List 5",
+ "List Bullet",
+ "List Bullet 2",
+ "List Bullet 3",
+ "List Bullet 4",
+ "List Bullet 5",
+ "List Number",
+ "List Number 2",
+ "List Number 3",
+ "List Number 4",
+ "List Number 5",
+ "Title",
+ "Closing",
+ "Signature",
+ "Default Paragraph Font",
+ "Body Text",
+ "Body Text Indent",
+ "List Continue",
+ "List Continue 2",
+ "List Continue 3",
+ "List Continue 4",
+ "List Continue 5",
+ "Message Header",
+ "Subtitle",
+ "Salutation",
+ "Date",
+ "Body Text First Indent",
+ "Body Text First Indent 2",
+ "Note Heading",
+ "Body Text 2",
+ "Body Text 3",
+ "Body Text Indent 2",
+ "Body Text Indent 3",
+ "Block Text",
+ "Hyperlink",
+ "Followed Hyperlink",
+ "Strong",
+ "Emphasis",
+ "Document Map",
+ "Plain Text"
+ };
+
+ DBG_ASSERT( (SAL_N_ELEMENTS(stiName)) == ww::stiMax, "WrongSizeOfArray" );
+
+ return stiName;
+ }
+}
+
+namespace ww
+{
+ //Original code/idea by Takashi Ono for CJK
+ sti GetCanonicalStiFromEnglishName(const String &rName) throw()
+ {
+ typedef const sal_Char** myIter;
+ sti eRet = stiUser;
+ myIter aBegin = GetStiNames();
+ myIter aEnd(aBegin);
+ std::advance(aEnd, stiMax);
+ myIter aIter = std::find_if(aBegin, aEnd, SameName(rName));
+ if (aIter != aEnd)
+ eRet = static_cast<sti>(std::distance(aBegin, aIter));
+ return eRet;
+ }
+
+ const sal_Char* GetEnglishNameFromSti(sti eSti) throw()
+ {
+ if (eSti >= stiMax)
+ return 0;
+ else
+ return GetStiNames()[eSti];
+ }
+
+ bool StandardStiIsCharStyle(sti eSti) throw()
+ {
+ switch (eSti)
+ {
+ case stiFtnRef:
+ case stiAtnRef:
+ case stiLnn:
+ case stiPgn:
+ case stiEdnRef:
+ case stiNormalChar:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ sti GetCanonicalStiFromStc(sal_uInt8 stc) throw()
+ {
+ if (stc == 0)
+ return stiNormal;
+ else if (stc < 222)
+ return stiUser;
+ else
+ {
+ static sti aMapping[] =
+ {
+ stiNil, stiAtnRef, stiAtnText, stiToc8, stiToc7, stiToc6,
+ stiToc5, stiToc4, stiToc3, stiToc2, stiToc1, stiIndex7,
+ stiIndex6, stiIndex5, stiIndex4, stiIndex3, stiIndex2,
+ stiIndex1, stiLnn, stiIndexHeading, stiFooter, stiHeader,
+ stiFtnRef, stiFtnText, stiLev9, stiLev8, stiLev7, stiLev6,
+ stiLev5, stiLev4, stiLev3, stiLev2, stiLev1, stiNormIndent
+ };
+ return aMapping[stc-222];
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/tracer.cxx b/sw/source/filter/ww8/tracer.cxx
new file mode 100644
index 000000000000..78b27197676f
--- /dev/null
+++ b/sw/source/filter/ww8/tracer.cxx
@@ -0,0 +1,209 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/urlobj.hxx> //INetURLObject
+#include <sfx2/docfile.hxx> //SfxMedium
+#include <filter/msfilter/msfiltertracer.hxx> //MSFilterTracer
+#include "tracer.hxx" //sw::log::Tracer
+
+using rtl::OUString;
+#define CAU(X) RTL_CONSTASCII_USTRINGPARAM(X)
+#define C2O(X) OUString(CAU(X))
+#define COMMENT(X) OUString()
+
+namespace sw
+{
+ namespace log
+ {
+ Tracer::Tracer(const SfxMedium &rMed)
+ : mpTrace(0)
+ {
+ using namespace ::com::sun::star::uno;
+ using namespace ::com::sun::star::beans;
+ Sequence<PropertyValue> aConfig(1);
+ PropertyValue aPropValue;
+ aPropValue.Value <<=
+ OUString(rMed.GetURLObject().GetMainURL(
+ INetURLObject::NO_DECODE));
+ aPropValue.Name = C2O("DocumentURL");
+ aConfig[0] = aPropValue;
+ OUString aTraceConfigPath(CAU("Office.Tracing/Import/Word"));
+ mpTrace = new MSFilterTracer(aTraceConfigPath, &aConfig);
+ if (mpTrace)
+ mpTrace->StartTracing();
+ }
+
+ Tracer::~Tracer()
+ {
+ if (mpTrace)
+ {
+ mpTrace->EndTracing();
+ delete mpTrace;
+ }
+ }
+
+ void Tracer::Log(Problem eProblem)
+ {
+ if (!mpTrace)
+ return;
+
+ OUString sID(CAU("sw"));
+ sID += rtl::OUString::valueOf(static_cast<sal_Int32>(eProblem));
+ switch (eProblem)
+ {
+ case ePrinterMetrics:
+ mpTrace->Trace(sID, COMMENT("PrinterMetrics"));
+ break;
+ case eExtraLeading:
+ mpTrace->Trace(sID, COMMENT("Extra Leading"));
+ break;
+ case eTabStopDistance:
+ mpTrace->Trace(sID, COMMENT("Minimum Tab Distance"));
+ break;
+ case eDontUseHTMLAutoSpacing:
+ mpTrace->Trace(sID, COMMENT("HTML AutoSpacing"));
+ break;
+ case eAutoWidthFrame:
+ mpTrace->Trace(sID, COMMENT("AutoWidth"));
+ break;
+ case eRowCanSplit:
+ mpTrace->Trace(sID, COMMENT("Splitable Row"));
+ break;
+ case eSpacingBetweenCells:
+ mpTrace->Trace(sID, COMMENT("Spacing Between Cells"));
+ break;
+ case eTabInNumbering:
+ mpTrace->Trace(sID, COMMENT("Tab In Numbering"));
+ break;
+ case eNegativeVertPlacement:
+ mpTrace->Trace(sID,
+ COMMENT("Negative Vertical Placement"));
+ break;
+ case eAutoColorBg:
+ mpTrace->Trace(sID,
+ COMMENT("Bad Background for Autocolour"));
+ break;
+ case eTooWideAsChar:
+ mpTrace->Trace(sID,
+ COMMENT("Inline wider than TextArea"));
+ break;
+ case eAnimatedText:
+ mpTrace->Trace(sID,
+ COMMENT("Animated Text"));
+ break;
+ case eDontAddSpaceForEqualStyles:
+ mpTrace->Trace(sID,
+ COMMENT("Don't Add Space between Equal Style"));
+ break;
+ case eBorderDistOutside:
+ mpTrace->Trace(sID,
+ COMMENT("Word draws the border outside"));
+ break;
+ case eContainsVisualBasic:
+ mpTrace->Trace(sID, COMMENT("Contains VBA"));
+ break;
+ case eContainsWordBasic:
+ mpTrace->Trace(sID, COMMENT("Contains Word Basic"));
+ break;
+ default:
+ mpTrace->Trace(sID, COMMENT("UNKNOWN"));
+ break;
+ }
+ }
+
+ rtl::OUString Tracer::GetContext(Environment eContext) const
+ {
+ rtl::OUString sContext;
+ switch (eContext)
+ {
+ case eMacros:
+ case eDocumentProperties:
+ sContext = C2O("Global");
+ break;
+ case eMainText:
+ sContext = C2O("Text");
+ break;
+ case eSubDoc:
+ sContext = C2O("Text");
+ break;
+ case eTable:
+ sContext = C2O("Table");
+ break;
+ default:
+ sContext = C2O("UNKNOWN");
+ break;
+ }
+ return sContext;
+ }
+
+ rtl::OUString Tracer::GetDetails(Environment eContext) const
+ {
+ rtl::OUString sDetails;
+ switch (eContext)
+ {
+ case eDocumentProperties:
+ sDetails = C2O("Document Properties");
+ break;
+ case eMacros:
+ sDetails = C2O("Macros");
+ break;
+ case eMainText:
+ sDetails = C2O("MainDocument");
+ break;
+ case eSubDoc:
+ sDetails = C2O("Unknown Subdocument");
+ break;
+ default:
+ sDetails = C2O("UNKNOWN");
+ break;
+ }
+ return sDetails;
+ }
+
+ void Tracer::EnterEnvironment(Environment eContext)
+ {
+ mpTrace->AddAttribute(GetContext(eContext), GetDetails(eContext));
+ }
+
+ void Tracer::EnterEnvironment(Environment eContext,
+ const rtl::OUString &rDetails)
+ {
+ mpTrace->AddAttribute(GetContext(eContext), rDetails);
+ }
+
+ void Tracer::LeaveEnvironment(Environment eContext)
+ {
+ mpTrace->RemoveAttribute(GetContext(eContext));
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/tracer.hxx b/sw/source/filter/ww8/tracer.hxx
new file mode 100644
index 000000000000..df6d7c497108
--- /dev/null
+++ b/sw/source/filter/ww8/tracer.hxx
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_TRACER_HXX
+#define SW_TRACER_HXX
+
+#include <rtl/ustring.hxx> //rtl::OUString
+
+class MSFilterTracer;
+class SfxMedium;
+
+namespace sw
+{
+ namespace log
+ {
+
+ enum Problem
+ {
+ ePrinterMetrics = 1,
+ eExtraLeading,
+ eTabStopDistance,
+ eDontUseHTMLAutoSpacing,
+ eAutoWidthFrame,
+ eRowCanSplit,
+ eSpacingBetweenCells,
+ eTabInNumbering,
+ eNegativeVertPlacement,
+ eAutoColorBg,
+ eTooWideAsChar,
+ eAnimatedText,
+ eDontAddSpaceForEqualStyles,
+ eBorderDistOutside,
+ eContainsVisualBasic,
+ eContainsWordBasic
+ };
+
+ enum Environment
+ {
+ eDocumentProperties,
+ eMacros,
+ eMainText,
+ eSubDoc,
+ eTable
+ };
+
+ class Tracer
+ {
+ private:
+ MSFilterTracer *mpTrace;
+ rtl::OUString GetContext(Environment eContext) const;
+ rtl::OUString GetDetails(Environment eContext) const;
+ public:
+ Tracer(const SfxMedium &rMedium);
+ MSFilterTracer *GetTrace() const { return mpTrace; }
+ void EnterEnvironment(Environment eContext);
+ void EnterEnvironment(Environment eContext,
+ const rtl::OUString &rDetails);
+ void Log(Problem eProblem);
+ void LeaveEnvironment(Environment eContext);
+ ~Tracer();
+ };
+ }
+}
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/types.hxx b/sw/source/filter/ww8/types.hxx
new file mode 100644
index 000000000000..652baec7bfc1
--- /dev/null
+++ b/sw/source/filter/ww8/types.hxx
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef WW_TYPES
+#define WW_TYPES
+
+#include <vector>
+
+//if part of OOo
+#include "typessw.hxx"
+//else
+//include standalonetypes.hxx
+//endif
+
+namespace ww
+{
+ typedef std::vector<sal_uInt8> bytes;
+
+ enum WordVersion {eWW2 = 2, eWW6 = 6, eWW7 = 7, eWW8 = 8};
+ inline bool IsSevenMinus(WordVersion eVer) { return eVer <= eWW7; }
+ inline bool IsEightPlus(WordVersion eVer) { return eVer >= eWW8; }
+
+ /** For custom wrapping
+
+ When you edit the wrap points of a contour in word, word uses a relative
+ scale of 0 to 21600 where 21600 is apparently 100% of the graphic width
+ */
+ const int nWrap100Percent = 21600;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/typessw.hxx b/sw/source/filter/ww8/typessw.hxx
new file mode 100644
index 000000000000..7d12833d49fe
--- /dev/null
+++ b/sw/source/filter/ww8/typessw.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef WW_TYPESSW
+#define WW_TYPESSW
+
+#include <sal/types.h>
+
+namespace ww
+{
+ typedef sal_Int8 sal_Int8;
+ typedef sal_Int16 sal_Int16;
+ typedef sal_Int32 sal_Int32;
+ typedef sal_uInt8 sal_uInt8;
+ typedef sal_uInt16 sal_uInt16;
+ typedef sal_uInt32 sal_uInt32;
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/writerhelper.cxx b/sw/source/filter/ww8/writerhelper.cxx
new file mode 100644
index 000000000000..cb1471fa88ab
--- /dev/null
+++ b/sw/source/filter/ww8/writerhelper.cxx
@@ -0,0 +1,784 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <com/sun/star/util/XCloseable.hpp>
+
+#include <doc.hxx>
+#include "writerhelper.hxx"
+#include <msfilter.hxx>
+#include <com/sun/star/container/XChild.hpp>
+#include <com/sun/star/embed/EmbedStates.hpp>
+
+#include <algorithm> //std::swap
+#include <functional> //std::binary_function
+#include <svl/itemiter.hxx> //SfxItemIter
+#include <svx/svdobj.hxx> //SdrObject
+#include <svx/svdoole2.hxx> //SdrOle2Obj
+#include <svx/fmglob.hxx> //FmFormInventor
+#include <editeng/brkitem.hxx> //SvxFmtBreakItem
+#include <editeng/tstpitem.hxx> //SvxTabStopItem
+#include <ndtxt.hxx> //SwTxtNode
+#include <ndnotxt.hxx> //SwNoTxtNode
+#include <fmtcntnt.hxx> //SwFmtCntnt
+#include <swtable.hxx> //SwTable
+#include <frmfmt.hxx> //SwFrmFmt
+#include <flypos.hxx> //SwPosFlyFrms
+#include <fmtanchr.hxx> //SwFmtAnchor
+#include <ndgrf.hxx> //SwGrfNode
+#include <fmtfsize.hxx> //SwFmtFrmSize
+#include <SwStyleNameMapper.hxx> //SwStyleNameMapper
+#include <docary.hxx> //SwCharFmts
+#include <charfmt.hxx> //SwCharFmt
+#include <fchrfmt.hxx> //SwFmtCharFmt
+#ifndef _UNOTOOLS_STREAMWRAP_HXX
+#include <unotools/streamwrap.hxx>
+#endif
+#include <numrule.hxx>
+
+using namespace com::sun::star;
+using namespace nsSwGetPoolIdFromName;
+
+
+namespace
+{
+ /*
+ Stroustroup forgets copy_if, See C++ Programming language Chp 18, pg 530
+ */
+ template <typename In , typename Out , typename Pred>
+ Out my_copy_if(In first, In last, Out res, Pred p)
+ {
+ while (first != last)
+ {
+ if (p(*first))
+ *res = *first;
+ ++first;
+ }
+ return res;
+ }
+
+ // #i98791# - adjust sorting
+ // Utility to sort SwTxtFmtColl's by their assigned outline style list level
+ class outlinecmp : public
+ std::binary_function<const SwTxtFmtColl*, const SwTxtFmtColl*, bool>
+ {
+ public:
+ bool operator()(const SwTxtFmtColl *pA, const SwTxtFmtColl *pB) const
+ {
+ // #i98791#
+ bool bResult( false );
+ const bool bIsAAssignedToOutlineStyle( pA->IsAssignedToListLevelOfOutlineStyle() );
+ const bool bIsBAssignedToOutlineStyle( pB->IsAssignedToListLevelOfOutlineStyle() );
+ if ( bIsAAssignedToOutlineStyle != bIsBAssignedToOutlineStyle )
+ {
+ bResult = bIsBAssignedToOutlineStyle;
+ }
+ else if ( !bIsAAssignedToOutlineStyle )
+ {
+ // pA and pB are equal regarding the sorting criteria.
+ // Thus return value does not matter.
+ bResult = false;
+ }
+ else
+ {
+ bResult = pA->GetAssignedOutlineStyleLevel() < pB->GetAssignedOutlineStyleLevel();
+ }
+
+ return bResult;
+ // <--
+ }
+ };
+ // <--
+
+ bool IsValidSlotWhich(sal_uInt16 nSlotId, sal_uInt16 nWhichId)
+ {
+ return (nSlotId != 0 && nWhichId != 0 && nSlotId != nWhichId);
+ }
+
+ /*
+ Utility to convert a SwPosFlyFrms into a simple vector of sw::Frames
+
+ The crucial thing is that a sw::Frame always has an anchor which
+ points to some content in the document. This is a requirement of exporting
+ to Word
+ */
+ sw::Frames SwPosFlyFrmsToFrames(const SwPosFlyFrms &rFlys)
+ {
+ sw::Frames aRet;
+ sal_uInt16 nEnd = rFlys.Count();
+ for (sal_uInt16 nI = 0; nI < nEnd; ++nI)
+ {
+ const SwFrmFmt &rEntry = rFlys[nI]->GetFmt();
+ if (const SwPosition* pAnchor = rEntry.GetAnchor().GetCntntAnchor())
+ aRet.push_back(sw::Frame(rEntry, *pAnchor));
+ else
+ {
+ SwPosition aPos(rFlys[nI]->GetNdIndex());
+ if (SwTxtNode* pTxtNd = aPos.nNode.GetNode().GetTxtNode())
+ aPos.nContent.Assign(pTxtNd, 0);
+ aRet.push_back(sw::Frame(rEntry, aPos));
+ }
+ }
+ return aRet;
+ }
+
+ //Utility to test if a frame is anchored at a given node index
+ class anchoredto: public std::unary_function<const sw::Frame&, bool>
+ {
+ private:
+ sal_uLong mnNode;
+ public:
+ anchoredto(sal_uLong nNode) : mnNode(nNode) {}
+ bool operator()(const sw::Frame &rFrame) const
+ {
+ return (mnNode == rFrame.GetPosition().nNode.GetNode().GetIndex());
+ }
+ };
+}
+
+namespace sw
+{
+ Frame::Frame(const SwFrmFmt &rFmt, const SwPosition &rPos)
+ : mpFlyFrm(&rFmt),
+ maPos(rPos),
+ maSize(),
+ maLayoutSize(), // #i43447#
+ meWriterType(eTxtBox),
+ mpStartFrameContent(0),
+ // #i43447# - move to initialization list
+ mbIsInline( (rFmt.GetAnchor().GetAnchorId() == FLY_AS_CHAR) )
+ {
+ switch (rFmt.Which())
+ {
+ case RES_FLYFRMFMT:
+ if (const SwNodeIndex* pIdx = rFmt.GetCntnt().GetCntntIdx())
+ {
+ SwNodeIndex aIdx(*pIdx, 1);
+ const SwNode &rNd = aIdx.GetNode();
+ using sw::util::GetSwappedInSize;
+ // #i43447# - determine layout size
+ {
+ SwRect aLayRect( rFmt.FindLayoutRect() );
+ Rectangle aRect( aLayRect.SVRect() );
+ // The Object is not rendered (e.g. something in unused
+ // header/footer) - thus, get the values from the format.
+ if ( aLayRect.IsEmpty() )
+ {
+ aRect.SetSize( rFmt.GetFrmSize().GetSize() );
+ }
+ maLayoutSize = aRect.GetSize();
+ }
+ // <--
+ switch (rNd.GetNodeType())
+ {
+ case ND_GRFNODE:
+ meWriterType = eGraphic;
+ maSize = GetSwappedInSize(*rNd.GetNoTxtNode());
+ break;
+ case ND_OLENODE:
+ meWriterType = eOle;
+ maSize = GetSwappedInSize(*rNd.GetNoTxtNode());
+ break;
+ default:
+ meWriterType = eTxtBox;
+ // #i43447# - Size equals layout size for text boxes
+ maSize = maLayoutSize;
+ // <--
+ break;
+ }
+ mpStartFrameContent = &rNd;
+ }
+ else
+ {
+ OSL_ENSURE(!this, "Impossible");
+ meWriterType = eTxtBox;
+ }
+ break;
+ default:
+ if (const SdrObject* pObj = rFmt.FindRealSdrObject())
+ {
+ if (pObj->GetObjInventor() == FmFormInventor)
+ meWriterType = eFormControl;
+ else
+ meWriterType = eDrawing;
+ maSize = pObj->GetSnapRect().GetSize();
+ }
+ else
+ {
+ OSL_ENSURE(!this, "Impossible");
+ meWriterType = eDrawing;
+ }
+ break;
+ }
+ }
+
+ bool Frame::IsInline() const
+ {
+ return mbIsInline;
+ }
+
+ void Frame::ForceTreatAsInline()
+ {
+ mbIsInline = true;
+ }
+
+ namespace hack
+ {
+
+ sal_uInt16 TransformWhichBetweenPools(const SfxItemPool &rDestPool,
+ const SfxItemPool &rSrcPool, sal_uInt16 nWhich)
+ {
+ sal_uInt16 nSlotId = rSrcPool.GetSlotId(nWhich);
+ if (IsValidSlotWhich(nSlotId, nWhich))
+ nWhich = rDestPool.GetWhich(nSlotId);
+ else
+ nWhich = 0;
+ return nWhich;
+ }
+
+ sal_uInt16 GetSetWhichFromSwDocWhich(const SfxItemSet &rSet,
+ const SwDoc &rDoc, sal_uInt16 nWhich)
+ {
+ if (RES_WHICHHINT_END < *(rSet.GetRanges()))
+ {
+ nWhich = TransformWhichBetweenPools(*rSet.GetPool(),
+ rDoc.GetAttrPool(), nWhich);
+ }
+ return nWhich;
+ }
+
+ DrawingOLEAdaptor::DrawingOLEAdaptor(SdrOle2Obj &rObj,
+ SfxObjectShell &rPers)
+ : msOrigPersistName(rObj.GetPersistName()),
+ mxIPRef(rObj.GetObjRef()), mrPers(rPers),
+ mpGraphic( rObj.GetGraphic() )
+ {
+ rObj.AbandonObject();
+ }
+
+ bool DrawingOLEAdaptor::TransferToDoc( ::rtl::OUString &rName )
+ {
+ OSL_ENSURE(mxIPRef.is(), "Transferring invalid object to doc");
+ if (!mxIPRef.is())
+ return false;
+
+ uno::Reference < container::XChild > xChild( mxIPRef, uno::UNO_QUERY );
+ if ( xChild.is() )
+ xChild->setParent( mrPers.GetModel() );
+
+ bool bSuccess = mrPers.GetEmbeddedObjectContainer().InsertEmbeddedObject( mxIPRef, rName );
+ if (bSuccess)
+ {
+ if ( mpGraphic )
+ ::svt::EmbeddedObjectRef::SetGraphicToContainer( *mpGraphic,
+ mrPers.GetEmbeddedObjectContainer(),
+ rName,
+ ::rtl::OUString() );
+
+ mxIPRef = 0;
+ }
+
+ return bSuccess;
+ }
+
+ DrawingOLEAdaptor::~DrawingOLEAdaptor()
+ {
+ if (mxIPRef.is())
+ {
+ DBG_ASSERT( !mrPers.GetEmbeddedObjectContainer().HasEmbeddedObject( mxIPRef ), "Object in adaptor is inserted?!" );
+ try
+ {
+ uno::Reference < com::sun::star::util::XCloseable > xClose( mxIPRef, uno::UNO_QUERY );
+ if ( xClose.is() )
+ xClose->close(sal_True);
+ }
+ catch ( com::sun::star::util::CloseVetoException& )
+ {
+ }
+
+ mxIPRef = 0;
+ }
+ }
+ }
+
+ namespace util
+ {
+ SV_IMPL_OP_PTRARR_SORT(AuthorInfos, AuthorInfo_Ptr)
+
+ SwTwips MakeSafePositioningValue(SwTwips nIn)
+ {
+ if (nIn > SHRT_MAX)
+ nIn = SHRT_MAX;
+ else if (nIn < SHRT_MIN)
+ nIn = SHRT_MIN;
+ return nIn;
+ }
+
+ void SetLayer::SendObjectToHell(SdrObject &rObject) const
+ {
+ SetObjectLayer(rObject, eHell);
+ }
+
+ void SetLayer::SendObjectToHeaven(SdrObject &rObject) const
+ {
+ SetObjectLayer(rObject, eHeaven);
+ }
+
+ void SetLayer::SetObjectLayer(SdrObject &rObject, Layer eLayer) const
+ {
+ if (FmFormInventor == rObject.GetObjInventor())
+ rObject.SetLayer(mnFormLayer);
+ else
+ {
+ switch (eLayer)
+ {
+ case eHeaven:
+ rObject.SetLayer(mnHeavenLayer);
+ break;
+ case eHell:
+ rObject.SetLayer(mnHellLayer);
+ break;
+ }
+ }
+ }
+
+ //SetLayer boilerplate begin
+ void SetLayer::Swap(SetLayer& rOther) throw()
+ {
+ std::swap(mnHeavenLayer, rOther.mnHeavenLayer);
+ std::swap(mnHellLayer, rOther.mnHellLayer);
+ std::swap(mnFormLayer, rOther.mnFormLayer);
+ }
+
+ // #i38889# - by default put objects into the invisible layers.
+ SetLayer::SetLayer(const SwDoc &rDoc)
+ : mnHeavenLayer(rDoc.GetInvisibleHeavenId()),
+ mnHellLayer(rDoc.GetInvisibleHellId()),
+ mnFormLayer(rDoc.GetInvisibleControlsId())
+ {
+ }
+
+ SetLayer::SetLayer(const SetLayer& rOther) throw()
+ : mnHeavenLayer(rOther.mnHeavenLayer),
+ mnHellLayer(rOther.mnHellLayer),
+ mnFormLayer(rOther.mnFormLayer)
+ {
+ }
+
+ SetLayer& SetLayer::operator=(const SetLayer& rOther) throw()
+ {
+ SetLayer aTemp(rOther);
+ Swap(aTemp);
+ return *this;
+ }
+ //SetLayer boilerplate end
+
+ void GetPoolItems(const SfxItemSet &rSet, PoolItems &rItems, bool bExportParentItemSet )
+ {
+ if( bExportParentItemSet )
+ {
+ sal_uInt16 nTotal = rSet.TotalCount();
+ for( sal_uInt16 nItem =0; nItem < nTotal; ++nItem )
+ {
+ const SfxPoolItem* pItem = 0;
+ if( SFX_ITEM_SET == rSet.GetItemState( rSet.GetWhichByPos( nItem ), true, &pItem ) )
+ {
+ rItems[pItem->Which()] = pItem;
+ }
+ }
+ }
+ else if( rSet.Count())
+ {
+ SfxItemIter aIter(rSet);
+ if (const SfxPoolItem *pItem = aIter.GetCurItem())
+ {
+ do
+ rItems[pItem->Which()] = pItem;
+ while (!aIter.IsAtEnd() && 0 != (pItem = aIter.NextItem()));
+ }
+ }
+ }
+
+ const SfxPoolItem *SearchPoolItems(const PoolItems &rItems,
+ sal_uInt16 eType)
+ {
+ sw::cPoolItemIter aIter = rItems.find(eType);
+ if (aIter != rItems.end())
+ return aIter->second;
+ return 0;
+ }
+
+ void ClearOverridesFromSet(const SwFmtCharFmt &rFmt, SfxItemSet &rSet)
+ {
+ if (const SwCharFmt* pCharFmt = rFmt.GetCharFmt())
+ {
+ if (pCharFmt->GetAttrSet().Count())
+ {
+ SfxItemIter aIter(pCharFmt->GetAttrSet());
+ const SfxPoolItem *pItem = aIter.GetCurItem();
+ do
+ rSet.ClearItem(pItem->Which());
+ while (!aIter.IsAtEnd() && 0 != (pItem = aIter.NextItem()));
+ }
+ }
+ }
+
+ ParaStyles GetParaStyles(const SwDoc &rDoc)
+ {
+ ParaStyles aStyles;
+ typedef ParaStyles::size_type mysizet;
+
+ const SwTxtFmtColls *pColls = rDoc.GetTxtFmtColls();
+ mysizet nCount = pColls ? pColls->Count() : 0;
+ aStyles.reserve(nCount);
+ for (mysizet nI = 0; nI < nCount; ++nI)
+ aStyles.push_back((*pColls)[ static_cast< sal_uInt16 >(nI) ]);
+ return aStyles;
+ }
+
+ SwTxtFmtColl* GetParaStyle(SwDoc &rDoc, const String& rName)
+ {
+ // Search first in the Doc-Styles
+ SwTxtFmtColl* pColl = rDoc.FindTxtFmtCollByName(rName);
+ if (!pColl)
+ {
+ // Collection not found, try in Pool ?
+ sal_uInt16 n = SwStyleNameMapper::GetPoolIdFromUIName(rName,
+ nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL);
+ if (n != SAL_MAX_UINT16) // found or standard
+ pColl = rDoc.GetTxtCollFromPool(n, false);
+ }
+ return pColl;
+ }
+
+ SwCharFmt* GetCharStyle(SwDoc &rDoc, const String& rName)
+ {
+ SwCharFmt *pFmt = rDoc.FindCharFmtByName(rName);
+ if (!pFmt)
+ {
+ // Collection not found, try in Pool ?
+ sal_uInt16 n = SwStyleNameMapper::GetPoolIdFromUIName(rName,
+ nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
+ if (n != SAL_MAX_UINT16) // found or standard
+ pFmt = rDoc.GetCharFmtFromPool(n);
+ }
+ return pFmt;
+ }
+
+ // #i98791# - adjust sorting algorithm
+ void SortByAssignedOutlineStyleListLevel(ParaStyles &rStyles)
+ {
+ std::sort(rStyles.begin(), rStyles.end(), outlinecmp());
+ }
+
+ /*
+ Utility to extract flyfmts from a document, potentially from a
+ selection.
+ */
+ Frames GetFrames(const SwDoc &rDoc, SwPaM *pPaM /*, bool bAll*/)
+ {
+ SwPosFlyFrms aFlys;
+ rDoc.GetAllFlyFmts(aFlys, pPaM, true);
+ sw::Frames aRet(SwPosFlyFrmsToFrames(aFlys));
+ for (sal_uInt16 i = aFlys.Count(); i > 0;)
+ delete aFlys[--i];
+ return aRet;
+ }
+
+ Frames GetFramesInNode(const Frames &rFrames, const SwNode &rNode)
+ {
+ Frames aRet;
+ my_copy_if(rFrames.begin(), rFrames.end(),
+ std::back_inserter(aRet), anchoredto(rNode.GetIndex()));
+ return aRet;
+ }
+
+ const SwNumFmt* GetNumFmtFromTxtNode(const SwTxtNode &rTxtNode)
+ {
+ const SwNumRule *pRule = 0;
+ if (
+ rTxtNode.IsNumbered() && rTxtNode.IsCountedInList() &&
+ 0 != (pRule = rTxtNode.GetNumRule())
+ )
+ {
+ return &(pRule->Get( static_cast< sal_uInt16 >(rTxtNode.GetActualListLevel()) ));
+ }
+
+ OSL_ENSURE(rTxtNode.GetDoc(), "No document for node?, suspicious");
+ if (!rTxtNode.GetDoc())
+ return 0;
+
+ if (
+ rTxtNode.IsNumbered() && rTxtNode.IsCountedInList() &&
+ 0 != (pRule = rTxtNode.GetDoc()->GetOutlineNumRule())
+ )
+ {
+ return &(pRule->Get( static_cast< sal_uInt16 >(rTxtNode.GetActualListLevel()) ));
+ }
+
+ return 0;
+ }
+
+ const SwNumRule* GetNumRuleFromTxtNode(const SwTxtNode &rTxtNode)
+ {
+ return GetNormalNumRuleFromTxtNode(rTxtNode);
+ }
+
+ const SwNumRule* GetNormalNumRuleFromTxtNode(const SwTxtNode &rTxtNode)
+ {
+ const SwNumRule *pRule = 0;
+
+ if (
+ rTxtNode.IsNumbered() && rTxtNode.IsCountedInList() &&
+ 0 != (pRule = rTxtNode.GetNumRule())
+ )
+ {
+ return pRule;
+ }
+ return 0;
+ }
+
+
+ SwNoTxtNode *GetNoTxtNodeFromSwFrmFmt(const SwFrmFmt &rFmt)
+ {
+ const SwNodeIndex *pIndex = rFmt.GetCntnt().GetCntntIdx();
+ OSL_ENSURE(pIndex, "No NodeIndex in SwFrmFmt ?, suspicious");
+ if (!pIndex)
+ return 0;
+ SwNodeIndex aIdx(*pIndex, 1);
+ return aIdx.GetNode().GetNoTxtNode();
+ }
+
+ bool HasPageBreak(const SwNode &rNd)
+ {
+ const SvxFmtBreakItem *pBreak = 0;
+ if (rNd.IsTableNode() && rNd.GetTableNode())
+ {
+ const SwTable& rTable = rNd.GetTableNode()->GetTable();
+ const SwFrmFmt* pApply = rTable.GetFrmFmt();
+ OSL_ENSURE(pApply, "impossible");
+ if (pApply)
+ pBreak = &(ItemGet<SvxFmtBreakItem>(*pApply, RES_BREAK));
+ }
+ else if (const SwCntntNode *pNd = rNd.GetCntntNode())
+ pBreak = &(ItemGet<SvxFmtBreakItem>(*pNd, RES_BREAK));
+
+ if (pBreak && pBreak->GetBreak() == SVX_BREAK_PAGE_BEFORE)
+ return true;
+ return false;
+ }
+
+ Polygon PolygonFromPolyPolygon(const PolyPolygon &rPolyPoly)
+ {
+ if(1 == rPolyPoly.Count())
+ {
+ return rPolyPoly[0];
+ }
+ else
+ {
+ // This method will now just concatenate the polygons contained
+ // in the given PolyPolygon. Anything else which might be thought of
+ // for reducing to a single polygon will just need nore power and
+ // cannot create more correct results.
+ sal_uInt32 nPointCount(0L);
+ sal_uInt16 a;
+
+ for(a = 0; a < rPolyPoly.Count(); a++)
+ {
+ nPointCount += (sal_uInt32)rPolyPoly[a].GetSize();
+ }
+
+ if(nPointCount > 0x0000ffff)
+ {
+ OSL_FAIL("PolygonFromPolyPolygon: too many points for a single polygon (!)");
+ nPointCount = 0x0000ffff;
+ }
+
+ Polygon aRetval((sal_uInt16)nPointCount);
+ sal_uInt32 nAppendIndex(0L);
+
+ for(a = 0; a < rPolyPoly.Count(); a++)
+ {
+ const Polygon& rCandidate = rPolyPoly[a];
+
+ for(sal_uInt16 b(0); nAppendIndex <= nPointCount && b < rCandidate.GetSize(); b++)
+ {
+ aRetval[(sal_uInt16)nAppendIndex++] = rCandidate[b];
+ }
+ }
+
+ return aRetval;
+ }
+ }
+
+ bool IsStarSymbol(const String &rFontName)
+ {
+ String sFamilyNm(GetFontToken(rFontName, 0));
+ return (sFamilyNm.EqualsIgnoreCaseAscii("starsymbol") ||
+ sFamilyNm.EqualsIgnoreCaseAscii("opensymbol"));
+ }
+
+ Size GetSwappedInSize(const SwNoTxtNode& rNd)
+ {
+ Size aGrTwipSz(rNd.GetTwipSize());
+ if ((!aGrTwipSz.Width() || !aGrTwipSz.Height()))
+ {
+ SwGrfNode *pGrfNode = const_cast<SwGrfNode*>(rNd.GetGrfNode());
+ if (pGrfNode && (GRAPHIC_NONE != pGrfNode->GetGrf().GetType()))
+ {
+ bool bWasSwappedOut = pGrfNode->GetGrfObj().IsSwappedOut();
+ pGrfNode->SwapIn();
+ aGrTwipSz = pGrfNode->GetTwipSize();
+ if (bWasSwappedOut)
+ pGrfNode->SwapOut();
+ }
+ }
+
+ OSL_ENSURE(aGrTwipSz.Width() && aGrTwipSz.Height(), "0 x 0 graphic ?");
+ return aGrTwipSz;
+ }
+
+ void RedlineStack::open(const SwPosition& rPos, const SfxPoolItem& rAttr)
+ {
+ OSL_ENSURE(rAttr.Which() == RES_FLTR_REDLINE, "not a redline");
+ maStack.push_back(new SwFltStackEntry(rPos,rAttr.Clone()));
+ }
+
+
+ class SameOpenRedlineType :
+ public std::unary_function<const SwFltStackEntry*, bool>
+ {
+ private:
+ RedlineType_t meType;
+ public:
+ SameOpenRedlineType(RedlineType_t eType) : meType(eType) {}
+ bool operator()(const SwFltStackEntry *pEntry) const
+ {
+ const SwFltRedline *pTest = static_cast<const SwFltRedline *>
+ (pEntry->pAttr);
+ return (pEntry->bLocked && (pTest->eType == meType));
+ }
+ };
+
+ bool RedlineStack::close(const SwPosition& rPos, RedlineType_t eType)
+ {
+ //Search from end for same type
+ myriter aResult = std::find_if(maStack.rbegin(), maStack.rend(),
+ SameOpenRedlineType(eType));
+ if (aResult != maStack.rend())
+ {
+ (*aResult)->SetEndPos(rPos);
+ return true;
+ }
+ return false;
+ }
+
+
+
+ void RedlineStack::closeall(const SwPosition& rPos)
+ {
+ std::for_each(maStack.begin(), maStack.end(), CloseIfOpen(rPos));
+ }
+
+
+ void SetInDocAndDelete::operator()(SwFltStackEntry *pEntry)
+ {
+ SwPaM aRegion(pEntry->nMkNode);
+ if (
+ pEntry->MakeRegion(&mrDoc, aRegion, true) &&
+ (*aRegion.GetPoint() != *aRegion.GetMark())
+ )
+ {
+ mrDoc.SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_ON | nsRedlineMode_t::REDLINE_SHOW_INSERT |
+ nsRedlineMode_t::REDLINE_SHOW_DELETE));
+ const SwFltRedline *pFltRedline = static_cast<const SwFltRedline*>
+ (pEntry->pAttr);
+
+ if (USHRT_MAX != pFltRedline->nAutorNoPrev)
+ {
+ SwRedlineData aData(pFltRedline->eTypePrev,
+ pFltRedline->nAutorNoPrev, pFltRedline->aStampPrev, aEmptyStr,
+ 0);
+
+ mrDoc.AppendRedline(new SwRedline(aData, aRegion), true);
+ }
+
+ SwRedlineData aData(pFltRedline->eType, pFltRedline->nAutorNo,
+ pFltRedline->aStamp, aEmptyStr, 0);
+
+ mrDoc.AppendRedline(new SwRedline(aData, aRegion), true);
+ mrDoc.SetRedlineMode((RedlineMode_t)(nsRedlineMode_t::REDLINE_NONE | nsRedlineMode_t::REDLINE_SHOW_INSERT |
+ nsRedlineMode_t::REDLINE_SHOW_DELETE ));
+ }
+ delete pEntry;
+ }
+
+
+ bool CompareRedlines::operator()(const SwFltStackEntry *pOneE,
+ const SwFltStackEntry *pTwoE) const
+ {
+ const SwFltRedline *pOne= static_cast<const SwFltRedline*>
+ (pOneE->pAttr);
+ const SwFltRedline *pTwo= static_cast<const SwFltRedline*>
+ (pTwoE->pAttr);
+
+ //Return the earlier time, if two have the same time, prioritize
+ //inserts over deletes
+ if (pOne->aStamp == pTwo->aStamp)
+ return (pOne->eType == nsRedlineType_t::REDLINE_INSERT && pTwo->eType != nsRedlineType_t::REDLINE_INSERT);
+ else
+ return (pOne->aStamp < pTwo->aStamp) ? true : false;
+ }
+
+
+ RedlineStack::~RedlineStack()
+ {
+ std::sort(maStack.begin(), maStack.end(), CompareRedlines());
+ std::for_each(maStack.begin(), maStack.end(), SetInDocAndDelete(mrDoc));
+ }
+
+ sal_uInt16 WrtRedlineAuthor::AddName( const String& rNm )
+ {
+ sal_uInt16 nRet;
+ typedef std::vector<String>::iterator myiter;
+ myiter aIter = std::find(maAuthors.begin(), maAuthors.end(), rNm);
+ if (aIter != maAuthors.end())
+ nRet = static_cast< sal_uInt16 >(aIter - maAuthors.begin());
+ else
+ {
+ nRet = static_cast< sal_uInt16 >(maAuthors.size());
+ maAuthors.push_back(rNm);
+ }
+ return nRet;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/writerhelper.hxx b/sw/source/filter/ww8/writerhelper.hxx
new file mode 100644
index 000000000000..2f16b06f770f
--- /dev/null
+++ b/sw/source/filter/ww8/writerhelper.hxx
@@ -0,0 +1,922 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_WRITERHELPER
+#define SW_WRITERHELPER
+
+#include <typeinfo>
+#include <vector>
+#include <map>
+#include <com/sun/star/embed/XEmbeddedObject.hpp>
+
+#include <sfx2/objsh.hxx>
+#include "types.hxx"
+#include <svl/itempool.hxx> //SfxItemPool
+#include <svl/itemset.hxx> //SfxItemSet
+#include <format.hxx> //SwFmt
+#include <node.hxx> //SwCntntNode
+#include <pam.hxx> //SwPaM
+#include <tools/poly.hxx> //Polygon, PolyPolygon
+#include <doc.hxx> //SwDoc
+
+class SwTxtFmtColl;
+class SwCharFmt;
+class SdrObject;
+class SdrOle2Obj;
+class OutlinerParaObject;
+class SdrTextObj;
+class SwNumFmt;
+class SwTxtNode;
+class SwNoTxtNode;
+class SwFmtCharFmt;
+class Graphic;
+class SwDoc;
+class SwNumRule;
+
+namespace sw
+{
+ namespace util
+ {
+ class ItemSort
+ : public std::binary_function<sal_uInt16, sal_uInt16, bool>
+ {
+ public:
+ bool operator()(sal_uInt16 nA, sal_uInt16 nB) const;
+ };
+ }
+}
+
+namespace sw
+{
+ /// STL container of Paragraph Styles (SwTxtFmtColl)
+ typedef std::vector<SwTxtFmtColl *> ParaStyles;
+ /// STL iterator for ParaStyles
+ typedef ParaStyles::iterator ParaStyleIter;
+ /// STL container of SfxPoolItems (Attributes)
+ typedef std::map<sal_uInt16, const SfxPoolItem *, sw::util::ItemSort> PoolItems;
+ /// STL const iterator for ParaStyles
+ typedef PoolItems::const_iterator cPoolItemIter;
+
+
+ /** Make exporting a Writer Frame easy
+
+ In word all frames are effectively anchored to character or as
+ character. This is nice and simple, writer is massively complex in this
+ area, so this sw::Frame simplies matters by providing a single unified
+ view of the multitute of elements in writer and their differing quirks.
+
+ A sw::Frame wraps a writer frame and is guaranted to have a suitable
+ anchor position available from it. It hides much of the needless
+ complexity of the multitude of floating/inline elements in writer, it...
+
+ Guarantees an anchor position for a frame.
+ Provides a readable way to see if we are anchored inline. (as character)
+ Provides a simple way to flag what type of entity this frame describes.
+ Provides the size of the element as drawn by writer.
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ class Frame
+ {
+ public:
+ enum WriterSource {eTxtBox, eGraphic, eOle, eDrawing, eFormControl};
+ private:
+ const SwFrmFmt* mpFlyFrm;
+ SwPosition maPos;
+ Size maSize;
+ // #i43447# - Size of the frame in the layout.
+ // Especially needed for graphics, whose layout size can differ from its
+ // size, because it is scaled into its environment.
+ Size maLayoutSize;
+
+ WriterSource meWriterType;
+ const SwNode *mpStartFrameContent;
+ bool mbIsInline;
+ public:
+ Frame(const SwFrmFmt &rFlyFrm, const SwPosition &rPos);
+
+ /** Get the writer SwFrmFmt that this object describes
+
+ @return
+ The wrapped SwFrmFmt
+ */
+ const SwFrmFmt &GetFrmFmt() const { return *mpFlyFrm; }
+
+ /** Get the position this frame is anchored at
+
+ @return
+ The anchor position of this frame
+ */
+ const SwPosition &GetPosition() const { return maPos; }
+
+ /** Get the node this frame is anchored into
+
+ @return
+ The SwTxtNode this frame is anchored inside
+ */
+ const SwCntntNode *GetCntntNode() const
+ { return maPos.nNode.GetNode().GetCntntNode(); }
+
+ /** Get the type of frame that this wraps
+
+ @return
+ a WriterSource which describes the source type of this wrapper
+ */
+ WriterSource GetWriterType() const { return meWriterType; }
+
+ /** Is this frame inline (as character)
+
+ @return
+ whether this is inline or not
+ */
+ bool IsInline() const;
+
+
+ /** Even if the frame isn't an inline frame, force it to behave as one
+
+ There are a variety of circumstances where word cannot have
+ anything except inline elements, e.g. inside frames. So its easier
+ to force this sw::Frame into behaving as one, instead of special
+ casing export code all over the place.
+
+ */
+ void ForceTreatAsInline();
+
+ /** Get the first node of content in the frame
+
+ @return
+ the first node of content in the frame, might not be any at all.
+ */
+ const SwNode *GetContent() const { return mpStartFrameContent; }
+
+
+ /** Does this sw::Frame refer to the same writer content as another
+
+ @return
+ if the two sw::Frames are handling the same writer frame
+ */
+ bool RefersToSameFrameAs(const Frame &rOther) const
+ {
+ return (mpFlyFrm == rOther.mpFlyFrm);
+ }
+
+ /** The Size of the contained element
+
+ @return
+ the best size to use to export to word
+ */
+ const Size GetSize() const { return maSize; }
+
+ /** The layout size of the contained element
+
+ #i43447# - Needed for graphics, which are scaled into its environment
+
+ @return layout size
+ */
+ const Size GetLayoutSize() const
+ {
+ return maLayoutSize;
+ }
+ };
+
+ /// STL container of Frames
+ typedef std::vector<Frame> Frames;
+ /// STL iterator for Frames
+ typedef std::vector<Frame>::iterator FrameIter;
+}
+
+namespace sw
+{
+ namespace util
+ {
+ /** Provide a dynamic_cast style cast for SfxPoolItems
+
+ A SfxPoolItem generally need to be cast back to its original type
+ to be useful, which is both tedious and errorprone. So item_cast is
+ a helper template to aid the process and test if the cast is
+ correct.
+
+ @param rItem
+ The SfxPoolItem which is to be casted
+
+ @tplparam T
+ A SfxPoolItem derived class to cast rItem to
+
+ @return A rItem upcasted back to a T
+
+ @exception std::bad_cast Thrown if the rItem was not a T
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ template<class T> const T & item_cast(const SfxPoolItem &rItem)
+ throw(std::bad_cast)
+ {
+ if (!rItem.IsA(STATICTYPE(T)))
+ throw std::bad_cast();
+ return static_cast<const T &>(rItem);
+ }
+
+ /** Provide a dynamic_cast style cast for SfxPoolItems
+
+ A SfxPoolItem generally need to be cast back to its original type
+ to be useful, which is both tedious and errorprone. So item_cast is
+ a helper template to aid the process and test if the cast is
+ correct.
+
+ @param pItem
+ The SfxPoolItem which is to be casted
+
+ @tplparam T
+ A SfxPoolItem derived class to cast pItem to
+
+ @return A pItem upcasted back to a T or 0 if pItem was not a T
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ template<class T> const T * item_cast(const SfxPoolItem *pItem)
+ {
+ if (pItem && !pItem->IsA(STATICTYPE(T)))
+ pItem = 0;
+ return static_cast<const T *>(pItem);
+ }
+
+ /** Extract a SfxPoolItem derived property from a SwCntntNode
+
+ Writer's attributes are retrieved by passing a numeric identifier
+ and receiving a SfxPoolItem reference which must then typically be
+ cast back to its original type which is both tedious and verbose.
+
+ ItemGet uses item_cast () on the retrived reference to test that the
+ retrived property is of the type that the developer thinks it is.
+
+ @param rNode
+ The SwCntntNode to retrieve the property from
+
+ @param eType
+ The numeric identifier of the property to be retrieved
+
+ @tplparam T
+ A SfxPoolItem derived class of the retrieved property
+
+ @exception std::bad_cast Thrown if the property was not a T
+
+ @return The T requested
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ template<class T> const T & ItemGet(const SwCntntNode &rNode,
+ sal_uInt16 eType) throw(std::bad_cast)
+ {
+ return item_cast<T>(rNode.GetAttr(eType));
+ }
+
+ /** Extract a SfxPoolItem derived property from a SwFmt
+
+ Writer's attributes are retrieved by passing a numeric identifier
+ and receiving a SfxPoolItem reference which must then typically be
+ cast back to its original type which is both tedious and verbose.
+
+ ItemGet uses item_cast () on the retrived reference to test that the
+ retrived property is of the type that the developer thinks it is.
+
+ @param rFmt
+ The SwFmt to retrieve the property from
+
+ @param eType
+ The numeric identifier of the property to be retrieved
+
+ @tplparam T
+ A SfxPoolItem derived class of the retrieved property
+
+ @exception std::bad_cast Thrown if the property was not a T
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ template<class T> const T & ItemGet(const SwFmt &rFmt,
+ sal_uInt16 eType) throw(std::bad_cast)
+ {
+ return item_cast<T>(rFmt.GetFmtAttr(eType));
+ }
+
+ /** Extract a SfxPoolItem derived property from a SfxItemSet
+
+ Writer's attributes are retrieved by passing a numeric identifier
+ and receiving a SfxPoolItem reference which must then typically be
+ cast back to its original type which is both tedious and verbose.
+
+ ItemGet uses item_cast () on the retrived reference to test that the
+ retrived property is of the type that the developer thinks it is.
+
+ @param rSet
+ The SfxItemSet to retrieve the property from
+
+ @param eType
+ The numeric identifier of the property to be retrieved
+
+ @tplparam T
+ A SfxPoolItem derived class of the retrieved property
+
+ @exception std::bad_cast Thrown if the property was not a T
+
+ @return The T requested
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ template<class T> const T & ItemGet(const SfxItemSet &rSet,
+ sal_uInt16 eType) throw(std::bad_cast)
+ {
+ return item_cast<T>(rSet.Get(eType));
+ }
+
+ /** Extract a default SfxPoolItem derived property from a SfxItemPool
+
+ Writer's attributes are retrieved by passing a numeric identifier
+ and receiving a SfxPoolItem reference which must then typically be
+ cast back to its original type which is both tedious and verbose.
+
+ DefaultItemGet returns a reference to the default property of a
+ given SfxItemPool for a given property id, e.g. default fontsize
+
+ DefaultItemGet uses item_cast () on the retrived reference to test
+ that the retrived property is of the type that the developer thinks
+ it is.
+
+ @param rPool
+ The SfxItemPool whose default property we want
+
+ @param eType
+ The numeric identifier of the default property to be retrieved
+
+ @tplparam T
+ A SfxPoolItem derived class of the retrieved property
+
+ @exception std::bad_cast Thrown if the property was not a T
+
+ @return The T requested
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ template<class T> const T & DefaultItemGet(const SfxItemPool &rPool,
+ sal_uInt16 eType) throw(std::bad_cast)
+ {
+ return item_cast<T>(rPool.GetDefaultItem(eType));
+ }
+
+ /** Extract a default SfxPoolItem derived property from a SwDoc
+
+ Writer's attributes are retrieved by passing a numeric identifier
+ and receiving a SfxPoolItem reference which must then typically be
+ cast back to its original type which is both tedious and verbose.
+
+ DefaultItemGet returns a reference to the default property of a
+ given SwDoc (Writer Document) for a given property id, e.g default
+ fontsize
+
+ DefaultItemGet uses item_cast () on the retrived reference to test
+ that the retrived property is of the type that the developer thinks
+ it is.
+
+ @param rPool
+ The SfxItemPool whose default property we want
+
+ @param eType
+ The numeric identifier of the default property to be retrieved
+
+ @tplparam T
+ A SfxPoolItem derived class of the retrieved property
+
+ @exception std::bad_cast Thrown if the property was not a T
+
+ @return The T requested
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ template<class T> const T & DefaultItemGet(const SwDoc &rDoc,
+ sal_uInt16 eType) throw(std::bad_cast)
+ {
+ return DefaultItemGet<T>(rDoc.GetAttrPool(), eType);
+ }
+
+ /** Return a pointer to a SfxPoolItem derived class if it exists in an
+ SfxItemSet
+
+ Writer's attributes are retrieved by passing a numeric identifier
+ and receiving a SfxPoolItem reference which must then typically be
+ cast back to its original type which is both tedious and verbose.
+
+ HasItem returns a pointer to the requested SfxPoolItem for a given
+ property id if it exists in the SfxItemSet or its chain of parents,
+ e.g. fontsize
+
+ HasItem uses item_cast () on the retrived pointer to test that the
+ retrived property is of the type that the developer thinks it is.
+
+ @param rSet
+ The SfxItemSet whose property we want
+
+ @param eType
+ The numeric identifier of the default property to be retrieved
+
+ @tplparam T
+ A SfxPoolItem derived class of the retrieved property
+
+ @return The T requested or 0 if no T found with id eType
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ template<class T> const T* HasItem(const SfxItemSet &rSet,
+ sal_uInt16 eType)
+ {
+ return item_cast<T>(rSet.GetItem(eType));
+ }
+
+ /** Return a pointer to a SfxPoolItem derived class if it exists in an
+ SwFmt
+
+ Writer's attributes are retrieved by passing a numeric identifier
+ and receiving a SfxPoolItem reference which must then typically be
+ cast back to its original type which is both tedious and verbose.
+
+ HasItem returns a pointer to the requested SfxPoolItem for a given
+ property id if it exists in the SwFmt e.g. fontsize
+
+ HasItem uses item_cast () on the retrived pointer to test that the
+ retrived property is of the type that the developer thinks it is.
+
+ @param rSet
+ The SwFmt whose property we want
+
+ @param eType
+ The numeric identifier of the default property to be retrieved
+
+ @tplparam T
+ A SfxPoolItem derived class of the retrieved property
+
+ @return The T requested or 0 if no T found with id eType
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ template<class T> const T* HasItem(const SwFmt &rFmt,
+ sal_uInt16 eType)
+ {
+ return HasItem<T>(rFmt.GetAttrSet(), eType);
+ }
+
+ /** Get the Paragraph Styles of a SwDoc
+
+ Writer's styles are in one of those dreaded macro based pre-STL
+ containers. Give me an STL container of the paragraph styles
+ instead.
+
+ @param rDoc
+ The SwDoc document to get the styles from
+
+ @return A ParaStyles containing the SwDoc's Paragraph Styles
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ ParaStyles GetParaStyles(const SwDoc &rDoc);
+
+
+ /** Get a Paragraph Style which fits a given name
+
+ Its surprisingly tricky to get a style when all you have is a name,
+ but that's what this does
+
+ @param rDoc
+ The SwDoc document to search in
+
+ @param rName
+ The name of the style to search for
+
+ @return A Paragraph Style if one exists which matches the name
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ SwTxtFmtColl* GetParaStyle(SwDoc &rDoc, const String& rName);
+
+ /** Get a Character Style which fits a given name
+
+ Its surprisingly tricky to get a style when all you have is a name,
+ but that's what this does
+
+ @param rDoc
+ The SwDoc document to search in
+
+ @param rName
+ The name of the style to search for
+
+ @return A Character Style if one exists which matches the name
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ SwCharFmt* GetCharStyle(SwDoc &rDoc, const String& rName);
+
+ /** Sort sequence of Paragraph Styles by assigned outline style list level
+
+ Sort ParaStyles in ascending order of assigned outline style list level,
+ e.g. given Normal/Heading1/Heading2/.../Heading10 at their default
+ assigned outline style list levels of body level/level 1/level 2/.../level 10
+
+ #i98791#
+ adjust the sorting algorithm due to introduced outline level attribute
+
+ @param rStyles
+ The ParaStyles to sort
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ void SortByAssignedOutlineStyleListLevel(ParaStyles &rStyles);
+
+ /** Get the SfxPoolItems of a SfxItemSet
+
+ Writer's SfxPoolItems (attributes) are in one of those dreaded
+ macro based pre-STL containers. Give me an STL container of the
+ items instead.
+
+ @param rSet
+ The SfxItemSet to get the items from
+
+ @param rItems
+ The sw::PoolItems to put the items into
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ void GetPoolItems(const SfxItemSet &rSet, PoolItems &rItems, bool bExportParentItemSet );
+
+ const SfxPoolItem *SearchPoolItems(const PoolItems &rItems,
+ sal_uInt16 eType);
+
+ template<class T> const T* HasItem(const sw::PoolItems &rItems,
+ sal_uInt16 eType)
+ {
+ return item_cast<T>(SearchPoolItems(rItems, eType));
+ }
+
+
+ /** Remove properties from an SfxItemSet which a SwFmtCharFmt overrides
+
+ Given an SfxItemSet and a SwFmtCharFmt remove from the rSet all the
+ properties which the SwFmtCharFmt would override. An SfxItemSet
+ contains attributes, and a SwFmtCharFmt is a "Character Style",
+ so if the SfxItemSet contains bold and so does the character style
+ then delete bold from the SfxItemSet
+
+ @param
+ rFmt the SwFmtCharFmt which describes the Character Style
+
+ @param
+ rSet the SfxItemSet from which we want to remove any properties
+ which the rFmt would override
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+
+ @see #i24291# for examples
+ */
+ void ClearOverridesFromSet(const SwFmtCharFmt &rFmt, SfxItemSet &rSet);
+
+ /** Get the Floating elements in a SwDoc
+
+ Writer's FrmFmts may or may not be anchored to some text content,
+ e.g. Page Anchored elements will not be. For the winword export we
+ need them to have something to be anchored to. So this method
+ returns all the floating elements in a document as a STL container
+ of sw::Frames which are guaranteed to have an appropiate anchor.
+
+ @param rDoc
+ The SwDoc document to get the styles from
+
+ @param pPaM
+ The SwPam to describe the selection in the document to get the
+ elements from. 0 means the entire document.
+
+ @return A Frames containing the selections Floating elements
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ Frames GetFrames(const SwDoc &rDoc, SwPaM *pPaM = 0);
+
+ /** Get the Frames anchored to a given node
+
+ Given a container of frames, find the ones anchored to a given node
+
+ @param rFrames
+ The container of frames to search in
+
+ @param rNode
+ The SwNode to check for anchors to
+
+ @return the Frames in rFrames anchored to rNode
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ Frames GetFramesInNode(const Frames &rFrames, const SwNode &rNode);
+
+ /** Get the Numbering Format used on a paragraph
+
+ There are two differing types of numbering formats that may be on a
+ paragraph, normal and outline. The outline is that numbering you
+ see in tools->outline numbering. Theres no difference in the
+ numbering itself, just how you get it from the SwTxtNode. Needless
+ to say the filter generally couldn't care less what type of
+ numbering is in use.
+
+ @param rTxtNode
+ The SwTxtNode that is the paragraph
+
+ @return A SwNumFmt pointer that describes the numbering level
+ on this paragraph, or 0 if there is none.
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ const SwNumFmt* GetNumFmtFromTxtNode(const SwTxtNode &rTxtNode);
+
+ const SwNumRule* GetNumRuleFromTxtNode(const SwTxtNode &rTxtNd);
+ const SwNumRule* GetNormalNumRuleFromTxtNode(const SwTxtNode &rTxtNd);
+
+
+ /** Get the SwNoTxtNode associated with a SwFrmFmt if here is one
+
+ There are two differing types of numbering formats that may be on a
+ paragraph, normal and outline. The outline is that numbering you
+ see in tools->outline numbering. Theres no difference in the
+ numbering itself, just how you get it from the SwTxtNode. Needless
+ to say the filter generally couldn't care less what type of
+ numbering is in use.
+
+ @param rFmt
+ The SwFrmFmt that may describe a graphic
+
+ @return A SwNoTxtNode pointer that describes the graphic of this
+ frame if there is one, or 0 if there is none.
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ SwNoTxtNode *GetNoTxtNodeFromSwFrmFmt(const SwFrmFmt &rFmt);
+
+ /** Does a node have a "page break before" applied
+
+ Both text nodes and tables in writer can have "page break before"
+ This function gives a unified view to both entities
+
+ @param rNode
+ The SwNode to query the page break of
+
+ @return true if there is a page break, false otherwise
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ bool HasPageBreak(const SwNode &rNode);
+
+
+ /** Make a best fit Polygon from a PolyPolygon
+
+ For custom contours in writer we use a PolyPolygon, while word uses
+ a simple polygon, so we need to try and make the best polygon from
+ a PolyPolygon
+
+ @param rPolyPoly
+ The PolyPolygon to try and turn into a Polygon
+
+ @return best fit Polygon from rPolyPoly
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ Polygon PolygonFromPolyPolygon(const PolyPolygon &rPolyPoly);
+
+ /** Determine if the font is the special Star|Open Symbol font
+
+ @param rFontName
+ The FontName to test for being Star|Open Symbol
+
+ @return true if this is Star|Open Symbol
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ bool IsStarSymbol(const String &rFontName);
+
+ /** Make setting a drawing object's layer in a Writer document easy
+
+
+ Word has the simple concept of a drawing object either in the
+ foreground and in the background. We have an additional complexity
+ that form components live in a seperate layer, which seems
+ unnecessarily complicated. So in the winword filter we set the
+ object's layer through this class with either SendObjectToHell for
+ the bottom layer and SendObjectToHeaven for the top and we don't
+ worry about the odd form layer design wrinkle.
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ class SetLayer
+ {
+ private:
+ sal_uInt8 mnHeavenLayer, mnHellLayer, mnFormLayer;
+ enum Layer {eHeaven, eHell};
+ void SetObjectLayer(SdrObject &rObject, Layer eLayer) const;
+ void Swap(SetLayer &rOther) throw();
+ public:
+
+ /** Make Object live in the bottom drawing layer
+
+ @param rObject
+ The object to be set to the bottom layer
+ */
+ void SendObjectToHell(SdrObject &rObject) const;
+
+ /** Make Object lives in the top top layer
+
+ @param rObject
+ The object to be set to the bottom layer
+ */
+ void SendObjectToHeaven(SdrObject &rObject) const;
+
+ /** Normal constructor
+
+ @param rDoc
+ The Writer document whose drawing layers we will be inserting
+ objects into
+ */
+ SetLayer(const SwDoc &rDoc);
+
+ SetLayer(const SetLayer &rOther) throw();
+ SetLayer& operator=(const SetLayer &rOther) throw();
+ };
+ }
+
+ namespace hack
+ {
+ /** Map an ID valid in one SfxItemPool to its equivalent in another
+
+ Given a WhichId (the id that identifies a property e.g. bold) which
+ is correct in a given SfxItemPool, get the equivalent whichId in
+ another SfxItemPool
+
+ This arises because the drawing layer uses the same properties as
+ writer e.g. SvxWeight, but for some reason uses different ids
+ for the same properties as writer.
+
+ @param rDestPool
+ The SfxItemPool in whose terms the Id is returned
+
+ @param rSrcPool
+ The SfxItemPool in whose terms the Id is passed in
+
+ @param nWhich
+ The Id to transform from source to dest
+
+ @return 0 on failure, the correct property Id on success
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ sal_uInt16 TransformWhichBetweenPools(const SfxItemPool &rDestPool,
+ const SfxItemPool &rSrcPool, sal_uInt16 nWhich);
+
+ /** Map a SwDoc WhichId to the equivalent Id for a given SfxItemSet
+
+ Given a WhichId (the id that identifies a property e.g. bold) which
+ is correct for a Writer document, get the equivalent whichId which
+ for a given SfxItemSet.
+
+ This arises because the drawing layer uses the same properties as
+ writer e.g. SvxWeight, but for some reason uses different ids
+ for the same properties as writer.
+
+ This is effectively the same as TransformWhichBetweenPools except
+ at a slightly different layer.
+
+ @param rSet
+ The SfxItemSet in whose terms the Id is returned
+
+ @param rDoc
+ The SwDoc in whose terms the Id is passed in
+
+ @param nWhich
+ The Id to transform from writer to the SfxItemSet's domain
+
+ @return 0 on failure, the correct SfxItemSet Id on success
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ sal_uInt16 GetSetWhichFromSwDocWhich(const SfxItemSet &rSet,
+ const SwDoc &rDoc, sal_uInt16 nWhich);
+
+
+ /** Make inserting an OLE object into a Writer document easy
+
+ The rest of Office uses SdrOle2Obj for their OLE objects, Writer
+ doesn't, which makes things a bit difficult as this is the type of
+ object that the escher import code shared by the MSOffice filters
+ produces when it imports an OLE object.
+
+ This utility class takes ownership of the OLE object away from a
+ SdrOle2Obj and can massage it into the condition best suited to
+ insertion into Writer.
+
+ If the object was not transferred into Writer then it is deleted
+ during destruction.
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ class DrawingOLEAdaptor
+ {
+ private:
+ String msOrigPersistName;
+ com::sun::star::uno::Reference < com::sun::star::embed::XEmbeddedObject > mxIPRef;
+ SfxObjectShell& mrPers;
+ Graphic* mpGraphic;
+ public:
+ /** Take ownership of a SdrOle2Objs OLE object
+
+ @param rObj
+ The SdrOle2Obj whose OLE object we want to take control of
+
+ @param rPers
+ The SvPersist of a SwDoc (SwDoc::GetPersist()) into which we
+ may want to move the object, or remove it from if unwanted.
+ */
+ DrawingOLEAdaptor(SdrOle2Obj &rObj, SfxObjectShell &rPers);
+
+ /// Destructor will destroy the owned OLE object if not transferred
+ ~DrawingOLEAdaptor();
+
+ /** Transfer ownership of the OLE object to a document's SvPersist
+
+ TransferToDoc moves the object into the persist under the name
+ passed in. This name is then suitable to be used as an argument
+ to SwDoc::InsertOLE.
+
+ The object is no longer owned by the adaptor after this call,
+ subsequent calls are an error and return false.
+
+ @param rName
+ The name to store the object under in the document.
+
+ @return On success true is returned, otherwise false. On
+ success rName is then suitable for user with SwDoc::InsertOLE
+ */
+ bool TransferToDoc(::rtl::OUString &rName);
+ private:
+ /// No assigning allowed
+ DrawingOLEAdaptor& operator=(const DrawingOLEAdaptor&);
+ /// No copying allowed
+ DrawingOLEAdaptor(const DrawingOLEAdaptor &rDoc);
+ };
+ }
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/writerwordglue.cxx b/sw/source/filter/ww8/writerwordglue.cxx
new file mode 100644
index 000000000000..878286ccbb23
--- /dev/null
+++ b/sw/source/filter/ww8/writerwordglue.cxx
@@ -0,0 +1,1026 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <msfilter.hxx>
+#include "writerwordglue.hxx"
+#include <doc.hxx>
+#include "writerhelper.hxx"
+
+#include <algorithm> //std::find_if
+#include <functional> //std::unary_function
+
+#include <unicode/ubidi.h> //ubidi_getLogicalRun
+#include <tools/tenccvt.hxx> //GetExtendedTextEncoding
+#include <com/sun/star/i18n/ScriptType.hdl> //ScriptType
+
+#include <unotools/fontcvt.hxx> //GetSubsFontName
+#include <editeng/paperinf.hxx> //lA0Width...
+#include <editeng/lrspitem.hxx> //SvxLRSpaceItem
+#include <editeng/ulspitem.hxx> //SvxULSpaceItem
+#include <editeng/boxitem.hxx> //SvxBoxItem
+#include <editeng/fontitem.hxx> //SvxFontItem
+#include <frmfmt.hxx> //SwFrmFmt
+#include <fmtclds.hxx> //SwFmtCol
+#include <hfspacingitem.hxx> //SwHeaderAndFooterEatSpacingItem
+#include <fmtfsize.hxx> //SwFmtFrmSize
+#include <swrect.hxx> //SwRect
+#include <fmthdft.hxx> //SwFmtHeader/SwFmtFooter
+#include <frmatr.hxx> //GetLRSpace...
+#include <ndtxt.hxx> //SwTxtNode
+#include <breakit.hxx> //pBreakIt
+#include <i18npool/mslangid.hxx>
+
+#define ASSIGN_CONST_ASC(s) AssignAscii(RTL_CONSTASCII_STRINGPARAM(s))
+
+namespace myImplHelpers
+{
+ SwTwips CalcHdFtDist(const SwFrmFmt& rFmt, sal_uInt16 nSpacing)
+ {
+ /*
+ The normal case for reexporting word docs is to have dynamic spacing,
+ as this is word's only setting, and the reason for the existance of the
+ dynamic spacing features. If we have dynamic spacing active then we can
+ add its spacing to the value height of the h/f and get the wanted total
+ size for word.
+
+ Otherwise we have to get the real layout rendered
+ height, which is totally nonoptimum, but the best we can do.
+ */
+ long nDist=0;
+ const SwFmtFrmSize& rSz = rFmt.GetFrmSize();
+
+ const SwHeaderAndFooterEatSpacingItem &rSpacingCtrl =
+ sw::util::ItemGet<SwHeaderAndFooterEatSpacingItem>
+ (rFmt, RES_HEADER_FOOTER_EAT_SPACING);
+ if (rSpacingCtrl.GetValue())
+ nDist += rSz.GetHeight();
+ else
+ {
+ SwRect aRect(rFmt.FindLayoutRect(false));
+ if (aRect.Height())
+ nDist += aRect.Height();
+ else
+ {
+ const SwFmtFrmSize& rSize = rFmt.GetFrmSize();
+ if (ATT_VAR_SIZE != rSize.GetHeightSizeType())
+ nDist += rSize.GetHeight();
+ else
+ {
+ nDist += 274; // default for 12pt text
+ nDist += nSpacing;
+ }
+ }
+ }
+ return nDist;
+ }
+
+ SwTwips CalcHdDist(const SwFrmFmt& rFmt)
+ {
+ return CalcHdFtDist(rFmt, rFmt.GetULSpace().GetUpper());
+ }
+
+ SwTwips CalcFtDist(const SwFrmFmt& rFmt)
+ {
+ return CalcHdFtDist(rFmt, rFmt.GetULSpace().GetLower());
+ }
+
+ /*
+ SwTxtFmtColl and SwCharFmt are quite distinct types and how they are
+ gotten is also distinct, but the algorithm to match word's eqivalents into
+ them is the same, so we put the different stuff into two seperate helper
+ implementations and a core template that uses the helpers that uses the
+ same algorithm to do the work. We'll make the helpers specializations of a
+ non existing template so I can let the compiler figure out the right one
+ to use from a simple argument to the algorithm class
+ */
+ template <class C> class MapperImpl;
+ template<> class MapperImpl<SwTxtFmtColl>
+ {
+ private:
+ SwDoc &mrDoc;
+ public:
+ MapperImpl(SwDoc &rDoc) : mrDoc(rDoc) {}
+ SwTxtFmtColl* GetBuiltInStyle(ww::sti eSti);
+ SwTxtFmtColl* GetStyle(const String &rName);
+ SwTxtFmtColl* MakeStyle(const String &rName);
+ };
+
+ SwTxtFmtColl* MapperImpl<SwTxtFmtColl>::GetBuiltInStyle(ww::sti eSti)
+ {
+ const RES_POOL_COLLFMT_TYPE RES_NONE = RES_POOLCOLL_DOC_END;
+ static const RES_POOL_COLLFMT_TYPE aArr[]=
+ {
+ RES_POOLCOLL_STANDARD, RES_POOLCOLL_HEADLINE1,
+ RES_POOLCOLL_HEADLINE2, RES_POOLCOLL_HEADLINE3,
+ RES_POOLCOLL_HEADLINE4, RES_POOLCOLL_HEADLINE5,
+ RES_POOLCOLL_HEADLINE6, RES_POOLCOLL_HEADLINE7,
+ RES_POOLCOLL_HEADLINE8, RES_POOLCOLL_HEADLINE9,
+ RES_POOLCOLL_TOX_IDX1, RES_POOLCOLL_TOX_IDX2,
+ RES_POOLCOLL_TOX_IDX3, RES_NONE, RES_NONE, RES_NONE, RES_NONE,
+ RES_NONE, RES_NONE, RES_POOLCOLL_TOX_CNTNT1,
+ RES_POOLCOLL_TOX_CNTNT2, RES_POOLCOLL_TOX_CNTNT3,
+ RES_POOLCOLL_TOX_CNTNT4, RES_POOLCOLL_TOX_CNTNT5,
+ RES_POOLCOLL_TOX_CNTNT6, RES_POOLCOLL_TOX_CNTNT7,
+ RES_POOLCOLL_TOX_CNTNT8, RES_POOLCOLL_TOX_CNTNT9, RES_NONE,
+ RES_POOLCOLL_FOOTNOTE, RES_NONE, RES_POOLCOLL_HEADER,
+ RES_POOLCOLL_FOOTER, RES_POOLCOLL_TOX_IDXH, RES_NONE, RES_NONE,
+ RES_POOLCOLL_JAKETADRESS, RES_POOLCOLL_SENDADRESS, RES_NONE,
+ RES_NONE, RES_NONE, RES_NONE, RES_NONE, RES_POOLCOLL_ENDNOTE,
+ RES_NONE, RES_NONE, RES_NONE, RES_POOLCOLL_LISTS_BEGIN,
+ RES_NONE, RES_NONE, RES_NONE, RES_NONE, RES_NONE, RES_NONE,
+ RES_NONE, RES_NONE, RES_NONE, RES_NONE, RES_NONE, RES_NONE,
+ RES_NONE, RES_NONE, RES_POOLCOLL_HEADLINE_BASE, RES_NONE,
+ RES_POOLCOLL_SIGNATURE, RES_NONE, RES_POOLCOLL_TEXT,
+ RES_POOLCOLL_TEXT_MOVE, RES_NONE, RES_NONE, RES_NONE, RES_NONE,
+ RES_NONE, RES_NONE, RES_POOLCOLL_DOC_SUBTITEL
+ };
+
+ const size_t nArrSize = (SAL_N_ELEMENTS(aArr));
+ OSL_ENSURE(nArrSize == 75, "Style Array has false size");
+
+ SwTxtFmtColl* pRet = 0;
+ //If this is a built-in word style that has a built-in writer
+ //equivalent, then map it to one of our built in styles regardless
+ //of its name
+ if (sal::static_int_cast< size_t >(eSti) < nArrSize && aArr[eSti] != RES_NONE)
+ pRet = mrDoc.GetTxtCollFromPool( static_cast< sal_uInt16 >(aArr[eSti]), false);
+ return pRet;
+ }
+
+ SwTxtFmtColl* MapperImpl<SwTxtFmtColl>::GetStyle(const String &rName)
+ {
+ return sw::util::GetParaStyle(mrDoc, rName);
+ }
+
+ SwTxtFmtColl* MapperImpl<SwTxtFmtColl>::MakeStyle(const String &rName)
+ {
+ return mrDoc.MakeTxtFmtColl(rName,
+ const_cast<SwTxtFmtColl *>(mrDoc.GetDfltTxtFmtColl()));
+ }
+
+ template<> class MapperImpl<SwCharFmt>
+ {
+ private:
+ SwDoc &mrDoc;
+ public:
+ MapperImpl(SwDoc &rDoc) : mrDoc(rDoc) {}
+ SwCharFmt* GetBuiltInStyle(ww::sti eSti);
+ SwCharFmt* GetStyle(const String &rName);
+ SwCharFmt* MakeStyle(const String &rName);
+ };
+
+ SwCharFmt* MapperImpl<SwCharFmt>::GetBuiltInStyle(ww::sti eSti)
+ {
+ RES_POOL_CHRFMT_TYPE eLookup = RES_POOLCHR_NORMAL_END;
+ switch (eSti)
+ {
+ case ww::stiFtnRef:
+ eLookup = RES_POOLCHR_FOOTNOTE;
+ break;
+ case ww::stiLnn:
+ eLookup = RES_POOLCHR_LINENUM;
+ break;
+ case ww::stiPgn:
+ eLookup = RES_POOLCHR_PAGENO;
+ break;
+ case ww::stiEdnRef:
+ eLookup = RES_POOLCHR_ENDNOTE;
+ break;
+ case ww::stiHyperlink:
+ eLookup = RES_POOLCHR_INET_NORMAL;
+ break;
+ case ww::stiHyperlinkFollowed:
+ eLookup = RES_POOLCHR_INET_VISIT;
+ break;
+ case ww::stiStrong:
+ eLookup = RES_POOLCHR_HTML_STRONG;
+ break;
+ case ww::stiEmphasis:
+ eLookup = RES_POOLCHR_HTML_EMPHASIS;
+ break;
+ default:
+ eLookup = RES_POOLCHR_NORMAL_END;
+ break;
+ }
+ SwCharFmt *pRet = 0;
+ if (eLookup != RES_POOLCHR_NORMAL_END)
+ pRet = mrDoc.GetCharFmtFromPool( static_cast< sal_uInt16 >(eLookup) );
+ return pRet;
+ }
+
+ SwCharFmt* MapperImpl<SwCharFmt>::GetStyle(const String &rName)
+ {
+ return sw::util::GetCharStyle(mrDoc, rName);
+ }
+
+ SwCharFmt* MapperImpl<SwCharFmt>::MakeStyle(const String &rName)
+ {
+ return mrDoc.MakeCharFmt(rName, mrDoc.GetDfltCharFmt());
+ }
+
+ template<class C> class StyleMapperImpl
+ {
+ private:
+ MapperImpl<C> maHelper;
+ std::set<const C*> maUsedStyles;
+ C* MakeNonCollidingStyle(const String& rName);
+ public:
+ typedef std::pair<C*, bool> StyleResult;
+ StyleMapperImpl(SwDoc &rDoc) : maHelper(rDoc) {}
+ StyleResult GetStyle(const String& rName, ww::sti eSti);
+ };
+
+ template<class C>
+ typename StyleMapperImpl<C>::StyleResult
+ StyleMapperImpl<C>::GetStyle(const String& rName, ww::sti eSti)
+ {
+ C *pRet = maHelper.GetBuiltInStyle(eSti);
+
+ //If we've used it once, don't reuse it
+ if (pRet && (maUsedStyles.end() != maUsedStyles.find(pRet)))
+ pRet = 0;
+
+ if (!pRet)
+ {
+ pRet = maHelper.GetStyle(rName);
+ //If we've used it once, don't reuse it
+ if (pRet && (maUsedStyles.end() != maUsedStyles.find(pRet)))
+ pRet = 0;
+ }
+
+ bool bStyExist = pRet ? true : false;
+
+ if (!pRet)
+ {
+ String aName(rName);
+ xub_StrLen nPos = aName.Search(',');
+ // No commas allow in SW style names
+ if (STRING_NOTFOUND != nPos)
+ aName.Erase(nPos);
+ pRet = MakeNonCollidingStyle(aName);
+ }
+
+ if (pRet)
+ maUsedStyles.insert(pRet);
+
+ return StyleResult(pRet, bStyExist);
+ }
+
+ template<class C>
+ C* StyleMapperImpl<C>::MakeNonCollidingStyle(const String& rName)
+ {
+ String aName(rName);
+ C* pColl = 0;
+
+ if (0 != (pColl = maHelper.GetStyle(aName)))
+ {
+ //If the style collides first stick WW- in front of it, unless
+ //it already has it and then successively add a larger and
+ //larger number after it, its got to work at some stage!
+ if (!aName.EqualsIgnoreCaseAscii("WW-", 0, 3))
+ aName.InsertAscii("WW-" , 0);
+
+ sal_Int32 nI = 1;
+ while (
+ 0 != (pColl = maHelper.GetStyle(aName)) &&
+ (nI < SAL_MAX_INT32)
+ )
+ {
+ aName += String::CreateFromInt32(nI++);
+ }
+ }
+
+ return pColl ? 0 : maHelper.MakeStyle(aName);
+ }
+
+ String FindBestMSSubstituteFont(const String &rFont)
+ {
+ String sRet;
+ if (sw::util::IsStarSymbol(rFont))
+ sRet.ASSIGN_CONST_ASC("Arial Unicode MS");
+ else
+ sRet = GetSubsFontName(rFont, SUBSFONT_ONLYONE | SUBSFONT_MS);
+ return sRet;
+ }
+
+ //Utility to remove entries before a given starting position
+ class IfBeforeStart
+ : public std::unary_function<const sw::util::CharRunEntry&, bool>
+ {
+ private:
+ xub_StrLen mnStart;
+ public:
+ IfBeforeStart(xub_StrLen nStart) : mnStart(nStart) {}
+ bool operator()(const sw::util::CharRunEntry &rEntry) const
+ {
+ return rEntry.mnEndPos < mnStart;
+ }
+ };
+}
+
+namespace sw
+{
+ namespace util
+ {
+
+ bool IsPlausableSingleWordSection(const SwFrmFmt &rTitleFmt,
+ const SwFrmFmt &rFollowFmt)
+ {
+ bool bPlausableTitlePage = true;
+
+ const SwFmtCol& rFirstCols = rTitleFmt.GetCol();
+ const SwFmtCol& rFollowCols = rFollowFmt.GetCol();
+ const SwColumns& rFirstColumns = rFirstCols.GetColumns();
+ const SwColumns& rFollowColumns = rFollowCols.GetColumns();
+ const SvxLRSpaceItem &rOneLR = rTitleFmt.GetLRSpace();
+ const SvxLRSpaceItem &rTwoLR= rFollowFmt.GetLRSpace();
+
+ if (rFirstColumns.Count() != rFollowColumns.Count())
+ {
+ //e.g. #i4320#
+ bPlausableTitlePage = false;
+ }
+ else if (rOneLR != rTwoLR)
+ bPlausableTitlePage = false;
+ else
+ {
+ HdFtDistanceGlue aOne(rTitleFmt.GetAttrSet());
+ HdFtDistanceGlue aTwo(rFollowFmt.GetAttrSet());
+ //e.g. #i14509#
+ if (!aOne.EqualTopBottom(aTwo))
+ bPlausableTitlePage = false;
+ }
+ return bPlausableTitlePage;
+ }
+
+ HdFtDistanceGlue::HdFtDistanceGlue(const SfxItemSet &rPage)
+ {
+ if (const SvxBoxItem *pBox = HasItem<SvxBoxItem>(rPage, RES_BOX))
+ {
+ dyaHdrTop = pBox->CalcLineSpace(BOX_LINE_TOP);
+ dyaHdrBottom = pBox->CalcLineSpace(BOX_LINE_BOTTOM);
+ }
+ else
+ {
+ dyaHdrTop = dyaHdrBottom = 0;
+ dyaHdrBottom = 0;
+ }
+ const SvxULSpaceItem &rUL =
+ ItemGet<SvxULSpaceItem>(rPage, RES_UL_SPACE);
+ dyaHdrTop = dyaHdrTop + rUL.GetUpper();
+ dyaHdrBottom = dyaHdrBottom + rUL.GetLower();
+
+ dyaTop = dyaHdrTop;
+ dyaBottom = dyaHdrBottom;
+
+ using sw::types::msword_cast;
+
+ const SwFmtHeader *pHd = HasItem<SwFmtHeader>(rPage, RES_HEADER);
+ if (pHd && pHd->IsActive() && pHd->GetHeaderFmt())
+ {
+ mbHasHeader = true;
+ dyaTop = dyaTop + static_cast< sal_uInt16 >( (myImplHelpers::CalcHdDist(*(pHd->GetHeaderFmt()))) );
+ }
+ else
+ mbHasHeader = false;
+
+ const SwFmtFooter *pFt = HasItem<SwFmtFooter>(rPage, RES_FOOTER);
+ if (pFt && pFt->IsActive() && pFt->GetFooterFmt())
+ {
+ mbHasFooter = true;
+ dyaBottom = dyaBottom + static_cast< sal_uInt16 >( (myImplHelpers::CalcFtDist(*(pFt->GetFooterFmt()))) );
+ }
+ else
+ mbHasFooter = false;
+ }
+
+ bool HdFtDistanceGlue::EqualTopBottom(const HdFtDistanceGlue &rOther)
+ const
+ {
+ return (dyaTop == rOther.dyaTop && dyaBottom == rOther.dyaBottom);
+ }
+
+ ParaStyleMapper::ParaStyleMapper(SwDoc &rDoc)
+ : mpImpl(new myImplHelpers::StyleMapperImpl<SwTxtFmtColl>(rDoc))
+ {
+ }
+
+ ParaStyleMapper::~ParaStyleMapper()
+ {
+ delete mpImpl;
+ }
+
+ ParaStyleMapper::StyleResult ParaStyleMapper::GetStyle(
+ const String& rName, ww::sti eSti)
+ {
+ return mpImpl->GetStyle(rName, eSti);
+ }
+
+ CharStyleMapper::CharStyleMapper(SwDoc &rDoc)
+ : mpImpl(new myImplHelpers::StyleMapperImpl<SwCharFmt>(rDoc))
+ {
+ }
+
+ CharStyleMapper::~CharStyleMapper()
+ {
+ delete mpImpl;
+ }
+
+ CharStyleMapper::StyleResult CharStyleMapper::GetStyle(
+ const String& rName, ww::sti eSti)
+ {
+ return mpImpl->GetStyle(rName, eSti);
+ }
+
+ FontMapExport::FontMapExport(const String &rFamilyName)
+ {
+ msPrimary = GetFontToken(rFamilyName, 0);
+ msSecondary = myImplHelpers::FindBestMSSubstituteFont(msPrimary);
+ if (!msSecondary.Len())
+ msSecondary = GetFontToken(rFamilyName, 1);
+ }
+
+ bool FontMapExport::HasDistinctSecondary() const
+ {
+ if (msSecondary.Len() && msSecondary != msPrimary)
+ return true;
+ return false;
+ }
+
+ bool ItemSort::operator()(sal_uInt16 nA, sal_uInt16 nB) const
+ {
+ /*
+ #i24291#
+ All we want to do is ensure for now is that if a charfmt exist
+ in the character properties that it rises to the top and is
+ exported first. In the future we might find more ordering
+ depandancies for export, in which case this is the place to do
+ it
+ */
+ if (nA == nB)
+ return false;
+ if (nA == RES_TXTATR_CHARFMT)
+ return true;
+ if (nB == RES_TXTATR_CHARFMT)
+ return false;
+ return nA < nB;
+ }
+
+ CharRuns GetPseudoCharRuns(const SwTxtNode& rTxtNd,
+ xub_StrLen nTxtStart, bool bSplitOnCharSet)
+ {
+ const String &rTxt = rTxtNd.GetTxt();
+
+ bool bParaIsRTL = false;
+ OSL_ENSURE(rTxtNd.GetDoc(), "No document for node?, suspicious");
+ if (rTxtNd.GetDoc())
+ {
+ if (FRMDIR_HORI_RIGHT_TOP ==
+ rTxtNd.GetDoc()->GetTextDirection(SwPosition(rTxtNd)))
+ {
+ bParaIsRTL = true;
+ }
+ }
+
+ using namespace ::com::sun::star::i18n;
+
+ sal_uInt16 nScript = i18n::ScriptType::LATIN;
+ if (rTxt.Len() && pBreakIt && pBreakIt->GetBreakIter().is())
+ nScript = pBreakIt->GetBreakIter()->getScriptType(rTxt, 0);
+
+ rtl_TextEncoding eChrSet = ItemGet<SvxFontItem>(rTxtNd,
+ GetWhichOfScript(RES_CHRATR_FONT, nScript)).GetCharSet();
+ eChrSet = GetExtendedTextEncoding(eChrSet);
+
+ CharRuns aRunChanges;
+
+ if (!rTxt.Len())
+ {
+ aRunChanges.push_back(CharRunEntry(0, nScript, eChrSet,
+ bParaIsRTL));
+ return aRunChanges;
+ }
+
+ typedef std::pair<int32_t, bool> DirEntry;
+ typedef std::vector<DirEntry> DirChanges;
+ typedef DirChanges::const_iterator cDirIter;
+
+ typedef std::pair<xub_StrLen, sal_Int16> CharSetEntry;
+ typedef std::vector<CharSetEntry> CharSetChanges;
+ typedef CharSetChanges::const_iterator cCharSetIter;
+
+ typedef std::pair<xub_StrLen, sal_uInt16> ScriptEntry;
+ typedef std::vector<ScriptEntry> ScriptChanges;
+ typedef ScriptChanges::const_iterator cScriptIter;
+
+ DirChanges aDirChanges;
+ CharSetChanges aCharSets;
+ ScriptChanges aScripts;
+
+ UBiDiDirection eDefaultDir = bParaIsRTL ? UBIDI_RTL : UBIDI_LTR;
+ UErrorCode nError = U_ZERO_ERROR;
+ UBiDi* pBidi = ubidi_openSized(rTxt.Len(), 0, &nError);
+ ubidi_setPara(pBidi, reinterpret_cast<const UChar *>(rTxt.GetBuffer()), rTxt.Len(),
+ static_cast< UBiDiLevel >(eDefaultDir), 0, &nError);
+
+ sal_Int32 nCount = ubidi_countRuns(pBidi, &nError);
+ aDirChanges.reserve(nCount);
+
+ int32_t nStart = 0;
+ int32_t nEnd;
+ UBiDiLevel nCurrDir;
+
+ for (sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx)
+ {
+ ubidi_getLogicalRun(pBidi, nStart, &nEnd, &nCurrDir);
+ /*
+ UBiDiLevel is the type of the level values in this BiDi
+ implementation.
+
+ It holds an embedding level and indicates the visual direction
+ by its bit 0 (even/odd value).
+
+ The value for UBIDI_DEFAULT_LTR is even and the one for
+ UBIDI_DEFAULT_RTL is odd
+ */
+ aDirChanges.push_back(DirEntry(nEnd, nCurrDir & 0x1));
+ nStart = nEnd;
+ }
+ ubidi_close(pBidi);
+
+ if (bSplitOnCharSet)
+ {
+ //Split unicode text into plausable 8bit ranges for export to
+ //older non unicode aware format
+ xub_StrLen nLen = rTxt.Len();
+ xub_StrLen nPos = 0;
+ while (nPos != nLen)
+ {
+ rtl_TextEncoding ScriptType =
+ getBestMSEncodingByChar(rTxt.GetChar(nPos++));
+ while (
+ (nPos != nLen) &&
+ (ScriptType == getBestMSEncodingByChar(rTxt.GetChar(nPos)))
+ )
+ {
+ ++nPos;
+ }
+
+ aCharSets.push_back(CharSetEntry(nPos, ScriptType));
+ }
+ }
+
+ using sw::types::writer_cast;
+
+ if (pBreakIt && pBreakIt->GetBreakIter().is())
+ {
+ xub_StrLen nLen = rTxt.Len();
+ xub_StrLen nPos = 0;
+ while (nPos < nLen)
+ {
+ sal_Int32 nEnd2 = pBreakIt->GetBreakIter()->endOfScript(rTxt, nPos,
+ nScript);
+ if (nEnd2 < 0)
+ break;
+ nPos = static_cast< xub_StrLen >(nEnd2);
+ aScripts.push_back(ScriptEntry(nPos, nScript));
+ nScript = pBreakIt->GetBreakIter()->getScriptType(rTxt, nPos);
+ }
+ }
+
+ cDirIter aBiDiEnd = aDirChanges.end();
+ cCharSetIter aCharSetEnd = aCharSets.end();
+ cScriptIter aScriptEnd = aScripts.end();
+
+ cDirIter aBiDiIter = aDirChanges.begin();
+ cCharSetIter aCharSetIter = aCharSets.begin();
+ cScriptIter aScriptIter = aScripts.begin();
+
+ bool bCharIsRTL = bParaIsRTL;
+
+ while (
+ aBiDiIter != aBiDiEnd ||
+ aCharSetIter != aCharSetEnd ||
+ aScriptIter != aScriptEnd
+ )
+ {
+ xub_StrLen nMinPos = rTxt.Len();
+
+ if (aBiDiIter != aBiDiEnd)
+ {
+ if (aBiDiIter->first < nMinPos)
+ nMinPos = static_cast< xub_StrLen >(aBiDiIter->first);
+ bCharIsRTL = aBiDiIter->second;
+ }
+
+ if (aCharSetIter != aCharSetEnd)
+ {
+ if (aCharSetIter->first < nMinPos)
+ nMinPos = aCharSetIter->first;
+ eChrSet = aCharSetIter->second;
+ }
+
+ if (aScriptIter != aScriptEnd)
+ {
+ if (aScriptIter->first < nMinPos)
+ nMinPos = aScriptIter->first;
+ nScript = aScriptIter->second;
+ }
+
+ aRunChanges.push_back(
+ CharRunEntry(nMinPos, nScript, eChrSet, bCharIsRTL));
+
+ if (aBiDiIter != aBiDiEnd)
+ {
+ if (aBiDiIter->first == nMinPos)
+ ++aBiDiIter;
+ }
+
+ if (aCharSetIter != aCharSetEnd)
+ {
+ if (aCharSetIter->first == nMinPos)
+ ++aCharSetIter;
+ }
+
+ if (aScriptIter != aScriptEnd)
+ {
+ if (aScriptIter->first == nMinPos)
+ ++aScriptIter;
+ }
+ }
+
+ aRunChanges.erase(std::remove_if(aRunChanges.begin(),
+ aRunChanges.end(), myImplHelpers::IfBeforeStart(nTxtStart)), aRunChanges.end());
+
+ return aRunChanges;
+ }
+ }
+
+ namespace ms
+ {
+ sal_uInt8 rtl_TextEncodingToWinCharset(rtl_TextEncoding eTextEncoding)
+ {
+ sal_uInt8 nRet =
+ rtl_getBestWindowsCharsetFromTextEncoding(eTextEncoding);
+ switch (eTextEncoding)
+ {
+ case RTL_TEXTENCODING_DONTKNOW:
+ case RTL_TEXTENCODING_UCS2:
+ case RTL_TEXTENCODING_UTF7:
+ case RTL_TEXTENCODING_UTF8:
+ case RTL_TEXTENCODING_JAVA_UTF8:
+ OSL_ENSURE(nRet != 0x80, "This method may be redundant");
+ nRet = 0x80;
+ break;
+ default:
+ break;
+ }
+ return nRet;
+ }
+
+ long DateTime2DTTM( const DateTime& rDT )
+ {
+ /*
+ mint short :6 0000003F minutes (0-59)
+ hr short :5 000007C0 hours (0-23)
+ dom short :5 0000F800 days of month (1-31)
+ mon short :4 000F0000 months (1-12)
+ yr short :9 1FF00000 years (1900-2411)-1900
+ wdy short :3 E0000000 weekday(Sunday=0
+ Monday=1
+ ( wdy can be ignored ) Tuesday=2
+ Wednesday=3
+ Thursday=4
+ Friday=5
+ Saturday=6)
+ */
+
+ if ( rDT.GetDate() == 0L )
+ return 0L;
+ long nDT = ( rDT.GetDayOfWeek() + 1 ) % 7;
+ nDT <<= 9;
+ nDT += ( rDT.GetYear() - 1900 ) & 0x1ff;
+ nDT <<= 4;
+ nDT += rDT.GetMonth() & 0xf;
+ nDT <<= 5;
+ nDT += rDT.GetDay() & 0x1f;
+ nDT <<= 5;
+ nDT += rDT.GetHour() & 0x1f;
+ nDT <<= 6;
+ nDT += rDT.GetMin() & 0x3f;
+ return nDT;
+ }
+
+ DateTime DTTM2DateTime( long lDTTM )
+ {
+ /*
+ mint short :6 0000003F minutes (0-59)
+ hr short :5 000007C0 hours (0-23)
+ dom short :5 0000F800 days of month (1-31)
+ mon short :4 000F0000 months (1-12)
+ yr short :9 1FF00000 years (1900-2411)-1900
+ wdy short :3 E0000000 weekday(Sunday=0
+ Monday=1
+ ( wdy can be ignored ) Tuesday=2
+ Wednesday=3
+ Thursday=4
+ Friday=5
+ Saturday=6)
+ */
+ DateTime aDateTime(Date( 0 ), Time( 0 ));
+ if( lDTTM )
+ {
+ sal_uInt16 lMin = (sal_uInt16)(lDTTM & 0x0000003F);
+ lDTTM >>= 6;
+ sal_uInt16 lHour= (sal_uInt16)(lDTTM & 0x0000001F);
+ lDTTM >>= 5;
+ sal_uInt16 lDay = (sal_uInt16)(lDTTM & 0x0000001F);
+ lDTTM >>= 5;
+ sal_uInt16 lMon = (sal_uInt16)(lDTTM & 0x0000000F);
+ lDTTM >>= 4;
+ sal_uInt16 lYear= (sal_uInt16)(lDTTM & 0x000001FF) + 1900;
+ aDateTime = DateTime(Date(lDay, lMon, lYear), Time(lHour, lMin));
+ }
+ return aDateTime;
+ }
+
+ sal_uLong MSDateTimeFormatToSwFormat(String& rParams,
+ SvNumberFormatter *pFormatter, sal_uInt16 &rLang, bool bHijri,
+ sal_uInt16 nDocLang)
+ {
+ // tell the Formatter about the new entry
+ sal_uInt16 nCheckPos = 0;
+ short nType = NUMBERFORMAT_DEFINED;
+ sal_uInt32 nKey = 0;
+
+ SwapQuotesInField(rParams);
+
+ // Force to Japanese when finding one of 'geaE'
+ rtl::OUString sJChars(RTL_CONSTASCII_USTRINGPARAM("geE"));
+ bool bForceJapanese = ( STRING_NOTFOUND != rParams.SearchChar( sJChars.getStr() ) );
+ if ( bForceJapanese )
+ {
+ rParams.SearchAndReplaceAll( String::CreateFromAscii( "ee" ),
+ String::CreateFromAscii( "yyyy" ) );
+ rParams.SearchAndReplaceAll( String::CreateFromAscii( "EE" ),
+ String::CreateFromAscii( "YYYY" ) );
+ }
+ if (LANGUAGE_FRENCH != nDocLang)
+ {
+ // Handle the 'a' case here
+ xub_StrLen nLastPos = 0;
+ do
+ {
+ xub_StrLen nPos = rParams.Search( 'a', nLastPos + 1 );
+ bForceJapanese |= ( nPos != STRING_NOTFOUND && IsNotAM( rParams, nPos ) );
+ nLastPos = nPos;
+ } while ( STRING_NOTFOUND != nLastPos );
+ }
+
+ // Force to NatNum when finding one of 'oOA'
+ String sOldParams( rParams );
+ rParams.SearchAndReplaceAll( String::CreateFromAscii( "o" ),
+ String::CreateFromAscii( "m" ) );
+ rParams.SearchAndReplaceAll( String::CreateFromAscii( "O" ),
+ String::CreateFromAscii( "M" ) );
+ bool bForceNatNum = !sOldParams.Equals( rParams );
+ if (LANGUAGE_FRENCH != nDocLang)
+ {
+ // Handle the 'A' case here
+ xub_StrLen nLastPos = 0;
+ do
+ {
+ xub_StrLen nPos = rParams.Search( 'A', nLastPos + 1 );
+ bool bIsCharA = ( nPos != STRING_NOTFOUND && IsNotAM( rParams, nPos ) );
+ bForceNatNum |= bIsCharA;
+ if ( bIsCharA )
+ rParams.SetChar( nPos, 'D' );
+ nLastPos = nPos;
+ } while ( STRING_NOTFOUND != nLastPos );
+ }
+
+ xub_StrLen nLen = rParams.Len();
+ xub_StrLen nI = 0;
+ while (nI < nLen)
+ {
+ if (rParams.GetChar(nI) == '\\')
+ nI++;
+ else if (rParams.GetChar(nI) == '\"')
+ {
+ ++nI;
+ //While not at the end and not at an unescaped end quote
+ while ((nI < nLen) && (!(rParams.GetChar(nI) == '\"') && (rParams.GetChar(nI-1) != '\\')))
+ ++nI;
+ }
+ else //normal unquoted section
+ {
+ sal_Unicode nChar = rParams.GetChar(nI);
+
+ // Change the localized word string to english
+ switch ( nDocLang )
+ {
+ case LANGUAGE_FRENCH:
+ if ( ( nChar == 'a' || nChar == 'A' ) && IsNotAM(rParams, nI) )
+ rParams.SetChar(nI, 'Y');
+ break;
+ default:
+ ;
+ }
+ if (nChar == '/')
+ {
+ // MM We have to escape '/' in case it's used as a char
+ rParams.Replace(nI, 1, CREATE_CONST_ASC("\\/"));
+ nI++;
+ nLen++;
+ }
+
+ // Deal with language differences in date format expression.
+ // Should be made with i18n framework.
+ // The list of the mappings and of those "special" locales is to be found at:
+ // http://l10n.openoffice.org/i18n_framework/LocaleData.html
+ if ( !bForceJapanese && !bForceNatNum )
+ {
+ // Convert to the localized equivalent for OOo
+ switch ( rLang )
+ {
+ case LANGUAGE_FINNISH:
+ {
+ if (nChar == 'y' || nChar == 'Y')
+ rParams.SetChar (nI, 'V');
+ else if (nChar == 'm' || nChar == 'M')
+ rParams.SetChar (nI, 'K');
+ else if (nChar == 'd' || nChar == 'D')
+ rParams.SetChar (nI, 'P');
+ else if (nChar == 'h' || nChar == 'H')
+ rParams.SetChar (nI, 'T');
+ }
+ break;
+ case LANGUAGE_DANISH:
+ case LANGUAGE_NORWEGIAN:
+ case LANGUAGE_NORWEGIAN_BOKMAL:
+ case LANGUAGE_NORWEGIAN_NYNORSK:
+ case LANGUAGE_SWEDISH:
+ case LANGUAGE_SWEDISH_FINLAND:
+ {
+ if (nChar == 'h' || nChar == 'H')
+ rParams.SetChar (nI, 'T');
+ }
+ break;
+ case LANGUAGE_PORTUGUESE:
+ case LANGUAGE_PORTUGUESE_BRAZILIAN:
+ case LANGUAGE_SPANISH_MODERN:
+ case LANGUAGE_SPANISH_DATED:
+ case LANGUAGE_SPANISH_MEXICAN:
+ case LANGUAGE_SPANISH_GUATEMALA:
+ case LANGUAGE_SPANISH_COSTARICA:
+ case LANGUAGE_SPANISH_PANAMA:
+ case LANGUAGE_SPANISH_DOMINICAN_REPUBLIC:
+ case LANGUAGE_SPANISH_VENEZUELA:
+ case LANGUAGE_SPANISH_COLOMBIA:
+ case LANGUAGE_SPANISH_PERU:
+ case LANGUAGE_SPANISH_ARGENTINA:
+ case LANGUAGE_SPANISH_ECUADOR:
+ case LANGUAGE_SPANISH_CHILE:
+ case LANGUAGE_SPANISH_URUGUAY:
+ case LANGUAGE_SPANISH_PARAGUAY:
+ case LANGUAGE_SPANISH_BOLIVIA:
+ case LANGUAGE_SPANISH_EL_SALVADOR:
+ case LANGUAGE_SPANISH_HONDURAS:
+ case LANGUAGE_SPANISH_NICARAGUA:
+ case LANGUAGE_SPANISH_PUERTO_RICO:
+ {
+ if (nChar == 'a' || nChar == 'A')
+ rParams.SetChar (nI, 'O');
+ else if (nChar == 'y' || nChar == 'Y')
+ rParams.SetChar (nI, 'A');
+ }
+ break;
+ case LANGUAGE_DUTCH:
+ case LANGUAGE_DUTCH_BELGIAN:
+ {
+ if (nChar == 'y' || nChar == 'Y')
+ rParams.SetChar (nI, 'J');
+ else if (nChar == 'u' || nChar == 'U')
+ rParams.SetChar (nI, 'H');
+ }
+ break;
+ case LANGUAGE_ITALIAN:
+ case LANGUAGE_ITALIAN_SWISS:
+ {
+ if (nChar == 'a' || nChar == 'A')
+ rParams.SetChar (nI, 'O');
+ else if (nChar == 'g' || nChar == 'G')
+ rParams.SetChar (nI, 'X');
+ else if (nChar == 'y' || nChar == 'Y')
+ rParams.SetChar(nI, 'A');
+ else if (nChar == 'd' || nChar == 'D')
+ rParams.SetChar (nI, 'G');
+ }
+ break;
+ case LANGUAGE_GERMAN:
+ case LANGUAGE_GERMAN_SWISS:
+ case LANGUAGE_GERMAN_AUSTRIAN:
+ case LANGUAGE_GERMAN_LUXEMBOURG:
+ case LANGUAGE_GERMAN_LIECHTENSTEIN:
+ {
+ if (nChar == 'y' || nChar == 'Y')
+ rParams.SetChar (nI, 'J');
+ else if (nChar == 'd' || nChar == 'D')
+ rParams.SetChar (nI, 'T');
+ }
+ break;
+ case LANGUAGE_FRENCH:
+ case LANGUAGE_FRENCH_BELGIAN:
+ case LANGUAGE_FRENCH_CANADIAN:
+ case LANGUAGE_FRENCH_SWISS:
+ case LANGUAGE_FRENCH_LUXEMBOURG:
+ case LANGUAGE_FRENCH_MONACO:
+ {
+ if (nChar == 'y' || nChar == 'Y' || nChar == 'a')
+ rParams.SetChar (nI, 'A');
+ else if (nChar == 'd' || nChar == 'D' || nChar == 'j')
+ rParams.SetChar (nI, 'J');
+ }
+ break;
+ default:
+ {
+ ; // Nothing
+ }
+ }
+ }
+ }
+ ++nI;
+ }
+
+ if (bForceNatNum)
+ bForceJapanese = true;
+
+ if (bForceJapanese)
+ rLang = LANGUAGE_JAPANESE;
+
+ if (bForceNatNum)
+ rParams.Insert(CREATE_CONST_ASC("[NatNum1][$-411]"),0);
+
+ if (bHijri)
+ rParams.Insert(CREATE_CONST_ASC("[~hijri]"), 0);
+
+ pFormatter->PutEntry(rParams, nCheckPos, nType, nKey, rLang);
+
+ return nKey;
+ }
+
+ bool IsNotAM(String& rParams, xub_StrLen nPos)
+ {
+ return (
+ (nPos == rParams.Len() - 1) ||
+ (
+ (rParams.GetChar(nPos+1) != 'M') &&
+ (rParams.GetChar(nPos+1) != 'm')
+ )
+ );
+ }
+
+ void SwapQuotesInField(String &rFmt)
+ {
+ //Swap unescaped " and ' with ' and "
+ xub_StrLen nLen = rFmt.Len();
+ for (xub_StrLen nI = 0; nI < nLen; ++nI)
+ {
+ if ((rFmt.GetChar(nI) == '\"') && (!nI || rFmt.GetChar(nI-1) != '\\'))
+ rFmt.SetChar(nI, '\'');
+ else if ((rFmt.GetChar(nI) == '\'') && (!nI || rFmt.GetChar(nI-1) != '\\'))
+ rFmt.SetChar(nI, '\"');
+ }
+ }
+
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/writerwordglue.hxx b/sw/source/filter/ww8/writerwordglue.hxx
new file mode 100644
index 000000000000..7d5f9baea666
--- /dev/null
+++ b/sw/source/filter/ww8/writerwordglue.hxx
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef SW_WRITERWORDGLUE
+#define SW_WRITERWORDGLUE
+
+#include "needed_cast.hxx"
+#include "types.hxx"
+
+class SwFrmFmt;
+class SfxItemSet;
+
+namespace sw
+{
+ namespace types
+ {
+ /** A static_cast style cast for conversion of word types to writer's
+
+ There are a number of places where the winword types are larger
+ than the writer equivalents requiring a cast to silence warnings.
+ To avoid throwing away this useful information writer_cast is used
+ to identify where writer's types are smaller than word's.
+
+ Based on needed_cast it will compile time assert if the cast
+ becomes unnecessary at any time in the future.
+
+ @tplparam
+ Ret the desired return type
+
+ @tplparam
+ Param the type of the in param
+
+ @param
+ in the value to cast from Param to Ret
+
+ @return in casted to type Ret
+ */
+ template<typename Ret, typename Param> Ret writer_cast(Param in)
+ {
+ return ww::needed_cast<Ret, Param>(in);
+ }
+
+ /** A static_cast style cast for conversion of writer types to word's
+
+ There are a number of places where the writer types are larger than
+ the winword equivalents requiring a cast to silence warnings. To
+ avoid throwing away this useful information writer_cast is used to
+ identify where word's types are smaller than writers's.
+
+ Based on needed_cast it will compile time assert if the cast
+ becomes unnecessary at any time in the future.
+
+ @tplparam
+ Ret the desired return type
+
+ @tplparam
+ Param the type of the in param
+
+ @param
+ in the value to cast from Param to Ret
+
+ @return in casted to type Ret
+ */
+ template<typename Ret, typename Param> Ret msword_cast(Param in)
+ {
+ return ww::needed_cast<Ret, Param>(in);
+ }
+ }
+
+ namespace util
+ {
+ /** See if two page formats can be expressed as a single word section
+
+ Word doesn't have the idea of page descriptors and follow styles
+ like writer does, the only thing it has is a section with a
+ different title page. The only difference of the title page from
+ the rest of the section is different headers/footers, everything
+ else is the same.
+
+ So this function compares two writer page fmts and sees if the
+ follow frame and the title frame are the same from word persecptive
+ except for the content of their headers.
+
+ @return true if the rTitleFmt followed by rFollowFmt could be
+ expressed in word as a single word Section with different title
+ page enabled.
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+
+ @see #i4320#/#i14509#/#i11717# for examples
+ */
+ bool IsPlausableSingleWordSection(const SwFrmFmt &rTitleFmt,
+ const SwFrmFmt &rFollowFmt);
+
+ /** Make export a word section top/bottom values easy
+
+ The top and bottom margins in word and writer are expressed in very
+ different ways. This class provides the equivalent word values for
+ header/footer distances from a given writer attrset of a page
+
+ @author
+ <a href="mailto:cmc@openoffice.org">Caol&aacute;n McNamara</a>
+ */
+ class HdFtDistanceGlue
+ {
+ private:
+ bool mbHasHeader;
+ bool mbHasFooter;
+ public:
+ sal_uInt16 dyaHdrTop;
+ sal_uInt16 dyaHdrBottom;
+ sal_uInt16 dyaTop;
+ sal_uInt16 dyaBottom;
+ HdFtDistanceGlue(const SfxItemSet &rPage);
+ bool HasHeader() const { return mbHasHeader; }
+ bool HasFooter() const { return mbHasFooter; }
+
+ /** Is the top of the page the same in both objects
+
+ Ignoring the difference in header and footers, will the main
+ document text have the same top/bottom bounds in word between
+ both these objects.
+
+ @param
+ rOther the other HdFtDistanceGlue to compare against
+
+ @return true if the main text areas top and bottom is at the
+ same location, false otherwise.
+ */
+ bool EqualTopBottom(const HdFtDistanceGlue &rOther) const;
+
+ };
+ }
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/wrtw8esh.cxx b/sw/source/filter/ww8/wrtw8esh.cxx
new file mode 100644
index 000000000000..6bf28901dc83
--- /dev/null
+++ b/sw/source/filter/ww8/wrtw8esh.cxx
@@ -0,0 +1,2811 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <com/sun/star/embed/Aspects.hpp>
+
+
+#include <hintids.hxx>
+
+#define _SVSTDARR_ULONGSSORT
+#define _SVSTDARR_USHORTS
+#include <svl/svstdarr.hxx>
+#include <vcl/cvtgrf.hxx>
+#include <vcl/virdev.hxx>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <vcl/svapp.hxx>
+#include <sot/storage.hxx>
+#include <svtools/filter.hxx>
+#include <svl/itemiter.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/outlobj.hxx>
+#include <editeng/editobj.hxx>
+#include <svx/unoshape.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svx/svdoole2.hxx>
+#include <editeng/editeng.hxx>
+#ifndef _SVX_FLDITEM_HXX
+//miserable hack to get around #98519#
+
+#include <editeng/flditem.hxx>
+#endif
+
+#include <comphelper/seqstream.hxx>
+#include <unotools/ucbstreamhelper.hxx>
+#include <svx/fmglob.hxx>
+#include <svx/svdouno.hxx>
+#include <svx/unoapi.hxx>
+
+// #i71538#
+#include <svx/svdview.hxx>
+#include <fmtcnct.hxx>
+#include <fmtanchr.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtornt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtfollowtextflow.hxx> // #i30669#
+#include <dcontact.hxx>
+#include <frmfmt.hxx>
+#include <fmtcntnt.hxx>
+#include <ndindex.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <swrect.hxx>
+#include <ndgrf.hxx>
+#include <grfatr.hxx>
+#include <ndole.hxx>
+#include <unodraw.hxx>
+#include <pagedesc.hxx>
+#include <ww8par.hxx>
+#include <breakit.hxx>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include "ww8attributeoutput.hxx"
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "wrtww8.hxx"
+#include "escher.hxx"
+#include <ndtxt.hxx>
+#include "WW8FFData.hxx"
+
+using ::editeng::SvxBorderLine;
+using namespace com::sun::star;
+using namespace sw::util;
+using namespace sw::types;
+using namespace nsFieldFlags;
+
+// get a part fix for this type of element
+bool WW8Export::MiserableFormFieldExportHack(const SwFrmFmt& rFrmFmt)
+{
+ OSL_ENSURE(bWrtWW8, "Not allowed");
+ if (!bWrtWW8)
+ return false;
+ bool bHack = false;
+ const SdrObject *pObject = rFrmFmt.FindRealSdrObject();
+ if (pObject && pObject->GetObjInventor() == FmFormInventor)
+ {
+ if (SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObject))
+ {
+ uno::Reference< awt::XControlModel > xControlModel =
+ pFormObj->GetUnoControlModel();
+ uno::Reference< lang::XServiceInfo > xInfo(xControlModel,
+ uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xPropSet(xControlModel, uno::UNO_QUERY);
+ if (xInfo->supportsService(C2U("com.sun.star.form.component.ComboBox")))
+ {
+ DoComboBox(xPropSet);
+ bHack = true;
+ }
+ else if (xInfo->supportsService(C2U("com.sun.star.form.component.CheckBox")))
+ {
+ DoCheckBox(xPropSet);
+ bHack = true;
+ }
+ }
+ }
+ return bHack;
+}
+
+
+void WW8Export::DoComboBox(uno::Reference<beans::XPropertySet> xPropSet)
+{
+ rtl::OUString sSelected;
+ uno::Sequence<rtl::OUString> aListItems;
+ xPropSet->getPropertyValue(C2U("StringItemList")) >>= aListItems;
+ sal_Int32 nNoStrings = aListItems.getLength();
+ if (nNoStrings)
+ {
+ uno::Any aTmp = xPropSet->getPropertyValue(C2U("DefaultText"));
+ const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
+ if (pStr)
+ sSelected = *pStr;
+ }
+
+ rtl::OUString sName;
+ {
+ uno::Any aTmp = xPropSet->getPropertyValue(C2U("Name"));
+ const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
+ if (pStr)
+ sName = *pStr;
+ }
+
+
+ rtl::OUString sHelp;
+ {
+ // property "Help" does not exist and due to the no-existence an exception is thrown.
+ try
+ {
+ uno::Any aTmp = xPropSet->getPropertyValue(C2U("HelpText"));
+ // <--
+ const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
+ if (pStr)
+ sHelp = *pStr;
+ }
+ catch( uno::Exception& )
+ {}
+ // <--
+ }
+
+ rtl::OUString sToolTip;
+ {
+ uno::Any aTmp = xPropSet->getPropertyValue(C2U("Name"));
+ const rtl::OUString *pStr = (const rtl::OUString *)aTmp.getValue();
+ if (pStr)
+ sToolTip = *pStr;
+ }
+
+ DoComboBox(sName, sHelp, sToolTip, sSelected, aListItems);
+}
+
+void WW8Export::DoComboBox(const rtl::OUString &rName,
+ const rtl::OUString &rHelp,
+ const rtl::OUString &rToolTip,
+ const rtl::OUString &rSelected,
+ uno::Sequence<rtl::OUString> &rListItems)
+{
+ OSL_ENSURE(bWrtWW8, "Not allowed");
+ if (!bWrtWW8)
+ return;
+ OutputField(0, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
+ WRITEFIELD_START | WRITEFIELD_CMD_START);
+ // write the refence to the "picture" structure
+ sal_uLong nDataStt = pDataStrm->Tell();
+ pChpPlc->AppendFkpEntry( Strm().Tell() );
+
+ WriteChar( 0x01 );
+
+ static sal_uInt8 aArr1[] =
+ {
+ 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
+ 0x06, 0x08, 0x01, // sprmCFData
+ 0x55, 0x08, 0x01, // sprmCFSpec
+ 0x02, 0x08, 0x01 // sprmCFFldVanish
+ };
+ sal_uInt8* pDataAdr = aArr1 + 2;
+ Set_UInt32( pDataAdr, nDataStt );
+
+ pChpPlc->AppendFkpEntry(Strm().Tell(), sizeof(aArr1), aArr1);
+
+ OutputField(0, ww::eFORMDROPDOWN, FieldString(ww::eFORMDROPDOWN),
+ WRITEFIELD_CLOSE);
+
+ ::sw::WW8FFData aFFData;
+
+ aFFData.setType(2);
+ aFFData.setName(rName);
+ aFFData.setHelp(rHelp);
+ aFFData.setStatus(rToolTip);
+
+ sal_uInt32 nListItems = rListItems.getLength();
+
+ for (sal_uInt32 i = 0; i < nListItems; i++)
+ {
+ if (i < 0x20 && rSelected == rListItems[i])
+ aFFData.setResult(::sal::static_int_cast<sal_uInt8>(i));
+ aFFData.addListboxEntry(rListItems[i]);
+ }
+
+ aFFData.Write(pDataStrm);
+}
+
+void WW8Export::DoCheckBox(uno::Reference<beans::XPropertySet> xPropSet)
+{
+ uno::Reference<beans::XPropertySetInfo> xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+
+ OutputField(0, ww::eFORMCHECKBOX, FieldString(ww::eFORMCHECKBOX),
+ WRITEFIELD_START | WRITEFIELD_CMD_START);
+ // write the refence to the "picture" structure
+ sal_uLong nDataStt = pDataStrm->Tell();
+ pChpPlc->AppendFkpEntry( Strm().Tell() );
+
+ WriteChar( 0x01 );
+ static sal_uInt8 aArr1[] = {
+ 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
+
+ 0x06, 0x08, 0x01, // sprmCFData
+ 0x55, 0x08, 0x01, // sprmCFSpec
+ 0x02, 0x08, 0x01 // sprmCFFldVanish
+ };
+ sal_uInt8* pDataAdr = aArr1 + 2;
+ Set_UInt32( pDataAdr, nDataStt );
+
+ pChpPlc->AppendFkpEntry(Strm().Tell(),
+ sizeof( aArr1 ), aArr1 );
+
+ ::sw::WW8FFData aFFData;
+
+ aFFData.setType(1);
+ aFFData.setCheckboxHeight(0x14);
+
+ sal_Int16 nTemp = 0;
+ xPropSet->getPropertyValue(C2U("DefaultState")) >>= nTemp;
+ aFFData.setDefaultResult(nTemp);
+
+ xPropSet->getPropertyValue(C2U("State")) >>= nTemp;
+ aFFData.setResult(nTemp);
+
+ ::rtl::OUString aStr;
+ static ::rtl::OUString sName(C2U("Name"));
+ if (xPropSetInfo->hasPropertyByName(sName))
+ {
+ xPropSet->getPropertyValue(sName) >>= aStr;
+ aFFData.setName(aStr);
+ }
+
+ static ::rtl::OUString sHelpText(C2U("HelpText"));
+ if (xPropSetInfo->hasPropertyByName(sHelpText))
+ {
+ xPropSet->getPropertyValue(sHelpText) >>= aStr;
+ aFFData.setHelp(aStr);
+ }
+ static ::rtl::OUString sHelpF1Text(C2U("HelpF1Text"));
+ if (xPropSetInfo->hasPropertyByName(sHelpF1Text))
+ {
+ xPropSet->getPropertyValue(sHelpF1Text) >>= aStr;
+ aFFData.setStatus(aStr);
+ }
+
+ aFFData.Write(pDataStrm);
+
+ OutputField(0, ww::eFORMCHECKBOX, aEmptyStr, WRITEFIELD_CLOSE);
+}
+
+void WW8Export::DoFormText(const SwInputField * pFld)
+{
+ OutputField(0, ww::eFORMTEXT, FieldString(ww::eFORMTEXT),
+ WRITEFIELD_START | WRITEFIELD_CMD_START);
+ // write the refence to the "picture" structure
+ sal_uLong nDataStt = pDataStrm->Tell();
+ pChpPlc->AppendFkpEntry( Strm().Tell() );
+
+ WriteChar( 0x01 );
+ static sal_uInt8 aArr1[] = {
+ 0x02, 0x08, 0x81, // sprmCFFldVanish
+ 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
+
+ 0x06, 0x08, 0x01, // sprmCFData
+ 0x55, 0x08, 0x01 // sprmCFSpec
+ };
+ sal_uInt8* pDataAdr = aArr1 + 5;
+ Set_UInt32( pDataAdr, nDataStt );
+
+ pChpPlc->AppendFkpEntry(Strm().Tell(),
+ sizeof( aArr1 ), aArr1 );
+
+ ::sw::WW8FFData aFFData;
+
+ aFFData.setType(0);
+ aFFData.setName(pFld->GetPar2());
+ aFFData.setHelp(pFld->GetHelp());
+ aFFData.setStatus(pFld->GetToolTip());
+ aFFData.Write(pDataStrm);
+
+ OutputField(0, ww::eFORMTEXT, aEmptyStr, WRITEFIELD_CMD_END);
+
+ String const fieldStr( pFld->ExpandField(true) );
+ SwWW8Writer::WriteString16(Strm(), fieldStr, false);
+
+ static sal_uInt8 aArr2[] = {
+ 0x03, 0x6a, 0x00, 0x00, 0x00, 0x00, // sprmCPicLocation
+ 0x55, 0x08, 0x01, // sprmCFSpec
+ 0x75, 0x08, 0x01 // ???
+ };
+
+ pDataAdr = aArr2 + 2;
+ Set_UInt32( pDataAdr, nDataStt );
+ pChpPlc->AppendFkpEntry(Strm().Tell(),
+ sizeof( aArr2 ), aArr2 );
+
+ OutputField(0, ww::eFORMTEXT, aEmptyStr, WRITEFIELD_CLOSE);
+}
+
+PlcDrawObj::~PlcDrawObj()
+{
+}
+
+//Its irritating to have to change the RTL frames position into LTR ones
+//so that word will have to place them in the right place. Doubly so that
+//the SO drawings and writer frames have different ideas themselves as to
+//how to be positioned when in RTL mode!
+bool RTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
+sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
+ SwTwips nPageRight, SwTwips nPageSize)
+{
+ bool bRet = false;
+ if (eHoriOri == text::HoriOrientation::NONE)
+ {
+ if (eHoriRel == text::RelOrientation::PAGE_FRAME)
+ {
+ rLeft = nPageSize - rLeft;
+ bRet = true;
+ }
+ else if (
+ (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
+ (eHoriRel == text::RelOrientation::FRAME) ||
+ (eHoriRel == text::RelOrientation::PRINT_AREA)
+ )
+ {
+ rLeft = nPageSize - nPageLeft - nPageRight - rLeft;
+ bRet = true;
+ }
+ }
+ if (bRet)
+ rLeft -= nWidth;
+ return bRet;
+}
+
+bool RTLDrawingsHack(long &rLeft, long /*nWidth*/,
+ sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
+ SwTwips nPageRight, SwTwips nPageSize)
+{
+ bool bRet = false;
+ if (eHoriOri == text::HoriOrientation::NONE)
+ {
+ if (eHoriRel == text::RelOrientation::PAGE_FRAME)
+ {
+ rLeft = nPageSize + rLeft;
+ bRet = true;
+ }
+ else if (
+ (eHoriRel == text::RelOrientation::PAGE_PRINT_AREA) ||
+ (eHoriRel == text::RelOrientation::FRAME) ||
+ (eHoriRel == text::RelOrientation::PRINT_AREA)
+ )
+ {
+ rLeft = nPageSize - nPageLeft - nPageRight + rLeft;
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+bool WW8Export::MiserableRTLFrmFmtHack(SwTwips &rLeft, SwTwips &rRight,
+ const sw::Frame &rFrmFmt)
+{
+ //Require nasty bidi swap
+ if (FRMDIR_HORI_RIGHT_TOP != pDoc->GetTextDirection(rFrmFmt.GetPosition()))
+ return false;
+
+ SwTwips nWidth = rRight - rLeft;
+ SwTwips nPageLeft, nPageRight;
+ SwTwips nPageSize = CurrentPageWidth(nPageLeft, nPageRight);
+
+ const SwFmtHoriOrient& rHOr = rFrmFmt.GetFrmFmt().GetHoriOrient();
+
+ bool bRet = false;
+ sw::Frame::WriterSource eSource = rFrmFmt.GetWriterType();
+ if (eSource == sw::Frame::eDrawing || eSource == sw::Frame::eFormControl)
+ {
+ if (RTLDrawingsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
+ rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
+ {
+ bRet = true;
+ }
+ }
+ else
+ {
+ if (RTLGraphicsHack(rLeft, nWidth, rHOr.GetHoriOrient(),
+ rHOr.GetRelationOrient(), nPageLeft, nPageRight, nPageSize))
+ {
+ bRet = true;
+ }
+ }
+ if (bRet)
+ rRight = rLeft + nWidth;
+ return bRet;
+}
+
+void PlcDrawObj::WritePlc( WW8Export& rWrt ) const
+{
+ if (8 > rWrt.pFib->nVersion) // Cannot export drawobject in vers 7-
+ return;
+
+ sal_uInt32 nFcStart = rWrt.pTableStrm->Tell();
+
+ if (!maDrawObjs.empty())
+ {
+ // write CPs
+ WW8Fib& rFib = *rWrt.pFib;
+ WW8_CP nCpOffs = GetCpOffset(rFib);
+
+ cDrawObjIter aEnd = maDrawObjs.end();
+ cDrawObjIter aIter;
+
+ for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnCp - nCpOffs);
+
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, rFib.ccpText + rFib.ccpFtn +
+ rFib.ccpHdr + rFib.ccpEdn + rFib.ccpTxbx + rFib.ccpHdrTxbx + 1);
+
+ for (aIter = maDrawObjs.begin(); aIter < aEnd; ++aIter)
+ {
+ // write the fspa-struct
+ const sw::Frame &rFrmFmt = aIter->maCntnt;
+ const SwFrmFmt &rFmt = rFrmFmt.GetFrmFmt();
+ const SdrObject* pObj = rFmt.FindRealSdrObject();
+
+ Rectangle aRect;
+ SwFmtVertOrient rVOr = rFmt.GetVertOrient();
+ SwFmtHoriOrient rHOr = rFmt.GetHoriOrient();
+ // #i30669# - convert the positioning attributes.
+ // Most positions are converted, if layout information exists.
+ const bool bPosConverted =
+ WinwordAnchoring::ConvertPosition( rHOr, rVOr, rFmt );
+ // <--
+
+ Point aObjPos;
+ if (RES_FLYFRMFMT == rFmt.Which())
+ {
+ SwRect aLayRect(rFmt.FindLayoutRect(false, &aObjPos));
+ // the Object is not visible - so get the values from
+ // the format. The Position may not be correct.
+ if( aLayRect.IsEmpty() )
+ aRect.SetSize( rFmt.GetFrmSize().GetSize() );
+ else
+ {
+ // #i56090# Do not only consider the first client
+ // Note that we actually would have to find the maximum size of the
+ // frame format clients. However, this already should work in most cases.
+ const SwRect aSizeRect(rFmt.FindLayoutRect());
+ if ( aSizeRect.Width() > aLayRect.Width() )
+ aLayRect.Width( aSizeRect.Width() );
+ // <--
+
+ aRect = aLayRect.SVRect();
+ }
+ }
+ else
+ {
+ OSL_ENSURE(pObj, "wo ist das SDR-Object?");
+ if (pObj)
+ {
+ aRect = pObj->GetSnapRect();
+ }
+ }
+
+ // #i30669# - use converted position, if conversion is performed.
+ // Unify position determination of Writer fly frames
+ // and drawing objects.
+ if ( bPosConverted )
+ {
+ aRect.SetPos( Point( rHOr.GetPos(), rVOr.GetPos() ) );
+ }
+ else
+ {
+ aRect -= aIter->maParentPos;
+ aObjPos = aRect.TopLeft();
+ if (text::VertOrientation::NONE == rVOr.GetVertOrient())
+ {
+ // #i22673#
+ sal_Int16 eOri = rVOr.GetRelationOrient();
+ if (eOri == text::RelOrientation::CHAR || eOri == text::RelOrientation::TEXT_LINE)
+ aObjPos.Y() = -rVOr.GetPos();
+ else
+ aObjPos.Y() = rVOr.GetPos();
+ }
+ if (text::HoriOrientation::NONE == rHOr.GetHoriOrient())
+ aObjPos.X() = rHOr.GetPos();
+ aRect.SetPos( aObjPos );
+ }
+ // <--
+
+ sal_Int32 nThick = aIter->mnThick;
+
+ //If we are being exported as an inline hack, set
+ //corner to 0 and forget about border thickness for positioning
+ if (rFrmFmt.IsInline())
+ {
+ aRect.SetPos(Point(0,0));
+ nThick = 0;
+ }
+
+ // spid
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, aIter->mnShapeId);
+
+ SwTwips nLeft = aRect.Left() + nThick;
+ SwTwips nRight = aRect.Right() - nThick;
+
+ //Nasty swap for bidi if neccessary
+ rWrt.MiserableRTLFrmFmtHack(nLeft, nRight, rFrmFmt);
+
+ //xaLeft/yaTop/xaRight/yaBottom - rel. to anchor
+ //(most of) the border is outside the graphic is word, so
+ //change dimensions to fit
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, nLeft);
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm,aRect.Top() + nThick);
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, nRight);
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm,aRect.Bottom() - nThick);
+
+ //fHdr/bx/by/wr/wrk/fRcaSimple/fBelowText/fAnchorLock
+ sal_uInt16 nFlags=0;
+ //If nFlags isn't 0x14 its overridden by the escher properties
+ if (FLY_AT_PAGE == rFmt.GetAnchor().GetAnchorId())
+ nFlags = 0x0000;
+ else
+ nFlags = 0x0014; // x-rel to text, y-rel to text
+
+ const SwFmtSurround& rSurr = rFmt.GetSurround();
+ sal_uInt16 nContour = rSurr.IsContour() ? 0x0080 : 0x0040;
+ SwSurround eSurround = rSurr.GetSurround();
+
+ /*
+ #i3958#
+ The inline elements being export as anchored to character inside
+ the shape field hack are required to be wrap through so as to flow
+ over the following dummy 0x01 graphic
+ */
+ if (rFrmFmt.IsInline())
+ eSurround = SURROUND_THROUGHT;
+
+ switch (eSurround)
+ {
+ case SURROUND_NONE:
+ nFlags |= 0x0020;
+ break;
+ case SURROUND_THROUGHT:
+ nFlags |= 0x0060;
+ break;
+ case SURROUND_PARALLEL:
+ nFlags |= 0x0000 | nContour;
+ break;
+ case SURROUND_IDEAL:
+ nFlags |= 0x0600 | nContour;
+ break;
+ case SURROUND_LEFT:
+ nFlags |= 0x0200 | nContour;
+ break;
+ case SURROUND_RIGHT:
+ nFlags |= 0x0400 | nContour;
+ break;
+ default:
+ OSL_ENSURE(!this, "Unsupported surround type for export");
+ break;
+ }
+ if (pObj && (pObj->GetLayer() == rWrt.pDoc->GetHellId() ||
+ pObj->GetLayer() == rWrt.pDoc->GetInvisibleHellId()))
+ {
+ nFlags |= 0x4000;
+ }
+
+ /*
+ #i3958# Required to make this inline stuff work in WordXP, not
+ needed for 2003 interestingly
+ */
+ if (rFrmFmt.IsInline())
+ nFlags |= 0x8000;
+
+ SwWW8Writer::WriteShort(*rWrt.pTableStrm, nFlags);
+
+ // cTxbx
+ SwWW8Writer::WriteLong(*rWrt.pTableStrm, 0);
+ }
+
+ RegisterWithFib(rFib, nFcStart, rWrt.pTableStrm->Tell() - nFcStart);
+ }
+}
+
+void MainTxtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
+ sal_uInt32 nLen) const
+{
+ rFib.fcPlcfspaMom = nStart;
+ rFib.lcbPlcfspaMom = nLen;
+}
+
+WW8_CP MainTxtPlcDrawObj::GetCpOffset(const WW8Fib &) const
+{
+ return 0;
+}
+
+void HdFtPlcDrawObj::RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
+ sal_uInt32 nLen) const
+{
+ rFib.fcPlcfspaHdr = nStart;
+ rFib.lcbPlcfspaHdr = nLen;
+}
+
+WW8_CP HdFtPlcDrawObj::GetCpOffset(const WW8Fib &rFib) const
+{
+ return rFib.ccpText + rFib.ccpFtn;
+}
+
+DrawObj& DrawObj::operator=(const DrawObj& rOther)
+{
+ mnCp = rOther.mnCp;
+ mnShapeId = rOther.mnShapeId;
+ maCntnt = rOther.maCntnt;
+ maParentPos = rOther.maParentPos;
+ mnThick = rOther.mnThick;
+ mnDirection = rOther.mnDirection;
+ mnHdFtIndex = rOther.mnHdFtIndex;
+ return *this;
+}
+
+bool PlcDrawObj::Append( WW8Export& rWrt, WW8_CP nCp, const sw::Frame& rFmt,
+ const Point& rNdTopLeft )
+{
+ bool bRet = false;
+ const SwFrmFmt &rFormat = rFmt.GetFrmFmt();
+ if (TXT_HDFT == rWrt.nTxtTyp || TXT_MAINTEXT == rWrt.nTxtTyp)
+ {
+ if (RES_FLYFRMFMT == rFormat.Which())
+ {
+ // check for textflyframe and if it is the first in a Chain
+ if (rFormat.GetCntnt().GetCntntIdx())
+ bRet = true;
+ }
+ else
+ bRet = true;
+ }
+
+ if (bRet)
+ {
+ DrawObj aObj(rFmt, nCp, rNdTopLeft, rWrt.TrueFrameDirection(rFormat),
+ rWrt.GetHdFtIndex());
+ maDrawObjs.push_back(aObj);
+ }
+ return bRet;
+}
+
+void DrawObj::SetShapeDetails(sal_uInt32 nId, sal_Int32 nThick)
+{
+ mnShapeId = nId;
+ mnThick = nThick;
+}
+
+bool WW8_WrPlcTxtBoxes::WriteTxt( WW8Export& rWrt )
+{
+ bool bRet = false;
+ rWrt.bInWriteEscher = true;
+ WW8_CP& rccp=TXT_TXTBOX == nTyp ? rWrt.pFib->ccpTxbx : rWrt.pFib->ccpHdrTxbx;
+
+ bRet = WriteGenericTxt( rWrt, nTyp, rccp );
+
+ WW8_CP nCP = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+ WW8Fib& rFib = *rWrt.pFib;
+ WW8_CP nMyOffset = rFib.ccpText + rFib.ccpFtn + rFib.ccpHdr + rFib.ccpAtn
+ + rFib.ccpEdn;
+ if( TXT_TXTBOX == nTyp )
+ rWrt.pFldTxtBxs->Finish( nCP, nMyOffset );
+ else
+ rWrt.pFldHFTxtBxs->Finish( nCP, nMyOffset + rFib.ccpTxbx );
+ rWrt.bInWriteEscher = false;
+ return bRet;
+}
+
+void WW8_WrPlcTxtBoxes::Append( const SdrObject& rObj, sal_uInt32 nShapeId )
+{
+ void* p = (void*)&rObj;
+ aCntnt.Insert( p, aCntnt.Count() );
+ aShapeIds.Insert( nShapeId, aShapeIds.Count() );
+}
+
+const SvULongs* WW8_WrPlcTxtBoxes::GetShapeIdArr() const
+{
+ return &aShapeIds;
+}
+
+/* */
+
+sal_uInt32 WW8Export::GetSdrOrdNum( const SwFrmFmt& rFmt ) const
+{
+ sal_uInt32 nOrdNum;
+ const SdrObject* pObj = rFmt.FindRealSdrObject();
+ if( pObj )
+ nOrdNum = pObj->GetOrdNum();
+ else
+ {
+ // no Layout for this format, then recalc the ordnum
+ SwFrmFmt* pFmt = (SwFrmFmt*)&rFmt;
+ nOrdNum = pDoc->GetSpzFrmFmts()->GetPos( pFmt );
+
+ const SdrModel* pModel = pDoc->GetDrawModel();
+ if( pModel )
+ nOrdNum += pModel->GetPage( 0 )->GetObjCount();
+ }
+ return nOrdNum;
+}
+
+void WW8Export::AppendFlyInFlys(const sw::Frame& rFrmFmt,
+ const Point& rNdTopLeft)
+{
+ OSL_ENSURE(bWrtWW8, "this has gone horribly wrong");
+ OSL_ENSURE(!pEscher, "der EscherStream wurde schon geschrieben!");
+ if (pEscher)
+ return ;
+ PlcDrawObj *pDrwO;
+ if (TXT_HDFT == nTxtTyp)
+ pDrwO = pHFSdrObjs;
+ else
+ pDrwO = pSdrObjs;
+
+ if (rFrmFmt.IsInline())
+ {
+ OutputField(0, ww::eSHAPE, FieldString(ww::eSHAPE),
+ WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
+ }
+
+ WW8_CP nCP = Fc2Cp(Strm().Tell());
+ bool bSuccess = pDrwO->Append(*this, nCP, rFrmFmt, rNdTopLeft);
+ OSL_ENSURE(bSuccess, "Couldn't export a graphical element!");
+
+ if (bSuccess)
+ {
+ static const sal_uInt8 aSpec8[] =
+ {
+ 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation
+ 0x55, 0x08, 1 // sprmCFSpec
+ };
+ // fSpec-Attribut true
+ // Fuer DrawObjets muss ein Spezial-Zeichen
+ // in den Text und darum ein fSpec-Attribut
+ pChpPlc->AppendFkpEntry( Strm().Tell() );
+ WriteChar( 0x8 );
+ pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aSpec8 ), aSpec8 );
+
+ //Need dummy picture frame
+ if (rFrmFmt.IsInline())
+ OutGrf(rFrmFmt);
+ }
+
+ if (rFrmFmt.IsInline())
+ OutputField(0, ww::eSHAPE, aEmptyStr, WRITEFIELD_CLOSE);
+}
+
+MSWord_SdrAttrIter::MSWord_SdrAttrIter( MSWordExportBase& rWr,
+ const EditTextObject& rEditObj, sal_uInt8 nTyp )
+ : MSWordAttrIter( rWr ), pEditObj(&rEditObj), pEditPool(0),
+ aTxtAtrArr( 0, 4 ), aChrTxtAtrArr( 0, 4 ), aChrSetArr( 0, 4 ),
+ mnTyp(nTyp)
+{
+ NextPara( 0 );
+}
+
+void MSWord_SdrAttrIter::NextPara( sal_uInt16 nPar )
+{
+ nPara = nPar;
+ // Attributwechsel an Pos 0 wird ignoriert, da davon ausgegangen
+ // wird, dass am Absatzanfang sowieso die Attribute neu ausgegeben
+ // werden.
+ aChrTxtAtrArr.Remove( 0, aChrTxtAtrArr.Count() );
+ aChrSetArr.Remove( 0, aChrSetArr.Count() );
+ nAktSwPos = nTmpSwPos = 0;
+
+ SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
+ pEditPool = aSet.GetPool();
+ eNdChrSet = ItemGet<SvxFontItem>(aSet,EE_CHAR_FONTINFO).GetCharSet();
+
+ if( pBreakIt->GetBreakIter().is() )
+ nScript = pBreakIt->GetBreakIter()->getScriptType( pEditObj->GetText(nPara), 0);
+ else
+ nScript = i18n::ScriptType::LATIN;
+
+ pEditObj->GetCharAttribs( nPara, aTxtAtrArr );
+ nAktSwPos = SearchNext( 1 );
+}
+
+rtl_TextEncoding MSWord_SdrAttrIter::GetNextCharSet() const
+{
+ if( aChrSetArr.Count() )
+ return (rtl_TextEncoding)aChrSetArr[ aChrSetArr.Count() - 1 ];
+ return eNdChrSet;
+}
+
+// der erste Parameter in SearchNext() liefert zurueck, ob es ein TxtAtr ist.
+xub_StrLen MSWord_SdrAttrIter::SearchNext( xub_StrLen nStartPos )
+{
+ xub_StrLen nPos;
+ xub_StrLen nMinPos = STRING_MAXLEN;
+ xub_StrLen i;
+
+ for( i = 0; i < aTxtAtrArr.Count(); i++ )
+ {
+ const EECharAttrib& rHt = aTxtAtrArr[ i ];
+ nPos = rHt.nStart; // gibt erstes Attr-Zeichen
+ if( nPos >= nStartPos && nPos <= nMinPos )
+ {
+ nMinPos = nPos;
+ SetCharSet(rHt, true);
+ }
+
+ {
+ nPos = rHt.nEnd; // gibt letztes Attr-Zeichen + 1
+ if( nPos >= nStartPos && nPos < nMinPos )
+ {
+ nMinPos = nPos;
+ SetCharSet(rHt, false);
+ }
+ }
+
+ }
+ return nMinPos;
+}
+
+void MSWord_SdrAttrIter::SetCharSet(const EECharAttrib& rAttr, bool bStart)
+{
+ void* p = 0;
+ rtl_TextEncoding eChrSet;
+ const SfxPoolItem& rItem = *rAttr.pAttr;
+ switch( rItem.Which() )
+ {
+ case EE_CHAR_FONTINFO:
+ p = (void*)&rAttr;
+ eChrSet = ((SvxFontItem&)rItem).GetCharSet();
+ break;
+ }
+
+ if( p )
+ {
+ sal_uInt16 nPos;
+ if( bStart )
+ {
+ nPos = aChrSetArr.Count();
+ aChrSetArr.Insert( eChrSet, nPos );
+ aChrTxtAtrArr.Insert( p, nPos );
+ }
+ else if( USHRT_MAX != ( nPos = aChrTxtAtrArr.GetPos( p )) )
+ {
+ aChrTxtAtrArr.Remove( nPos );
+ aChrSetArr.Remove( nPos );
+ }
+ }
+}
+
+void MSWord_SdrAttrIter::OutEEField(const SfxPoolItem& rHt)
+{
+ const SvxFieldItem &rField = (const SvxFieldItem &)rHt;
+ const SvxFieldData *pFld = rField.GetField();
+ if (pFld && pFld->ISA(SvxURLField))
+ {
+ sal_uInt8 nOldTxtTyp = m_rExport.nTxtTyp;
+ m_rExport.nTxtTyp = mnTyp;
+ const SvxURLField *pURL = (const SvxURLField *)pFld;
+ m_rExport.AttrOutput().StartURL( pURL->GetURL(), pURL->GetTargetFrame() );
+
+ const String &rStr = pURL->GetRepresentation();
+ m_rExport.AttrOutput().RawText( rStr, true, GetNodeCharSet() ); // FIXME kendy: is the 'true' actually correct here? It was here before, but... ;-)
+
+ m_rExport.AttrOutput().EndURL();
+ m_rExport.nTxtTyp = nOldTxtTyp;
+ }
+}
+
+void MSWord_SdrAttrIter::OutAttr( xub_StrLen nSwPos )
+{
+ OutParaAttr(true);
+
+ if( aTxtAtrArr.Count() )
+ {
+ const SwModify* pOldMod = m_rExport.pOutFmtNode;
+ m_rExport.pOutFmtNode = 0;
+
+ const SfxItemPool* pSrcPool = pEditPool;
+ const SfxItemPool& rDstPool = m_rExport.pDoc->GetAttrPool();
+
+ nTmpSwPos = nSwPos;
+ sal_uInt16 i, nWhich, nSlotId;
+ for( i = 0; i < aTxtAtrArr.Count(); i++ )
+ {
+ const EECharAttrib& rHt = aTxtAtrArr[ i ];
+ if (nSwPos >= rHt.nStart && nSwPos < rHt.nEnd)
+ {
+ nWhich = rHt.pAttr->Which();
+ if (nWhich == EE_FEATURE_FIELD)
+ {
+ OutEEField(*rHt.pAttr);
+ continue;
+ }
+ else if (nWhich == EE_FEATURE_TAB)
+ {
+ m_rExport.WriteChar(0x9);
+ continue;
+ }
+ nSlotId = pSrcPool->GetSlotId(nWhich);
+
+ if (nSlotId && nWhich != nSlotId)
+ {
+ nWhich = rDstPool.GetWhich(nSlotId);
+ if (nWhich && nWhich != nSlotId &&
+ nWhich < RES_UNKNOWNATR_BEGIN &&
+ m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
+ {
+ // use always the SW-Which Id !
+ SfxPoolItem* pI = rHt.pAttr->Clone();
+ pI->SetWhich( nWhich );
+ m_rExport.AttrOutput().OutputItem( *pI );
+ delete pI;
+ }
+ }
+ }
+
+ if( nSwPos < rHt.nStart )
+ break;
+ }
+
+ nTmpSwPos = 0; // HasTextItem nur in dem obigen Bereich erlaubt
+ m_rExport.pOutFmtNode = pOldMod;
+ }
+}
+
+bool MSWord_SdrAttrIter::IsTxtAttr(xub_StrLen nSwPos)
+{
+ for (sal_uInt16 i = 0; i < aTxtAtrArr.Count(); ++i)
+ {
+ const EECharAttrib& rHt = aTxtAtrArr[ i ];
+ if (nSwPos >= rHt.nStart && nSwPos < rHt.nEnd)
+ {
+ if (
+ (rHt.pAttr->Which() == EE_FEATURE_FIELD) ||
+ (rHt.pAttr->Which() == EE_FEATURE_TAB)
+ )
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// HasItem ist fuer die Zusammenfassung des Doppel-Attributes Underline
+// und WordLineMode als TextItems. OutAttr() ruft die Ausgabefunktion,
+// die dann ueber HasItem() nach anderen Items an der
+// Attribut-Anfangposition fragen kann.
+// Es koennen nur Attribute mit Ende abgefragt werden.
+// Es wird mit bDeep gesucht
+const SfxPoolItem* MSWord_SdrAttrIter::HasTextItem(sal_uInt16 nWhich) const
+{
+ const SfxPoolItem* pRet = 0;
+ nWhich = sw::hack::TransformWhichBetweenPools(*pEditPool,
+ m_rExport.pDoc->GetAttrPool(), nWhich);
+ if (nWhich)
+ {
+ for (sal_uInt16 i = 0; i < aTxtAtrArr.Count(); ++i)
+ {
+ const EECharAttrib& rHt = aTxtAtrArr[i];
+ if (
+ nWhich == rHt.pAttr->Which() && nTmpSwPos >= rHt.nStart &&
+ nTmpSwPos < rHt.nEnd
+ )
+ {
+ pRet = rHt.pAttr; // Found
+ break;
+ }
+ else if (nTmpSwPos < rHt.nStart)
+ break; // dann kommt da nichts mehr
+ }
+ }
+ return pRet;
+}
+
+const SfxPoolItem& MSWord_SdrAttrIter::GetItem( sal_uInt16 nWhich ) const
+{
+ using sw::hack::GetSetWhichFromSwDocWhich;
+ const SfxPoolItem* pRet = HasTextItem(nWhich);
+ if (!pRet)
+ {
+ SfxItemSet aSet(pEditObj->GetParaAttribs(nPara));
+ nWhich = GetSetWhichFromSwDocWhich(aSet, *m_rExport.pDoc, nWhich);
+ OSL_ENSURE(nWhich, "Impossible, catastrophic failure imminent");
+ pRet = &aSet.Get(nWhich);
+ }
+ return *pRet;
+}
+
+void MSWord_SdrAttrIter::OutParaAttr(bool bCharAttr)
+{
+ SfxItemSet aSet( pEditObj->GetParaAttribs( nPara ));
+ if( aSet.Count() )
+ {
+ const SfxItemSet* pOldSet = m_rExport.GetCurItemSet();
+ m_rExport.SetCurItemSet( &aSet );
+
+ SfxItemIter aIter( aSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+
+ const SfxItemPool* pSrcPool = pEditPool,
+ * pDstPool = &m_rExport.pDoc->GetAttrPool();
+
+ do {
+ sal_uInt16 nWhich = pItem->Which(),
+ nSlotId = pSrcPool->GetSlotId( nWhich );
+
+ if ( nSlotId && nWhich != nSlotId &&
+ 0 != ( nWhich = pDstPool->GetWhich( nSlotId ) ) &&
+ nWhich != nSlotId &&
+ ( bCharAttr ? ( nWhich >= RES_CHRATR_BEGIN && nWhich < RES_TXTATR_END )
+ : ( nWhich >= RES_PARATR_BEGIN && nWhich < RES_FRMATR_END ) ) )
+ {
+ // use always the SW-Which Id !
+ SfxPoolItem* pI = pItem->Clone();
+ pI->SetWhich( nWhich );
+ if (m_rExport.CollapseScriptsforWordOk(nScript,nWhich))
+ m_rExport.AttrOutput().OutputItem( *pI );
+ delete pI;
+ }
+ } while( !aIter.IsAtEnd() && 0 != ( pItem = aIter.NextItem() ) );
+ m_rExport.SetCurItemSet( pOldSet );
+ }
+}
+
+void WW8Export::WriteSdrTextObj(const SdrObject& rObj, sal_uInt8 nTyp)
+{
+ const SdrTextObj* pTxtObj = PTR_CAST(SdrTextObj, &rObj);
+ OSL_ENSURE(pTxtObj, "That is no SdrTextObj!");
+ if (!pTxtObj)
+ return;
+
+ const OutlinerParaObject* pParaObj = 0;
+ bool bOwnParaObj = false;
+
+ /*
+ #i13885#
+ When the object is actively being edited, that text is not set into
+ the objects normal text object, but lives in a seperate object.
+ */
+ if (pTxtObj->IsTextEditActive())
+ {
+ pParaObj = pTxtObj->GetEditOutlinerParaObject();
+ bOwnParaObj = true;
+ }
+ else
+ {
+ pParaObj = pTxtObj->GetOutlinerParaObject();
+ }
+
+ if( pParaObj )
+ {
+ WriteOutliner(*pParaObj, nTyp);
+ if( bOwnParaObj )
+ delete pParaObj;
+ }
+}
+
+void WW8Export::WriteOutliner(const OutlinerParaObject& rParaObj, sal_uInt8 nTyp)
+{
+ bool bAnyWrite = false;
+ const EditTextObject& rEditObj = rParaObj.GetTextObject();
+ MSWord_SdrAttrIter aAttrIter( *this, rEditObj, nTyp );
+
+ sal_uInt16 nPara = rEditObj.GetParagraphCount();
+ sal_uInt8 bNul = 0;
+ for( sal_uInt16 n = 0; n < nPara; ++n )
+ {
+ if( n )
+ aAttrIter.NextPara( n );
+
+ rtl_TextEncoding eChrSet = aAttrIter.GetNodeCharSet();
+
+ OSL_ENSURE( !pO->Count(), " pO ist am Zeilenanfang nicht leer" );
+
+ String aStr( rEditObj.GetText( n ));
+ xub_StrLen nAktPos = 0;
+ xub_StrLen nEnd = aStr.Len();
+ do {
+ xub_StrLen nNextAttr = aAttrIter.WhereNext();
+ rtl_TextEncoding eNextChrSet = aAttrIter.GetNextCharSet();
+
+ if( nNextAttr > nEnd )
+ nNextAttr = nEnd;
+
+ bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
+ if( !bTxtAtr )
+ OutSwString( aStr, nAktPos, nNextAttr - nAktPos,
+ true, eChrSet );
+
+ // Am Zeilenende werden die Attribute bis ueber das CR
+ // aufgezogen. Ausnahme: Fussnoten am Zeilenende
+ if( nNextAttr == nEnd && !bTxtAtr )
+ WriteCR(); // CR danach
+
+ // Ausgabe der Zeichenattribute
+ aAttrIter.OutAttr( nAktPos ); // nAktPos - 1 ??
+ pChpPlc->AppendFkpEntry( Strm().Tell(),
+ pO->Count(), pO->GetData() );
+ pO->Remove( 0, pO->Count() ); // leeren
+
+ // Ausnahme: Fussnoten am Zeilenende
+ if( nNextAttr == nEnd && bTxtAtr )
+ WriteCR(); // CR danach
+ nAktPos = nNextAttr;
+ eChrSet = eNextChrSet;
+ aAttrIter.NextPos();
+ }
+ while( nAktPos < nEnd );
+
+ OSL_ENSURE( !pO->Count(), " pO ist am ZeilenEnde nicht leer" );
+
+ pO->Insert( bNul, pO->Count() ); // Style # as short
+ pO->Insert( bNul, pO->Count() );
+
+ aAttrIter.OutParaAttr(false);
+
+ sal_uLong nPos = Strm().Tell();
+ pPapPlc->AppendFkpEntry( Strm().Tell(),
+ pO->Count(), pO->GetData() );
+ pO->Remove( 0, pO->Count() ); // leeren
+ pChpPlc->AppendFkpEntry( nPos );
+ }
+
+ bAnyWrite = 0 != nPara;
+ if( !bAnyWrite )
+ WriteStringAsPara( aEmptyStr );
+}
+
+void WinwordAnchoring::WriteData( EscherEx& rEx ) const
+{
+ //Toplevel groups get their winword extra data attached, and sub elements
+ //use the defaults
+ if (rEx.GetGroupLevel() <= 1)
+ {
+ SvStream& rSt = rEx.GetStream();
+ //The last argument denotes the number of sub properties in this atom
+ if (mbInline)
+ {
+ rEx.AddAtom(18, DFF_msofbtUDefProp, 3, 3); //Prop id is 0xF122
+ rSt << (sal_uInt16)0x0390 << sal_uInt32(3);
+ rSt << (sal_uInt16)0x0392 << sal_uInt32(3);
+ //This sub property is required to be in the dummy inline frame as
+ //well
+ rSt << (sal_uInt16)0x053F << nInlineHack;
+ }
+ else
+ {
+ rEx.AddAtom(24, DFF_msofbtUDefProp, 3, 4 ); //Prop id is 0xF122
+ rSt << (sal_uInt16)0x038F << mnXAlign;
+ rSt << (sal_uInt16)0x0390 << mnXRelTo;
+ rSt << (sal_uInt16)0x0391 << mnYAlign;
+ rSt << (sal_uInt16)0x0392 << mnYRelTo;
+ }
+ }
+}
+
+/* */
+
+void WW8Export::CreateEscher()
+{
+ SfxItemState eBackSet =
+ (const_cast<const SwDoc*>(pDoc))->GetPageDesc(0).GetMaster().
+ GetItemState(RES_BACKGROUND);
+ if (pHFSdrObjs->size() || pSdrObjs->size() || SFX_ITEM_SET == eBackSet)
+ {
+ OSL_ENSURE( !pEscher, "wer hat den Pointer nicht geloescht?" );
+ SvMemoryStream* pEscherStrm = new SvMemoryStream;
+ pEscherStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ pEscher = new SwEscherEx(pEscherStrm, *this);
+ }
+}
+
+void WW8Export::WriteEscher()
+{
+ if (pEscher)
+ {
+ sal_uLong nStart = pTableStrm->Tell();
+
+ pEscher->WritePictures();
+ pEscher->FinishEscher();
+
+ pFib->fcDggInfo = nStart;
+ pFib->lcbDggInfo = pTableStrm->Tell() - nStart;
+ delete pEscher, pEscher = 0;
+ }
+}
+
+void SwEscherEx::WritePictures()
+{
+ if( SvStream* pPicStrm = static_cast< SwEscherExGlobal& >( *mxGlobal ).GetPictureStream() )
+ {
+ // set the blip - entries to the correct stream pos
+ sal_Int32 nEndPos = rWrt.Strm().Tell();
+ mxGlobal->SetNewBlipStreamOffset( nEndPos );
+
+ pPicStrm->Seek( 0 );
+ rWrt.Strm() << *pPicStrm;
+ }
+ Flush();
+}
+
+/* */
+
+// Output- Routines for Escher Export
+
+SwEscherExGlobal::SwEscherExGlobal()
+{
+}
+
+SwEscherExGlobal::~SwEscherExGlobal()
+{
+}
+
+SvStream* SwEscherExGlobal::ImplQueryPictureStream()
+{
+ // this function will be called exactly once
+ mxPicStrm.reset( new SvMemoryStream );
+ mxPicStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ return mxPicStrm.get();
+}
+
+SwBasicEscherEx::SwBasicEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
+ : EscherEx( EscherExGlobalRef( new SwEscherExGlobal ), *pStrm), rWrt(rWW8Wrt), pEscherStrm(pStrm)
+{
+ Init();
+}
+
+SwBasicEscherEx::~SwBasicEscherEx()
+{
+}
+
+void SwBasicEscherEx::WriteFrmExtraData(const SwFrmFmt&)
+{
+ AddAtom(4, ESCHER_ClientAnchor);
+ GetStream() << (sal_uInt32)0x80000000;
+}
+
+void SwBasicEscherEx::WriteEmptyFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
+{
+ OpenContainer(ESCHER_SpContainer);
+ AddShape(ESCHER_ShpInst_PictureFrame, 0xa00, nShapeId);
+ // store anchor attribute
+ WriteFrmExtraData(rFmt);
+
+ AddAtom(6, DFF_msofbtUDefProp, 3, 1); //Prop id is 0xF122
+ GetStream() << (sal_uInt16)0x053F << nInlineHack;
+
+ CloseContainer(); // ESCHER_SpContainer
+}
+
+sal_uInt32 AddMirrorFlags(sal_uInt32 nFlags, const SwMirrorGrf &rMirror)
+{
+ switch (rMirror.GetValue())
+ {
+ default:
+ case RES_MIRROR_GRAPH_DONT:
+ break;
+ case RES_MIRROR_GRAPH_VERT:
+ nFlags |= SHAPEFLAG_FLIPH;
+ break;
+ case RES_MIRROR_GRAPH_HOR:
+ nFlags |= SHAPEFLAG_FLIPV;
+ break;
+ case RES_MIRROR_GRAPH_BOTH:
+ nFlags |= SHAPEFLAG_FLIPH;
+ nFlags |= SHAPEFLAG_FLIPV;
+ break;
+
+ }
+ return nFlags;
+}
+
+sal_Int32 SwBasicEscherEx::WriteGrfFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
+{
+ sal_Int32 nBorderThick=0;
+ SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(rFmt);
+ SwGrfNode *pGrfNd = pNd ? pNd->GetGrfNode() : 0;
+ OSL_ENSURE(pGrfNd, "No SwGrfNode ?, suspicious");
+ if (!pGrfNd)
+ return nBorderThick;
+
+ OpenContainer( ESCHER_SpContainer );
+
+ const SwMirrorGrf &rMirror = pGrfNd->GetSwAttrSet().GetMirrorGrf();
+ AddShape(ESCHER_ShpInst_PictureFrame, AddMirrorFlags(0xa00, rMirror),
+ nShapeId);
+
+ EscherPropertyContainer aPropOpt;
+
+ sal_uInt32 nFlags = ESCHER_BlipFlagDefault;
+
+ if (pGrfNd->IsLinkedFile())
+ {
+ String sURL;
+ pGrfNd->GetFileFilterNms( &sURL, 0 );
+
+ WW8Bytes aBuf;
+ SwWW8Writer::InsAsString16( aBuf, sURL );
+ SwWW8Writer::InsUInt16( aBuf, 0 );
+
+ sal_uInt16 nArrLen = aBuf.Count();
+ sal_uInt8* pArr = new sal_uInt8[ nArrLen ];
+ memcpy( pArr, aBuf.GetData(), nArrLen );
+
+ aPropOpt.AddOpt(ESCHER_Prop_pibName, true, nArrLen, pArr, nArrLen);
+ nFlags = ESCHER_BlipFlagLinkToFile | ESCHER_BlipFlagURL |
+ ESCHER_BlipFlagDoNotSave;
+ }
+ else
+ {
+ pGrfNd->SwapIn(true);
+
+ Graphic aGraphic(pGrfNd->GetGrf());
+ GraphicObject aGraphicObject( aGraphic );
+ ByteString aUniqueId = aGraphicObject.GetUniqueID();
+
+ if ( aUniqueId.Len() )
+ {
+ const MapMode aMap100mm( MAP_100TH_MM );
+ Size aSize( aGraphic.GetPrefSize() );
+
+ if ( MAP_PIXEL == aGraphic.GetPrefMapMode().GetMapUnit() )
+ {
+ aSize = Application::GetDefaultDevice()->PixelToLogic(
+ aSize, aMap100mm );
+ }
+ else
+ {
+ aSize = OutputDevice::LogicToLogic( aSize,
+ aGraphic.GetPrefMapMode(), aMap100mm );
+ }
+
+ Point aEmptyPoint = Point();
+ Rectangle aRect( aEmptyPoint, aSize );
+
+ sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
+ aUniqueId, aRect, NULL, 0 );
+ if (nBlibId)
+ aPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
+ }
+ }
+
+ aPropOpt.AddOpt( ESCHER_Prop_pibFlags, nFlags );
+ nBorderThick = WriteFlyFrameAttr(rFmt,mso_sptPictureFrame,aPropOpt);
+ WriteGrfAttr(*pGrfNd, aPropOpt);
+
+ aPropOpt.Commit( GetStream() );
+
+ // store anchor attribute
+ WriteFrmExtraData( rFmt );
+
+ CloseContainer(); // ESCHER_SpContainer
+ return nBorderThick;
+}
+
+void SwBasicEscherEx::WriteGrfAttr(const SwNoTxtNode& rNd,
+ EscherPropertyContainer& rPropOpt)
+{
+ const SfxPoolItem* pItem;
+ sal_uInt32 nMode = GRAPHICDRAWMODE_STANDARD;
+ sal_Int32 nContrast = 0;
+ sal_Int16 nBrightness = 0;
+
+ if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CONTRAST,
+ true, &pItem))
+ {
+ nContrast = ((SfxInt16Item*)pItem)->GetValue();
+ }
+
+ if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_LUMINANCE,
+ true, &pItem))
+ {
+ nBrightness = ((SfxInt16Item*)pItem)->GetValue();
+ }
+
+
+ if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_DRAWMODE,
+ true, &pItem))
+ {
+ nMode = ((SfxEnumItem*)pItem)->GetValue();
+ if (nMode == GRAPHICDRAWMODE_WATERMARK)
+ {
+ /*
+ There is no real watermark mode in word, we must use standard
+ mode and modify our ones by 70% extra brightness and 70% less
+ contrast. This means that unmodified default OOo watermark
+ will turn back into watermark, and modified OOo watermark will
+ change into a close visual representation in standardmode
+ */
+ nBrightness += 70;
+ if (nBrightness > 100)
+ nBrightness = 100;
+ nContrast -= 70;
+ if (nContrast < -100)
+ nContrast = -100;
+ nMode = GRAPHICDRAWMODE_STANDARD;
+ }
+ }
+
+ if (nMode == GRAPHICDRAWMODE_GREYS)
+ nMode = 0x40004;
+ else if (nMode == GRAPHICDRAWMODE_MONO)
+ nMode = 0x60006;
+ else
+ nMode = 0;
+ rPropOpt.AddOpt( ESCHER_Prop_pictureActive, nMode );
+
+ if (nContrast != 0)
+ {
+ nContrast+=100;
+ if (nContrast == 100)
+ nContrast = 0x10000;
+ else if (nContrast < 100)
+ {
+ nContrast *= 0x10000;
+ nContrast /= 100;
+ }
+ else if (nContrast < 200)
+ nContrast = (100 * 0x10000) / (200-nContrast);
+ else
+ nContrast = 0x7fffffff;
+ rPropOpt.AddOpt( ESCHER_Prop_pictureContrast, nContrast);
+ }
+
+ if (nBrightness != 0)
+ rPropOpt.AddOpt( ESCHER_Prop_pictureBrightness, nBrightness * 327 );
+
+ if (SFX_ITEM_SET == rNd.GetSwAttrSet().GetItemState(RES_GRFATR_CROPGRF,
+ true, &pItem))
+ {
+ const Size aSz( rNd.GetTwipSize() );
+ sal_Int32 nVal;
+ if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetLeft() ) )
+ rPropOpt.AddOpt( ESCHER_Prop_cropFromLeft, ToFract16( nVal, aSz.Width()) );
+ if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetRight() ) )
+ rPropOpt.AddOpt( ESCHER_Prop_cropFromRight, ToFract16( nVal, aSz.Width()));
+ if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetTop() ) )
+ rPropOpt.AddOpt( ESCHER_Prop_cropFromTop, ToFract16( nVal, aSz.Height()));
+ if( 0 != ( nVal = ((SwCropGrf*)pItem )->GetBottom() ) )
+ rPropOpt.AddOpt( ESCHER_Prop_cropFromBottom, ToFract16( nVal, aSz.Height()));
+ }
+}
+
+void SwBasicEscherEx::SetPicId(const SdrObject &, sal_uInt32,
+ EscherPropertyContainer &)
+{
+}
+
+void SwEscherEx::SetPicId(const SdrObject &rSdrObj, sal_uInt32 nShapeId,
+ EscherPropertyContainer &rPropOpt)
+{
+ pTxtBxs->Append(rSdrObj, nShapeId);
+ sal_uInt32 nPicId = pTxtBxs->Count();
+ nPicId *= 0x10000;
+ rPropOpt.AddOpt( ESCHER_Prop_pictureId, nPicId );
+}
+
+sal_Int32 SwBasicEscherEx::WriteOLEFlyFrame(const SwFrmFmt& rFmt, sal_uInt32 nShapeId)
+{
+ sal_Int32 nBorderThick = 0;
+ if (const SdrObject* pSdrObj = rFmt.FindRealSdrObject())
+ {
+ SwNodeIndex aIdx(*rFmt.GetCntnt().GetCntntIdx(), 1);
+ SwOLENode& rOLENd = *aIdx.GetNode().GetOLENode();
+ sal_Int64 nAspect = rOLENd.GetAspect();
+
+ uno::Reference < embed::XEmbeddedObject > xObj(rOLENd.GetOLEObj().GetOleRef());
+
+ // the rectangle is used to transport the size of the object
+ // the left, top corner is set to ( 0, 0 ) by default constructor,
+ // if the width and height are set correctly bRectIsSet should be set to true
+ awt::Rectangle aRect;
+ sal_Bool bRectIsSet = sal_False;
+
+
+ // TODO/LATER: should the icon size be stored in case of iconified object?
+ if ( xObj.is() && nAspect != embed::Aspects::MSOLE_ICON )
+ {
+ try
+ {
+ awt::Size aSize = xObj->getVisualAreaSize( nAspect );
+ aRect.Width = aSize.Width;
+ aRect.Height = aSize.Height;
+ bRectIsSet = sal_True;
+ }
+ catch( uno::Exception& )
+ {}
+ }
+
+ /*
+ #i5970#
+ Export floating ole2 .doc ver 8+ wmf ole2 previews as emf previews
+ instead ==> allows unicode text to be preserved
+ */
+#ifdef OLE_PREVIEW_AS_EMF
+ Graphic* pGraphic = rOLENd.GetGraphic();
+#endif
+ OpenContainer(ESCHER_SpContainer);
+
+ EscherPropertyContainer aPropOpt;
+ const SwMirrorGrf &rMirror = rOLENd.GetSwAttrSet().GetMirrorGrf();
+ WriteOLEPicture(aPropOpt, AddMirrorFlags(0xa00 | SHAPEFLAG_OLESHAPE,
+ rMirror), pGraphic ? *pGraphic : Graphic(), *pSdrObj, nShapeId, bRectIsSet ? &aRect : NULL );
+
+ nBorderThick = WriteFlyFrameAttr(rFmt, mso_sptPictureFrame, aPropOpt);
+ WriteGrfAttr(rOLENd, aPropOpt);
+ aPropOpt.Commit(GetStream());
+
+ // store anchor attribute
+ WriteFrmExtraData( rFmt );
+
+ CloseContainer(); // ESCHER_SpContainer
+ }
+ return nBorderThick;
+}
+
+void SwBasicEscherEx::WriteBrushAttr(const SvxBrushItem &rBrush,
+ EscherPropertyContainer& rPropOpt)
+{
+ bool bSetOpacity = false;
+ sal_uInt32 nOpaque = 0;
+ if (const GraphicObject *pGraphicObject = rBrush.GetGraphicObject())
+ {
+ ByteString aUniqueId = pGraphicObject->GetUniqueID();
+ if (aUniqueId.Len())
+ {
+ const Graphic &rGraphic = pGraphicObject->GetGraphic();
+ Size aSize(rGraphic.GetPrefSize());
+ const MapMode aMap100mm(MAP_100TH_MM);
+ if (MAP_PIXEL == rGraphic.GetPrefMapMode().GetMapUnit())
+ {
+ aSize = Application::GetDefaultDevice()->PixelToLogic(
+ aSize, aMap100mm);
+ }
+ else
+ {
+ aSize = OutputDevice::LogicToLogic(aSize,
+ rGraphic.GetPrefMapMode(), aMap100mm);
+ }
+
+ Point aEmptyPoint = Point();
+ Rectangle aRect(aEmptyPoint, aSize);
+
+ sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
+ aUniqueId, aRect, NULL, 0);
+ if (nBlibId)
+ rPropOpt.AddOpt(ESCHER_Prop_fillBlip,nBlibId,sal_True);
+ }
+
+ if (0 != (nOpaque = pGraphicObject->GetAttr().GetTransparency()))
+ bSetOpacity = true;
+
+ rPropOpt.AddOpt( ESCHER_Prop_fillType, ESCHER_FillPicture );
+ rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
+ rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0 );
+ }
+ else
+ {
+ sal_uInt32 nFillColor = GetColor(rBrush.GetColor(), false);
+ rPropOpt.AddOpt( ESCHER_Prop_fillColor, nFillColor );
+ rPropOpt.AddOpt( ESCHER_Prop_fillBackColor, nFillColor ^ 0xffffff );
+ rPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100010 );
+
+ if (0 != (nOpaque = rBrush.GetColor().GetTransparency()))
+ bSetOpacity = true;
+ }
+
+ if (bSetOpacity)
+ {
+ nOpaque = (nOpaque * 100) / 0xFE;
+ nOpaque = ((100 - nOpaque) << 16) / 100;
+ rPropOpt.AddOpt(ESCHER_Prop_fillOpacity, nOpaque);
+ }
+}
+
+sal_Int32 SwBasicEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt,
+ MSO_SPT eShapeType, EscherPropertyContainer& rPropOpt)
+{
+ sal_Int32 nLineWidth=0;
+ const SfxPoolItem* pItem;
+ bool bFirstLine = true;
+ if (SFX_ITEM_SET == rFmt.GetItemState(RES_BOX, true, &pItem))
+ {
+ static const sal_uInt16 aExhperProp[4] =
+ {
+ ESCHER_Prop_dyTextTop, ESCHER_Prop_dyTextBottom,
+ ESCHER_Prop_dxTextLeft, ESCHER_Prop_dxTextRight
+ };
+ const SvxBorderLine* pLine;
+
+ for( sal_uInt16 n = 0; n < 4; ++n )
+ if( 0 != ( pLine = ((SvxBoxItem*)pItem)->GetLine( n )) )
+ {
+ if( bFirstLine )
+ {
+ sal_uInt32 nLineColor = GetColor(pLine->GetColor(), false);
+ rPropOpt.AddOpt( ESCHER_Prop_lineColor, nLineColor );
+ rPropOpt.AddOpt( ESCHER_Prop_lineBackColor,
+ nLineColor ^ 0xffffff );
+
+ MSO_LineStyle eStyle;
+ if( pLine->isDouble() )
+ {
+ // double line
+ nLineWidth = pLine->GetWidth();
+ if( pLine->GetInWidth() == pLine->GetOutWidth() )
+ eStyle = mso_lineDouble;
+ else if( pLine->GetInWidth() < pLine->GetOutWidth() )
+ eStyle = mso_lineThickThin;
+ else
+ eStyle = mso_lineThinThick;
+ }
+ else
+ {
+ // simple line
+ eStyle = mso_lineSimple;
+ nLineWidth = pLine->GetWidth();
+ }
+
+ rPropOpt.AddOpt( ESCHER_Prop_lineStyle, eStyle );
+ rPropOpt.AddOpt( ESCHER_Prop_lineWidth,
+ DrawModelToEmu( nLineWidth ));
+
+ MSO_LineDashing eDashing = mso_lineSolid;
+ switch ( pLine->GetStyle( ) )
+ {
+ case ::editeng::DASHED:
+ eDashing = mso_lineDashGEL;
+ break;
+ case ::editeng::DOTTED:
+ eDashing = mso_lineDotGEL;
+ break;
+ case ::editeng::SOLID:
+ default:
+ break;
+ }
+ rPropOpt.AddOpt( ESCHER_Prop_lineDashing, eDashing );
+ rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x8000E );
+
+ //Use import logic to determine how much of border will go
+ //outside graphic
+ nLineWidth = SwMSDffManager::GetEscherLineMatch(
+ eStyle,eShapeType,nLineWidth);
+ bFirstLine = false;
+ }
+ rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(
+ ((SvxBoxItem*)pItem)->GetDistance( n ) ));
+ }
+ else
+ // MM If there is no line the distance should be set to 0
+ rPropOpt.AddOpt( aExhperProp[ n ], DrawModelToEmu(0));
+ }
+ if( bFirstLine ) // no valid line found
+ {
+ rPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
+ rPropOpt.AddOpt( ESCHER_Prop_dyTextTop, 0 );
+ rPropOpt.AddOpt( ESCHER_Prop_dyTextBottom, 0 );
+ rPropOpt.AddOpt( ESCHER_Prop_dxTextLeft, 0 );
+ rPropOpt.AddOpt( ESCHER_Prop_dxTextRight, 0 );
+ }
+
+ SvxBrushItem aBrush(rWrt.TrueFrameBgBrush(rFmt));
+ WriteBrushAttr(aBrush, rPropOpt);
+
+ const SdrObject* pObj = rFmt.FindRealSdrObject();
+ if( pObj && (pObj->GetLayer() == GetHellLayerId() ||
+ pObj->GetLayer() == GetInvisibleHellId() ))
+ {
+ rPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
+ }
+
+ return nLineWidth;
+}
+
+sal_Int32 SwEscherEx::WriteFlyFrameAttr(const SwFrmFmt& rFmt, MSO_SPT eShapeType,
+ EscherPropertyContainer& rPropOpt)
+{
+ sal_Int32 nLineWidth = SwBasicEscherEx::WriteFlyFrameAttr(rFmt, eShapeType,
+ rPropOpt);
+
+ /*
+ These are not in SwBasicEscherEx::WriteFlyFrameAttr because inline objs
+ can't do it in word and it hacks it in by stretching the graphic that
+ way, perhaps we should actually draw in this space into the graphic we
+ are exporting!
+ */
+ const SfxPoolItem* pItem;
+ if (SFX_ITEM_SET == rFmt.GetItemState(RES_LR_SPACE, true, &pItem))
+ {
+ rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft,
+ DrawModelToEmu( ((SvxLRSpaceItem*)pItem)->GetLeft() ) );
+ rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight,
+ DrawModelToEmu( ((SvxLRSpaceItem*)pItem)->GetRight() ) );
+ }
+ else
+ {
+ rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistLeft, 0 );
+ rPropOpt.AddOpt( ESCHER_Prop_dxWrapDistRight, 0 );
+ }
+
+ if (SFX_ITEM_SET == rFmt.GetItemState(RES_UL_SPACE, true, &pItem))
+ {
+ rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistTop,
+ DrawModelToEmu( ((SvxULSpaceItem*)pItem)->GetUpper() ) );
+ rPropOpt.AddOpt( ESCHER_Prop_dyWrapDistBottom,
+ DrawModelToEmu( ((SvxULSpaceItem*)pItem)->GetLower() ) );
+ }
+
+ if (rFmt.GetSurround().IsContour())
+ {
+ if (const SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(rFmt))
+ {
+ const PolyPolygon *pPolyPoly = pNd->HasContour();
+ if (pPolyPoly && pPolyPoly->Count())
+ {
+ Polygon aPoly(PolygonFromPolyPolygon(*pPolyPoly));
+ const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
+ Fraction aMapPolyX(ww::nWrap100Percent, rOrigSize.Width());
+ Fraction aMapPolyY(ww::nWrap100Percent, rOrigSize.Height());
+ aPoly.Scale(aMapPolyX, aMapPolyY);
+
+ /*
+ a) stretch right bound by 15twips
+ b) shrink bottom bound to where it would have been in word
+ c) Move it to the left by 15twips
+
+ See the import for details
+ */
+ const Size &rSize = pNd->GetTwipSize();
+ Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
+ aMoveHack *= Fraction(15, 1);
+ long nMove(aMoveHack);
+
+ Fraction aHackX(ww::nWrap100Percent + nMove,
+ ww::nWrap100Percent);
+ Fraction aHackY(ww::nWrap100Percent - nMove,
+ ww::nWrap100Percent);
+ aPoly.Scale(aHackX, aHackY);
+
+ aPoly.Move(-nMove, 0);
+
+ SvMemoryStream aPolyDump;
+ aPolyDump.SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+
+ sal_uInt16 nLen = aPoly.GetSize();
+ aPolyDump << nLen;
+ aPolyDump << nLen;
+ aPolyDump << sal_uInt16(8);
+ for (sal_uInt16 nI = 0; nI < nLen; ++nI)
+ {
+ aPolyDump << sal_uInt32(aPoly[nI].X());
+ aPolyDump << sal_uInt32(aPoly[nI].Y());
+ }
+
+ sal_uInt16 nArrLen = msword_cast<sal_uInt16>(aPolyDump.Tell());
+ void *pArr = const_cast<void *>(aPolyDump.GetData());
+ //PropOpt wants to own the buffer
+ aPolyDump.ObjectOwnsMemory(false);
+ rPropOpt.AddOpt(DFF_Prop_pWrapPolygonVertices, false,
+ nArrLen, static_cast<sal_uInt8 *>(pArr), nArrLen);
+ }
+ }
+ }
+
+ return nLineWidth;
+}
+
+void SwBasicEscherEx::Init()
+{
+ MapUnit eMap = MAP_TWIP;
+ if (SdrModel *pModel = rWrt.pDoc->GetDrawModel())
+ {
+ // PPT arbeitet nur mit Einheiten zu 576DPI
+ // WW hingegen verwendet twips, dh. 1440DPI.
+ eMap = pModel->GetScaleUnit();
+ }
+
+ // MS-DFF-Properties sind grossteils in EMU (English Metric Units) angegeben
+ // 1mm=36000emu, 1twip=635emu
+ Fraction aFact(360, 1);
+ aFact /= GetMapFactor(MAP_100TH_MM, eMap).X();
+ // create little values
+ aFact = Fraction(aFact.GetNumerator(), aFact.GetDenominator());
+ mnEmuMul = aFact.GetNumerator();
+ mnEmuDiv = aFact.GetDenominator();
+
+ SetHellLayerId(rWrt.pDoc->GetHellId());
+}
+
+sal_Int32 SwBasicEscherEx::ToFract16(sal_Int32 nVal, sal_uInt32 nMax) const
+{
+ if (nMax)
+ {
+ sal_Int32 nMSVal = (nVal / 65536) * nMax;
+ nMSVal += (nVal * 65536 ) / nMax;
+ return nMSVal;
+ }
+ return 0;
+}
+
+SdrLayerID SwBasicEscherEx::GetInvisibleHellId() const
+{
+ return rWrt.pDoc->GetInvisibleHellId();
+}
+
+void SwBasicEscherEx::WritePictures()
+{
+ if( SvStream* pPicStrm = static_cast< SwEscherExGlobal& >( *mxGlobal ).GetPictureStream() )
+ {
+ // set the blip - entries to the correct stream pos
+ sal_Int32 nEndPos = pPicStrm->Tell();
+ mxGlobal->WriteBlibStoreEntry(*pEscherStrm, 1, sal_True, nEndPos);
+
+ pPicStrm->Seek(0);
+ *pEscherStrm << *pPicStrm;
+ }
+}
+
+SwEscherEx::SwEscherEx(SvStream* pStrm, WW8Export& rWW8Wrt)
+ : SwBasicEscherEx(pStrm, rWW8Wrt),
+ pTxtBxs(0)
+{
+ aHostData.SetClientData(&aWinwordAnchoring);
+ OpenContainer( ESCHER_DggContainer );
+
+ sal_uInt16 nColorCount = 4;
+ *pStrm << (sal_uInt16)( nColorCount << 4 ) // instance
+ << (sal_uInt16)ESCHER_SplitMenuColors // record type
+ << (sal_uInt32)( nColorCount * 4 ) // size
+ << (sal_uInt32)0x08000004
+ << (sal_uInt32)0x08000001
+ << (sal_uInt32)0x08000002
+ << (sal_uInt32)0x100000f7;
+
+ CloseContainer(); // ESCHER_DggContainer
+
+ sal_uInt8 i = 2; // for header/footer and the other
+ PlcDrawObj *pSdrObjs = rWrt.pHFSdrObjs;
+ pTxtBxs = rWrt.pHFTxtBxs;
+
+ // if no header/footer -> skip over
+ if (!pSdrObjs->size())
+ {
+ --i;
+ pSdrObjs = rWrt.pSdrObjs;
+ pTxtBxs = rWrt.pTxtBxs;
+ }
+
+ for( ; i--; pSdrObjs = rWrt.pSdrObjs, pTxtBxs = rWrt.pTxtBxs )
+ {
+ // "dummy char" (or any Count ?) - why? This knows only M$
+ GetStream() << (sal_Char)i;
+
+ OpenContainer( ESCHER_DgContainer );
+
+ EnterGroup( 0 );
+
+ sal_uLong nSecondShapeId = pSdrObjs == rWrt.pSdrObjs ? GenerateShapeId() : 0;
+
+ // write now all Writer-/DrawObjects
+ DrawObjPointerVector aSorted;
+ MakeZOrderArrAndFollowIds(pSdrObjs->GetObjArr(), aSorted);
+
+ sal_uInt32 nShapeId=0;
+ DrawObjPointerIter aEnd = aSorted.end();
+ for (DrawObjPointerIter aIter = aSorted.begin(); aIter != aEnd; ++aIter)
+ {
+ sal_Int32 nBorderThick=0;
+ DrawObj *pObj = (*aIter);
+ OSL_ENSURE(pObj, "impossible");
+ if (!pObj)
+ continue;
+ const sw::Frame &rFrame = pObj->maCntnt;
+ const SwFrmFmt& rFmt = rFrame.GetFrmFmt();
+
+ switch (rFrame.GetWriterType())
+ {
+ case sw::Frame::eTxtBox:
+ case sw::Frame::eOle:
+ case sw::Frame::eGraphic:
+ nBorderThick = WriteFlyFrm(*pObj, nShapeId, aSorted);
+ break;
+ case sw::Frame::eFormControl:
+ WriteOCXControl(rFmt, nShapeId = GenerateShapeId());
+ break;
+ case sw::Frame::eDrawing:
+ aWinwordAnchoring.SetAnchoring(rFmt);
+ const SdrObject* pSdrObj = rFmt.FindRealSdrObject();
+ if (pSdrObj)
+ {
+ bool bSwapInPage = false;
+ if (!pSdrObj->GetPage())
+ {
+ if (SdrModel* pModel = rWrt.pDoc->GetDrawModel())
+ {
+ if (SdrPage *pPage = pModel->GetPage(0))
+ {
+ bSwapInPage = true;
+ (const_cast<SdrObject*>(pSdrObj))->SetPage(pPage);
+ }
+ }
+ }
+
+ nShapeId = AddSdrObject(*pSdrObj);
+
+ if (bSwapInPage)
+ (const_cast<SdrObject*>(pSdrObj))->SetPage(0);
+ }
+#if OSL_DEBUG_LEVEL > 1
+ else
+ OSL_ENSURE( !this, "Where is the SDR-Object?" );
+#endif
+ }
+
+ if( !nShapeId )
+ {
+ nShapeId = AddDummyShape();
+ }
+
+ pObj->SetShapeDetails(nShapeId, nBorderThick);
+ }
+
+ EndSdrObjectPage(); // ???? Bugfix for 74724
+
+ if( nSecondShapeId )
+ {
+ OpenContainer( ESCHER_SpContainer );
+
+ AddShape( ESCHER_ShpInst_Rectangle, 0xe00, nSecondShapeId );
+
+ EscherPropertyContainer aPropOpt;
+ const SwFrmFmt &rFmt = const_cast<const SwDoc *>(rWrt.pDoc)->GetPageDesc(0).GetMaster();
+ const SfxPoolItem* pItem = 0;
+ SfxItemState eState = rFmt.GetItemState(RES_BACKGROUND, true,
+ &pItem);
+ if (SFX_ITEM_SET == eState && pItem)
+ {
+ const SvxBrushItem* pBrush = (const SvxBrushItem*)pItem;
+ WriteBrushAttr(*pBrush, aPropOpt);
+ }
+ aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x8000001 );
+ aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x00080008 );
+ aPropOpt.AddOpt( ESCHER_Prop_shadowColor, 0x8000002 );
+ aPropOpt.AddOpt( ESCHER_Prop_lineWidth, 0 );
+
+ aPropOpt.Commit( *pStrm );
+
+ AddAtom( 4, ESCHER_ClientData );
+ GetStream() << 1L;
+
+ CloseContainer(); // ESCHER_SpContainer
+ }
+ CloseContainer(); // ESCHER_DgContainer
+ }
+}
+
+SwEscherEx::~SwEscherEx()
+{
+}
+
+void SwEscherEx::FinishEscher()
+{
+ pEscherStrm->Seek(0);
+ *rWrt.pTableStrm << *pEscherStrm;
+ delete pEscherStrm, pEscherStrm = 0;
+}
+
+/** method to perform conversion of positioning attributes with the help
+ of corresponding layout information
+
+ #i30669#
+ Because most of the Writer object positions doesn't correspond to the
+ object positions in WW8, this method converts the positioning
+ attributes. For this conversion the corresponding layout information
+ is needed. If no layout information exists - e.g. no layout exists - no
+ conversion is performed.
+ No conversion is performed for as-character anchored objects. Whose
+ object positions are already treated special in method <WriteData(..)>.
+
+ @param _iorHoriOri
+ input/output parameter - containing the current horizontal position
+ attributes, which are converted by this method.
+
+ @param _iorVertOri
+ input/output parameter - containing the current vertical position
+ attributes, which are converted by this method.
+
+ @param _rFrmFmt
+ input parameter - frame format of the anchored object
+
+ @return boolean, indicating, if a conversion has been performed.
+*/
+bool WinwordAnchoring::ConvertPosition( SwFmtHoriOrient& _iorHoriOri,
+ SwFmtVertOrient& _iorVertOri,
+ const SwFrmFmt& _rFrmFmt )
+{
+ const RndStdIds eAnchor = _rFrmFmt.GetAnchor().GetAnchorId();
+
+ if ( (FLY_AS_CHAR == eAnchor) || (FLY_AT_FLY == eAnchor) )
+ {
+ // no conversion for as-character or at frame anchored objects
+ return false;
+ }
+
+ // determine anchored object
+ SwAnchoredObject* pAnchoredObj( 0L );
+ {
+ const SwContact* pContact = _rFrmFmt.FindContactObj();
+ if ( pContact )
+ {
+ std::list<SwAnchoredObject*> aAnchoredObjs;
+ pContact->GetAnchoredObjs( aAnchoredObjs );
+ if ( !aAnchoredObjs.empty() )
+ {
+ pAnchoredObj = aAnchoredObjs.front();
+ }
+ }
+ }
+ if ( !pAnchoredObj )
+ {
+ // no anchored object found. Thus, the needed layout information can't
+ // be determined. --> no conversion
+ return false;
+ }
+ // no conversion for anchored drawing object, which aren't attached to an
+ // anchor frame.
+ // This is the case for drawing objects, which are anchored inside a page
+ // header/footer of an *unused* page style.
+ if ( dynamic_cast<SwAnchoredDrawObject*>(pAnchoredObj) &&
+ !pAnchoredObj->GetAnchorFrm() )
+ {
+ return false;
+ }
+ // <--
+
+ bool bConverted( false );
+
+ // determine value of attribute 'Follow text flow', because positions aligned
+ // at page areas have to be converted, if it's set.
+ const bool bFollowTextFlow = _rFrmFmt.GetFollowTextFlow().GetValue();
+
+ // check, if horizontal and vertical position have to be converted due to
+ // the fact, that the object is anchored at a paragraph, which has a "column
+ // break before" attribute
+ bool bConvDueToAnchoredAtColBreakPara( false );
+ if ( ( (eAnchor == FLY_AT_PARA) || (eAnchor == FLY_AT_CHAR) ) &&
+ _rFrmFmt.GetAnchor().GetCntntAnchor() &&
+ _rFrmFmt.GetAnchor().GetCntntAnchor()->nNode.GetNode().IsTxtNode() )
+ {
+ SwTxtNode& rAnchorTxtNode =
+ dynamic_cast<SwTxtNode&>(_rFrmFmt.GetAnchor().GetCntntAnchor()->nNode.GetNode());
+ const SvxFmtBreakItem* pBreak = &(ItemGet<SvxFmtBreakItem>(rAnchorTxtNode, RES_BREAK));
+ if ( pBreak &&
+ pBreak->GetBreak() == SVX_BREAK_COLUMN_BEFORE )
+ {
+ bConvDueToAnchoredAtColBreakPara = true;
+ }
+ }
+ // <--
+
+ // convert horizontal position, if needed
+ {
+ enum HoriConv { NO_CONV, CONV2PG, CONV2COL, CONV2CHAR };
+ HoriConv eHoriConv( NO_CONV );
+
+ // determine, if conversion has to be performed due to the position orientation
+ bool bConvDueToOrientation( false );
+ {
+ const sal_Int16 eHOri = _iorHoriOri.GetHoriOrient();
+ bConvDueToOrientation = eHOri == text::HoriOrientation::LEFT || eHOri == text::HoriOrientation::RIGHT ||
+ eHOri == text::HoriOrientation::INSIDE || eHOri == text::HoriOrientation::OUTSIDE ||
+ ( eHOri != text::HoriOrientation::CENTER && _iorHoriOri.IsPosToggle() );
+ }
+
+ // determine conversion type due to the position relation
+ if ( bConvDueToAnchoredAtColBreakPara )
+ {
+ eHoriConv = CONV2PG;
+ }
+ else
+ {
+ switch ( _iorHoriOri.GetRelationOrient() )
+ {
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ {
+ if ( bConvDueToOrientation || bFollowTextFlow )
+ eHoriConv = CONV2PG;
+ }
+ break;
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_RIGHT:
+ {
+ // relation not supported by WW8. Thus, conversion always needed.
+ eHoriConv = CONV2PG;
+ }
+ break;
+ case text::RelOrientation::FRAME:
+ {
+ if ( bConvDueToOrientation )
+ eHoriConv = CONV2COL;
+ }
+ break;
+ case text::RelOrientation::PRINT_AREA:
+ case text::RelOrientation::FRAME_LEFT:
+ case text::RelOrientation::FRAME_RIGHT:
+ {
+ // relation not supported by WW8. Thus, conversion always needed.
+ eHoriConv = CONV2COL;
+ }
+ break;
+ case text::RelOrientation::CHAR:
+ {
+ if ( bConvDueToOrientation )
+ eHoriConv = CONV2CHAR;
+ }
+ break;
+ default:
+ OSL_FAIL( "<WinwordAnchoring::ConvertPosition(..)> - unknown horizontal relation" );
+ }
+ }
+ // <--
+ if ( eHoriConv != NO_CONV )
+ {
+ _iorHoriOri.SetHoriOrient( text::HoriOrientation::NONE );
+ SwTwips nPosX( 0L );
+ {
+ Point aPos;
+ if ( eHoriConv == CONV2PG )
+ {
+ _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
+ // #i33818#
+ bool bRelToTableCell( false );
+ aPos = pAnchoredObj->GetRelPosToPageFrm( bFollowTextFlow,
+ bRelToTableCell );
+ if ( bRelToTableCell )
+ {
+ _iorHoriOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
+ }
+ // <--
+ }
+ else if ( eHoriConv == CONV2COL )
+ {
+ _iorHoriOri.SetRelationOrient( text::RelOrientation::FRAME );
+ aPos = pAnchoredObj->GetRelPosToAnchorFrm();
+ }
+ else if ( eHoriConv == CONV2CHAR )
+ {
+ _iorHoriOri.SetRelationOrient( text::RelOrientation::CHAR );
+ aPos = pAnchoredObj->GetRelPosToChar();
+ }
+ // No distinction between layout directions, because of missing
+ // information about WW8 in vertical layout.
+ nPosX = aPos.X();
+ }
+ _iorHoriOri.SetPos( nPosX );
+ bConverted = true;
+ }
+ }
+
+ // convert vertical position, if needed
+ {
+ enum VertConv { NO_CONV, CONV2PG, CONV2PARA, CONV2LINE };
+ VertConv eVertConv( NO_CONV );
+
+ // determine, if conversion has to be performed due to the position orientation
+ bool bConvDueToOrientation( false );
+ {
+ const sal_Int16 eVOri = _iorVertOri.GetVertOrient();
+ bConvDueToOrientation = ( eVOri == text::VertOrientation::TOP ||
+ eVOri == text::VertOrientation::BOTTOM ||
+ eVOri == text::VertOrientation::CHAR_TOP ||
+ eVOri == text::VertOrientation::CHAR_BOTTOM ||
+ eVOri == text::VertOrientation::CHAR_CENTER ||
+ eVOri == text::VertOrientation::LINE_TOP ||
+ eVOri == text::VertOrientation::LINE_BOTTOM ||
+ eVOri == text::VertOrientation::LINE_CENTER );
+ }
+
+ // determine conversion type due to the position relation
+ if ( bConvDueToAnchoredAtColBreakPara )
+ {
+ eVertConv = CONV2PG;
+ }
+ else
+ {
+ switch ( _iorVertOri.GetRelationOrient() )
+ {
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ {
+ if ( bConvDueToOrientation || bFollowTextFlow )
+ eVertConv = CONV2PG;
+ }
+ break;
+ case text::RelOrientation::FRAME:
+ {
+ if ( bConvDueToOrientation ||
+ _iorVertOri.GetVertOrient() == text::VertOrientation::CENTER )
+ {
+ eVertConv = CONV2PARA;
+ }
+ }
+ break;
+ case text::RelOrientation::PRINT_AREA:
+ {
+ // relation not supported by WW8. Thus, conversion always needed.
+ eVertConv = CONV2PARA;
+ }
+ break;
+ case text::RelOrientation::CHAR:
+ {
+ // relation not supported by WW8. Thus, conversion always needed.
+ eVertConv = CONV2PARA;
+ }
+ break;
+ case text::RelOrientation::TEXT_LINE:
+ {
+ if ( bConvDueToOrientation ||
+ _iorVertOri.GetVertOrient() == text::VertOrientation::NONE )
+ {
+ eVertConv = CONV2LINE;
+ }
+ }
+ break;
+ case text::RelOrientation::PAGE_LEFT:
+ case text::RelOrientation::PAGE_RIGHT:
+ case text::RelOrientation::FRAME_LEFT:
+ case text::RelOrientation::FRAME_RIGHT:
+ default:
+ OSL_FAIL( "<WinwordAnchoring::ConvertPosition(..)> - unknown vertical relation" );
+ }
+ }
+
+ if ( eVertConv != NO_CONV )
+ {
+ _iorVertOri.SetVertOrient( text::VertOrientation::NONE );
+ SwTwips nPosY( 0L );
+ {
+ Point aPos;
+ if ( eVertConv == CONV2PG )
+ {
+ _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_FRAME );
+ // #i33818#
+ bool bRelToTableCell( false );
+ aPos = pAnchoredObj->GetRelPosToPageFrm( bFollowTextFlow,
+ bRelToTableCell );
+ if ( bRelToTableCell )
+ {
+ _iorVertOri.SetRelationOrient( text::RelOrientation::PAGE_PRINT_AREA );
+ }
+ // <--
+ }
+ else if ( eVertConv == CONV2PARA )
+ {
+ _iorVertOri.SetRelationOrient( text::RelOrientation::FRAME );
+ aPos = pAnchoredObj->GetRelPosToAnchorFrm();
+ }
+ else if ( eVertConv == CONV2LINE )
+ {
+ _iorVertOri.SetRelationOrient( text::RelOrientation::TEXT_LINE );
+ aPos = pAnchoredObj->GetRelPosToLine();
+ }
+ // No distinction between layout directions, because of missing
+ // information about WW8 in vertical layout.
+ nPosY = aPos.Y();
+ }
+ _iorVertOri.SetPos( nPosY );
+ bConverted = true;
+ }
+ }
+
+ return bConverted;
+}
+
+void WinwordAnchoring::SetAnchoring(const SwFrmFmt& rFmt)
+{
+ const RndStdIds eAnchor = rFmt.GetAnchor().GetAnchorId();
+ mbInline = (eAnchor == FLY_AS_CHAR);
+
+ SwFmtHoriOrient rHoriOri = rFmt.GetHoriOrient();
+ SwFmtVertOrient rVertOri = rFmt.GetVertOrient();
+
+ // #i30669# - convert the positioning attributes.
+ // Most positions are converted, if layout information exists.
+ const bool bPosConverted = ConvertPosition( rHoriOri, rVertOri, rFmt );
+
+ const sal_Int16 eHOri = rHoriOri.GetHoriOrient();
+ const sal_Int16 eVOri = rVertOri.GetVertOrient(); // #i22673#
+
+ const sal_Int16 eHRel = rHoriOri.GetRelationOrient();
+ const sal_Int16 eVRel = rVertOri.GetRelationOrient();
+
+ // horizontal Adjustment
+ switch (eHOri)
+ {
+ default:
+ case text::HoriOrientation::NONE:
+ mnXAlign = 0;
+ break;
+ case text::HoriOrientation::LEFT:
+ mnXAlign = 1;
+ break;
+ case text::HoriOrientation::CENTER:
+ mnXAlign = 2;
+ break;
+ case text::HoriOrientation::RIGHT:
+ mnXAlign = 3;
+ break;
+ case text::HoriOrientation::INSIDE:
+ mnXAlign = 4;
+ break;
+ case text::HoriOrientation::OUTSIDE:
+ mnXAlign = 5;
+ break;
+ }
+
+ // vertical Adjustment
+ // #i22673#
+ // When adjustment is vertically relative to line or to char
+ // bottom becomes top and vice versa
+ const bool bVertSwap = !bPosConverted &&
+ ( (eVRel == text::RelOrientation::CHAR) ||
+ (eVRel == text::RelOrientation::TEXT_LINE) );
+ switch (eVOri)
+ {
+ default:
+ case text::VertOrientation::NONE:
+ mnYAlign = 0;
+ break;
+ case text::VertOrientation::TOP:
+ case text::VertOrientation::LINE_TOP:
+ case text::VertOrientation::CHAR_TOP:
+ mnYAlign = bVertSwap ? 3 : 1;
+ break;
+ case text::VertOrientation::CENTER:
+ case text::VertOrientation::LINE_CENTER:
+ mnYAlign = 2;
+ break;
+ case text::VertOrientation::BOTTOM:
+ case text::VertOrientation::LINE_BOTTOM:
+ case text::VertOrientation::CHAR_BOTTOM:
+ mnYAlign = bVertSwap ? 1 : 3;
+ break;
+ }
+
+ // Adjustment is horizontally relative to...
+ switch (eHRel)
+ {
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ mnXRelTo = 0;
+ break;
+ case text::RelOrientation::PAGE_FRAME:
+ case text::RelOrientation::PAGE_LEFT: //:-(
+ case text::RelOrientation::PAGE_RIGHT: //:-(
+ mnXRelTo = 1;
+ break;
+ case text::RelOrientation::FRAME:
+ case text::RelOrientation::FRAME_LEFT: //:-(
+ case text::RelOrientation::FRAME_RIGHT: //:-(
+ if (eAnchor == FLY_AT_PAGE)
+ mnXRelTo = 1;
+ else
+ mnXRelTo = 2;
+ break;
+ case text::RelOrientation::PRINT_AREA:
+ if (eAnchor == FLY_AT_PAGE)
+ mnXRelTo = 0;
+ else
+ mnXRelTo = 2;
+ break;
+ case text::RelOrientation::CHAR:
+ mnXRelTo = 3;
+ break;
+ case text::RelOrientation::TEXT_LINE:
+ break;
+ }
+
+ // Adjustment is vertically relative to...
+ switch (eVRel)
+ {
+ case text::RelOrientation::PAGE_PRINT_AREA:
+ mnYRelTo = 0;
+ break;
+ case text::RelOrientation::PAGE_FRAME:
+ mnYRelTo = 1;
+ break;
+ case text::RelOrientation::PRINT_AREA:
+ if (eAnchor == FLY_AT_PAGE)
+ mnYRelTo = 0;
+ else
+ mnYRelTo = 2;
+ break;
+ case text::RelOrientation::FRAME:
+ if (eAnchor == FLY_AT_PAGE)
+ mnYRelTo = 1;
+ else
+ mnYRelTo = 2;
+ break;
+ case text::RelOrientation::CHAR:
+ case text::RelOrientation::TEXT_LINE: // #i22673# - vertical alignment at top of line
+ case text::RelOrientation::PAGE_LEFT: //nonsense
+ case text::RelOrientation::PAGE_RIGHT: //nonsense
+ case text::RelOrientation::FRAME_LEFT: //nonsense
+ case text::RelOrientation::FRAME_RIGHT: //nonsense
+ mnYRelTo = 3;
+ break;
+ }
+}
+
+void SwEscherEx::WriteFrmExtraData( const SwFrmFmt& rFmt )
+{
+ aWinwordAnchoring.SetAnchoring(rFmt);
+ aWinwordAnchoring.WriteData(*this);
+
+ AddAtom(4, ESCHER_ClientAnchor);
+ GetStream() << 0L;
+
+ AddAtom(4, ESCHER_ClientData);
+ GetStream() << 1L;
+}
+
+sal_Int32 SwEscherEx::WriteFlyFrm(const DrawObj &rObj, sal_uInt32 &rShapeId,
+ DrawObjPointerVector &rPVec)
+{
+ const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
+
+ // check for textflyframe and if it is the first in a Chain
+ sal_Int32 nBorderThick = 0;
+ const SwNodeIndex* pNdIdx = rFmt.GetCntnt().GetCntntIdx();
+ if( pNdIdx )
+ {
+ SwNodeIndex aIdx( *pNdIdx, 1 );
+ switch( aIdx.GetNode().GetNodeType() )
+ {
+ case ND_GRFNODE:
+ nBorderThick = WriteGrfFlyFrame( rFmt, rShapeId = GenerateShapeId() );
+ break;
+ case ND_OLENODE:
+ nBorderThick = WriteOLEFlyFrame( rFmt, rShapeId = GenerateShapeId() );
+ break;
+ default:
+ if (const SdrObject* pObj = rFmt.FindRealSdrObject())
+ {
+ // check for the first in a Chain
+ sal_uInt32 nTxtId;
+ sal_uInt16 nOff = 0;
+ const SwFrmFmt* pFmt = &rFmt, *pPrev;
+ while( 0 != ( pPrev = pFmt->GetChain().GetPrev() ))
+ {
+ ++nOff;
+ pFmt = pPrev;
+ }
+
+ rShapeId = GetFlyShapeId(rFmt, rObj.mnHdFtIndex, rPVec);
+ if( !nOff )
+ {
+ void* p = (void*)pObj;
+ nTxtId = pTxtBxs->GetPos( p );
+ if( USHRT_MAX == nTxtId )
+ {
+ pTxtBxs->Append( *pObj, rShapeId );
+ nTxtId = pTxtBxs->Count();
+ }
+ else
+ ++nTxtId;
+ }
+ else
+ {
+ const SdrObject* pPrevObj = pFmt->FindRealSdrObject();
+ void* p = (void*)pPrevObj;
+ nTxtId = pTxtBxs->GetPos( p );
+ if( USHRT_MAX == nTxtId )
+ {
+ sal_uInt32 nPrevShapeId =
+ GetFlyShapeId(*pFmt, rObj.mnHdFtIndex, rPVec);
+ pTxtBxs->Append( *pPrevObj, nPrevShapeId );
+ nTxtId = pTxtBxs->Count();
+ }
+ else
+ ++nTxtId;
+ }
+ nTxtId *= 0x10000;
+ nTxtId += nOff;
+
+ nBorderThick = WriteTxtFlyFrame(rObj, rShapeId, nTxtId, rPVec);
+ }
+ }
+ }
+ return nBorderThick;
+}
+
+sal_uInt16 FindPos(const SwFrmFmt &rFmt, unsigned int nHdFtIndex,
+ DrawObjPointerVector &rPVec)
+{
+ DrawObjPointerIter aEnd = rPVec.end();
+ for (DrawObjPointerIter aIter = rPVec.begin(); aIter != aEnd; ++aIter)
+ {
+ const DrawObj *pObj = (*aIter);
+ OSL_ENSURE(pObj, "Impossible");
+ if (!pObj)
+ continue;
+ if (
+ nHdFtIndex == pObj->mnHdFtIndex &&
+ &rFmt == (&pObj->maCntnt.GetFrmFmt())
+ )
+ {
+ return static_cast< sal_uInt16 >(aIter - rPVec.begin());
+ }
+ }
+ return USHRT_MAX;
+}
+
+sal_Int32 SwEscherEx::WriteTxtFlyFrame(const DrawObj &rObj, sal_uInt32 nShapeId,
+ sal_uInt32 nTxtBox, DrawObjPointerVector &rPVec)
+{
+ const SwFrmFmt &rFmt = rObj.maCntnt.GetFrmFmt();
+ short nDirection = rObj.mnDirection;
+
+ sal_Int32 nBorderThick=0;
+ OpenContainer( ESCHER_SpContainer );
+
+ AddShape( ESCHER_ShpInst_TextBox, 0xa00, nShapeId );
+ EscherPropertyContainer aPropOpt;
+ aPropOpt.AddOpt(ESCHER_Prop_lTxid, nTxtBox);
+ if (const SwFrmFmt *pNext = rFmt.GetChain().GetNext())
+ {
+ sal_uInt16 nPos = FindPos(*pNext, rObj.mnHdFtIndex, rPVec);
+ if (USHRT_MAX != nPos && aFollowShpIds[nPos])
+ aPropOpt.AddOpt(ESCHER_Prop_hspNext, aFollowShpIds[nPos]);
+ }
+ nBorderThick = WriteFlyFrameAttr( rFmt, mso_sptTextBox, aPropOpt );
+
+ MSO_TextFlow nFlow;
+
+ switch (nDirection)
+ {
+ default:
+ OSL_ENSURE(!this, "unknown direction type");
+ case FRMDIR_HORI_LEFT_TOP:
+ nFlow=mso_txflHorzN;
+ break;
+ case FRMDIR_HORI_RIGHT_TOP:
+ nFlow=mso_txflHorzN;
+ break;
+ case FRMDIR_VERT_TOP_LEFT: //not really possible in word
+ case FRMDIR_VERT_TOP_RIGHT:
+ nFlow=mso_txflTtoBA;
+ break;
+ }
+ aPropOpt.AddOpt( ESCHER_Prop_txflTextFlow, nFlow );
+
+ aPropOpt.Commit( GetStream() );
+
+ // store anchor attribute
+ WriteFrmExtraData( rFmt );
+
+ AddAtom( 4, ESCHER_ClientTextbox ); GetStream() << nTxtBox;
+
+ CloseContainer(); // ESCHER_SpContainer
+ return nBorderThick;
+}
+
+void SwBasicEscherEx::WriteOLEPicture(EscherPropertyContainer &rPropOpt,
+ sal_uInt32 nShapeFlags, const Graphic &rGraphic, const SdrObject &rObj,
+ sal_uInt32 nShapeId, const awt::Rectangle* pVisArea )
+{
+ //nShapeFlags == 0xA00 + flips and ole active
+ AddShape(ESCHER_ShpInst_PictureFrame, nShapeFlags, nShapeId);
+
+ GraphicObject aGraphicObject(rGraphic);
+ ByteString aId = aGraphicObject.GetUniqueID();
+ if (aId.Len())
+ {
+ Rectangle aRect = rObj.GetLogicRect();
+ aRect.SetPos(Point(0,0));
+ aRect.Right() = DrawModelToEmu(aRect.Right());
+ aRect.Bottom() = DrawModelToEmu(aRect.Bottom());
+ sal_uInt32 nBlibId = mxGlobal->GetBlibID( *QueryPictureStream(),
+ aId, aRect, pVisArea, 0); // SJ: the fourth parameter (VisArea) should be set..
+ if (nBlibId)
+ rPropOpt.AddOpt(ESCHER_Prop_pib, nBlibId, sal_True);
+ }
+
+ SetPicId(rObj, nShapeId, rPropOpt);
+ rPropOpt.AddOpt( ESCHER_Prop_pictureActive, 0x10000 );
+}
+
+void SwEscherEx::WriteOCXControl( const SwFrmFmt& rFmt, sal_uInt32 nShapeId )
+{
+ if (const SdrObject* pSdrObj = rFmt.FindRealSdrObject())
+ {
+ OpenContainer( ESCHER_SpContainer );
+
+ SdrModel *pModel = rWrt.pDoc->GetDrawModel();
+ OutputDevice *pDevice = Application::GetDefaultDevice();
+ OSL_ENSURE(pModel && pDevice, "no model or device");
+
+ // #i71538# use complete SdrViews
+ // SdrExchangeView aExchange(pModel, pDevice);
+ SdrView aExchange(pModel, pDevice);
+
+ Graphic aGraphic(aExchange.GetObjGraphic(pModel, pSdrObj));
+
+ EscherPropertyContainer aPropOpt;
+ WriteOLEPicture(aPropOpt, 0xa00 | SHAPEFLAG_OLESHAPE, aGraphic,
+ *pSdrObj, nShapeId, NULL );
+
+ WriteFlyFrameAttr( rFmt, mso_sptPictureFrame , aPropOpt );
+ aPropOpt.Commit( GetStream() );
+
+ // store anchor attribute
+ WriteFrmExtraData( rFmt );
+
+ CloseContainer(); // ESCHER_SpContainer
+ }
+}
+
+void SwEscherEx::MakeZOrderArrAndFollowIds(
+ std::vector<DrawObj>& rSrcArr, std::vector<DrawObj*>&rDstArr)
+{
+ sal_uInt16 n, nCnt = static_cast< sal_uInt16 >(rSrcArr.size());
+ SvULongsSort aSort( 255 < nCnt ? 255 : nCnt, 255 );
+ rDstArr.clear();
+ rDstArr.reserve(nCnt);
+ for (n = 0; n < nCnt; ++n)
+ {
+ const SwFrmFmt &rFmt = rSrcArr[n].maCntnt.GetFrmFmt();
+ sal_uLong nOrdNum = rWrt.GetSdrOrdNum(rFmt);
+ sal_uInt16 nPos;
+ //returns what will be the index in rDstArr of p as nPos
+ aSort.Insert(nOrdNum, nPos);
+ DrawObj &rObj = rSrcArr[n];
+ rDstArr.insert(rDstArr.begin() + nPos, &rObj);
+ }
+
+ if (aFollowShpIds.Count())
+ aFollowShpIds.Remove(0, aFollowShpIds.Count());
+
+ for (n = 0; n < nCnt; ++n)
+ {
+ const SwFrmFmt &rFmt = rDstArr[n]->maCntnt.GetFrmFmt();
+ bool bNeedsShapeId = false;
+
+ if (RES_FLYFRMFMT == rFmt.Which())
+ {
+ const SwFmtChain &rChain = rFmt.GetChain();
+ if (rChain.GetPrev() || rChain.GetNext())
+ bNeedsShapeId = true;
+ }
+
+ sal_uLong nShapeId = bNeedsShapeId ? GenerateShapeId() : 0;
+
+ aFollowShpIds.Insert(nShapeId, n);
+ }
+}
+
+sal_uInt32 SwEscherEx::GetFlyShapeId(const SwFrmFmt& rFmt,
+ unsigned int nHdFtIndex, DrawObjPointerVector &rpVec)
+{
+ sal_uInt16 nPos = FindPos(rFmt, nHdFtIndex, rpVec);
+ sal_uInt32 nShapeId;
+ if (USHRT_MAX != nPos)
+ {
+ if (0 == (nShapeId = aFollowShpIds[nPos]))
+ {
+ nShapeId = GenerateShapeId();
+ aFollowShpIds[ nPos ] = nShapeId;
+ }
+ }
+ else
+ nShapeId = GenerateShapeId();
+ return nShapeId;
+}
+
+sal_uInt32 SwEscherEx::QueryTextID(
+ const uno::Reference< drawing::XShape>& xXShapeRef, sal_uInt32 nShapeId )
+{
+ sal_uInt32 nId = 0;
+ if (SdrObject* pObj = GetSdrObjectFromXShape(xXShapeRef))
+ {
+ pTxtBxs->Append( *pObj, nShapeId );
+ nId = pTxtBxs->Count();
+ nId *= 0x10000;
+ }
+ return nId;
+}
+
+bool SwMSConvertControls::ExportControl(WW8Export &rWW8Wrt, const SdrObject *pObj)
+{
+ if (!rWW8Wrt.bWrtWW8)
+ return false;
+
+ SdrUnoObj *pFormObj = PTR_CAST(SdrUnoObj,pObj);
+ uno::Reference< awt::XControlModel > xControlModel =
+ pFormObj->GetUnoControlModel();
+
+ //Why oh lord do we use so many different units ?
+ //I think I painted myself into a little bit of a
+ //corner by trying to use the uno interface for
+ //controls export
+ Rectangle aRect = pFormObj->GetLogicRect();
+ aRect.SetPos(Point(0,0));
+ awt::Size aSize;
+ aSize.Width = TWIPS_TO_MM(aRect.Right());
+ aSize.Height = TWIPS_TO_MM(aRect.Bottom());
+
+ //Open the ObjectPool
+ SvStorageRef xObjPool = rWW8Wrt.GetWriter().GetStorage().OpenSotStorage(
+ CREATE_CONST_ASC(SL::aObjectPool), STREAM_READWRITE |
+ STREAM_SHARE_DENYALL);
+
+ //Create a destination storage for the microsoft control
+ String sStorageName('_');
+ sStorageName += String::CreateFromInt32((sal_uInt32)(sal_uIntPtr)pObj);
+ SvStorageRef xOleStg = xObjPool->OpenSotStorage(sStorageName,
+ STREAM_READWRITE|STREAM_SHARE_DENYALL);
+
+ if (!xOleStg.Is())
+ return false;
+
+ String sName;
+ if (!WriteOCXStream(xOleStg,xControlModel,aSize,sName))
+ return false;
+
+ sal_uInt8 aSpecOLE[] =
+ {
+ 0x03, 0x6a, 0xFF, 0xFF, 0xFF, 0xFF, // sprmCPicLocation
+ 0x0a, 0x08, 1, // sprmCFOLE2
+ 0x55, 0x08, 1, // sprmCFSpec
+ 0x56, 0x08, 1 // sprmCFObj
+ };
+ //Set the obj id into the sprmCPicLocation
+ sal_uInt8 *pData = aSpecOLE+2;
+ Set_UInt32(pData,(sal_uInt32)(sal_uIntPtr)pObj);
+
+ String sFld(FieldString(ww::eCONTROL));
+ sFld.APPEND_CONST_ASC("Forms.");
+ sFld += sName;
+ sFld.APPEND_CONST_ASC(".1 \\s ");
+
+ rWW8Wrt.OutputField(0, ww::eCONTROL, sFld,
+ WRITEFIELD_START|WRITEFIELD_CMD_START|WRITEFIELD_CMD_END);
+
+ rWW8Wrt.pChpPlc->AppendFkpEntry(rWW8Wrt.Strm().Tell(),sizeof(aSpecOLE),
+ aSpecOLE);
+ rWW8Wrt.WriteChar( 0x1 );
+ rWW8Wrt.OutputField(0, ww::eCONTROL, aEmptyStr, WRITEFIELD_END | WRITEFIELD_CLOSE);
+ return true;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/wrtw8nds.cxx b/sw/source/filter/ww8/wrtw8nds.cxx
new file mode 100644
index 000000000000..764b5438607f
--- /dev/null
+++ b/sw/source/filter/ww8/wrtw8nds.cxx
@@ -0,0 +1,2757 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <vector>
+#include <list>
+#include <utility>
+#include <algorithm>
+#include <functional>
+#include <iostream>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <cstdio>
+#endif
+
+#include <hintids.hxx>
+#include <tools/urlobj.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/svxfont.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/tstpitem.hxx>
+#include "svl/urihelper.hxx"
+#include <svl/whiter.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <fmtlsplt.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcntnt.hxx>
+#include <frmatr.hxx>
+#include <paratr.hxx>
+#include <txatbase.hxx>
+#include <fmtinfmt.hxx>
+#include <fmtrfmrk.hxx>
+#include <fchrfmt.hxx>
+#include <fmtautofmt.hxx>
+#include <charfmt.hxx>
+#include <tox.hxx>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <swtable.hxx>
+#include <swtblfmt.hxx>
+#include <section.hxx>
+#include <pagedesc.hxx>
+#include <swrect.hxx>
+#include <reffld.hxx>
+#include <redline.hxx>
+#include <wrtswtbl.hxx>
+#include <htmltbl.hxx>
+#include <txttxmrk.hxx>
+#include <fmtline.hxx>
+#include <fmtruby.hxx>
+#include <breakit.hxx>
+#include <txtatr.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtrowsplt.hxx>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <com/sun/star/i18n/WordType.hpp>
+
+#include <writerfilter/doctok/sprmids.hxx>
+
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include <numrule.hxx>
+#include "wrtww8.hxx"
+#include "ww8par.hxx"
+#include <IMark.hxx>
+#include "ww8attributeoutput.hxx"
+
+#include <ndgrf.hxx>
+#include <ndole.hxx>
+
+#include <cstdio>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::i18n;
+using namespace sw::util;
+using namespace sw::types;
+using namespace sw::mark;
+using namespace nsFieldFlags;
+
+static String lcl_getFieldCode( const IFieldmark* pFieldmark ) {
+ OSL_ENSURE(pFieldmark!=NULL, "where is my fieldmark???");
+
+ if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMTEXT ) ) ) {
+ return String::CreateFromAscii(" FORMTEXT ");
+ } else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMDROPDOWN ) ) ) {
+ return String::CreateFromAscii(" FORMDROPDOWN ");
+ } else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) ) ) {
+ return String::CreateFromAscii(" FORMCHECKBOX ");
+ } else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_TOC ) ) ) {
+ return String::CreateFromAscii(" TOC ");
+ } else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_HYPERLINK ) ) ) {
+ return String::CreateFromAscii(" HYPERLINK ");
+ } else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_PAGEREF ) ) ) {
+ return String::CreateFromAscii(" PAGEREF ");
+ } else {
+ return pFieldmark->GetFieldname();
+ }
+}
+
+ww::eField lcl_getFieldId( const IFieldmark* pFieldmark ) {
+ OSL_ENSURE(pFieldmark!=NULL, "where is my fieldmark???");
+ if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMTEXT ) ) ) {
+ return ww::eFORMTEXT;
+ } else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMDROPDOWN ) ) ) {
+ return ww::eFORMDROPDOWN;
+ } else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) ) ) {
+ return ww::eFORMCHECKBOX;
+ } else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_TOC ) ) ) {
+ return ww::eTOC;
+ } else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_HYPERLINK ) ) ) {
+ return ww::eHYPERLINK;
+ } else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_PAGEREF ) ) ) {
+ return ww::ePAGEREF;
+ } else {
+ return ww::eUNKNOWN;
+ }
+}
+
+/* */
+
+MSWordAttrIter::MSWordAttrIter( MSWordExportBase& rExport )
+ : pOld( rExport.pChpIter ), m_rExport( rExport )
+{
+ m_rExport.pChpIter = this;
+}
+
+MSWordAttrIter::~MSWordAttrIter()
+{
+ m_rExport.pChpIter = pOld;
+}
+
+class sortswflys :
+ public std::binary_function<const sw::Frame&, const sw::Frame&, bool>
+{
+public:
+ bool operator()(const sw::Frame &rOne, const sw::Frame &rTwo) const
+ {
+ return rOne.GetPosition() < rTwo.GetPosition();
+ }
+};
+
+void SwWW8AttrIter::IterToCurrent()
+{
+ OSL_ENSURE(maCharRuns.begin() != maCharRuns.end(), "Impossible");
+ mnScript = maCharRunIter->mnScript;
+ meChrSet = maCharRunIter->meCharSet;
+ mbCharIsRTL = maCharRunIter->mbRTL;
+}
+
+SwWW8AttrIter::SwWW8AttrIter(MSWordExportBase& rWr, const SwTxtNode& rTxtNd) :
+ MSWordAttrIter(rWr),
+ rNd(rTxtNd),
+ maCharRuns(GetPseudoCharRuns(rTxtNd, 0, !rWr.SupportsUnicode())),
+ pCurRedline(0),
+ nAktSwPos(0),
+ nCurRedlinePos(USHRT_MAX),
+ mrSwFmtDrop(rTxtNd.GetSwAttrSet().GetDrop())
+{
+
+ SwPosition aPos(rTxtNd);
+ if (FRMDIR_HORI_RIGHT_TOP == rWr.pDoc->GetTextDirection(aPos))
+ mbParaIsRTL = true;
+ else
+ mbParaIsRTL = false;
+
+ maCharRunIter = maCharRuns.begin();
+ IterToCurrent();
+
+ /*
+ #i2916#
+ Get list of any graphics which may be anchored from this paragraph.
+ */
+ maFlyFrms = GetFramesInNode(rWr.maFrames, rNd);
+ std::sort(maFlyFrms.begin(), maFlyFrms.end(), sortswflys());
+
+ /*
+ #i18480#
+ If we are inside a frame then anything anchored inside this frame can
+ only be supported by word anchored inline ("as character"), so force
+ this in the supportable case.
+ */
+ if (rWr.SupportsUnicode() && rWr.bInWriteEscher)
+ {
+ std::for_each(maFlyFrms.begin(), maFlyFrms.end(),
+ std::mem_fun_ref(&sw::Frame::ForceTreatAsInline));
+ }
+
+ maFlyIter = maFlyFrms.begin();
+
+ if ( m_rExport.pDoc->GetRedlineTbl().Count() )
+ {
+ SwPosition aPosition( rNd, SwIndex( (SwTxtNode*)&rNd ) );
+ pCurRedline = m_rExport.pDoc->GetRedline( aPosition, &nCurRedlinePos );
+ }
+
+ nAktSwPos = SearchNext(1);
+}
+
+xub_StrLen lcl_getMinPos( xub_StrLen pos1, xub_StrLen pos2 )
+{
+ xub_StrLen min = STRING_NOTFOUND;
+ if ( pos1 == STRING_NOTFOUND && pos2 != STRING_NOTFOUND )
+ min = pos2;
+ else if ( pos2 == STRING_NOTFOUND && pos1 != STRING_NOTFOUND )
+ min = pos1;
+ else if ( pos2 != STRING_NOTFOUND && pos2 != STRING_NOTFOUND )
+ {
+ if ( pos1 < pos2 )
+ min = pos1;
+ else
+ min = pos2;
+ }
+
+ return min;
+}
+
+xub_StrLen SwWW8AttrIter::SearchNext( xub_StrLen nStartPos )
+{
+ xub_StrLen nPos;
+ xub_StrLen nMinPos = STRING_MAXLEN;
+ xub_StrLen i=0;
+
+ const String aTxt = rNd.GetTxt();
+ xub_StrLen fieldEndPos = aTxt.Search(CH_TXT_ATR_FIELDEND, nStartPos);
+ xub_StrLen fieldStartPos = aTxt.Search(CH_TXT_ATR_FIELDSTART, nStartPos);
+ xub_StrLen formElementPos = aTxt.Search(CH_TXT_ATR_FORMELEMENT, nStartPos);
+
+ xub_StrLen pos = lcl_getMinPos( fieldEndPos, fieldStartPos );
+ pos = lcl_getMinPos( pos, formElementPos );
+
+ if (pos!=STRING_NOTFOUND)
+ nMinPos=pos;
+
+ // first the redline, then the attributes
+ if( pCurRedline )
+ {
+ const SwPosition* pEnd = pCurRedline->End();
+ if (pEnd->nNode == rNd && ((i = pEnd->nContent.GetIndex()) >= nStartPos) && i < nMinPos )
+ nMinPos = i;
+ }
+
+ if ( nCurRedlinePos < m_rExport.pDoc->GetRedlineTbl().Count() )
+ {
+ // nCurRedlinePos point to the next redline
+ nPos = nCurRedlinePos;
+ if( pCurRedline )
+ ++nPos;
+
+ for ( ; nPos < m_rExport.pDoc->GetRedlineTbl().Count(); ++nPos )
+ {
+ const SwRedline* pRedl = m_rExport.pDoc->GetRedlineTbl()[ nPos ];
+
+ const SwPosition* pStt = pRedl->Start();
+ const SwPosition* pEnd = pStt == pRedl->GetPoint()
+ ? pRedl->GetMark()
+ : pRedl->GetPoint();
+
+ if( pStt->nNode == rNd )
+ {
+ if( ( i = pStt->nContent.GetIndex() ) >= nStartPos &&
+ i < nMinPos )
+ nMinPos = i;
+ }
+ else
+ break;
+
+ if( pEnd->nNode == rNd &&
+ ( i = pEnd->nContent.GetIndex() ) < nMinPos &&
+ i >= nStartPos )
+ nMinPos = i;
+ }
+ }
+
+
+ if (mrSwFmtDrop.GetWholeWord() && nStartPos <= rNd.GetDropLen(0))
+ nMinPos = rNd.GetDropLen(0);
+ else if(nStartPos <= mrSwFmtDrop.GetChars())
+ nMinPos = mrSwFmtDrop.GetChars();
+
+ if(const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
+ {
+
+// kann noch optimiert werden, wenn ausgenutzt wird, dass die TxtAttrs
+// nach der Anfangsposition geordnet sind. Dann muessten
+// allerdings noch 2 Indices gemerkt werden
+ for( i = 0; i < pTxtAttrs->Count(); i++ )
+ {
+ const SwTxtAttr* pHt = (*pTxtAttrs)[i];
+ nPos = *pHt->GetStart(); // gibt erstes Attr-Zeichen
+ if( nPos >= nStartPos && nPos <= nMinPos )
+ nMinPos = nPos;
+
+ if( pHt->GetEnd() ) // Attr mit Ende
+ {
+ nPos = *pHt->GetEnd(); // gibt letztes Attr-Zeichen + 1
+ if( nPos >= nStartPos && nPos <= nMinPos )
+ nMinPos = nPos;
+ }
+ if (pHt->HasDummyChar())
+ {
+ // pos + 1 because of CH_TXTATR in Text
+ nPos = *pHt->GetStart() + 1;
+ if( nPos >= nStartPos && nPos <= nMinPos )
+ nMinPos = nPos;
+ }
+ }
+ }
+
+ if (maCharRunIter != maCharRuns.end())
+ {
+ if (maCharRunIter->mnEndPos < nMinPos)
+ nMinPos = maCharRunIter->mnEndPos;
+ IterToCurrent();
+ }
+
+ /*
+ #i2916#
+ Check to see if there are any graphics anchored to characters in this
+ paragraph's text. Set nMinPos to 1 past the placement for anchored to
+ character because anchors in Word appear after the character they are
+ anchored to.
+ */
+ if (maFlyIter != maFlyFrms.end())
+ {
+ const SwPosition &rAnchor = maFlyIter->GetPosition();
+
+ nPos = rAnchor.nContent.GetIndex();
+ if (nPos >= nStartPos && nPos <= nMinPos)
+ nMinPos = nPos;
+
+ if (maFlyIter->GetFrmFmt().GetAnchor().GetAnchorId() == FLY_AT_CHAR)
+ {
+ ++nPos;
+ if (nPos >= nStartPos && nPos <= nMinPos)
+ nMinPos = nPos;
+ }
+ }
+
+ //nMinPos found and not going to change at this point
+
+ if (maCharRunIter != maCharRuns.end())
+ {
+ if (maCharRunIter->mnEndPos == nMinPos)
+ ++maCharRunIter;
+ }
+
+ return nMinPos;
+}
+
+bool lcl_isFontsizeItem( const SfxPoolItem& rItem )
+{
+ return ( rItem.Which( ) == RES_CHRATR_FONTSIZE ||
+ rItem.Which( ) == RES_CHRATR_CJK_FONTSIZE ||
+ rItem.Which( ) == RES_CHRATR_CTL_FONTSIZE );
+}
+
+void SwWW8AttrIter::OutAttr( xub_StrLen nSwPos, bool bRuby )
+{
+ m_rExport.AttrOutput().RTLAndCJKState( IsCharRTL(), GetScript() );
+
+ /*
+ Depending on whether text is in CTL/CJK or Western, get the id of that
+ script, the idea is that the font that is actually in use to render this
+ range of text ends up in pFont
+ */
+ sal_uInt16 nFontId = GetWhichOfScript( RES_CHRATR_FONT, GetScript() );
+
+ const SvxFontItem &rParentFont = ItemGet<SvxFontItem>(
+ (const SwTxtFmtColl&)rNd.GetAnyFmtColl(), nFontId);
+ const SvxFontItem *pFont = &rParentFont;
+
+ SfxItemSet aExportSet(*rNd.GetSwAttrSet().GetPool(),
+ RES_CHRATR_BEGIN, RES_TXTATR_END - 1);
+
+ //The hard formatting properties that affect the entire paragraph
+ if (rNd.HasSwAttrSet())
+ {
+ sal_Bool bDeep = sal_False;
+ // only copy hard attributes - bDeep = false
+ aExportSet.Set(rNd.GetSwAttrSet(), bDeep);
+ // get the current font item. Use rNd.GetSwAttrSet instead of aExportSet:
+ const SvxFontItem &rNdFont = ItemGet<SvxFontItem>(rNd.GetSwAttrSet(), nFontId);
+ pFont = &rNdFont;
+ aExportSet.ClearItem(nFontId);
+ }
+
+ //The additional hard formatting properties that affect this range in the
+ //paragraph
+ sw::PoolItems aRangeItems;
+ if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
+ {
+ for (xub_StrLen i = 0; i < pTxtAttrs->Count(); ++i)
+ {
+ const SwTxtAttr* pHt = (*pTxtAttrs)[i];
+ const xub_StrLen* pEnd = pHt->GetEnd();
+
+ if (pEnd ? ( nSwPos >= *pHt->GetStart() && nSwPos < *pEnd)
+ : nSwPos == *pHt->GetStart() )
+ {
+ sal_uInt16 nWhich = pHt->GetAttr().Which();
+ if (nWhich == nFontId)
+ pFont = &(item_cast<SvxFontItem>(pHt->GetAttr()));
+ else if( nWhich == RES_TXTATR_AUTOFMT )
+ {
+ const SwFmtAutoFmt& rAutoFmt = static_cast<const SwFmtAutoFmt&>(pHt->GetAttr());
+ const boost::shared_ptr<SfxItemSet> pSet = rAutoFmt.GetStyleHandle();
+ SfxWhichIter aIter( *pSet );
+ const SfxPoolItem* pItem;
+ sal_uInt16 nWhichId = aIter.FirstWhich();
+ while( nWhichId )
+ {
+ if( SFX_ITEM_SET == pSet->GetItemState( nWhichId, sal_False, &pItem ))
+ {
+ if (nWhichId == nFontId)
+ pFont = &(item_cast<SvxFontItem>(*pItem));
+ else
+ aRangeItems[nWhichId] = pItem;
+ }
+ nWhichId = aIter.NextWhich();
+ }
+ }
+ else
+ aRangeItems[nWhich] = (&(pHt->GetAttr()));
+ }
+ else if (nSwPos < *pHt->GetStart())
+ break;
+ }
+ }
+
+ /*
+ For #i24291# we need to explictly remove any properties from the
+ aExportSet which a SwCharFmt would override, we can't rely on word doing
+ this for us like writer does
+ */
+ const SwFmtCharFmt *pCharFmtItem =
+ HasItem< SwFmtCharFmt >( aRangeItems, RES_TXTATR_CHARFMT );
+ if ( pCharFmtItem )
+ ClearOverridesFromSet( *pCharFmtItem, aExportSet );
+
+ sw::PoolItems aExportItems;
+ GetPoolItems( aExportSet, aExportItems, false );
+
+ sw::cPoolItemIter aEnd = aRangeItems.end();
+ for ( sw::cPoolItemIter aI = aRangeItems.begin(); aI != aEnd; ++aI )
+ {
+ if ( !bRuby || !lcl_isFontsizeItem( *aI->second ) )
+ aExportItems[aI->first] = aI->second;
+ }
+
+ if ( !aExportItems.empty() )
+ {
+ const SwModify* pOldMod = m_rExport.pOutFmtNode;
+ m_rExport.pOutFmtNode = &rNd;
+ m_rExport.m_aCurrentCharPropStarts.push( nSwPos );
+
+ m_rExport.ExportPoolItemsToCHP( aExportItems, GetScript() );
+
+ // HasTextItem nur in dem obigen Bereich erlaubt
+ m_rExport.m_aCurrentCharPropStarts.pop();
+ m_rExport.pOutFmtNode = pOldMod;
+ }
+
+ OSL_ENSURE( pFont, "must be *some* font associated with this txtnode" );
+ if ( pFont )
+ {
+ SvxFontItem aFont( *pFont );
+
+ /*
+ If we are a nonunicode aware format then we set the charset we want to
+ use for export of this range. If necessary this will generate a pseudo
+ font to use for this range.
+
+ So now we are guaranteed to have a font with the correct charset set
+ for WW6/95 which will match the script we have exported this range in,
+ this makes older nonunicode aware versions of word display the correct
+ characters.
+ */
+ if ( !m_rExport.SupportsUnicode() )
+ aFont.SetCharSet( GetCharSet() );
+
+ if ( rParentFont != aFont )
+ m_rExport.AttrOutput().OutputItem( aFont );
+ }
+}
+
+void SwWW8AttrIter::OutFlys(xub_StrLen nSwPos)
+{
+ /*
+ #i2916#
+ May have an anchored graphic to be placed, loop through sorted array
+ and output all at this position
+ */
+ while ( maFlyIter != maFlyFrms.end() )
+ {
+ const SwPosition &rAnchor = maFlyIter->GetPosition();
+ xub_StrLen nPos = rAnchor.nContent.GetIndex();
+
+ if ( nPos != nSwPos )
+ break;
+ else
+ {
+ m_rExport.AttrOutput().OutputFlyFrame( *maFlyIter );
+ ++maFlyIter;
+ }
+ }
+}
+
+bool SwWW8AttrIter::IsTxtAttr( xub_StrLen nSwPos )
+{
+ // search for attrs with CH_TXTATR
+ if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
+ {
+ for (sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i)
+ {
+ const SwTxtAttr* pHt = (*pTxtAttrs)[i];
+ if ( pHt->HasDummyChar() && (*pHt->GetStart() == nSwPos) )
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool SwWW8AttrIter::IsDropCap( int nSwPos )
+{
+ // see if the current position falls on a DropCap
+ int nDropChars = mrSwFmtDrop.GetChars();
+ bool bWholeWord = mrSwFmtDrop.GetWholeWord();
+ if (bWholeWord)
+ {
+ short nWordLen = rNd.GetDropLen(0);
+ if(nSwPos == nWordLen && nSwPos != 0)
+ return true;
+ }
+ else
+ {
+ if (nSwPos == nDropChars && nSwPos != 0)
+ return true;
+ }
+ return false;
+}
+
+bool SwWW8AttrIter::RequiresImplicitBookmark()
+{
+ SwImplBookmarksIter bkmkIterEnd = m_rExport.maImplicitBookmarks.end();
+ for ( SwImplBookmarksIter aIter = m_rExport.maImplicitBookmarks.begin(); aIter != bkmkIterEnd; ++aIter )
+ {
+ sal_uLong sample = aIter->second;
+
+ if ( sample == rNd.GetIndex() )
+ return true;
+ }
+ return false;
+}
+
+// HasItem ist fuer die Zusammenfassung des Doppel-Attributes Underline
+// und WordLineMode als TextItems. OutAttr() ruft die Ausgabefunktion,
+// die dann ueber HasItem() nach anderen Items an der
+// Attribut-Anfangposition fragen kann.
+// Es koennen nur Attribute mit Ende abgefragt werden.
+// Es wird mit bDeep gesucht
+const SfxPoolItem* SwWW8AttrIter::HasTextItem( sal_uInt16 nWhich ) const
+{
+ const SfxPoolItem* pRet = 0;
+ const SwpHints* pTxtAttrs = rNd.GetpSwpHints();
+
+ if (pTxtAttrs && m_rExport.m_aCurrentCharPropStarts.size())
+ {
+ xub_StrLen nTmpSwPos = m_rExport.m_aCurrentCharPropStarts.top();
+ for (sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i)
+ {
+ const SwTxtAttr* pHt = (*pTxtAttrs)[i];
+ const SfxPoolItem* pItem = &pHt->GetAttr();
+ const xub_StrLen* pAtrEnd = 0;
+ if( 0 != ( pAtrEnd = pHt->GetEnd() ) && // nur Attr mit Ende
+ nWhich == pItem->Which() && //
+ nTmpSwPos >= *pHt->GetStart() && nTmpSwPos < *pAtrEnd )
+ {
+ pRet = pItem; // gefunden
+ break;
+ }
+ else if (nTmpSwPos < *pHt->GetStart())
+ break; // dann kommt da nichts mehr
+ }
+ }
+ return pRet;
+}
+
+void WW8Export::GetCurrentItems(WW8Bytes& rItems) const
+{
+ sal_uInt16 nEnd = pO ? pO->Count() : 0;
+ for (sal_uInt16 nI = 0; nI < nEnd; ++nI)
+ rItems.Insert((*pO)[nI], rItems.Count());
+}
+
+const SfxPoolItem& SwWW8AttrIter::GetItem(sal_uInt16 nWhich) const
+{
+ const SfxPoolItem* pRet = HasTextItem(nWhich);
+ return pRet ? *pRet : rNd.SwCntntNode::GetAttr(nWhich);
+}
+
+void WW8AttributeOutput::StartRuby( const SwTxtNode& rNode, xub_StrLen /*nPos*/, const SwFmtRuby& rRuby )
+{
+ String aStr( FieldString( ww::eEQ ) );
+ aStr.APPEND_CONST_ASC( "\\* jc" );
+ sal_Int32 nJC = 0;
+ sal_Char cDirective = 0;
+ switch ( rRuby.GetAdjustment() )
+ {
+ case 0:
+ nJC = 3;
+ cDirective = 'l';
+ break;
+ case 1:
+ //defaults to 0
+ break;
+ case 2:
+ nJC = 4;
+ cDirective = 'r';
+ break;
+ case 3:
+ nJC = 1;
+ cDirective = 'd';
+ break;
+ case 4:
+ nJC = 2;
+ cDirective = 'd';
+ break;
+ default:
+ OSL_ENSURE( !this,"Unhandled Ruby justication code" );
+ break;
+ }
+ aStr += String::CreateFromInt32( nJC );
+
+ /*
+ MS needs to know the name and size of the font used in the ruby item,
+ but we coud have written it in a mixture of asian and western
+ scripts, and each of these can be a different font and size than the
+ other, so we make a guess based upon the first character of the text,
+ defaulting to asian.
+ */
+ sal_uInt16 nRubyScript;
+ if( pBreakIt->GetBreakIter().is() )
+ nRubyScript = pBreakIt->GetBreakIter()->getScriptType( rRuby.GetText(), 0);
+ else
+ nRubyScript = i18n::ScriptType::ASIAN;
+
+ const SwTxtRuby* pRubyTxt = rRuby.GetTxtRuby();
+ const SwCharFmt* pFmt = pRubyTxt ? pRubyTxt->GetCharFmt() : 0;
+ String sFamilyName;
+ long nHeight;
+ if ( pFmt )
+ {
+ const SvxFontItem &rFont = ItemGet< SvxFontItem >( *pFmt,
+ GetWhichOfScript(RES_CHRATR_FONT,nRubyScript) );
+ sFamilyName = rFont.GetFamilyName();
+
+ const SvxFontHeightItem &rHeight = ItemGet< SvxFontHeightItem >( *pFmt,
+ GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) );
+ nHeight = rHeight.GetHeight();
+ }
+ else
+ {
+ /*Get defaults if no formatting on ruby text*/
+
+ const SfxItemPool *pPool = rNode.GetSwAttrSet().GetPool();
+ pPool = pPool ? pPool : &m_rWW8Export.pDoc->GetAttrPool();
+
+ const SvxFontItem &rFont = DefaultItemGet< SvxFontItem >( *pPool,
+ GetWhichOfScript( RES_CHRATR_FONT,nRubyScript ) );
+ sFamilyName = rFont.GetFamilyName();
+
+ const SvxFontHeightItem &rHeight = DefaultItemGet< SvxFontHeightItem >
+ ( *pPool, GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) );
+ nHeight = rHeight.GetHeight();
+ }
+ nHeight = (nHeight + 5)/10;
+
+ aStr.APPEND_CONST_ASC( " \\* \"Font:" );
+ aStr.Append( sFamilyName );
+ aStr.APPEND_CONST_ASC( "\" \\* hps" );
+ aStr += String::CreateFromInt32( nHeight );
+ aStr.APPEND_CONST_ASC( " \\o" );
+ if ( cDirective )
+ {
+ aStr.APPEND_CONST_ASC( "\\a" );
+ aStr.Append( cDirective );
+ }
+ aStr.APPEND_CONST_ASC( "(\\s\\up " );
+
+
+ if ( pBreakIt->GetBreakIter().is() )
+ nRubyScript = pBreakIt->GetBreakIter()->getScriptType( rNode.GetTxt(),
+ *( pRubyTxt->GetStart() ) );
+ else
+ nRubyScript = i18n::ScriptType::ASIAN;
+
+ const SwAttrSet& rSet = rNode.GetSwAttrSet();
+ const SvxFontHeightItem &rHeightItem =
+ ( const SvxFontHeightItem& )rSet.Get(
+ GetWhichOfScript( RES_CHRATR_FONTSIZE, nRubyScript ) );
+ nHeight = (rHeightItem.GetHeight() + 10)/20-1;
+ aStr += String::CreateFromInt32(nHeight);
+ aStr += '(';
+ aStr += rRuby.GetText();
+ aStr.APPEND_CONST_ASC( ")" );
+
+ // The parameter separator depends on the FIB.lid
+ if ( m_rWW8Export.pFib->getNumDecimalSep() == '.' )
+ aStr.APPEND_CONST_ASC( "," );
+ else
+ aStr.APPEND_CONST_ASC( ";" );
+
+ m_rWW8Export.OutputField( 0, ww::eEQ, aStr,
+ WRITEFIELD_START | WRITEFIELD_CMD_START );
+}
+
+void WW8AttributeOutput::EndRuby()
+{
+ m_rWW8Export.WriteChar( ')' );
+ m_rWW8Export.OutputField( 0, ww::eEQ, aEmptyStr, WRITEFIELD_END | WRITEFIELD_CLOSE );
+}
+
+/*#i15387# Better ideas welcome*/
+String &TruncateBookmark( String &rRet )
+{
+ if ( rRet.Len() > 40 )
+ rRet.Erase( 40 );
+ OSL_ENSURE( rRet.Len() <= 40, "Word cannot have bookmarks longer than 40 chars" );
+ return rRet;
+}
+
+bool AttributeOutputBase::AnalyzeURL( const String& rUrl, const String& /*rTarget*/, String* pLinkURL, String* pMark )
+{
+ bool bBookMarkOnly = false;
+
+ INetURLObject aURL( rUrl );
+ String sMark;
+ String sURL;
+
+ if ( rUrl.Len() > 1 && rUrl.GetChar(0) == INET_MARK_TOKEN )
+ {
+ sMark = BookmarkToWriter( rUrl.Copy(1) );
+
+ xub_StrLen nPos = sMark.SearchBackward( cMarkSeperator );
+
+ String sRefType( sMark.Copy( nPos+1 ) );
+ sRefType.EraseAllChars();
+
+ // i21465 Only interested in outline references
+ if ( sRefType.EqualsAscii( pMarkToOutline ) )
+ {
+ String sLink = sMark.Copy(0, nPos);
+ SwImplBookmarksIter bkmkIterEnd = GetExport().maImplicitBookmarks.end();
+ for ( SwImplBookmarksIter aIter = GetExport().maImplicitBookmarks.begin(); aIter != bkmkIterEnd; ++aIter )
+ {
+ String bkmkName = aIter->first;
+
+ if ( bkmkName == sLink )
+ {
+ sMark = String( RTL_CONSTASCII_USTRINGPARAM( "_toc" ) );
+ sMark += String::CreateFromInt32( aIter->second );
+ }
+ }
+ }
+ }
+ else
+ {
+ sURL = aURL.GetURLNoMark( INetURLObject::DECODE_UNAMBIGUOUS );
+ sMark = aURL.GetMark( INetURLObject::DECODE_UNAMBIGUOUS );
+
+ }
+
+ if ( sMark.Len() && !sURL.Len() )
+ bBookMarkOnly = true;
+
+
+
+ *pMark = sMark;
+ *pLinkURL = sURL;
+ return bBookMarkOnly;
+}
+
+bool WW8AttributeOutput::AnalyzeURL( const String& rUrl, const String& rTarget, String* pLinkURL, String* pMark )
+{
+ bool bBookMarkOnly = AttributeOutputBase::AnalyzeURL( rUrl, rTarget, pLinkURL, pMark );
+
+ String sURL = *pLinkURL;
+ String sMark = *pMark;
+
+ if ( sURL.Len() )
+ sURL = URIHelper::simpleNormalizedMakeRelative( m_rWW8Export.GetWriter().GetBaseURL(), sURL );
+
+ if ( bBookMarkOnly )
+ sURL = FieldString( ww::eHYPERLINK );
+ else
+ {
+ String sFld( FieldString( ww::eHYPERLINK ) );
+ sFld.APPEND_CONST_ASC( "\"" );
+ sURL.Insert( sFld, 0 );
+ sURL += '\"';
+ }
+
+ if ( sMark.Len() )
+ ( ( sURL.APPEND_CONST_ASC( " \\l \"" ) ) += sMark ) += '\"';
+
+ if ( rTarget.Len() )
+ ( sURL.APPEND_CONST_ASC( " \\n " ) ) += rTarget;
+
+ *pLinkURL = sURL;
+ *pMark = sMark;
+
+ return bBookMarkOnly;
+}
+
+bool WW8AttributeOutput::StartURL( const String &rUrl, const String &rTarget )
+{
+ // hyperlinks only in WW8
+ if ( !m_rWW8Export.bWrtWW8 )
+ return false;
+
+ INetURLObject aURL( rUrl );
+ String sURL;
+ String sMark;
+
+ bool bBookMarkOnly = AnalyzeURL( rUrl, rTarget, &sURL, &sMark );
+
+
+ m_rWW8Export.OutputField( 0, ww::eHYPERLINK, sURL, WRITEFIELD_START | WRITEFIELD_CMD_START );
+
+ // write the refence to the "picture" structure
+ sal_uLong nDataStt = m_rWW8Export.pDataStrm->Tell();
+ m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell() );
+
+// WinWord 2000 doesn't write this - so its a temp solution by W97 ?
+ m_rWW8Export.WriteChar( 0x01 );
+
+ static sal_uInt8 aArr1[] = {
+ 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
+
+ 0x06, 0x08, 0x01, // sprmCFData
+ 0x55, 0x08, 0x01, // sprmCFSpec
+ 0x02, 0x08, 0x01 // sprmCFFldVanish
+ };
+ sal_uInt8* pDataAdr = aArr1 + 2;
+ Set_UInt32( pDataAdr, nDataStt );
+
+ m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), sizeof( aArr1 ), aArr1 );
+
+ m_rWW8Export.OutputField( 0, ww::eHYPERLINK, sURL, WRITEFIELD_CMD_END );
+
+ // now write the picture structur
+ sURL = aURL.GetURLNoMark();
+
+ //all links end up in the data stream as absolute references.
+ bool bAbsolute = !bBookMarkOnly;
+
+ static sal_uInt8 aURLData1[] = {
+ 0,0,0,0, // len of struct
+ 0x44,0, // the start of "next" data
+ 0,0,0,0,0,0,0,0,0,0, // PIC-Structure!
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // |
+ 0,0,0,0, // /
+ };
+ static sal_uInt8 MAGIC_A[] = {
+ // start of "next" data
+ 0xD0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
+ 0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
+ };
+
+ m_rWW8Export.pDataStrm->Write( aURLData1, sizeof( aURLData1 ) );
+ sal_uInt8 nAnchor = 0x00;
+ if ( sMark.Len() )
+ nAnchor = 0x08;
+ m_rWW8Export.pDataStrm->Write( &nAnchor, 1 );
+ m_rWW8Export.pDataStrm->Write( MAGIC_A, sizeof(MAGIC_A) );
+ SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 0x00000002);
+ sal_uInt32 nFlag = bBookMarkOnly ? 0 : 0x01;
+ if ( bAbsolute )
+ nFlag |= 0x02;
+ if ( sMark.Len() )
+ nFlag |= 0x08;
+ SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, nFlag );
+
+ INetProtocol eProto = aURL.GetProtocol();
+ if ( eProto == INET_PROT_FILE || eProto == INET_PROT_SMB )
+ {
+ // version 1 (for a document)
+
+ static sal_uInt8 MAGIC_C[] = {
+ 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46,
+ 0x00, 0x00
+ };
+
+ static sal_uInt8 MAGIC_D[] = {
+ 0xFF, 0xFF, 0xAD, 0xDE, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+
+ // save the links to files as relative
+ sURL = URIHelper::simpleNormalizedMakeRelative( m_rWW8Export.GetWriter().GetBaseURL(), sURL );
+ if ( eProto == INET_PROT_FILE && sURL.EqualsAscii( "/", 0, 1 ) )
+ sURL = aURL.PathToFileName();
+
+ // special case for the absolute windows names
+ // (convert '/c:/foo/bar.doc' into 'c:\foo\bar.doc')
+ sal_Unicode aDrive = ( sURL.Len() > 1 )? sURL.GetChar( 1 ): 0;
+ if ( sURL.EqualsAscii( "/", 0, 1 ) &&
+ ( ( aDrive >= 'A' && aDrive <= 'Z' ) || ( aDrive >= 'a' && aDrive <= 'z' ) ) &&
+ sURL.EqualsAscii( ":", 2, 1 ) )
+ {
+ sURL.Erase( 0, 1 );
+ sURL.SearchAndReplaceAll( '/', '\\' );
+ }
+
+ // n#261623 convert smb notation to '\\'
+ const char pSmb[] = "smb://";
+ if ( eProto == INET_PROT_SMB &&
+ sURL.EqualsAscii( pSmb, 0, sizeof( pSmb ) - 1 ) )
+ {
+ sURL.Erase( 0, sizeof( pSmb ) - 3 );
+ sURL.SearchAndReplaceAll( '/', '\\' );
+ }
+
+ m_rWW8Export.pDataStrm->Write( MAGIC_C, sizeof(MAGIC_C) );
+ SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sURL.Len()+1 );
+ SwWW8Writer::WriteString8( *m_rWW8Export.pDataStrm, sURL, true,
+ RTL_TEXTENCODING_MS_1252 );
+ m_rWW8Export.pDataStrm->Write( MAGIC_D, sizeof( MAGIC_D ) );
+
+ SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.Len() + 6 );
+ SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2*sURL.Len() );
+ SwWW8Writer::WriteShort( *m_rWW8Export.pDataStrm, 3 );
+ SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sURL, false );
+ }
+ else if ( eProto != INET_PROT_NOT_VALID )
+ {
+ // version 2 (simple url)
+ // an write some data to the data stream, but dont ask
+ // what the data mean, except for the URL.
+ // The First piece is the WW8_PIC structure.
+ //
+ static sal_uInt8 MAGIC_B[] = {
+ 0xE0,0xC9,0xEA,0x79,0xF9,0xBA,0xCE,0x11,
+ 0x8C,0x82,0x00,0xAA,0x00,0x4B,0xA9,0x0B
+ };
+
+ m_rWW8Export.pDataStrm->Write( MAGIC_B, sizeof(MAGIC_B) );
+ SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, 2 * ( sURL.Len() + 1 ) );
+ SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sURL, true );
+ }
+
+ if ( sMark.Len() )
+ {
+ SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, sMark.Len()+1 );
+ SwWW8Writer::WriteString16( *m_rWW8Export.pDataStrm, sMark, true );
+ }
+ SwWW8Writer::WriteLong( *m_rWW8Export.pDataStrm, nDataStt,
+ m_rWW8Export.pDataStrm->Tell() - nDataStt );
+
+ return true;
+}
+
+bool WW8AttributeOutput::EndURL()
+{
+ // hyperlinks only in WW8
+ if ( !m_rWW8Export.bWrtWW8 )
+ return false;
+
+ m_rWW8Export.OutputField( 0, ww::eHYPERLINK, aEmptyStr, WRITEFIELD_CLOSE );
+
+ return true;
+}
+
+String BookmarkToWord(const String &rBookmark)
+{
+ String sRet(INetURLObject::encode(rBookmark,
+ INetURLObject::PART_REL_SEGMENT_EXTRA, '%',
+ INetURLObject::ENCODE_ALL, RTL_TEXTENCODING_ASCII_US));
+ return TruncateBookmark(sRet);
+}
+
+String BookmarkToWriter(const String &rBookmark)
+{
+ return INetURLObject::decode(rBookmark, '%',
+ INetURLObject::DECODE_UNAMBIGUOUS, RTL_TEXTENCODING_ASCII_US);
+}
+
+void SwWW8AttrIter::OutSwFmtRefMark(const SwFmtRefMark& rAttr, bool)
+{
+ if ( m_rExport.HasRefToObject( REF_SETREFATTR, &rAttr.GetRefName(), 0 ) )
+ m_rExport.AppendBookmark( m_rExport.GetBookmarkName( REF_SETREFATTR,
+ &rAttr.GetRefName(), 0 ));
+}
+
+void WW8AttributeOutput::FieldVanish( const String& rTxt, ww::eField /*eType*/ )
+{
+ WW8Bytes aItems;
+ m_rWW8Export.GetCurrentItems( aItems );
+
+ // sprmCFFldVanish
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFFldVanish );
+ else
+ aItems.Insert( 67, aItems.Count() );
+ aItems.Insert( 1, aItems.Count() );
+
+ sal_uInt16 nStt_sprmCFSpec = aItems.Count();
+
+ // sprmCFSpec -- fSpec-Attribut true
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( aItems, 0x855 );
+ else
+ aItems.Insert( 117, aItems.Count() );
+ aItems.Insert( 1, aItems.Count() );
+
+ m_rWW8Export.WriteChar( '\x13' );
+ m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.Count(),
+ aItems.GetData() );
+ m_rWW8Export.OutSwString( rTxt, 0, rTxt.Len(), m_rWW8Export.IsUnicode(),
+ RTL_TEXTENCODING_MS_1252 );
+ m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), nStt_sprmCFSpec,
+ aItems.GetData() );
+ m_rWW8Export.WriteChar( '\x15' );
+ m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), aItems.Count(),
+ aItems.GetData() );
+}
+
+void AttributeOutputBase::TOXMark( const SwTxtNode& rNode, const SwTOXMark& rAttr )
+{
+ // its a field; so get the Text form the Node and build the field
+ String sTxt;
+ ww::eField eType = ww::eNONE;
+
+ const SwTxtTOXMark& rTxtTOXMark = *rAttr.GetTxtTOXMark();
+ const xub_StrLen* pTxtEnd = rTxtTOXMark.GetEnd();
+ if ( pTxtEnd ) // has range?
+ {
+ sTxt = rNode.GetExpandTxt( *rTxtTOXMark.GetStart(),
+ *pTxtEnd - *rTxtTOXMark.GetStart() );
+ }
+ else
+ sTxt = rAttr.GetAlternativeText();
+
+ switch ( rAttr.GetTOXType()->GetType() )
+ {
+ case TOX_INDEX:
+ eType = ww::eXE;
+ if ( rAttr.GetPrimaryKey().Len() )
+ {
+ if ( rAttr.GetSecondaryKey().Len() )
+ {
+ sTxt.Insert( ':', 0 );
+ sTxt.Insert( rAttr.GetSecondaryKey(), 0 );
+ }
+
+ sTxt.Insert( ':', 0 );
+ sTxt.Insert( rAttr.GetPrimaryKey(), 0 );
+ }
+ sTxt.InsertAscii( " XE \"", 0 );
+ sTxt.InsertAscii( "\" " );
+ break;
+
+ case TOX_USER:
+ ( sTxt.APPEND_CONST_ASC( "\" \\f \"" ) )
+ += (sal_Char)( 'A' + GetExport( ).GetId( *rAttr.GetTOXType() ) );
+ // fall through - no break;
+ case TOX_CONTENT:
+ {
+ eType = ww::eTC;
+ sTxt.InsertAscii( " TC \"", 0 );
+ sal_uInt16 nLvl = rAttr.GetLevel();
+ if (nLvl > WW8ListManager::nMaxLevel)
+ nLvl = WW8ListManager::nMaxLevel;
+
+ ((sTxt.APPEND_CONST_ASC( "\" \\l " ))
+ += String::CreateFromInt32( nLvl )) += ' ';
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "Unhandled option for toc export" );
+ break;
+ }
+
+ if ( sTxt.Len() )
+ FieldVanish( sTxt, eType );
+}
+
+int SwWW8AttrIter::OutAttrWithRange(xub_StrLen nPos)
+{
+ int nRet = 0;
+ if ( const SwpHints* pTxtAttrs = rNd.GetpSwpHints() )
+ {
+ m_rExport.m_aCurrentCharPropStarts.push( nPos );
+ const xub_StrLen* pEnd;
+ for ( sal_uInt16 i = 0; i < pTxtAttrs->Count(); ++i )
+ {
+ const SwTxtAttr* pHt = (*pTxtAttrs)[i];
+ const SfxPoolItem* pItem = &pHt->GetAttr();
+ switch ( pItem->Which() )
+ {
+ case RES_TXTATR_INETFMT:
+ if ( nPos == *pHt->GetStart() )
+ {
+ const SwFmtINetFmt *rINet = static_cast< const SwFmtINetFmt* >( pItem );
+ if ( m_rExport.AttrOutput().StartURL( rINet->GetValue(), rINet->GetTargetFrame() ) )
+ ++nRet;
+ }
+ if ( 0 != ( pEnd = pHt->GetEnd() ) && nPos == *pEnd )
+ {
+ if ( m_rExport.AttrOutput().EndURL() )
+ --nRet;
+ }
+ break;
+ case RES_TXTATR_REFMARK:
+ if ( nPos == *pHt->GetStart() )
+ {
+ OutSwFmtRefMark( *static_cast< const SwFmtRefMark* >( pItem ), true );
+ ++nRet;
+ }
+ if ( 0 != ( pEnd = pHt->GetEnd() ) && nPos == *pEnd )
+ {
+ OutSwFmtRefMark( *static_cast< const SwFmtRefMark* >( pItem ), false );
+ --nRet;
+ }
+ break;
+ case RES_TXTATR_TOXMARK:
+ if ( nPos == *pHt->GetStart() )
+ m_rExport.AttrOutput().TOXMark( rNd, *static_cast< const SwTOXMark* >( pItem ) );
+ break;
+ case RES_TXTATR_CJK_RUBY:
+ if ( nPos == *pHt->GetStart() )
+ {
+ m_rExport.AttrOutput().StartRuby( rNd, nPos, *static_cast< const SwFmtRuby* >( pItem ) );
+ ++nRet;
+ }
+ if ( 0 != ( pEnd = pHt->GetEnd() ) && nPos == *pEnd )
+ {
+ m_rExport.AttrOutput().EndRuby();
+ --nRet;
+ }
+ break;
+ }
+ }
+ m_rExport.m_aCurrentCharPropStarts.pop(); // HasTextItem nur in dem obigen Bereich erlaubt
+ }
+ return nRet;
+}
+
+bool SwWW8AttrIter::IsRedlineAtEnd( xub_StrLen nEnd ) const
+{
+ bool bRet = false;
+ // search next Redline
+ for( sal_uInt16 nPos = nCurRedlinePos;
+ nPos < m_rExport.pDoc->GetRedlineTbl().Count(); ++nPos )
+ {
+ const SwPosition* pEnd = m_rExport.pDoc->GetRedlineTbl()[ nPos ]->End();
+ if( pEnd->nNode == rNd )
+ {
+ if( pEnd->nContent.GetIndex() == nEnd )
+ {
+ bRet = true;
+ break;
+ }
+ }
+ else
+ break;
+ }
+ return bRet;
+}
+
+const SwRedlineData* SwWW8AttrIter::GetRedline( xub_StrLen nPos )
+{
+ if( pCurRedline )
+ {
+ const SwPosition* pEnd = pCurRedline->End();
+ if( pEnd->nNode == rNd &&
+ pEnd->nContent.GetIndex() <= nPos )
+ {
+ pCurRedline = 0;
+ ++nCurRedlinePos;
+ }
+ else
+ {
+ // write data of current redline
+ return &( pCurRedline->GetRedlineData() );
+ }
+ }
+
+ if( !pCurRedline )
+ {
+ // search next Redline
+ for( ; nCurRedlinePos < m_rExport.pDoc->GetRedlineTbl().Count();
+ ++nCurRedlinePos )
+ {
+ const SwRedline* pRedl = m_rExport.pDoc->GetRedlineTbl()[ nCurRedlinePos ];
+
+ const SwPosition* pStt = pRedl->Start();
+ const SwPosition* pEnd = pStt == pRedl->GetPoint()
+ ? pRedl->GetMark()
+ : pRedl->GetPoint();
+
+ if( pStt->nNode == rNd )
+ {
+ if( pStt->nContent.GetIndex() >= nPos )
+ {
+ if( pStt->nContent.GetIndex() == nPos )
+ {
+ // write data of this redline
+ pCurRedline = pRedl;
+ return &( pCurRedline->GetRedlineData() );
+ }
+ break;
+ }
+ }
+ else
+ break;
+
+ if( pEnd->nNode == rNd &&
+ pEnd->nContent.GetIndex() < nPos )
+ {
+ pCurRedline = pRedl;
+ break;
+ }
+ }
+ }
+ return NULL;
+}
+
+/* */
+
+short MSWordExportBase::GetCurrentPageDirection() const
+{
+ const SwFrmFmt &rFmt = pAktPageDesc
+ ? pAktPageDesc->GetMaster()
+ : const_cast<const SwDoc *>( pDoc )->GetPageDesc( 0 ).GetMaster();
+ return rFmt.GetFrmDir().GetValue();
+}
+
+short MSWordExportBase::GetDefaultFrameDirection( ) const
+{
+ short nDir = FRMDIR_ENVIRONMENT;
+
+ if ( bOutPageDescs )
+ nDir = GetCurrentPageDirection( );
+ else if ( pOutFmtNode )
+ {
+ if ( bOutFlyFrmAttrs ) //frame
+ {
+ nDir = TrueFrameDirection( *( const SwFrmFmt * ) pOutFmtNode );
+ }
+ else if ( pOutFmtNode->ISA( SwCntntNode ) ) //pagagraph
+ {
+ const SwCntntNode *pNd = ( const SwCntntNode * ) pOutFmtNode;
+ SwPosition aPos( *pNd );
+ nDir = pDoc->GetTextDirection( aPos );
+ }
+ else if ( pOutFmtNode->ISA( SwTxtFmtColl ) )
+ nDir = FRMDIR_HORI_LEFT_TOP; //what else can we do :-(
+ }
+
+ if ( nDir == FRMDIR_ENVIRONMENT )
+ nDir = FRMDIR_HORI_LEFT_TOP; //Set something
+
+ return nDir;
+}
+
+short MSWordExportBase::TrueFrameDirection( const SwFrmFmt &rFlyFmt ) const
+{
+ const SwFrmFmt *pFlyFmt = &rFlyFmt;
+ const SvxFrameDirectionItem* pItem = 0;
+ while ( pFlyFmt )
+ {
+ pItem = &pFlyFmt->GetFrmDir();
+ if ( FRMDIR_ENVIRONMENT == pItem->GetValue() )
+ {
+ pItem = 0;
+ const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
+ if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
+ pAnchor->GetCntntAnchor() )
+ {
+ pFlyFmt = pAnchor->GetCntntAnchor()->nNode.GetNode().GetFlyFmt();
+ }
+ else
+ pFlyFmt = 0;
+ }
+ else
+ pFlyFmt = 0;
+ }
+
+ short nRet;
+ if ( pItem )
+ nRet = pItem->GetValue();
+ else
+ nRet = GetCurrentPageDirection();
+
+ OSL_ENSURE( nRet != FRMDIR_ENVIRONMENT, "leaving with environment direction" );
+ return nRet;
+}
+
+const SvxBrushItem* WW8Export::GetCurrentPageBgBrush() const
+{
+ const SwFrmFmt &rFmt = pAktPageDesc
+ ? pAktPageDesc->GetMaster()
+ : const_cast<const SwDoc *>(pDoc)->GetPageDesc(0).GetMaster();
+
+ const SfxPoolItem* pItem = 0;
+ //If not set, or "no fill", get real bg
+ SfxItemState eState = rFmt.GetItemState(RES_BACKGROUND, true, &pItem);
+
+ const SvxBrushItem* pRet = (const SvxBrushItem*)pItem;
+ if (SFX_ITEM_SET != eState || (!pRet->GetGraphic() &&
+ pRet->GetColor() == COL_TRANSPARENT))
+ {
+ pRet = &(DefaultItemGet<SvxBrushItem>(*pDoc,RES_BACKGROUND));
+ }
+ return pRet;
+}
+
+SvxBrushItem WW8Export::TrueFrameBgBrush(const SwFrmFmt &rFlyFmt) const
+{
+ const SwFrmFmt *pFlyFmt = &rFlyFmt;
+ const SvxBrushItem* pRet = 0;
+
+ while (pFlyFmt)
+ {
+ //If not set, or "no fill", get real bg
+ const SfxPoolItem* pItem = 0;
+ SfxItemState eState =
+ pFlyFmt->GetItemState(RES_BACKGROUND, true, &pItem);
+ pRet = (const SvxBrushItem*)pItem;
+ if (SFX_ITEM_SET != eState || (!pRet->GetGraphic() &&
+ pRet->GetColor() == COL_TRANSPARENT))
+ {
+ pRet = 0;
+ const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
+ if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
+ pAnchor->GetCntntAnchor())
+ {
+ pFlyFmt =
+ pAnchor->GetCntntAnchor()->nNode.GetNode().GetFlyFmt();
+ }
+ else
+ pFlyFmt = 0;
+ }
+ else
+ pFlyFmt = 0;
+ }
+
+ if (!pRet)
+ pRet = GetCurrentPageBgBrush();
+
+ const Color aTmpColor( COL_WHITE );
+ SvxBrushItem aRet( aTmpColor, RES_BACKGROUND );
+ if (pRet && (pRet->GetGraphic() ||( pRet->GetColor() != COL_TRANSPARENT)))
+ aRet = *pRet;
+
+ return aRet;
+}
+
+
+/*
+Convert characters that need to be converted, the basic replacements and the
+ridicously complicated title case attribute mapping to hardcoded upper case
+because word doesn't have the feature
+*/
+String SwWW8AttrIter::GetSnippet(const String &rStr, xub_StrLen nAktPos,
+ xub_StrLen nLen) const
+{
+ String aSnippet(rStr, nAktPos, nLen);
+ if (!nLen)
+ return aSnippet;
+
+ // 0x0a ( Hard Line Break ) -> 0x0b
+ // 0xad ( soft hyphen ) -> 0x1f
+ // 0x2011 ( hard hyphen ) -> 0x1e
+ aSnippet.SearchAndReplaceAll(0x0A, 0x0B);
+ aSnippet.SearchAndReplaceAll(CHAR_HARDHYPHEN, 0x1e);
+ aSnippet.SearchAndReplaceAll(CHAR_SOFTHYPHEN, 0x1f);
+
+ m_rExport.m_aCurrentCharPropStarts.push( nAktPos );
+ const SfxPoolItem &rItem = GetItem(RES_CHRATR_CASEMAP);
+
+ if (SVX_CASEMAP_TITEL == ((const SvxCaseMapItem&)rItem).GetValue())
+ {
+ sal_uInt16 nScriptType = i18n::ScriptType::LATIN;
+ if (pBreakIt->GetBreakIter().is())
+ nScriptType = pBreakIt->GetBreakIter()->getScriptType(aSnippet, 0);
+
+ LanguageType nLanguage;
+ switch (nScriptType)
+ {
+ case i18n::ScriptType::ASIAN:
+ nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_CJK_LANGUAGE)).GetLanguage();
+ break;
+ case i18n::ScriptType::COMPLEX:
+ nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_CTL_LANGUAGE)).GetLanguage();
+ break;
+ case i18n::ScriptType::LATIN:
+ default:
+ nLanguage = ((const SvxLanguageItem&)GetItem(RES_CHRATR_LANGUAGE)).GetLanguage();
+ break;
+ }
+
+ SvxFont aFontHelper;
+ aFontHelper.SetCaseMap(SVX_CASEMAP_TITEL);
+ aFontHelper.SetLanguage(nLanguage);
+ aSnippet = aFontHelper.CalcCaseMap(aSnippet);
+
+ //If we weren't at the begin of a word undo the case change.
+ //not done before doing the casemap because the sequence might start
+ //with whitespace
+ if (pBreakIt->GetBreakIter().is() && !pBreakIt->GetBreakIter()->isBeginWord(
+ rStr, nAktPos, pBreakIt->GetLocale(nLanguage),
+ i18n::WordType::ANYWORD_IGNOREWHITESPACES ) )
+ {
+ aSnippet.SetChar(0, rStr.GetChar(nAktPos));
+ }
+ }
+ m_rExport.m_aCurrentCharPropStarts.pop();
+
+ return aSnippet;
+}
+
+/** Delivers the right paragraph style
+
+ Because of the different style handling for delete operations,
+ the track changes have to be analysed. A deletion, starting in paragraph A
+ with style A, ending in paragraph B with style B, needs a hack.
+*/
+static SwTxtFmtColl& lcl_getFormatCollection( MSWordExportBase& rExport, const SwTxtNode* pTxtNode )
+{
+ sal_uInt16 nPos = 0;
+ sal_uInt16 nMax = rExport.pDoc->GetRedlineTbl().Count();
+ while( nPos < nMax )
+ {
+ const SwRedline* pRedl = rExport.pDoc->GetRedlineTbl()[ nPos++ ];
+ const SwPosition* pStt = pRedl->Start();
+ const SwPosition* pEnd = pStt == pRedl->GetPoint()
+ ? pRedl->GetMark()
+ : pRedl->GetPoint();
+ // Looking for deletions, which ends in current pTxtNode
+ if( nsRedlineType_t::REDLINE_DELETE == pRedl->GetRedlineData().GetType() &&
+ pEnd->nNode == *pTxtNode && pStt->nNode != *pTxtNode &&
+ pStt->nNode.GetNode().IsTxtNode() )
+ {
+ pTxtNode = pStt->nNode.GetNode().GetTxtNode();
+ nMax = nPos;
+ nPos = 0;
+ }
+ }
+ return static_cast<SwTxtFmtColl&>( pTxtNode->GetAnyFmtColl() );
+}
+
+void WW8AttributeOutput::FormatDrop( const SwTxtNode& rNode, const SwFmtDrop &rSwFmtDrop, sal_uInt16 nStyle,
+ ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
+{
+ short nDropLines = rSwFmtDrop.GetLines();
+ short nDistance = rSwFmtDrop.GetDistance();
+ int rFontHeight, rDropHeight, rDropDescent;
+
+ SVBT16 nSty;
+ ShortToSVBT16( nStyle, nSty );
+ m_rWW8Export.pO->Insert( (sal_uInt8*)&nSty, 2, m_rWW8Export.pO->Count() ); // Style #
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PPc ); // Alignment (sprmPPc)
+ m_rWW8Export.pO->Insert( 0x20, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PWr ); // Wrapping (sprmPWr)
+ m_rWW8Export.pO->Insert( 0x02, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDcs ); // Dropcap (sprmPDcs)
+ int nDCS = ( nDropLines << 3 ) | 0x01;
+ m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( nDCS ) );
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaFromText ); // Distance from text (sprmPDxaFromText)
+ m_rWW8Export.InsUInt16( nDistance );
+
+ if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaLine ); // Line spacing
+ m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -rDropHeight ) );
+ m_rWW8Export.InsUInt16( 0 );
+ }
+ }
+ else
+ {
+ m_rWW8Export.pO->Insert( 29, m_rWW8Export.pO->Count() ); // Alignment (sprmPPc)
+ m_rWW8Export.pO->Insert( 0x20, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.pO->Insert( 37, m_rWW8Export.pO->Count() ); // Wrapping (sprmPWr)
+ m_rWW8Export.pO->Insert( 0x02, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.pO->Insert( 46, m_rWW8Export.pO->Count() ); // Dropcap (sprmPDcs)
+ int nDCS = ( nDropLines << 3 ) | 0x01;
+ m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( nDCS ) );
+
+ m_rWW8Export.pO->Insert( 49, m_rWW8Export.pO->Count() ); // Distance from text (sprmPDxaFromText)
+ m_rWW8Export.InsUInt16( nDistance );
+
+ if (rNode.GetDropSize(rFontHeight, rDropHeight, rDropDescent))
+ {
+ m_rWW8Export.pO->Insert( 20, m_rWW8Export.pO->Count() ); // Line spacing
+ m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -rDropHeight ) );
+ m_rWW8Export.InsUInt16( 0 );
+ }
+ }
+
+ m_rWW8Export.WriteCR( pTextNodeInfoInner );
+
+ if ( pTextNodeInfo.get() != NULL )
+ {
+#ifdef DEBUG
+ ::std::clog << pTextNodeInfo->toString() << ::std::endl;
+#endif
+
+ TableInfoCell( pTextNodeInfoInner );
+ }
+
+ m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() );
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() );
+
+ if ( rNode.GetDropSize( rFontHeight, rDropHeight, rDropDescent ) )
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ const SwCharFmt *pSwCharFmt = rSwFmtDrop.GetCharFmt();
+ if ( pSwCharFmt )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CIstd );
+ m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *pSwCharFmt ) );
+ }
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CHpsPos ); // Lower the chars
+ m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -((nDropLines - 1)*rDropDescent) / 10 ) );
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CHps ); // Font Size
+ m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( rFontHeight / 10 ) );
+ }
+ else
+ {
+ const SwCharFmt *pSwCharFmt = rSwFmtDrop.GetCharFmt();
+ if ( pSwCharFmt )
+ {
+ m_rWW8Export.InsUInt16( 80 );
+ m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *pSwCharFmt ) );
+ }
+
+ m_rWW8Export.pO->Insert( 101, m_rWW8Export.pO->Count() ); // Lower the chars
+ m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( -((nDropLines - 1)*rDropDescent) / 10 ) );
+
+ m_rWW8Export.pO->Insert( 99, m_rWW8Export.pO->Count() ); // Font Size
+ m_rWW8Export.InsUInt16( static_cast< sal_uInt16 >( rFontHeight / 10 ) );
+ }
+ }
+
+ m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() );
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() );
+}
+
+xub_StrLen MSWordExportBase::GetNextPos( SwWW8AttrIter* aAttrIter, const SwTxtNode& rNode, xub_StrLen nAktPos )
+{
+ // Get the bookmarks for the normal run
+ xub_StrLen nNextPos = aAttrIter->WhereNext();
+ xub_StrLen nNextBookmark = nNextPos;
+
+ if( nNextBookmark > nAktPos )//no need to search for bookmarks otherwise
+ {
+ GetSortedBookmarks( rNode, nAktPos, nNextBookmark - nAktPos );
+ NearestBookmark( nNextBookmark, nAktPos, false );
+ }
+ return std::min( nNextPos, nNextBookmark );
+}
+
+void MSWordExportBase::UpdatePosition( SwWW8AttrIter* aAttrIter, xub_StrLen nAktPos, xub_StrLen /*nEnd*/ )
+{
+ xub_StrLen nNextPos;
+
+ // go to next attribute if no bookmark is found and if the next attribute position if at the current position
+ bool bNextBookmark = NearestBookmark( nNextPos, nAktPos, true );
+ if( !bNextBookmark && nAktPos >= aAttrIter->WhereNext() )
+ aAttrIter->NextPos();
+}
+
+bool MSWordExportBase::GetBookmarks( const SwTxtNode& rNd, xub_StrLen nStt,
+ xub_StrLen nEnd, IMarkVector& rArr )
+{
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ sal_uLong nNd = rNd.GetIndex( );
+
+ const sal_Int32 nMarks = pMarkAccess->getMarksCount();
+ for ( sal_Int32 i = 0; i < nMarks; i++ )
+ {
+ IMark* pMark = ( pMarkAccess->getMarksBegin() + i )->get();
+
+ // Only keep the bookmarks starting or ending in this node
+ if ( pMark->GetMarkStart().nNode == nNd ||
+ pMark->GetMarkEnd().nNode == nNd )
+ {
+ xub_StrLen nBStart = pMark->GetMarkStart().nContent.GetIndex();
+ xub_StrLen nBEnd = pMark->GetMarkEnd().nContent.GetIndex();
+
+ // Keep only the bookmars starting or ending in the snippet
+ bool bIsStartOk = ( nBStart >= nStt ) && ( nBStart <= nEnd );
+ bool bIsEndOk = ( nBEnd >= nStt ) && ( nBEnd <= nEnd );
+
+ if ( bIsStartOk || bIsEndOk )
+ rArr.push_back( pMark );
+ }
+ }
+ return ( rArr.size() > 0 );
+}
+
+class CompareMarksEnd : public std::binary_function < const IMark *, const IMark *, bool >
+{
+public:
+ inline bool operator() ( const IMark * pOneB, const IMark * pTwoB ) const
+ {
+ xub_StrLen nOEnd = pOneB->GetMarkEnd().nContent.GetIndex();
+ xub_StrLen nTEnd = pTwoB->GetMarkEnd().nContent.GetIndex();
+
+ return nOEnd < nTEnd;
+ }
+};
+
+bool MSWordExportBase::NearestBookmark( xub_StrLen& rNearest, const xub_StrLen nAktPos, bool bNextPositionOnly )
+{
+ bool bHasBookmark = false;
+
+ if ( m_rSortedMarksStart.size( ) > 0 )
+ {
+ IMark* pMarkStart = m_rSortedMarksStart.front();
+ xub_StrLen nNext = pMarkStart->GetMarkStart().nContent.GetIndex();
+ if( !bNextPositionOnly || (nNext > nAktPos ))
+ {
+ rNearest = nNext;
+ bHasBookmark = true;
+ }
+ }
+
+ if ( m_rSortedMarksEnd.size( ) > 0 )
+ {
+ IMark* pMarkEnd = m_rSortedMarksEnd[0];
+ xub_StrLen nNext = pMarkEnd->GetMarkEnd().nContent.GetIndex();
+ if( !bNextPositionOnly || nNext > nAktPos )
+ {
+ if ( !bHasBookmark )
+ rNearest = nNext;
+ else
+ rNearest = std::min( rNearest, nNext );
+ bHasBookmark = true;
+ }
+ }
+
+ return bHasBookmark;
+}
+
+void MSWordExportBase::GetSortedBookmarks( const SwTxtNode& rNode, xub_StrLen nAktPos, xub_StrLen nLen )
+{
+ IMarkVector aMarksStart;
+ if ( GetBookmarks( rNode, nAktPos, nAktPos + nLen, aMarksStart ) )
+ {
+ IMarkVector aSortedEnd;
+ IMarkVector aSortedStart;
+ for ( IMarkVector::const_iterator it = aMarksStart.begin(), end = aMarksStart.end();
+ it < end; ++it )
+ {
+ IMark* pMark = (*it);
+
+ // Remove the positions egals to the current pos
+ xub_StrLen nStart = pMark->GetMarkStart().nContent.GetIndex();
+ xub_StrLen nEnd = pMark->GetMarkEnd().nContent.GetIndex();
+
+ if ( nStart > nAktPos && ( pMark->GetMarkStart().nNode == rNode.GetIndex()) )
+ aSortedStart.push_back( pMark );
+
+ if ( nEnd > nAktPos && nEnd <= ( nAktPos + nLen ) && (pMark->GetMarkEnd().nNode == rNode.GetIndex()) )
+ aSortedEnd.push_back( pMark );
+ }
+
+ // Sort the bookmarks by end position
+ std::sort( aSortedEnd.begin(), aSortedEnd.end(), CompareMarksEnd() );
+
+ m_rSortedMarksStart.swap( aSortedStart );
+ m_rSortedMarksEnd.swap( aSortedEnd );
+ }
+ else
+ {
+ m_rSortedMarksStart.clear( );
+ m_rSortedMarksEnd.clear( );
+ }
+}
+
+void MSWordExportBase::OutputTextNode( const SwTxtNode& rNode )
+{
+#ifdef DEBUG
+ ::std::clog << "<OutWW8_SwTxtNode>" << ::std::endl;
+#endif
+
+ ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo( mpTableInfo->getTableNodeInfo( &rNode ) );
+
+ AttrOutput().StartParagraph( pTextNodeInfo );
+
+ bool bFlyInTable = mpParentFrame && bIsInTable;
+
+ if ( !bFlyInTable )
+ nStyleBeforeFly = GetId( lcl_getFormatCollection( *this, &rNode ) );
+
+ // nStyleBeforeFly may change when we recurse into another node, so we
+ // have to remember it in nStyle
+ sal_uInt16 nStyle = nStyleBeforeFly;
+
+ SwWW8AttrIter aAttrIter( *this, rNode );
+ rtl_TextEncoding eChrSet = aAttrIter.GetCharSet();
+
+ if ( bStartTOX )
+ {
+ // ignore TOX header section
+ const SwSectionNode* pSectNd = rNode.FindSectionNode();
+ if ( pSectNd && TOX_CONTENT_SECTION == pSectNd->GetSection().GetType() )
+ {
+ AttrOutput().StartTOX( pSectNd->GetSection() );
+ m_aCurrentCharPropStarts.push( 0 );
+ }
+ }
+
+ const SwSection* pTOXSect = 0;
+ if( bInWriteTOX )
+ {
+ // check for end of TOX
+ SwNodeIndex aIdx( rNode, 1 );
+ if( !aIdx.GetNode().IsTxtNode() )
+ {
+ const SwSectionNode* pTOXSectNd = rNode.FindSectionNode();
+ pTOXSect = &pTOXSectNd->GetSection();
+
+ const SwNode* pNxt = rNode.GetNodes().GoNext( &aIdx );
+ if( pNxt && pNxt->FindSectionNode() == pTOXSectNd )
+ pTOXSect = 0;
+ }
+ }
+
+ if ( aAttrIter.RequiresImplicitBookmark() )
+ {
+ String sBkmkName = String( RTL_CONSTASCII_USTRINGPARAM( "_toc" ) );
+ sBkmkName += String::CreateFromInt32( rNode.GetIndex() );
+ AppendWordBookmark( sBkmkName );
+ }
+
+ String aStr( rNode.GetTxt() );
+
+ xub_StrLen nAktPos = 0;
+ xub_StrLen nEnd = aStr.Len();
+ bool bRedlineAtEnd = false;
+ int nOpenAttrWithRange = 0;
+
+ ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner;
+ if ( pTextNodeInfo.get() != NULL )
+ pTextNodeInfoInner = pTextNodeInfo->getFirstInner();
+
+ do {
+ const SwRedlineData* pRedlineData = aAttrIter.GetRedline( nAktPos );
+
+ AttrOutput().StartRun( pRedlineData );
+ if( nTxtTyp == TXT_FTN || nTxtTyp == TXT_EDN )
+ AttrOutput().FootnoteEndnoteRefTag();
+
+ xub_StrLen nNextAttr = GetNextPos( &aAttrIter, rNode, nAktPos );
+
+ if( nNextAttr > nEnd )
+ nNextAttr = nEnd;
+
+ aAttrIter.OutFlys( nAktPos );
+ //Append bookmarks in this range after flys, exclusive of final
+ //position of this range
+ AppendBookmarks( rNode, nAktPos, nNextAttr - nAktPos );
+ bool bTxtAtr = aAttrIter.IsTxtAttr( nAktPos );
+ nOpenAttrWithRange += aAttrIter.OutAttrWithRange(nAktPos);
+
+ xub_StrLen nLen = nNextAttr - nAktPos;
+ if ( !bTxtAtr && nLen )
+ {
+ sal_Unicode ch = aStr.GetChar( nAktPos );
+ int ofs = ( ch == CH_TXT_ATR_FIELDSTART || ch == CH_TXT_ATR_FIELDEND || ch == CH_TXT_ATR_FORMELEMENT? 1: 0 );
+
+ IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ if ( ch == CH_TXT_ATR_FIELDSTART )
+ {
+ SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos ) );
+ ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
+ OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
+
+ if ( pFieldmark->GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMTEXT ) ) )
+ AppendBookmark( pFieldmark->GetName(), false );
+ ww::eField eFieldId = lcl_getFieldId( pFieldmark );
+ String sCode = lcl_getFieldCode( pFieldmark );
+ if ( pFieldmark->GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_UNHANDLED ) ) )
+ {
+ IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_ID_PARAM )) );
+ if ( it != pFieldmark->GetParameters()->end() )
+ {
+ rtl::OUString sFieldId;
+ it->second >>= sFieldId;
+ eFieldId = (ww::eField)sFieldId.toInt32();
+ }
+
+ it = pFieldmark->GetParameters()->find(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_CODE_PARAM )) );
+ if ( it != pFieldmark->GetParameters()->end() )
+ {
+ rtl::OUString sOUCode;
+ it->second >>= sOUCode;
+ sCode = sOUCode;
+ }
+ }
+ OutputField( NULL, eFieldId, sCode, WRITEFIELD_START | WRITEFIELD_CMD_START );
+ if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMTEXT ) ) )
+ WriteFormData( *pFieldmark );
+ else if ( pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_HYPERLINK ) ) )
+ WriteHyperlinkData( *pFieldmark );
+ OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CMD_END );
+
+ if ( pFieldmark->GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_UNHANDLED ) ) )
+ {
+ // Check for the presence of a linked OLE object
+ IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_OLE_PARAM )) );
+ if ( it != pFieldmark->GetParameters()->end() )
+ {
+ rtl::OUString sOleId;
+ uno::Any aValue = it->second;
+ aValue >>= sOleId;
+ if ( sOleId.getLength( ) > 0 )
+ OutputLinkedOLE( sOleId );
+ }
+ }
+ }
+ else if ( ch == CH_TXT_ATR_FIELDEND )
+ {
+ SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos - 1 ) );
+ ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
+ OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDEND??" );
+
+ ww::eField eFieldId = lcl_getFieldId( pFieldmark );
+ if ( pFieldmark->GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_UNHANDLED ) ) )
+ {
+ IFieldmark::parameter_map_t::const_iterator it = pFieldmark->GetParameters()->find(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_ID_PARAM )) );
+ if ( it != pFieldmark->GetParameters()->end() )
+ {
+ rtl::OUString sFieldId;
+ it->second >>= sFieldId;
+ eFieldId = (ww::eField)sFieldId.toInt32();
+ }
+ }
+
+ OutputField( NULL, eFieldId, String(), WRITEFIELD_CLOSE );
+ if ( pFieldmark->GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMTEXT ) ) )
+ AppendBookmark( pFieldmark->GetName(), false );
+ }
+ else if ( ch == CH_TXT_ATR_FORMELEMENT )
+ {
+ SwPosition aPosition( rNode, SwIndex( const_cast< SwTxtNode* >( &rNode ), nAktPos ) );
+ ::sw::mark::IFieldmark const * const pFieldmark = pMarkAccess->getFieldmarkFor( aPosition );
+ OSL_ENSURE( pFieldmark, "Looks like this doc is broken...; where is the Fieldmark for the FIELDSTART??" );
+
+ bool isDropdownOrCheckbox = pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMDROPDOWN ) ) ||
+ pFieldmark->GetFieldname( ).equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) );
+
+ if ( isDropdownOrCheckbox )
+ AppendBookmark( pFieldmark->GetName(), 0 );
+ OutputField( NULL, lcl_getFieldId( pFieldmark ),
+ lcl_getFieldCode( pFieldmark ),
+ WRITEFIELD_START | WRITEFIELD_CMD_START );
+ if ( isDropdownOrCheckbox )
+ WriteFormData( *pFieldmark );
+ OutputField( NULL, lcl_getFieldId( pFieldmark ), String(), WRITEFIELD_CLOSE );
+ if ( isDropdownOrCheckbox )
+ AppendBookmark( pFieldmark->GetName(), false );
+ }
+ nLen -= static_cast< sal_uInt16 >( ofs );
+
+ String aSnippet( aAttrIter.GetSnippet( aStr, nAktPos + static_cast< sal_uInt16 >( ofs ), nLen ) );
+ if ( ( nTxtTyp == TXT_EDN || nTxtTyp == TXT_FTN ) && nAktPos == 0 && nLen > 0 )
+ {
+ // Insert tab for aesthetic puposes #i24762#
+ if ( aSnippet.GetChar( 0 ) != 0x09 )
+ aSnippet.Insert( 0x09, 0 );
+ }
+ AttrOutput().RunText( aSnippet, eChrSet );
+ }
+
+ if ( aAttrIter.IsDropCap( nNextAttr ) )
+ AttrOutput().FormatDrop( rNode, aAttrIter.GetSwFmtDrop(), nStyle, pTextNodeInfo, pTextNodeInfoInner );
+
+ // At the end of line, output the attributes until the CR.
+ // Exception: footnotes at the end of line
+ if ( nNextAttr == nEnd )
+ {
+ OSL_ENSURE( nOpenAttrWithRange >= 0, "odd to see this happening, expected >= 0" );
+ if ( !bTxtAtr && nOpenAttrWithRange <= 0 )
+ {
+ if ( aAttrIter.IsRedlineAtEnd( nEnd ) )
+ bRedlineAtEnd = true;
+ else
+ {
+ // insert final graphic anchors if any before CR
+ aAttrIter.OutFlys( nEnd );
+ // insert final bookmarks if any before CR and after flys
+ AppendBookmarks( rNode, nEnd, 1 );
+ if ( pTOXSect )
+ {
+ m_aCurrentCharPropStarts.pop();
+ AttrOutput().EndTOX( *pTOXSect );
+ }
+ WriteCR( pTextNodeInfoInner );
+ }
+ }
+ }
+
+ // Output the character attributes
+ AttrOutput().StartRunProperties();
+ aAttrIter.OutAttr( nAktPos ); // nAktPos - 1 ??
+ AttrOutput().EndRunProperties( pRedlineData );
+
+ // Exception: footnotes at the end of line
+ if ( nNextAttr == nEnd )
+ {
+ OSL_ENSURE(nOpenAttrWithRange >= 0,
+ "odd to see this happening, expected >= 0");
+ bool bAttrWithRange = (nOpenAttrWithRange > 0);
+ if ( nAktPos != nEnd )
+ {
+ nOpenAttrWithRange += aAttrIter.OutAttrWithRange(nEnd);
+ OSL_ENSURE(nOpenAttrWithRange == 0,
+ "odd to see this happening, expected 0");
+ }
+
+ AttrOutput().OutputFKP();
+
+ if ( bTxtAtr || bAttrWithRange || bRedlineAtEnd )
+ {
+ // insert final graphic anchors if any before CR
+ aAttrIter.OutFlys( nEnd );
+ // insert final bookmarks if any before CR and after flys
+ AppendBookmarks( rNode, nEnd, 1 );
+
+ if ( pTOXSect )
+ {
+ m_aCurrentCharPropStarts.pop();
+ AttrOutput().EndTOX( *pTOXSect );
+ }
+
+ WriteCR( pTextNodeInfoInner );
+
+ if ( bRedlineAtEnd )
+ {
+ AttrOutput().Redline( aAttrIter.GetRedline( nEnd ) );
+ AttrOutput().OutputFKP();
+ }
+ }
+ }
+
+ AttrOutput().EndRun();
+
+ nAktPos = nNextAttr;
+ UpdatePosition( &aAttrIter, nAktPos, nEnd );
+ eChrSet = aAttrIter.GetCharSet();
+ }
+ while ( nAktPos < nEnd );
+
+ AttrOutput().StartParagraphProperties( rNode );
+
+ AttrOutput().ParagraphStyle( nStyle );
+
+ if ( mpParentFrame && !bIsInTable ) // Fly-Attrs
+ OutputFormat( mpParentFrame->GetFrmFmt(), false, false, true );
+
+ if ( pTextNodeInfo.get() != NULL )
+ {
+#ifdef DEBUG
+ ::std::clog << pTextNodeInfo->toString() << ::std::endl;
+#endif
+
+ AttrOutput().TableInfoCell( pTextNodeInfoInner );
+ if (pTextNodeInfoInner->isFirstInTable())
+ {
+ const SwTable * pTable = pTextNodeInfoInner->getTable();
+
+ const SwTableFmt * pTabFmt = pTable->GetTableFmt();
+ if (pTabFmt != NULL)
+ {
+ if (pTabFmt->GetBreak().GetBreak() == SVX_BREAK_PAGE_BEFORE)
+ AttrOutput().PageBreakBefore(true);
+ }
+ }
+ }
+
+ if ( !bFlyInTable )
+ {
+ SfxItemSet* pTmpSet = 0;
+ const sal_uInt8 nPrvNxtNd = rNode.HasPrevNextLayNode();
+
+ if( (ND_HAS_PREV_LAYNODE|ND_HAS_NEXT_LAYNODE ) != nPrvNxtNd )
+ {
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState(
+ RES_UL_SPACE, true, &pItem ) &&
+ ( ( !( ND_HAS_PREV_LAYNODE & nPrvNxtNd ) &&
+ ((SvxULSpaceItem*)pItem)->GetUpper()) ||
+ ( !( ND_HAS_NEXT_LAYNODE & nPrvNxtNd ) &&
+ ((SvxULSpaceItem*)pItem)->GetLower()) ))
+ {
+ pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() );
+ SvxULSpaceItem aUL( *(SvxULSpaceItem*)pItem );
+ // #i25901#- consider compatibility option
+ if (!pDoc->get(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES))
+ {
+ if( !(ND_HAS_PREV_LAYNODE & nPrvNxtNd ))
+ aUL.SetUpper( 0 );
+ }
+ // #i25901# - consider compatibility option
+ if (!pDoc->get(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS))
+ {
+ if( !(ND_HAS_NEXT_LAYNODE & nPrvNxtNd ))
+ aUL.SetLower( 0 );
+ }
+ pTmpSet->Put( aUL );
+ }
+ }
+
+ sal_Bool bParaRTL = sal_False;
+ const SvxFrameDirectionItem* pItem = (const SvxFrameDirectionItem*)
+ rNode.GetSwAttrSet().GetItem(RES_FRAMEDIR);
+ if ( aAttrIter.IsParaRTL())
+ bParaRTL = sal_True;
+
+ if( rNode.IsNumbered())
+ {
+ const SwNumRule* pRule = rNode.GetNumRule();
+ sal_uInt8 nLvl = static_cast< sal_uInt8 >( rNode.GetActualListLevel() );
+ const SwNumFmt* pFmt = pRule->GetNumFmt( nLvl );
+ if( !pFmt )
+ pFmt = &pRule->Get( nLvl );
+
+ if( !pTmpSet )
+ pTmpSet = new SfxItemSet( rNode.GetSwAttrSet() );
+
+ SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*pTmpSet, RES_LR_SPACE));
+ // #i86652#
+ if ( pFmt->GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aLR.SetTxtLeft( aLR.GetTxtLeft() + pFmt->GetAbsLSpace() );
+ }
+ // <--
+
+ if( rNode.IsNumbered() && rNode.IsCountedInList() )
+ {
+ // #i86652#
+ if ( pFmt->GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ if (bParaRTL)
+ aLR.SetTxtFirstLineOfstValue(pFmt->GetAbsLSpace() - pFmt->GetFirstLineOffset());
+ else
+ aLR.SetTxtFirstLineOfst(GetWordFirstLineOffset(*pFmt));
+ }
+ // <--
+
+ // correct fix for issue i94187
+ if (SFX_ITEM_SET !=
+ pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) )
+ {
+ // List style set via paragraph style - then put it into the itemset.
+ // This is needed to get list level and list id exported for
+ // the paragraph.
+ pTmpSet->Put( SwNumRuleItem( pRule->GetName() ));
+
+ // Put indent values into the itemset in case that the list
+ // style is applied via paragraph style and the list level
+ // indent values are not applicable.
+ if ( pFmt->GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_ALIGNMENT &&
+ !rNode.AreListLevelIndentsApplicable() )
+ {
+ pTmpSet->Put( aLR );
+ }
+ }
+ }
+ else
+ pTmpSet->ClearItem(RES_PARATR_NUMRULE);
+
+ // #i86652#
+ if ( pFmt->GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ pTmpSet->Put(aLR);
+
+ //#i21847#
+ SvxTabStopItem aItem(
+ ItemGet<SvxTabStopItem>(*pTmpSet, RES_PARATR_TABSTOP));
+ SvxTabStop aTabStop(pFmt->GetAbsLSpace());
+ aItem.Insert(aTabStop);
+ pTmpSet->Put(aItem);
+
+ MSWordExportBase::CorrectTabStopInSet(*pTmpSet, pFmt->GetAbsLSpace());
+ }
+ }
+
+ /*
+ If a given para is using the FRMDIR_ENVIRONMENT direction we
+ cannot export that, its its ltr then that's ok as thats word's
+ default. Otherwise we must add a RTL attribute to our export list
+ */
+ pItem = (const SvxFrameDirectionItem*)
+ rNode.GetSwAttrSet().GetItem(RES_FRAMEDIR);
+ if (
+ (!pItem || pItem->GetValue() == FRMDIR_ENVIRONMENT) &&
+ aAttrIter.IsParaRTL()
+ )
+ {
+ if ( !pTmpSet )
+ pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
+
+ pTmpSet->Put(SvxFrameDirectionItem(FRMDIR_HORI_RIGHT_TOP, RES_FRAMEDIR));
+ }
+ // move code for handling of numbered,
+ // but not counted paragraphs to this place. Otherwise, the paragraph
+ // isn't exported as numbered, but not counted, if no other attribute
+ // is found in <pTmpSet>
+ // #i44815# adjust numbering/indents for numbered paragraphs
+ // without number (NO_NUMLEVEL)
+ // #i47013# need to check rNode.GetNumRule()!=NULL as well.
+ if ( ! rNode.IsCountedInList() && rNode.GetNumRule()!=NULL )
+ {
+ // WW8 does not know numbered paragraphs without number
+ // (NO_NUMLEVEL). In WW8AttributeOutput::ParaNumRule(), we will export
+ // the RES_PARATR_NUMRULE as list-id 0, which in WW8 means
+ // no numbering. Here, we will adjust the indents to match
+ // visually.
+
+ if ( !pTmpSet )
+ pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
+
+ // create new LRSpace item, based on the current (if present)
+ const SfxPoolItem* pPoolItem = NULL;
+ pTmpSet->GetItemState(RES_LR_SPACE, sal_True, &pPoolItem);
+ SvxLRSpaceItem aLRSpace(
+ ( pPoolItem == NULL )
+ ? SvxLRSpaceItem(0, 0, 0, 0, RES_LR_SPACE)
+ : *static_cast<const SvxLRSpaceItem*>( pPoolItem ) );
+
+ // new left margin = old left + label space
+ const SwNumRule* pRule = rNode.GetNumRule();
+ const SwNumFmt& rNumFmt = pRule->Get( static_cast< sal_uInt16 >(rNode.GetActualListLevel()) );
+ // #i86652#
+ if ( rNumFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ aLRSpace.SetTxtLeft( aLRSpace.GetLeft() + rNumFmt.GetAbsLSpace() );
+
+ // new first line indent = 0
+ // (first line indent is ignored for NO_NUMLEVEL)
+ if (!bParaRTL)
+ aLRSpace.SetTxtFirstLineOfst( 0 );
+
+ // put back the new item
+ pTmpSet->Put( aLRSpace );
+ }
+ // <--
+
+ // assure that numbering rule is in <pTmpSet>
+ if (SFX_ITEM_SET != pTmpSet->GetItemState(RES_PARATR_NUMRULE, false) )
+ {
+ pTmpSet->Put( SwNumRuleItem( pRule->GetName() ));
+ }
+ }
+
+ // #i75457#
+ // Export page break after attribute from paragraph style.
+ // If page break attribute at the text node exist, an existing page
+ // break after at the paragraph style hasn't got to be considered.
+ if ( !rNode.GetpSwAttrSet() ||
+ SFX_ITEM_SET != rNode.GetpSwAttrSet()->GetItemState(RES_BREAK, false) )
+ {
+ const SvxFmtBreakItem* pBreakAtParaStyle =
+ &(ItemGet<SvxFmtBreakItem>(rNode.GetSwAttrSet(), RES_BREAK));
+ if ( pBreakAtParaStyle &&
+ pBreakAtParaStyle->GetBreak() == SVX_BREAK_PAGE_AFTER )
+ {
+ if ( !pTmpSet )
+ {
+ pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
+ }
+ pTmpSet->Put( *pBreakAtParaStyle );
+ }
+ else if( pTmpSet )
+ { // Even a pagedesc item is set, the break item can be set 'NONE',
+ // this has to be overruled.
+ const SwFmtPageDesc& rPageDescAtParaStyle =
+ ItemGet<SwFmtPageDesc>( rNode, RES_PAGEDESC );
+ if( rPageDescAtParaStyle.KnowsPageDesc() )
+ pTmpSet->ClearItem( RES_BREAK );
+ }
+ }
+
+ // #i76520# Emulate non-splitting tables
+ if ( bOutTable )
+ {
+ const SwTableNode* pTableNode = rNode.FindTableNode();
+
+ if ( pTableNode )
+ {
+ const SwTable& rTable = pTableNode->GetTable();
+ const SvxFmtKeepItem& rKeep = rTable.GetFrmFmt()->GetKeep();
+ const bool bKeep = rKeep.GetValue();
+ const bool bDontSplit = !bKeep ?
+ !rTable.GetFrmFmt()->GetLayoutSplit().GetValue() :
+ false;
+
+ if ( bKeep || bDontSplit )
+ {
+ // bKeep: set keep at first paragraphs in all lines
+ // bDontSplit : set keep at first paragraphs in all lines except from last line
+ // but only for non-complex tables
+ const SwTableBox* pBox = rNode.GetTblBox();
+ const SwTableLine* pLine = pBox ? pBox->GetUpper() : 0;
+
+ if ( pLine && !pLine->GetUpper() )
+ {
+ // check if box is first in that line:
+ if ( 0 == pLine->GetTabBoxes().GetPos( pBox ) && pBox->GetSttNd() )
+ {
+ // check if paragraph is first in that line:
+ if ( 1 == ( rNode.GetIndex() - pBox->GetSttNd()->GetIndex() ) )
+ {
+ bool bSetAtPara = false;
+ if ( bKeep )
+ bSetAtPara = true;
+ else if ( bDontSplit )
+ {
+ // check if pLine isn't last line in table
+ if ( rTable.GetTabLines().Count() - rTable.GetTabLines().GetPos( pLine ) != 1 )
+ bSetAtPara = true;
+ }
+
+ if ( bSetAtPara )
+ {
+ if ( !pTmpSet )
+ pTmpSet = new SfxItemSet(rNode.GetSwAttrSet());
+
+ const SvxFmtKeepItem aKeepItem( sal_True, RES_KEEP );
+ pTmpSet->Put( aKeepItem );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ // <--
+
+ const SfxItemSet* pNewSet = pTmpSet ? pTmpSet : rNode.GetpSwAttrSet();
+ if( pNewSet )
+ { // Para-Attrs
+ pStyAttr = &rNode.GetAnyFmtColl().GetAttrSet();
+
+ const SwModify* pOldMod = pOutFmtNode;
+ pOutFmtNode = &rNode;
+
+ // Pap-Attrs, so script is not necessary
+ OutputItemSet( *pNewSet, true, false, i18n::ScriptType::LATIN, false);
+
+ pStyAttr = 0;
+ pOutFmtNode = pOldMod;
+
+ if( pNewSet != rNode.GetpSwAttrSet() )
+ delete pNewSet;
+ }
+ }
+
+ // write attributes of the node itself
+ AttrOutput().StartRunProperties();
+ OutputItemSet( rNode.GetSwAttrSet(), false, true, i18n::ScriptType::LATIN, false);
+ AttrOutput().EndRunProperties( NULL );
+
+ AttrOutput().EndParagraphProperties();
+
+ AttrOutput().EndParagraph( pTextNodeInfoInner );
+
+#ifdef DEBUG
+ ::std::clog << "</OutWW8_SwTxtNode>" << ::std::endl;
+#endif
+}
+
+void WW8AttributeOutput::TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo )
+{
+ SVBT16 nSty;
+ ShortToSVBT16( GetExport().nStyleBeforeFly, nSty );
+
+ ww8::WW8TableNodeInfo::Inners_t::const_iterator aIt( pNodeInfo->getInners().begin() );
+ ww8::WW8TableNodeInfo::Inners_t::const_iterator aItEnd( pNodeInfo->getInners().end() );
+
+ while (aIt != aItEnd)
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
+ if ( pInner->isEndOfCell() )
+ {
+ TableRowEnd( pInner->getDepth() );
+
+ m_rWW8Export.pO->Insert( (sal_uInt8*)&nSty, 2, m_rWW8Export.pO->Count() ); // Style #
+ TableInfoRow( pInner );
+ m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
+ m_rWW8Export.pO->GetData() );
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
+ }
+
+ if ( pInner->isEndOfLine() )
+ {
+ }
+
+ ++aIt;
+ }
+}
+//---------------------------------------------------------------------------
+// Tabellen
+//---------------------------------------------------------------------------
+
+void WW8AttributeOutput::EmptyParagraph()
+{
+ m_rWW8Export.WriteStringAsPara( aEmptyStr );
+}
+
+bool MSWordExportBase::NoPageBreakSection( const SfxItemSet* pSet )
+{
+ bool bRet = false;
+ const SfxPoolItem* pI;
+ if( pSet)
+ {
+ bool bNoPageBreak = false;
+ if ( SFX_ITEM_ON != pSet->GetItemState(RES_PAGEDESC, true, &pI)
+ || 0 == ((SwFmtPageDesc*)pI)->GetPageDesc() )
+ {
+ bNoPageBreak = true;
+ }
+
+ if (bNoPageBreak)
+ {
+ if (SFX_ITEM_ON != pSet->GetItemState(RES_BREAK, true, &pI))
+ bNoPageBreak = true;
+ else
+ {
+ SvxBreak eBreak = ((const SvxFmtBreakItem*)pI)->GetBreak();
+ switch (eBreak)
+ {
+ case SVX_BREAK_PAGE_BEFORE:
+ case SVX_BREAK_PAGE_AFTER:
+ bNoPageBreak = false;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ bRet = bNoPageBreak;
+ }
+ return bRet;
+}
+
+/* */
+
+void MSWordExportBase::OutputSectionNode( const SwSectionNode& rSectionNode )
+{
+ const SwSection& rSection = rSectionNode.GetSection();
+
+ SwNodeIndex aIdx( rSectionNode, 1 );
+ const SwNode& rNd = aIdx.GetNode();
+ if ( !rNd.IsSectionNode() && !bIsInTable ) //No sections in table
+ {
+ // Bug 74245 - if the first Node inside the section has an own
+ // PageDesc or PageBreak attribut, then dont write
+ // here the section break
+ sal_uLong nRstLnNum = 0;
+ const SfxItemSet* pSet;
+ if ( rNd.IsTableNode() )
+ pSet = &rNd.GetTableNode()->GetTable().GetFrmFmt()->GetAttrSet();
+ else if ( rNd.IsCntntNode() )
+ {
+ pSet = &rNd.GetCntntNode()->GetSwAttrSet();
+ nRstLnNum = ((SwFmtLineNumber&)pSet->Get(
+ RES_LINENUMBER )).GetStartValue();
+ }
+ else
+ pSet = 0;
+
+ if ( pSet && NoPageBreakSection( pSet ) )
+ pSet = 0;
+
+ if ( !pSet )
+ {
+ // new Section with no own PageDesc/-Break
+ // -> write follow section break;
+ const SwSectionFmt& rFmt = *rSection.GetFmt();
+ ReplaceCr( msword::PageBreak ); // Indikator fuer Page/Section-Break
+
+ //Get the page in use at the top of this section
+ SwNodeIndex aIdxTmp(rSectionNode, 1);
+ const SwPageDesc *pCurrent =
+ SwPageDesc::GetPageDescOfNode(aIdxTmp.GetNode());
+ if (!pCurrent)
+ pCurrent = pAktPageDesc;
+
+ AppendSection( pCurrent, &rFmt, nRstLnNum );
+ }
+ }
+ if ( TOX_CONTENT_SECTION == rSection.GetType() )
+ bStartTOX = true;
+}
+
+
+void WW8Export::AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum )
+{
+ pSepx->AppendSep(Fc2Cp(Strm().Tell()), pPageDesc, pFmt, nLnNum);
+}
+
+/* */
+
+//---------------------------------------------------------------------------
+// Flys
+//---------------------------------------------------------------------------
+
+void WW8Export::OutWW6FlyFrmsInCntnt( const SwTxtNode& rNd )
+{
+ OSL_ENSURE(!bWrtWW8, "I shouldn't be needed for Word >=8");
+ if ( bWrtWW8 )
+ return;
+
+ if (const SwpHints* pTxtAttrs = rNd.GetpSwpHints())
+ {
+ for( sal_uInt16 n=0; n < pTxtAttrs->Count(); ++n )
+ {
+ const SwTxtAttr* pAttr = (*pTxtAttrs)[ n ];
+ if( RES_TXTATR_FLYCNT == pAttr->Which() )
+ {
+ // zeichengebundenes Attribut
+ const SwFmtFlyCnt& rFlyCntnt = pAttr->GetFlyCnt();
+ const SwFlyFrmFmt& rFlyFrmFmt = *(SwFlyFrmFmt*)rFlyCntnt.GetFrmFmt();
+ const SwNodeIndex* pNodeIndex = rFlyFrmFmt.GetCntnt().GetCntntIdx();
+
+ if( pNodeIndex )
+ {
+ sal_uLong nStt = pNodeIndex->GetIndex()+1,
+ nEnd = pNodeIndex->GetNode().EndOfSectionIndex();
+
+ if( (nStt < nEnd) && !pDoc->GetNodes()[ nStt ]->IsNoTxtNode() )
+ {
+ Point aOffset;
+ // Rechtecke des Flys und des Absatzes besorgen
+ SwRect aParentRect(rNd.FindLayoutRect(false, &aOffset)),
+ aFlyRect(rFlyFrmFmt.FindLayoutRect(false, &aOffset ) );
+
+ aOffset = aFlyRect.Pos() - aParentRect.Pos();
+
+ // PaM umsetzen: auf Inhalt des Fly-Frameformats
+ SaveData( nStt, nEnd );
+
+ // wird in OutputFormat() ausgewertet
+ pFlyOffset = &aOffset;
+ eNewAnchorType = rFlyFrmFmt.GetAnchor().GetAnchorId();
+ sw::Frame aFrm(rFlyFrmFmt, SwPosition(rNd));
+ mpParentFrame = &aFrm;
+ // Ok, rausschreiben:
+ WriteText();
+
+ RestoreData();
+ }
+ }
+ }
+ }
+ }
+}
+
+void WW8AttributeOutput::OutputFlyFrame_Impl( const sw::Frame& rFmt, const Point& rNdTopLeft )
+{
+ const SwFrmFmt &rFrmFmt = rFmt.GetFrmFmt();
+ const SwFmtAnchor& rAnch = rFrmFmt.GetAnchor();
+
+ bool bUseEscher = m_rWW8Export.bWrtWW8;
+
+ if ( m_rWW8Export.bWrtWW8 && rFmt.IsInline() )
+ {
+ sw::Frame::WriterSource eType = rFmt.GetWriterType();
+ if ((eType == sw::Frame::eGraphic) || (eType == sw::Frame::eOle))
+ bUseEscher = false;
+ else
+ bUseEscher = true;
+
+ /*
+ A special case for converting some inline form controls to form fields
+ when in winword 8+ mode
+ */
+ if ((bUseEscher == true) && (eType == sw::Frame::eFormControl))
+ {
+ if ( m_rWW8Export.MiserableFormFieldExportHack( rFrmFmt ) )
+ return ;
+ }
+ }
+
+ if (bUseEscher)
+ {
+ OSL_ENSURE( m_rWW8Export.bWrtWW8, "this has gone horribly wrong" );
+ // write as escher
+ m_rWW8Export.AppendFlyInFlys(rFmt, rNdTopLeft);
+ }
+ else
+ {
+ bool bDone = false;
+
+ // Hole vom Node und vom letzten Node die Position in der Section
+ const SwNodeIndex* pNodeIndex = rFrmFmt.GetCntnt().GetCntntIdx();
+
+ sal_uLong nStt = pNodeIndex ? pNodeIndex->GetIndex()+1 : 0;
+ sal_uLong nEnd = pNodeIndex ? pNodeIndex->GetNode().EndOfSectionIndex() : 0;
+
+ if( nStt >= nEnd ) // kein Bereich, also kein gueltiger Node
+ return;
+
+ if ( !m_rWW8Export.bIsInTable && rFmt.IsInline() )
+ {
+ //Test to see if this textbox contains only a single graphic/ole
+ SwTxtNode* pParTxtNode = rAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode();
+ if ( pParTxtNode && !m_rWW8Export.pDoc->GetNodes()[ nStt ]->IsNoTxtNode() )
+ bDone = true;
+ }
+ if( !bDone )
+ {
+
+ m_rWW8Export.SaveData( nStt, nEnd );
+
+ Point aOffset;
+ if ( m_rWW8Export.mpParentFrame )
+ {
+ /* Munge flys in fly into absolutely positioned elements for word 6 */
+ const SwTxtNode* pParTxtNode = rAnch.GetCntntAnchor()->nNode.GetNode().GetTxtNode();
+ const SwRect aPageRect = pParTxtNode->FindPageFrmRect( sal_False, 0, sal_False );
+
+ aOffset = rFrmFmt.FindLayoutRect().Pos();
+ aOffset -= aPageRect.Pos();
+
+ m_rWW8Export.pFlyOffset = &aOffset;
+ m_rWW8Export.eNewAnchorType = FLY_AT_PAGE;
+ }
+
+ m_rWW8Export.mpParentFrame = &rFmt;
+ if (
+ m_rWW8Export.bIsInTable &&
+ (FLY_AT_PAGE != rAnch.GetAnchorId()) &&
+ !m_rWW8Export.pDoc->GetNodes()[ nStt ]->IsNoTxtNode()
+ )
+ {
+ // Beachten: Flag bOutTable wieder setzen,
+ // denn wir geben ja ganz normalen Content der
+ // Tabelenzelle aus und keinen Rahmen
+ // (Flag wurde oben in aSaveData() geloescht)
+ m_rWW8Export.bOutTable = true;
+ const String& rName = rFrmFmt.GetName();
+ m_rWW8Export.StartCommentOutput(rName);
+ m_rWW8Export.WriteText();
+ m_rWW8Export.EndCommentOutput(rName);
+ }
+ else
+ m_rWW8Export.WriteText();
+
+ m_rWW8Export.RestoreData();
+ }
+ }
+}
+
+void AttributeOutputBase::OutputFlyFrame( const sw::Frame& rFmt )
+{
+ if ( !rFmt.GetCntntNode() )
+ return;
+
+ const SwCntntNode &rNode = *rFmt.GetCntntNode();
+ Point aNdPos, aPgPos;
+ Point* pLayPos;
+ bool bValidNdPos = false, bValidPgPos = false;
+
+ if (FLY_AT_PAGE == rFmt.GetFrmFmt().GetAnchor().GetAnchorId())
+ {
+ // get the Layout Node-Position.
+ if ( !bValidPgPos )
+ {
+ aPgPos = rNode.FindPageFrmRect(false, &aPgPos).Pos();
+ bValidPgPos = true;
+ }
+ pLayPos = &aPgPos;
+ }
+ else
+ {
+ // get the Layout Node-Position.
+ if ( !bValidNdPos )
+ {
+ aNdPos = rNode.FindLayoutRect(false, &aNdPos).Pos();
+ bValidNdPos = true;
+ }
+ pLayPos = &aNdPos;
+ }
+
+ OutputFlyFrame_Impl( rFmt, *pLayPos );
+}
+
+// write data of any redline
+void WW8AttributeOutput::Redline( const SwRedlineData* pRedline )
+{
+ if ( !pRedline )
+ return;
+
+ if ( pRedline->Next() )
+ Redline( pRedline->Next() );
+
+ static sal_uInt16 aSprmIds[ 2 * 2 * 3 ] =
+ {
+ // Ids for insert
+ NS_sprm::LN_CFRMark, NS_sprm::LN_CIbstRMark, NS_sprm::LN_CDttmRMark, // for WW8
+ 0x0042, 0x0045, 0x0046, // for WW6
+ // Ids for delete
+ NS_sprm::LN_CFRMarkDel, NS_sprm::LN_CIbstRMarkDel, NS_sprm::LN_CDttmRMarkDel, // for WW8
+ 0x0041, 0x0045, 0x0046 // for WW6
+ };
+
+ const sal_uInt16* pSprmIds = 0;
+ switch( pRedline->GetType() )
+ {
+ case nsRedlineType_t::REDLINE_INSERT:
+ pSprmIds = aSprmIds;
+ break;
+
+ case nsRedlineType_t::REDLINE_DELETE:
+ pSprmIds = aSprmIds + (2 * 3);
+ break;
+
+ case nsRedlineType_t::REDLINE_FORMAT:
+ if( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CPropRMark );
+ m_rWW8Export.pO->Insert( 7, m_rWW8Export.pO->Count() ); // len
+ m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( m_rWW8Export.AddRedlineAuthor( pRedline->GetAuthor() ) );
+ m_rWW8Export.InsUInt32( sw::ms::DateTime2DTTM( pRedline->GetTimeStamp() ));
+ }
+ break;
+ default:
+ OSL_ENSURE(!this, "Unhandled redline type for export");
+ break;
+ }
+
+ if ( pSprmIds )
+ {
+ if ( !m_rWW8Export.bWrtWW8 )
+ pSprmIds += 3;
+
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( pSprmIds[0] );
+ else
+ m_rWW8Export.pO->Insert( msword_cast<sal_uInt8>(pSprmIds[0]), m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
+
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( pSprmIds[1] );
+ else
+ m_rWW8Export.pO->Insert( msword_cast<sal_uInt8>(pSprmIds[1]), m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( m_rWW8Export.AddRedlineAuthor( pRedline->GetAuthor() ) );
+
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( pSprmIds[2] );
+ else
+ m_rWW8Export.pO->Insert( msword_cast<sal_uInt8>(pSprmIds[2]), m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt32( sw::ms::DateTime2DTTM( pRedline->GetTimeStamp() ));
+ }
+}
+
+/* */
+
+void MSWordExportBase::OutputContentNode( const SwCntntNode& rNode )
+{
+ switch ( rNode.GetNodeType() )
+ {
+ case ND_TEXTNODE:
+ {
+ const SwTxtNode& rTextNode = *rNode.GetTxtNode();
+ if( !mbOutOutlineOnly || rTextNode.IsOutline() )
+ OutputTextNode( rTextNode );
+ }
+ break;
+ case ND_GRFNODE:
+ OutputGrfNode( *rNode.GetGrfNode() );
+ break;
+ case ND_OLENODE:
+ OutputOLENode( *rNode.GetOLENode() );
+ break;
+ default:
+ OSL_TRACE("Unhandled node, type == %d\n", rNode.GetNodeType() );
+ break;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/wrtw8num.cxx b/sw/source/filter/ww8/wrtw8num.cxx
new file mode 100644
index 000000000000..38f37ea04648
--- /dev/null
+++ b/sw/source/filter/ww8/wrtw8num.cxx
@@ -0,0 +1,918 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <hintids.hxx>
+#include <vcl/font.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <numrule.hxx>
+#include <paratr.hxx>
+#include <charfmt.hxx>
+#include <ndtxt.hxx>
+#include <com/sun/star/i18n/ScriptType.hdl>
+
+#include <writerfilter/doctok/sprmids.hxx>
+
+#include "ww8attributeoutput.hxx"
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "wrtww8.hxx"
+#include "ww8par.hxx"
+
+using namespace ::com::sun::star;
+using namespace sw::types;
+using namespace sw::util;
+
+sal_uInt16 MSWordExportBase::DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 nLevel, sal_uInt16 nVal )
+{
+ sal_uInt16 nNumId = USHRT_MAX;
+ String sPrefix( CREATE_CONST_ASC( "WW8TempExport" ) );
+ sPrefix += String::CreateFromInt32( nUniqueList++ );
+ SwNumRule* pMyNumRule =
+ new SwNumRule( pDoc->GetUniqueNumRuleName( &sPrefix ),
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
+ pUsedNumTbl->Insert( pMyNumRule, pUsedNumTbl->Count() );
+
+ for ( sal_uInt16 i = 0; i < MAXLEVEL; i++ )
+ {
+ const SwNumFmt& rSubRule = pRule->Get(i);
+ pMyNumRule->Set( i, rSubRule );
+ }
+
+ SwNumFmt aNumFmt( pMyNumRule->Get( nLevel ) );
+ aNumFmt.SetStart( nVal );
+ pMyNumRule->Set( nLevel, aNumFmt );
+
+ nNumId = GetId( *pMyNumRule );
+
+ //Map the old list to our new list
+ aRuleDuplicates[GetId( *pRule )] = nNumId;
+
+ return nNumId;
+}
+
+sal_uInt16 MSWordExportBase::GetId( const SwNumRule& rNumRule )
+{
+ if ( !pUsedNumTbl )
+ {
+ pUsedNumTbl = new SwNumRuleTbl;
+ pUsedNumTbl->Insert( &pDoc->GetNumRuleTbl(), 0 );
+ // Check, if the outline rule is already inserted into <pUsedNumTbl>.
+ // If yes, do not insert it again.
+ bool bOutlineRuleAdded( false );
+ for ( sal_uInt16 n = pUsedNumTbl->Count(); n; )
+ {
+ const SwNumRule& rRule = *pUsedNumTbl->GetObject( --n );
+ if ( !pDoc->IsUsed( rRule ) )
+ {
+ pUsedNumTbl->Remove( n );
+ }
+ else if ( &rRule == pDoc->GetOutlineNumRule() )
+ {
+ bOutlineRuleAdded = true;
+ }
+ }
+
+ if ( !bOutlineRuleAdded )
+ {
+ // jetzt noch die OutlineRule einfuegen
+ SwNumRule* pR = (SwNumRule*)pDoc->GetOutlineNumRule();
+ pUsedNumTbl->Insert( pR, pUsedNumTbl->Count() );
+ }
+ // <--
+ }
+ SwNumRule* p = (SwNumRule*)&rNumRule;
+ sal_uInt16 nRet = pUsedNumTbl->GetPos(p);
+
+ //Is this list now duplicated into a new list which we should use
+ // #i77812# - perform 'deep' search in duplication map
+ ::std::map<sal_uInt16,sal_uInt16>::const_iterator aResult = aRuleDuplicates.end();
+ do {
+ aResult = aRuleDuplicates.find(nRet);
+ if ( aResult != aRuleDuplicates.end() )
+ {
+ nRet = (*aResult).second;
+ }
+ } while ( aResult != aRuleDuplicates.end() );
+ // <--
+
+ return nRet;
+}
+
+//GetFirstLineOffset should problem never appear unadorned apart from
+//here in the ww export filter
+sal_Int16 GetWordFirstLineOffset(const SwNumFmt &rFmt)
+{
+ OSL_ENSURE( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
+ "<GetWordFirstLineOffset> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
+
+ short nFirstLineOffset;
+ if (rFmt.GetNumAdjust() == SVX_ADJUST_RIGHT)
+ nFirstLineOffset = -rFmt.GetCharTextDistance();
+ else
+ nFirstLineOffset = rFmt.GetFirstLineOffset();
+ return nFirstLineOffset;
+}
+
+void WW8Export::WriteNumbering()
+{
+ if ( !pUsedNumTbl )
+ return; // no numbering is used
+
+ // list formats - LSTF
+ pFib->fcPlcfLst = pTableStrm->Tell();
+ SwWW8Writer::WriteShort( *pTableStrm, pUsedNumTbl->Count() );
+ NumberingDefinitions();
+ // set len to FIB
+ pFib->lcbPlcfLst = pTableStrm->Tell() - pFib->fcPlcfLst;
+
+ // list formats - LVLF
+ AbstractNumberingDefinitions();
+
+ // list formats - LFO
+ OutOverrideListTab();
+
+ // list formats - ListNames
+ OutListNamesTab();
+}
+
+void WW8AttributeOutput::NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule )
+{
+ SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nId );
+ SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nId );
+
+ // mit keinen Styles verbunden
+ for ( int i = 0; i < WW8ListManager::nMaxLevel; ++i )
+ SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0xFFF );
+
+ sal_uInt8 nFlags = 0, nDummy = 0;
+ if ( rRule.IsContinusNum() )
+ nFlags |= 0x1;
+
+ *m_rWW8Export.pTableStrm << nFlags << nDummy;
+}
+
+void MSWordExportBase::NumberingDefinitions()
+{
+ if ( !pUsedNumTbl )
+ return; // no numbering is used
+
+ sal_uInt16 nCount = pUsedNumTbl->Count();
+
+ // Write static data of SwNumRule - LSTF
+ for ( sal_uInt16 n = 0; n < nCount; ++n )
+ {
+ const SwNumRule& rRule = *pUsedNumTbl->GetObject( n );
+
+ AttrOutput().NumberingDefinition( n + 1, rRule );
+ }
+}
+
+void WW8AttributeOutput::NumberingLevel( sal_uInt8 /*nLevel*/,
+ sal_uInt16 nStart,
+ sal_uInt16 nNumberingType,
+ SvxAdjust eAdjust,
+ const sal_uInt8 *pNumLvlPos,
+ sal_uInt8 nFollow,
+ const wwFont *pFont,
+ const SfxItemSet *pOutSet,
+ sal_Int16 nIndentAt,
+ sal_Int16 nFirstLineIndex,
+ sal_Int16 nListTabPos,
+ const String &rNumberingString
+ )
+{
+ // Start value
+ SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, nStart );
+
+ // Type
+ *m_rWW8Export.pTableStrm << WW8Export::GetNumId( nNumberingType );
+
+ // Justification
+ sal_uInt8 nAlign;
+ switch ( eAdjust )
+ {
+ case SVX_ADJUST_CENTER: nAlign = 1; break;
+ default: nAlign = 0; break;
+ }
+ *m_rWW8Export.pTableStrm << nAlign;
+
+ // Write the rgbxchNums[9], positions of placeholders for paragraph
+ // numbers in the text
+ m_rWW8Export.pTableStrm->Write( pNumLvlPos, WW8ListManager::nMaxLevel );
+
+ // Type of the character between the bullet and the text
+ *m_rWW8Export.pTableStrm << nFollow;
+
+ // dxaSoace/dxaIndent (Word 6 compatibility)
+ SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, 0 );
+ SwWW8Writer::WriteLong( *m_rWW8Export.pTableStrm, 0 );
+
+ // cbGrpprlChpx
+ WW8Bytes aCharAtrs;
+ if ( pOutSet )
+ {
+ WW8Bytes* pOldpO = m_rWW8Export.pO;
+ m_rWW8Export.pO = &aCharAtrs;
+ if ( pFont )
+ {
+ sal_uInt16 nFontID = m_rWW8Export.maFontHelper.GetId( *pFont );
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc0 );
+ m_rWW8Export.InsUInt16( nFontID );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc2 );
+ }
+ else
+ m_rWW8Export.pO->Insert( 93, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( nFontID );
+ }
+
+ m_rWW8Export.OutputItemSet( *pOutSet, false, true, i18n::ScriptType::LATIN, m_rWW8Export.mbExportModeRTF );
+
+ m_rWW8Export.pO = pOldpO;
+ }
+ *m_rWW8Export.pTableStrm << sal_uInt8( aCharAtrs.Count() );
+
+ // cbGrpprlPapx
+ sal_uInt8 aPapSprms [] = {
+ 0x5e, 0x84, 0, 0, // sprmPDxaLeft
+ 0x60, 0x84, 0, 0, // sprmPDxaLeft1
+ 0x15, 0xc6, 0x05, 0x00, 0x01, 0, 0, 0x06
+ };
+ *m_rWW8Export.pTableStrm << sal_uInt8( sizeof( aPapSprms ) );
+
+ // reserved
+ SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, 0 );
+
+ // pap sprms
+ sal_uInt8* pData = aPapSprms + 2;
+ Set_UInt16( pData, nIndentAt );
+ pData += 2;
+ Set_UInt16( pData, nFirstLineIndex );
+ pData += 5;
+ Set_UInt16( pData, nListTabPos );
+
+ m_rWW8Export.pTableStrm->Write( aPapSprms, sizeof( aPapSprms ));
+
+ // write Chpx
+ if( aCharAtrs.Count() )
+ m_rWW8Export.pTableStrm->Write( aCharAtrs.GetData(), aCharAtrs.Count() );
+
+ // write the num string
+ SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, rNumberingString.Len() );
+ SwWW8Writer::WriteString16( *m_rWW8Export.pTableStrm, rNumberingString, false );
+}
+
+void MSWordExportBase::AbstractNumberingDefinitions()
+{
+ sal_uInt16 nCount = pUsedNumTbl->Count();
+ sal_uInt16 n;
+
+ // prepare the NodeNum to generate the NumString
+ SwNumberTree::tNumberVector aNumVector;
+ for ( n = 0; n < WW8ListManager::nMaxLevel; ++n )
+ aNumVector.push_back( n );
+
+ StarSymbolToMSMultiFont *pConvert = 0;
+ for( n = 0; n < nCount; ++n )
+ {
+ AttrOutput().StartAbstractNumbering( n + 1 );
+
+ const SwNumRule& rRule = *pUsedNumTbl->GetObject( n );
+ sal_uInt8 nLvl;
+ sal_uInt8 nLevels = static_cast< sal_uInt8 >(rRule.IsContinusNum() ?
+ WW8ListManager::nMinLevel : WW8ListManager::nMaxLevel);
+ for( nLvl = 0; nLvl < nLevels; ++nLvl )
+ {
+ // write the static data of the SwNumFmt of this level
+ sal_uInt8 aNumLvlPos[WW8ListManager::nMaxLevel] = { 0,0,0,0,0,0,0,0,0 };
+
+ const SwNumFmt& rFmt = rRule.Get( nLvl );
+
+ sal_uInt8 nFollow = 0;
+ // #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ nFollow = 2; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
+ }
+ else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ switch ( rFmt.GetLabelFollowedBy() )
+ {
+ case SvxNumberFormat::LISTTAB:
+ {
+ // 0 (tab) unless there would be no content before the tab, in which case 2 (nothing)
+ nFollow = (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType()) ? 0 : 2;
+ }
+ break;
+ case SvxNumberFormat::SPACE:
+ {
+ // 1 (space) unless there would be no content before the space in which case 2 (nothing)
+ nFollow = (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType()) ? 1 : 2;
+ }
+ break;
+ case SvxNumberFormat::NOTHING:
+ {
+ nFollow = 2;
+ }
+ break;
+ default:
+ {
+ nFollow = 0;
+ OSL_FAIL( "unknown GetLabelFollowedBy() return value" );
+ }
+ }
+ }
+ // <--
+
+ // Build the NumString for this Level
+ String sNumStr;
+ String sFontName;
+ bool bWriteBullet = false;
+ const Font* pBulletFont=0;
+ rtl_TextEncoding eChrSet=0;
+ FontFamily eFamily=FAMILY_DECORATIVE;
+ if( SVX_NUM_CHAR_SPECIAL == rFmt.GetNumberingType() ||
+ SVX_NUM_BITMAP == rFmt.GetNumberingType() )
+ {
+ sNumStr = rFmt.GetBulletChar();
+ bWriteBullet = true;
+
+ pBulletFont = rFmt.GetBulletFont();
+ if (!pBulletFont)
+ {
+ pBulletFont = &numfunc::GetDefBulletFont();
+ }
+
+ eChrSet = pBulletFont->GetCharSet();
+ sFontName = pBulletFont->GetName();
+ eFamily = pBulletFont->GetFamily();
+
+ if ( sw::util::IsStarSymbol( sFontName ) )
+ SubstituteBullet( sNumStr, eChrSet, sFontName );
+
+ // #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ // <nFollow = 2>, if minimum label width equals 0 and
+ // minimum distance between label and text equals 0
+ nFollow = ( rFmt.GetFirstLineOffset() == 0 &&
+ rFmt.GetCharTextDistance() == 0 )
+ ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
+ }
+ // <--
+ }
+ else
+ {
+ if (SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType())
+ {
+ sal_uInt8* pLvlPos = aNumLvlPos;
+ // the numbering string has to be restrict
+ // to the level currently working on.
+ sNumStr = rRule.MakeNumString(aNumVector, false, true, nLvl);
+ // <--
+
+ // now search the nums in the string
+ for( sal_uInt8 i = 0; i <= nLvl; ++i )
+ {
+ String sSrch( String::CreateFromInt32( i ));
+ xub_StrLen nFnd = sNumStr.Search( sSrch );
+ if( STRING_NOTFOUND != nFnd )
+ {
+ *pLvlPos = (sal_uInt8)(nFnd + rFmt.GetPrefix().Len() + 1 );
+ ++pLvlPos;
+ sNumStr.SetChar( nFnd, (char)i );
+ }
+ }
+ // #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ // <nFollow = 2>, if minimum label width equals 0 and
+ // minimum distance between label and text equals 0
+ nFollow = ( rFmt.GetFirstLineOffset() == 0 &&
+ rFmt.GetCharTextDistance() == 0 )
+ ? 2 : 0; // ixchFollow: 0 - tab, 1 - blank, 2 - nothing
+ }
+ // <--
+ }
+
+ if( rFmt.GetPrefix().Len() )
+ sNumStr.Insert( rFmt.GetPrefix(), 0 );
+ sNumStr += rFmt.GetSuffix();
+ }
+
+ // Attributes of the numbering
+ wwFont *pPseudoFont = NULL;
+ const SfxItemSet* pOutSet = NULL;
+
+ // cbGrpprlChpx
+ SfxItemSet aSet( pDoc->GetAttrPool(), RES_CHRATR_BEGIN,
+ RES_CHRATR_END );
+ if ( rFmt.GetCharFmt() || bWriteBullet )
+ {
+ if ( bWriteBullet )
+ {
+ pOutSet = &aSet;
+
+ if ( rFmt.GetCharFmt() )
+ aSet.Put( rFmt.GetCharFmt()->GetAttrSet() );
+ aSet.ClearItem( RES_CHRATR_CJK_FONT );
+ aSet.ClearItem( RES_CHRATR_FONT );
+
+ if ( !sFontName.Len() )
+ sFontName = pBulletFont->GetName();
+
+ pPseudoFont = new wwFont( sFontName, pBulletFont->GetPitch(),
+ eFamily, eChrSet, SupportsUnicode() );
+ }
+ else
+ pOutSet = &rFmt.GetCharFmt()->GetAttrSet();
+ }
+
+ sal_Int16 nIndentAt = 0;
+ sal_Int16 nFirstLineIndex = 0;
+ sal_Int16 nListTabPos = 0;
+
+ // #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ nIndentAt = nListTabPos = rFmt.GetAbsLSpace();
+ nFirstLineIndex = GetWordFirstLineOffset(rFmt);
+ }
+ else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ nIndentAt = static_cast<sal_Int16>(rFmt.GetIndentAt());
+ nFirstLineIndex = static_cast<sal_Int16>(rFmt.GetFirstLineIndent());
+ nListTabPos = rFmt.GetLabelFollowedBy() == SvxNumberFormat::LISTTAB?
+ static_cast<sal_Int16>( rFmt.GetListtabPos() ) : 0;
+ }
+
+ AttrOutput().NumberingLevel( nLvl,
+ rFmt.GetStart(),
+ rFmt.GetNumberingType(),
+ rFmt.GetNumAdjust(),
+ aNumLvlPos,
+ nFollow,
+ pPseudoFont, pOutSet,
+ nIndentAt, nFirstLineIndex, nListTabPos,
+ sNumStr );
+
+ delete pPseudoFont;
+ }
+ AttrOutput().EndAbstractNumbering();
+ }
+ delete pConvert;
+}
+
+void WW8Export::OutOverrideListTab()
+{
+ if( !pUsedNumTbl )
+ return ; // no numbering is used
+
+ // write the "list format override" - LFO
+ sal_uInt16 nCount = pUsedNumTbl->Count();
+ sal_uInt16 n;
+
+ pFib->fcPlfLfo = pTableStrm->Tell();
+ SwWW8Writer::WriteLong( *pTableStrm, nCount );
+
+ for( n = 0; n < nCount; ++n )
+ {
+ SwWW8Writer::WriteLong( *pTableStrm, n + 1 );
+ SwWW8Writer::FillCount( *pTableStrm, 12 );
+ }
+ for( n = 0; n < nCount; ++n )
+ SwWW8Writer::WriteLong( *pTableStrm, -1 ); // no overwrite
+
+ // set len to FIB
+ pFib->lcbPlfLfo = pTableStrm->Tell() - pFib->fcPlfLfo;
+}
+
+void WW8Export::OutListNamesTab()
+{
+ if( !pUsedNumTbl )
+ return ; // no numbering is used
+
+ // write the "list format override" - LFO
+ sal_uInt16 nNms = 0, nCount = pUsedNumTbl->Count();
+
+ pFib->fcSttbListNames = pTableStrm->Tell();
+ SwWW8Writer::WriteShort( *pTableStrm, -1 );
+ SwWW8Writer::WriteLong( *pTableStrm, nCount );
+
+ for( ; nNms < nCount; ++nNms )
+ {
+ const SwNumRule& rRule = *pUsedNumTbl->GetObject( nNms );
+ String sNm;
+ if( !rRule.IsAutoRule() )
+ sNm = rRule.GetName();
+
+ SwWW8Writer::WriteShort( *pTableStrm, sNm.Len() );
+ if (sNm.Len())
+ SwWW8Writer::WriteString16(*pTableStrm, sNm, false);
+ }
+
+ SwWW8Writer::WriteLong( *pTableStrm, pFib->fcSttbListNames + 2, nNms );
+ // set len to FIB
+ pFib->lcbSttbListNames = pTableStrm->Tell() - pFib->fcSttbListNames;
+}
+
+/* */
+
+// old WW95-Code
+
+void WW8Export::OutputOlst( const SwNumRule& rRule )
+{
+ if ( bWrtWW8 )
+ return;
+
+ static sal_uInt8 aAnlvBase[] = { // Defaults
+ 1,0,0, // Upper Roman
+ 0x0C, // Hanging Indent, fPrev
+ 0,0,1,0x80,0,0,1,0,0x1b,1,0,0 };
+
+ static sal_uInt8 aSprmOlstHdr[] = { 133, 212 };
+
+ pO->Insert( aSprmOlstHdr, sizeof( aSprmOlstHdr ), pO->Count() );
+ WW8_OLST aOlst;
+ memset( &aOlst, 0, sizeof(aOlst) );
+ sal_uInt8* pC = aOlst.rgch;
+ sal_uInt8* pChars = (sal_uInt8*)pC;
+ sal_uInt16 nCharLen = 64;
+
+ for (sal_uInt16 j = 0; j < WW8ListManager::nMaxLevel; j++ ) // 9 variable ANLVs
+ {
+ memcpy( &aOlst.rganlv[j], aAnlvBase, sizeof( WW8_ANLV ) ); // Defaults
+
+ const SwNumFmt* pFmt = rRule.GetNumFmt( j );
+ if( pFmt )
+ BuildAnlvBase( aOlst.rganlv[j], pChars, nCharLen, rRule,
+ *pFmt, (sal_uInt8)j );
+ }
+
+ pO->Insert( (sal_uInt8*)&aOlst, sizeof( aOlst ), pO->Count() );
+}
+
+
+void WW8Export::Out_WwNumLvl( sal_uInt8 nWwLevel )
+{
+ pO->Insert( 13, pO->Count() );
+ pO->Insert( nWwLevel, pO->Count() );
+}
+
+void WW8Export::Out_SwNumLvl( sal_uInt8 nSwLevel )
+{
+ OSL_ENSURE( nSwLevel < MAXLEVEL, "numbered?");
+ Out_WwNumLvl( nSwLevel + 1 );
+}
+
+void WW8Export::BuildAnlvBulletBase(WW8_ANLV& rAnlv, sal_uInt8*& rpCh,
+ sal_uInt16& rCharLen, const SwNumFmt& rFmt)
+{
+ ByteToSVBT8(11, rAnlv.nfc);
+
+ sal_uInt8 nb = 0; // Zahlentyp
+ switch (rFmt.GetNumAdjust())
+ {
+ case SVX_ADJUST_RIGHT:
+ nb = 2;
+ break;
+ case SVX_ADJUST_CENTER:
+ nb = 1;
+ break;
+ case SVX_ADJUST_BLOCK:
+ case SVX_ADJUST_BLOCKLINE:
+ nb = 3;
+ break;
+ case SVX_ADJUST_LEFT:
+ case SVX_ADJUST_END:
+ break;
+ }
+
+ // #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ if (GetWordFirstLineOffset(rFmt) < 0)
+ nb |= 0x8; // number will be displayed using a hanging indent
+ }
+ // <--
+ ByteToSVBT8(nb, rAnlv.aBits1);
+
+ if (1 < rCharLen)
+ {
+ const Font& rFont = rFmt.GetBulletFont()
+ ? *rFmt.GetBulletFont()
+ : numfunc::GetDefBulletFont();
+ String sNumStr = rFmt.GetBulletChar();
+ rtl_TextEncoding eChrSet = rFont.GetCharSet();
+ String sFontName = rFont.GetName();
+
+ sal_uInt16 nFontId;
+ if (sw::util::IsStarSymbol(sFontName))
+ {
+ /*
+ If we are starsymbol then in ww7- mode we will always convert to a
+ windows 8bit symbol font and an index into it, to conversion to
+ 8 bit is complete at this stage.
+ */
+ SubstituteBullet(sNumStr, eChrSet, sFontName);
+ wwFont aPseudoFont(sFontName, rFont.GetPitch(), rFont.GetFamily(),
+ eChrSet, bWrtWW8);
+ nFontId = maFontHelper.GetId(aPseudoFont);
+ *rpCh = static_cast<sal_uInt8>(sNumStr.GetChar(0));
+ }
+ else
+ {
+ /*
+ Otherwise we are a unicode char and need to be converted back to
+ an 8 bit format. We happen to know that if the font is already an
+ 8 bit windows font currently, staroffice promotes the char into
+ the F000->F0FF range, so we can undo this, and we'll be back to
+ the equivalent 8bit location, otherwise we have to convert from
+ true unicode to an 8bit charset
+ */
+ nFontId = maFontHelper.GetId(rFont);
+ sal_Unicode cChar = sNumStr.GetChar(0);
+ if ( (eChrSet == RTL_TEXTENCODING_SYMBOL) && (cChar >= 0xF000) && (
+ cChar <= 0xF0FF) )
+ {
+ *rpCh = static_cast< sal_uInt8 >(cChar - 0xF000);
+ }
+ else
+ *rpCh = ByteString::ConvertFromUnicode(cChar, eChrSet);
+ }
+ rpCh++;
+ rCharLen--;
+ ShortToSVBT16(nFontId, rAnlv.ftc);
+ ByteToSVBT8( 1, rAnlv.cbTextBefore );
+ }
+ // #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ ShortToSVBT16( -GetWordFirstLineOffset(rFmt), rAnlv.dxaIndent );
+ ShortToSVBT16( rFmt.GetCharTextDistance(), rAnlv.dxaSpace );
+ }
+ else
+ {
+ ShortToSVBT16( 0, rAnlv.dxaIndent );
+ ShortToSVBT16( 0, rAnlv.dxaSpace );
+ }
+ // <--
+}
+
+void MSWordExportBase::SubstituteBullet( String& rNumStr,
+ rtl_TextEncoding& rChrSet, String& rFontName ) const
+{
+ StarSymbolToMSMultiFont *pConvert = 0;
+
+ if (!bSubstituteBullets)
+ return;
+
+ if (!bSubstituteBullets)
+ return;
+
+ if (!pConvert)
+ {
+ pConvert = CreateStarSymbolToMSMultiFont();
+ }
+ sal_Unicode cChar = rNumStr.GetChar(0);
+ String sFont = pConvert->ConvertChar(cChar);
+
+ if (sFont.Len())
+ {
+ rNumStr = static_cast< sal_Unicode >(cChar | 0xF000);
+ rFontName = sFont;
+ rChrSet = RTL_TEXTENCODING_SYMBOL;
+ }
+ else if ( SupportsUnicode() &&
+ (rNumStr.GetChar(0) < 0xE000 || rNumStr.GetChar(0) > 0xF8FF) )
+ {
+ /*
+ Ok we can't fit into a known windows unicode font, but
+ we are not in the private area, so we are a
+ standardized symbol, so turn off the symbol bit and
+ let words own font substitution kick in
+ */
+ rChrSet = RTL_TEXTENCODING_UNICODE;
+ rFontName = ::GetFontToken(rFontName, 0);
+ }
+ else
+ {
+ /*
+ Well we don't have an available substition, and we're
+ in our private area, so give up and show a standard
+ bullet symbol
+ */
+ rFontName.ASSIGN_CONST_ASC("Wingdings");
+ rNumStr = static_cast< sal_Unicode >(0x6C);
+ }
+ delete pConvert;
+}
+
+static void SwWw8_InsertAnlText( const String& rStr, sal_uInt8*& rpCh,
+ sal_uInt16& rCharLen, SVBT8& r8Len )
+{
+ sal_uInt8 nb = 0;
+ WW8Bytes aO;
+ SwWW8Writer::InsAsString8( aO, rStr, RTL_TEXTENCODING_MS_1252 );
+
+ sal_uInt16 nCnt = aO.Count();
+ if( nCnt && nCnt < rCharLen )
+ {
+ nb = (sal_uInt8)nCnt;
+ memcpy( rpCh, aO.GetData(), nCnt );
+ rpCh += nCnt;
+ rCharLen = rCharLen - nCnt;
+ }
+ ByteToSVBT8( nb, r8Len );
+}
+
+void WW8Export::BuildAnlvBase(WW8_ANLV& rAnlv, sal_uInt8*& rpCh,
+ sal_uInt16& rCharLen, const SwNumRule& rRul, const SwNumFmt& rFmt,
+ sal_uInt8 nSwLevel)
+{
+ ByteToSVBT8(WW8Export::GetNumId(rFmt.GetNumberingType()), rAnlv.nfc);
+
+ sal_uInt8 nb = 0;
+ switch (rFmt.GetNumAdjust())
+ {
+ case SVX_ADJUST_RIGHT:
+ nb = 2;
+ break;
+ case SVX_ADJUST_CENTER:
+ nb = 1;
+ break;
+ case SVX_ADJUST_BLOCK:
+ case SVX_ADJUST_BLOCKLINE:
+ nb = 3;
+ break;
+ case SVX_ADJUST_LEFT:
+ case SVX_ADJUST_END:
+ break;
+ }
+
+ bool bInclUpper = rFmt.GetIncludeUpperLevels() > 0;
+ if( bInclUpper )
+ nb |= 0x4; // include previous levels
+
+ if (GetWordFirstLineOffset(rFmt) < 0)
+ nb |= 0x8; // number will be displayed using a hanging indent
+ ByteToSVBT8( nb, rAnlv.aBits1 );
+
+ if( bInclUpper && !rRul.IsContinusNum() )
+ {
+ if( (nSwLevel >= WW8ListManager::nMinLevel )
+ && (nSwLevel<= WW8ListManager::nMaxLevel )
+ && (rFmt.GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) // UEberhaupt Nummerierung ?
+ { // -> suche, ob noch Zahlen davor
+ sal_uInt8 nUpper = rFmt.GetIncludeUpperLevels();
+ if( (nUpper <= WW8ListManager::nMaxLevel) &&
+ (rRul.Get(nUpper).GetNumberingType() != SVX_NUM_NUMBER_NONE ) ) // Nummerierung drueber ?
+ {
+ // dann Punkt einfuegen
+ SwWw8_InsertAnlText( aDotStr, rpCh, rCharLen,
+ rAnlv.cbTextBefore );
+ }
+
+ }
+ }
+ else
+ {
+ SwWw8_InsertAnlText( rFmt.GetPrefix(), rpCh, rCharLen,
+ rAnlv.cbTextBefore );
+ SwWw8_InsertAnlText( rFmt.GetSuffix(), rpCh, rCharLen,
+ rAnlv.cbTextAfter );
+ }
+
+ ShortToSVBT16( rFmt.GetStart(), rAnlv.iStartAt );
+ // #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ ShortToSVBT16( -GetWordFirstLineOffset(rFmt), rAnlv.dxaIndent );
+ ShortToSVBT16( rFmt.GetCharTextDistance(), rAnlv.dxaSpace );
+ }
+ else
+ {
+ ShortToSVBT16( 0, rAnlv.dxaIndent );
+ ShortToSVBT16( 0, rAnlv.dxaSpace );
+ }
+ // <--
+}
+
+void WW8Export::Out_NumRuleAnld( const SwNumRule& rRul, const SwNumFmt& rFmt,
+ sal_uInt8 nSwLevel )
+{
+ static sal_uInt8 aSprmAnldDefault[54] = {
+ 12, 52,
+ 1,0,0,0x0c,0,0,1,0x80,0,0,1,0,0x1b,1,0,0,0x2e,
+ 0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
+ sal_uInt8 aSprmAnld[54];
+
+ memcpy( aSprmAnld, aSprmAnldDefault, sizeof( aSprmAnld ) );
+ WW8_ANLD* pA = (WW8_ANLD*)(aSprmAnld + 2); // handlicher Pointer
+
+ sal_uInt8* pChars = (sal_uInt8*)(pA->rgchAnld);
+ sal_uInt16 nCharLen = 31;
+
+ if( nSwLevel == 11 )
+ BuildAnlvBulletBase( pA->eAnlv, pChars, nCharLen, rFmt );
+ else
+ BuildAnlvBase( pA->eAnlv, pChars, nCharLen, rRul, rFmt, nSwLevel );
+
+ // ... und raus damit
+ OutSprmBytes( (sal_uInt8*)&aSprmAnld, sizeof( aSprmAnld ) );
+}
+
+
+// Return: ist es eine Gliederung ?
+bool WW8Export::Out_SwNum(const SwTxtNode* pNd)
+{
+ int nLevel = pNd->GetActualListLevel();
+
+ if (nLevel < 0 || nLevel >= MAXLEVEL)
+ {
+ OSL_FAIL("Invalid level");
+
+ return false;
+ }
+
+ sal_uInt8 nSwLevel = static_cast< sal_uInt8 >(nLevel);
+
+ const SwNumRule* pRul = pNd->GetNumRule();
+ if( !pRul || nSwLevel == WW8ListManager::nMaxLevel)
+ return false;
+
+ bool bRet = true;
+
+ SwNumFmt aFmt(pRul->Get(nSwLevel));
+ // #i86652#
+ if ( aFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ const SvxLRSpaceItem& rLR = ItemGet<SvxLRSpaceItem>(*pNd, RES_LR_SPACE);
+ aFmt.SetAbsLSpace(writer_cast<short>(aFmt.GetAbsLSpace() + rLR.GetLeft()));
+ }
+
+ if (
+ aFmt.GetNumberingType() == SVX_NUM_NUMBER_NONE ||
+ aFmt.GetNumberingType() == SVX_NUM_CHAR_SPECIAL ||
+ aFmt.GetNumberingType() == SVX_NUM_BITMAP
+ )
+ {
+ Out_WwNumLvl(11);
+ Out_NumRuleAnld(*pRul, aFmt, 11);
+ bRet = false;
+ }
+ else if (
+ pRul->IsContinusNum() ||
+ (pRul->Get(1).GetIncludeUpperLevels() <= 1)
+ )
+ {
+ Out_WwNumLvl(10);
+ Out_NumRuleAnld(*pRul, aFmt, 10);
+ bRet = false;
+ }
+ else
+ {
+ Out_SwNumLvl(nSwLevel);
+ Out_NumRuleAnld(*pRul, aFmt, nSwLevel);
+ }
+ return bRet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/wrtw8sty.cxx b/sw/source/filter/ww8/wrtw8sty.cxx
new file mode 100644
index 000000000000..0f93dd67b669
--- /dev/null
+++ b/sw/source/filter/ww8/wrtw8sty.cxx
@@ -0,0 +1,2336 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <algorithm>
+#include <functional>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <rtl/tencinfo.h>
+#include <hintids.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdotext.hxx>
+#include <svx/fmglob.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <doc.hxx>
+#include <wrtww8.hxx>
+#include <docary.hxx>
+#include <poolfmt.hxx>
+#include <fmtpdsc.hxx>
+#include <pagedesc.hxx>
+#include <ndtxt.hxx>
+#include <ftninfo.hxx>
+#include <fmthdft.hxx>
+#include <section.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtftn.hxx>
+#include <ndindex.hxx>
+#include <txtftn.hxx>
+#include <charfmt.hxx>
+#include <docufld.hxx>
+#include <dcontact.hxx>
+#include <fmtcnct.hxx>
+#include <ftnidx.hxx>
+#include <fmtclds.hxx>
+#include <lineinfo.hxx>
+#include <fmtline.hxx>
+#include <swtable.hxx>
+#include <msfilter.hxx>
+#include <swmodule.hxx>
+
+#include <writerfilter/doctok/sprmids.hxx>
+
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "../inc/wwstyles.hxx"
+#include "ww8par.hxx"
+#include "ww8attributeoutput.hxx"
+#include "docxattributeoutput.hxx"
+#include "rtfattributeoutput.hxx"
+
+using namespace sw::util;
+using namespace nsHdFtFlags;
+
+struct WW8_SED
+{
+ SVBT16 aBits1; // orientation change + internal, Default: 6
+ SVBT32 fcSepx; // FC file offset to beginning of SEPX for section.
+ // 0xFFFFFFFF for no Sprms
+ SVBT16 fnMpr; // used internally by Windows Word, Default: 0
+ SVBT32 fcMpr; // FC, points to offset in FC space for MacWord
+ // Default: 0xffffffff ( nothing )
+ // cbSED is 12 (decimal)), C (hex).
+};
+
+SV_IMPL_VARARR( WW8_WrSepInfoPtrs, WW8_SepInfo )
+
+// class WW8_WrPlc0 ist erstmal nur fuer Header / Footer-Positionen, d.h. es
+// gibt keine inhaltstragende Struktur.
+class WW8_WrPlc0
+{
+private:
+ SvULongs aPos; // PTRARR von CPs / FCs
+ sal_uLong nOfs;
+
+ //No copying
+ WW8_WrPlc0(const WW8_WrPlc0&);
+ WW8_WrPlc0 &operator=(const WW8_WrPlc0&);
+public:
+ WW8_WrPlc0( sal_uLong nOffset );
+ sal_uInt16 Count() const { return aPos.Count(); }
+ void Append( sal_uLong nStartCpOrFc );
+ void Write( SvStream& rStrm );
+};
+
+//------------------------------------------------------------
+// Styles
+//------------------------------------------------------------
+
+#define WW8_RESERVED_SLOTS 15
+
+// GetId( SwCharFmt ) zur Benutzung im Text -> nil verboten,
+// "Default Char Style" stattdessen
+sal_uInt16 MSWordExportBase::GetId( const SwCharFmt& rFmt ) const
+{
+ sal_uInt16 nRet = pStyles->GetSlot( rFmt );
+ return ( nRet != 0x0fff ) ? nRet : 10; // Default Char Style
+}
+
+// GetId( SwTxtFmtColl ) zur Benutzung an TextNodes -> nil verboten,
+// "Standard" stattdessen
+sal_uInt16 MSWordExportBase::GetId( const SwTxtFmtColl& rColl ) const
+{
+ sal_uInt16 nRet = pStyles->GetSlot( rColl );
+ return ( nRet != 0xfff ) ? nRet : 0; // Default TxtFmtColl
+}
+
+
+
+//typedef pFmtT
+MSWordStyles::MSWordStyles( MSWordExportBase& rExport )
+ : m_rExport( rExport )
+{
+ // if exist any Foot-/End-Notes then get from the EndNoteInfo struct
+ // the CharFormats. They will create it!
+ if ( m_rExport.pDoc->GetFtnIdxs().Count() )
+ {
+ m_rExport.pDoc->GetEndNoteInfo().GetAnchorCharFmt( *m_rExport.pDoc );
+ m_rExport.pDoc->GetEndNoteInfo().GetCharFmt( *m_rExport.pDoc );
+ m_rExport.pDoc->GetFtnInfo().GetAnchorCharFmt( *m_rExport.pDoc );
+ m_rExport.pDoc->GetFtnInfo().GetCharFmt( *m_rExport.pDoc );
+ }
+ sal_uInt16 nAlloc = WW8_RESERVED_SLOTS + m_rExport.pDoc->GetCharFmts()->Count() - 1 +
+ m_rExport.pDoc->GetTxtFmtColls()->Count() - 1;
+
+ // etwas grosszuegig ( bis zu 15 frei )
+ pFmtA = new SwFmt*[ nAlloc ];
+ memset( pFmtA, 0, nAlloc * sizeof( SwFmt* ) );
+
+ BuildStylesTable();
+}
+
+MSWordStyles::~MSWordStyles()
+{
+ delete[] pFmtA;
+}
+
+// Sty_SetWWSlot() fuer Abhaengigkeiten der Styles -> nil ist erlaubt
+sal_uInt16 MSWordStyles::GetSlot( const SwFmt& rFmt ) const
+{
+ sal_uInt16 n;
+ for ( n = 0; n < nUsedSlots; n++ )
+ if ( pFmtA[n] == &rFmt )
+ return n;
+ return 0xfff; // 0xfff: WW: nil
+}
+
+sal_uInt16 MSWordStyles::BuildGetSlot( const SwFmt& rFmt )
+{
+ sal_uInt16 nRet;
+ switch ( nRet = rFmt.GetPoolFmtId() )
+ {
+ case RES_POOLCOLL_STANDARD:
+ nRet = 0;
+ break;
+
+ case RES_POOLCOLL_HEADLINE1:
+ case RES_POOLCOLL_HEADLINE2:
+ case RES_POOLCOLL_HEADLINE3:
+ case RES_POOLCOLL_HEADLINE4:
+ case RES_POOLCOLL_HEADLINE5:
+ case RES_POOLCOLL_HEADLINE6:
+ case RES_POOLCOLL_HEADLINE7:
+ case RES_POOLCOLL_HEADLINE8:
+ case RES_POOLCOLL_HEADLINE9:
+ nRet -= RES_POOLCOLL_HEADLINE1-1;
+ break;
+
+ default:
+ nRet = nUsedSlots++;
+ break;
+ }
+ return nRet;
+}
+
+sal_uInt16 MSWordStyles::GetWWId( const SwFmt& rFmt ) const
+{
+ sal_uInt16 nRet = ww::stiUser; // User-Style als default
+ sal_uInt16 nPoolId = rFmt.GetPoolFmtId();
+ if( nPoolId == RES_POOLCOLL_STANDARD )
+ nRet = 0;
+ else if( nPoolId >= RES_POOLCOLL_HEADLINE1 &&
+ nPoolId <= RES_POOLCOLL_HEADLINE9 )
+ nRet = static_cast< sal_uInt16 >(nPoolId + 1 - RES_POOLCOLL_HEADLINE1);
+ else if( nPoolId >= RES_POOLCOLL_TOX_IDX1 &&
+ nPoolId <= RES_POOLCOLL_TOX_IDX3 )
+ nRet = static_cast< sal_uInt16 >(nPoolId + 10 - RES_POOLCOLL_TOX_IDX1);
+ else if( nPoolId >= RES_POOLCOLL_TOX_CNTNT1 &&
+ nPoolId <= RES_POOLCOLL_TOX_CNTNT5 )
+ nRet = static_cast< sal_uInt16 >(nPoolId + 19 - RES_POOLCOLL_TOX_CNTNT1);
+ else if( nPoolId >= RES_POOLCOLL_TOX_CNTNT6 &&
+ nPoolId <= RES_POOLCOLL_TOX_CNTNT9 )
+ nRet = static_cast< sal_uInt16 >(nPoolId + 24 - RES_POOLCOLL_TOX_CNTNT6);
+ else
+ switch( nPoolId )
+ {
+ case RES_POOLCOLL_FOOTNOTE: nRet = 29; break;
+ case RES_POOLCOLL_MARGINAL: nRet = 30; break;
+ case RES_POOLCOLL_HEADER: nRet = 31; break;
+ case RES_POOLCOLL_FOOTER: nRet = 32; break;
+ case RES_POOLCOLL_TOX_IDXH: nRet = 33; break;
+ case RES_POOLCOLL_LABEL: nRet = 34; break;
+ case RES_POOLCOLL_LABEL_DRAWING: nRet = 35; break;
+ case RES_POOLCOLL_JAKETADRESS: nRet = 36; break;
+ case RES_POOLCOLL_SENDADRESS: nRet = 37; break;
+ case RES_POOLCOLL_ENDNOTE: nRet = 43; break;
+ case RES_POOLCOLL_TOX_AUTHORITIESH: nRet = 44; break;
+ case RES_POOLCOLL_TOX_CNTNTH: nRet = 46; break;
+ case RES_POOLCOLL_BUL_LEVEL1: nRet = 48; break;
+ case RES_POOLCOLL_LISTS_BEGIN: nRet = 47; break;
+ case RES_POOLCOLL_NUM_LEVEL1: nRet = 49; break;
+ case RES_POOLCOLL_BUL_LEVEL2: nRet = 54; break;
+ case RES_POOLCOLL_BUL_LEVEL3: nRet = 55; break;
+ case RES_POOLCOLL_BUL_LEVEL4: nRet = 56; break;
+ case RES_POOLCOLL_BUL_LEVEL5: nRet = 57; break;
+ case RES_POOLCOLL_NUM_LEVEL2: nRet = 58; break;
+ case RES_POOLCOLL_NUM_LEVEL3: nRet = 59; break;
+ case RES_POOLCOLL_NUM_LEVEL4: nRet = 60; break;
+ case RES_POOLCOLL_NUM_LEVEL5: nRet = 61; break;
+ case RES_POOLCOLL_DOC_TITEL: nRet = 62; break;
+ case RES_POOLCOLL_SIGNATURE: nRet = 64; break;
+ case RES_POOLCOLL_TEXT: nRet = 66; break;
+ case RES_POOLCOLL_TEXT_MOVE: nRet = 67; break;
+ case RES_POOLCOLL_BUL_NONUM1: nRet = 68; break;
+ case RES_POOLCOLL_BUL_NONUM2: nRet = 69; break;
+ case RES_POOLCOLL_BUL_NONUM3: nRet = 70; break;
+ case RES_POOLCOLL_BUL_NONUM4: nRet = 71; break;
+ case RES_POOLCOLL_BUL_NONUM5: nRet = 72; break;
+ case RES_POOLCOLL_DOC_SUBTITEL: nRet = 74; break;
+ case RES_POOLCOLL_GREETING: nRet = 75; break;
+ case RES_POOLCOLL_TEXT_IDENT: nRet = 77; break;
+
+ case RES_POOLCHR_FOOTNOTE_ANCHOR: nRet = 38; break;
+ case RES_POOLCHR_ENDNOTE_ANCHOR: nRet = 42; break;
+ case RES_POOLCHR_INET_NORMAL: nRet = 85; break;
+ case RES_POOLCHR_INET_VISIT: nRet = 86; break;
+ case RES_POOLCHR_HTML_STRONG: nRet = 87; break;
+ case RES_POOLCHR_HTML_EMPHASIS: nRet = 88; break;
+ case RES_POOLCHR_LINENUM: nRet = 40; break;
+ case RES_POOLCHR_PAGENO: nRet = 41; break;
+ }
+ return nRet;
+}
+
+void MSWordStyles::BuildStylesTable()
+{
+ nUsedSlots = WW8_RESERVED_SLOTS; // soviele sind reserviert fuer
+ // Standard und HeadingX u.a.
+ SwFmt* pFmt;
+ sal_uInt16 n;
+ const SvPtrarr& rArr = *m_rExport.pDoc->GetCharFmts(); // erst CharFmt
+ // das Default-ZeichenStyle ( 0 ) wird nicht mit ausgegeben !
+ for( n = 1; n < rArr.Count(); n++ )
+ {
+ pFmt = (SwFmt*)rArr[n];
+ pFmtA[ BuildGetSlot( *pFmt ) ] = pFmt;
+ }
+
+ const SvPtrarr& rArr2 = *m_rExport.pDoc->GetTxtFmtColls(); // dann TxtFmtColls
+ // das Default-TextStyle ( 0 ) wird nicht mit ausgegeben !
+ for( n = 1; n < rArr2.Count(); n++ )
+ {
+ pFmt = (SwFmt*)rArr2[n];
+ pFmtA[ BuildGetSlot( *pFmt ) ] = pFmt;
+ }
+}
+
+/// For WW8 only - extend pO so that the size of pTableStrm is even.
+static void impl_SkipOdd( WW8Bytes* pO, sal_Size nTableStrmTell )
+{
+ if ( ( nTableStrmTell + pO->Count() ) & 1 ) // Start auf gerader
+ pO->Insert( (sal_uInt8)0, pO->Count() ); // Adresse
+}
+
+void WW8AttributeOutput::EndStyle()
+{
+ impl_SkipOdd( m_rWW8Export.pO, m_rWW8Export.pTableStrm->Tell() );
+
+ short nLen = m_rWW8Export.pO->Count() - 2; // Laenge des Styles
+ sal_uInt8* p = (sal_uInt8*)m_rWW8Export.pO->GetData() + nPOPosStdLen1;
+ ShortToSVBT16( nLen, p ); // nachtragen
+ p = (sal_uInt8*)m_rWW8Export.pO->GetData() + nPOPosStdLen2;
+ ShortToSVBT16( nLen, p ); // dito
+
+ m_rWW8Export.pTableStrm->Write( m_rWW8Export.pO->GetData(), m_rWW8Export.pO->Count() ); // ins File damit
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren fuer naechsten
+}
+
+void WW8AttributeOutput::StartStyle( const String& rName, bool bPapFmt, sal_uInt16 nWwBase,
+ sal_uInt16 nWwNext, sal_uInt16 nWwId, sal_uInt16 /*nId*/, bool bAutoUpdate )
+{
+ sal_uInt8 aWW8_STD[ sizeof( WW8_STD ) ];
+ sal_uInt8* pData = aWW8_STD;
+ memset( &aWW8_STD, 0, sizeof( WW8_STD ) );
+
+ sal_uInt16 nBit16 = 0x1000; // fInvalHeight
+ nBit16 |= (ww::stiNil & nWwId);
+ Set_UInt16( pData, nBit16 );
+
+ nBit16 = nWwBase << 4; // istdBase
+ nBit16 |= bPapFmt ? 1 : 2; // sgc
+ Set_UInt16( pData, nBit16 );
+
+ nBit16 = nWwNext << 4; // istdNext
+ nBit16 |= bPapFmt ? 2 : 1; // cupx
+ Set_UInt16( pData, nBit16 );
+
+ pData += sizeof( sal_uInt16 ); // bchUpe
+
+ if( m_rWW8Export.bWrtWW8 )
+ {
+ nBit16 = bAutoUpdate ? 1 : 0; // fAutoRedef : 1
+ Set_UInt16( pData, nBit16 );
+ //-------- jetzt neu:
+ // ab Ver8 gibts zwei Felder mehr:
+ //sal_uInt16 fHidden : 1; /* hidden from UI? */
+ //sal_uInt16 : 14; /* unused bits */
+ }
+
+
+ sal_uInt16 nLen = static_cast< sal_uInt16 >( ( pData - aWW8_STD ) + 1 +
+ ((m_rWW8Export.bWrtWW8 ? 2 : 1 ) * (rName.Len() + 1)) ); // vorlaeufig
+
+ WW8Bytes* pO = m_rWW8Export.pO;
+ nPOPosStdLen1 = pO->Count(); // Adr1 zum nachtragen der Laenge
+
+ SwWW8Writer::InsUInt16( *pO, nLen );
+ pO->Insert( aWW8_STD, static_cast< sal_uInt16 >( pData - aWW8_STD ), pO->Count() );
+
+ nPOPosStdLen2 = nPOPosStdLen1 + 8; // Adr2 zum nachtragen von "end of upx"
+
+ // Namen schreiben
+ if( m_rWW8Export.bWrtWW8 )
+ {
+ SwWW8Writer::InsUInt16( *pO, rName.Len() ); // Laenge
+ SwWW8Writer::InsAsString16( *pO, rName );
+ }
+ else
+ {
+ pO->Insert( (sal_uInt8)rName.Len(), pO->Count() ); // Laenge
+ SwWW8Writer::InsAsString8( *pO, rName, RTL_TEXTENCODING_MS_1252 );
+ }
+ pO->Insert( (sal_uInt8)0, pO->Count() ); // Trotz P-String 0 am Ende!
+}
+
+void MSWordStyles::SetStyleDefaults( const SwFmt& rFmt, bool bPap )
+{
+ const SwModify* pOldMod = m_rExport.pOutFmtNode;
+ m_rExport.pOutFmtNode = &rFmt;
+ bool aFlags[ static_cast< sal_uInt16 >(RES_FRMATR_END) - RES_CHRATR_BEGIN ];
+ sal_uInt16 nStt, nEnd, n;
+ if( bPap )
+ nStt = RES_PARATR_BEGIN, nEnd = RES_FRMATR_END;
+ else
+ nStt = RES_CHRATR_BEGIN, nEnd = RES_TXTATR_END;
+
+ // dynamic defaults
+ const SfxItemPool& rPool = *rFmt.GetAttrSet().GetPool();
+ for( n = nStt; n < nEnd; ++n )
+ aFlags[ n - RES_CHRATR_BEGIN ] = 0 != rPool.GetPoolDefaultItem( n );
+
+ // static defaults, that differs between WinWord and SO
+ if( bPap )
+ {
+ aFlags[ static_cast< sal_uInt16 >(RES_PARATR_WIDOWS) - RES_CHRATR_BEGIN ] = 1;
+ aFlags[ static_cast< sal_uInt16 >(RES_PARATR_HYPHENZONE) - RES_CHRATR_BEGIN ] = 1;
+ }
+ else
+ {
+ aFlags[ RES_CHRATR_FONTSIZE - RES_CHRATR_BEGIN ] = 1;
+ aFlags[ RES_CHRATR_LANGUAGE - RES_CHRATR_BEGIN ] = 1;
+ }
+
+ const SfxItemSet* pOldI = m_rExport.GetCurItemSet();
+ m_rExport.SetCurItemSet( &rFmt.GetAttrSet() );
+
+ const bool* pFlags = aFlags + ( nStt - RES_CHRATR_BEGIN );
+ for ( n = nStt; n < nEnd; ++n, ++pFlags )
+ {
+ if ( *pFlags && !m_rExport.ignoreAttributeForStyles( n )
+ && SFX_ITEM_SET != rFmt.GetItemState(n, false))
+ {
+ //If we are a character property then see if it is one of the
+ //western/asian ones that must be collapsed together for export to
+ //word. If so default to the western varient.
+ if ( bPap || m_rExport.CollapseScriptsforWordOk(
+ i18n::ScriptType::LATIN, n) )
+ {
+ m_rExport.AttrOutput().OutputItem( rFmt.GetFmtAttr( n, true ) );
+ }
+ }
+ }
+
+ m_rExport.SetCurItemSet( pOldI );
+ m_rExport.pOutFmtNode = pOldMod;
+}
+
+void WW8AttributeOutput::StartStyleProperties( bool bParProp, sal_uInt16 nStyle )
+{
+ WW8Bytes* pO = m_rWW8Export.pO;
+
+ impl_SkipOdd( pO, m_rWW8Export.pTableStrm->Tell() );
+
+ sal_uInt16 nLen = ( bParProp ) ? 2 : 0; // Default-Laenge
+ m_nStyleLenPos = pO->Count(); // Laenge zum Nachtragen
+ // Keinen Pointer merken, da sich bei
+ // _grow der Pointer aendert !
+
+ SwWW8Writer::InsUInt16( *pO, nLen ); // Style-Len
+
+ m_nStyleStartSize = pO->Count();
+
+ if ( bParProp )
+ SwWW8Writer::InsUInt16( *pO, nStyle ); // Style-Nummer
+}
+
+void MSWordStyles::WriteProperties( const SwFmt* pFmt, bool bParProp, sal_uInt16 nPos,
+ bool bInsDefCharSiz )
+{
+ m_rExport.AttrOutput().StartStyleProperties( bParProp, nPos );
+
+ OSL_ENSURE( m_rExport.pCurrentStyle == NULL, "Current style not NULL" ); // set current style before calling out
+ m_rExport.pCurrentStyle = pFmt;
+
+ m_rExport.OutputFormat( *pFmt, bParProp, !bParProp );
+
+ OSL_ENSURE( m_rExport.pCurrentStyle == pFmt, "current style was changed" );
+ // reset current style...
+ m_rExport.pCurrentStyle = NULL;
+
+ if ( bInsDefCharSiz ) // nicht abgeleitet v. anderem Style
+ SetStyleDefaults( *pFmt, bParProp );
+
+ m_rExport.AttrOutput().EndStyleProperties( bParProp );
+}
+
+void WW8AttributeOutput::EndStyleProperties( bool /*bParProp*/ )
+{
+ WW8Bytes* pO = m_rWW8Export.pO;
+
+ sal_uInt16 nLen = pO->Count() - m_nStyleStartSize;
+ sal_uInt8* pUpxLen = (sal_uInt8*)pO->GetData() + m_nStyleLenPos; // Laenge zum Nachtragen
+ ShortToSVBT16( nLen, pUpxLen ); // Default-Laenge eintragen
+}
+
+void MSWordStyles::GetStyleData( SwFmt* pFmt, bool& bFmtColl, sal_uInt16& nBase, sal_uInt16& nNext )
+{
+ bFmtColl = pFmt->Which() == RES_TXTFMTCOLL || pFmt->Which() == RES_CONDTXTFMTCOLL;
+
+ // Default: none
+ nBase = 0xfff;
+
+ // Derived from?
+ if ( !pFmt->IsDefault() )
+ nBase = GetSlot( *pFmt->DerivedFrom() );
+
+ SwFmt* pNext;
+ if ( bFmtColl )
+ pNext = &((SwTxtFmtColl*)pFmt)->GetNextTxtFmtColl();
+ else
+ pNext = pFmt; // CharFmt: next CharFmt == self
+
+ nNext = GetSlot( *pNext );
+}
+
+void WW8AttributeOutput::DefaultStyle( sal_uInt16 nStyle )
+{
+ if ( nStyle == 10 ) // Default Char-Style ( nur WW )
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ static sal_uInt8 aDefCharSty[] = {
+ 0x42, 0x00,
+ 0x41, 0x40, 0xF2, 0xFF, 0xA1, 0x00, 0x42, 0x00,
+ 0x00, 0x00, 0x19, 0x00, 0x41, 0x00, 0x62, 0x00,
+ 0x73, 0x00, 0x61, 0x00, 0x74, 0x00, 0x7A, 0x00,
+ 0x2D, 0x00, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00,
+ 0x6E, 0x00, 0x64, 0x00, 0x61, 0x00, 0x72, 0x00,
+ 0x64, 0x00, 0x73, 0x00, 0x63, 0x00, 0x68, 0x00,
+ 0x72, 0x00, 0x69, 0x00, 0x66, 0x00, 0x74, 0x00,
+ 0x61, 0x00, 0x72, 0x00, 0x74, 0x00, 0x00, 0x00,
+ 0x00, 0x00 };
+ m_rWW8Export.pTableStrm->Write( &aDefCharSty, sizeof( aDefCharSty ) );
+ }
+ else
+ {
+ static sal_uInt8 aDefCharSty[] = {
+ 0x26, 0x00,
+ 0x41, 0x40, 0xF2, 0xFF, 0xA1, 0x00, 0x26, 0x00,
+ 0x19, 0x41, 0x62, 0x73, 0x61, 0x74, 0x7A, 0x2D,
+ 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64,
+ 0x73, 0x63, 0x68, 0x72, 0x69, 0x66, 0x74, 0x61,
+ 0x72, 0x74, 0x00, 0x00, 0x00, 0x00 };
+ m_rWW8Export.pTableStrm->Write( &aDefCharSty, sizeof( aDefCharSty ) );
+ }
+ }
+ else
+ {
+ sal_uInt16 n = 0;
+ m_rWW8Export.pTableStrm->Write( &n , 2 ); // leerer Style
+ }
+}
+
+// OutputStyle geht fuer TxtFmtColls und CharFmts
+void MSWordStyles::OutputStyle( SwFmt* pFmt, sal_uInt16 nPos )
+{
+ if ( !pFmt )
+ m_rExport.AttrOutput().DefaultStyle( nPos );
+ else
+ {
+ bool bFmtColl;
+ sal_uInt16 nBase, nWwNext;
+
+ GetStyleData( pFmt, bFmtColl, nBase, nWwNext );
+
+ String aName = pFmt->GetName();
+ if ( aName.EqualsAscii( "Default" ) )
+ aName = String::CreateFromAscii( "Normal" );
+
+ m_rExport.AttrOutput().StartStyle( aName, bFmtColl,
+ nBase, nWwNext, GetWWId( *pFmt ), nPos,
+ pFmt->IsAutoUpdateFmt() );
+
+ if ( bFmtColl )
+ WriteProperties( pFmt, true, nPos, nBase==0xfff ); // UPX.papx
+
+ WriteProperties( pFmt, false, nPos, bFmtColl && nBase==0xfff ); // UPX.chpx
+
+ m_rExport.AttrOutput().EndStyle();
+ }
+}
+
+void WW8AttributeOutput::StartStyles()
+{
+ WW8Fib& rFib = *m_rWW8Export.pFib;
+
+ sal_uLong nCurPos = m_rWW8Export.pTableStrm->Tell();
+ if ( nCurPos & 1 ) // Start auf gerader
+ {
+ *m_rWW8Export.pTableStrm << (char)0; // Adresse
+ ++nCurPos;
+ }
+ rFib.fcStshfOrig = rFib.fcStshf = nCurPos;
+ m_nStyAnzPos = nCurPos + 2; // Anzahl wird nachgetragen
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ static sal_uInt8 aStShi[] = {
+ 0x12, 0x00,
+ 0x0F, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x5B, 0x00,
+ 0x0F, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00 };
+
+ m_rWW8Export.pTableStrm->Write( &aStShi, sizeof( aStShi ) );
+ }
+ else
+ {
+ static sal_uInt8 aStShi[] = {
+ 0x0E, 0x00,
+ 0x0F, 0x00, 0x08, 0x00, 0x01, 0x00, 0x4B, 0x00,
+ 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ m_rWW8Export.pTableStrm->Write( &aStShi, sizeof( aStShi ) );
+ }
+}
+
+void WW8AttributeOutput::EndStyles( sal_uInt16 nNumberOfStyles )
+{
+ WW8Fib& rFib = *m_rWW8Export.pFib;
+
+ rFib.lcbStshfOrig = rFib.lcbStshf = m_rWW8Export.pTableStrm->Tell() - rFib.fcStshf;
+ SwWW8Writer::WriteShort( *m_rWW8Export.pTableStrm, m_nStyAnzPos, nNumberOfStyles );
+}
+
+void MSWordStyles::OutputStylesTable()
+{
+ m_rExport.bStyDef = true;
+
+ m_rExport.AttrOutput().StartStyles();
+
+ sal_uInt16 n;
+ for ( n = 0; n < nUsedSlots; n++ )
+ OutputStyle( pFmtA[n], n );
+
+ m_rExport.AttrOutput().EndStyles( nUsedSlots );
+
+ m_rExport.bStyDef = false;
+}
+
+//---------------------------------------------------------------------------
+// Fonts
+//---------------------------------------------------------------------------
+wwFont::wwFont(const String &rFamilyName, FontPitch ePitch, FontFamily eFamily,
+ rtl_TextEncoding eChrSet, bool bWrtWW8) : mbAlt(false), mbWrtWW8(bWrtWW8), mePitch(ePitch), meFamily(eFamily), meChrSet(eChrSet)
+{
+ FontMapExport aResult(rFamilyName);
+ msFamilyNm = aResult.msPrimary;
+ msAltNm = aResult.msSecondary;
+ if (msAltNm.Len() && msAltNm != msFamilyNm &&
+ (msFamilyNm.Len() + msAltNm.Len() + 2 <= 65) )
+ {
+ //max size of szFfn in 65 chars
+ mbAlt = true;
+ }
+
+ memset(maWW8_FFN, 0, sizeof(maWW8_FFN));
+
+ if (bWrtWW8)
+ {
+ maWW8_FFN[0] = (sal_uInt8)( 6 - 1 + 0x22 + ( 2 * ( 1 + msFamilyNm.Len() ) ));
+ if (mbAlt)
+ maWW8_FFN[0] = static_cast< sal_uInt8 >(maWW8_FFN[0] + 2 * ( 1 + msAltNm.Len()));
+ }
+ else
+ {
+ maWW8_FFN[0] = (sal_uInt8)( 6 - 1 + 1 + msFamilyNm.Len() );
+ if (mbAlt)
+ maWW8_FFN[0] = static_cast< sal_uInt8 >(maWW8_FFN[0] + 1 + msAltNm.Len());
+ }
+
+ sal_uInt8 aB = 0;
+ switch(ePitch)
+ {
+ case PITCH_VARIABLE:
+ aB |= 2; // aF.prg = 2
+ break;
+ case PITCH_FIXED:
+ aB |= 1;
+ break;
+ default: // aF.prg = 0 : DEFAULT_PITCH (windows.h)
+ break;
+ }
+ aB |= 1 << 2; // aF.fTrueType = 1; weiss ich nicht besser;
+
+ switch(eFamily)
+ {
+ case FAMILY_ROMAN:
+ aB |= 1 << 4; // aF.ff = 1;
+ break;
+ case FAMILY_SWISS:
+ aB |= 2 << 4; // aF.ff = 2;
+ break;
+ case FAMILY_MODERN:
+ aB |= 3 << 4; // aF.ff = 3;
+ break;
+ case FAMILY_SCRIPT:
+ aB |= 4 << 4; // aF.ff = 4;
+ break;
+ case FAMILY_DECORATIVE:
+ aB |= 5 << 4; // aF.ff = 5;
+ break;
+ default: // aF.ff = 0; FF_DONTCARE (windows.h)
+ break;
+ }
+ maWW8_FFN[1] = aB;
+
+ ShortToSVBT16( 400, &maWW8_FFN[2] ); // weiss ich nicht besser
+ // 400 == FW_NORMAL (windows.h)
+ //
+ //#i61927# For unicode fonts like Arial Unicode, Word 97+ sets the chs
+ //to SHIFTJIS presumably to capture that it's a multi-byte encoding font
+ //but Word95 doesn't do this, and sets it to 0 (ANSI), so we should do the
+ //same
+ maWW8_FFN[4] = bWrtWW8 ?
+ sw::ms::rtl_TextEncodingToWinCharset(eChrSet) :
+ rtl_getBestWindowsCharsetFromTextEncoding(eChrSet);
+
+ if (mbAlt)
+ maWW8_FFN[5] = static_cast< sal_uInt8 >(msFamilyNm.Len() + 1);
+}
+
+bool wwFont::Write(SvStream *pTableStrm) const
+{
+ pTableStrm->Write(maWW8_FFN, sizeof(maWW8_FFN)); // fixed part
+ if (mbWrtWW8)
+ {
+ // ab Ver8 sind folgende beiden Felder eingeschoben,
+ // werden von uns ignoriert.
+ //char panose[ 10 ]; // 0x6 PANOSE
+ //char fs[ 24 ]; // 0x10 FONTSIGNATURE
+ SwWW8Writer::FillCount(*pTableStrm, 0x22);
+ SwWW8Writer::WriteString16(*pTableStrm, msFamilyNm, true);
+ if (mbAlt)
+ SwWW8Writer::WriteString16(*pTableStrm, msAltNm, true);
+ }
+ else
+ {
+ SwWW8Writer::WriteString8(*pTableStrm, msFamilyNm, true,
+ RTL_TEXTENCODING_MS_1252);
+ if (mbAlt)
+ {
+ SwWW8Writer::WriteString8( *pTableStrm, msAltNm, true,
+ RTL_TEXTENCODING_MS_1252);
+ }
+ }
+ return true;
+}
+
+void wwFont::WriteDocx( const DocxAttributeOutput* rAttrOutput ) const
+{
+ // no font embedding, panose id, subsetting, ... implemented
+
+ rAttrOutput->StartFont( msFamilyNm );
+
+ if ( mbAlt )
+ rAttrOutput->FontAlternateName( msAltNm );
+ rAttrOutput->FontCharset( sw::ms::rtl_TextEncodingToWinCharset( meChrSet ), meChrSet );
+ rAttrOutput->FontFamilyType( meFamily );
+ rAttrOutput->FontPitchType( mePitch );
+
+ rAttrOutput->EndFont();
+}
+
+void wwFont::WriteRtf( const RtfAttributeOutput* rAttrOutput ) const
+{
+ rAttrOutput->FontFamilyType( meFamily, *this );
+ rAttrOutput->FontPitchType( mePitch );
+ rAttrOutput->FontCharset( sw::ms::rtl_TextEncodingToWinCharset( meChrSet ) );
+ rAttrOutput->StartFont( msFamilyNm );
+ if ( mbAlt )
+ rAttrOutput->FontAlternateName( msAltNm );
+ rAttrOutput->EndFont();
+}
+
+bool operator<(const wwFont &r1, const wwFont &r2)
+{
+ int nRet = memcmp(r1.maWW8_FFN, r2.maWW8_FFN, sizeof(r1.maWW8_FFN));
+ if (nRet == 0)
+ {
+ StringCompare eRet = r1.msFamilyNm.CompareTo(r2.msFamilyNm);
+ if (eRet == COMPARE_EQUAL)
+ eRet = r1.msAltNm.CompareTo(r2.msAltNm);
+ nRet = eRet;
+ }
+ return nRet < 0;
+}
+
+
+sal_uInt16 wwFontHelper::GetId(const wwFont &rFont)
+{
+ sal_uInt16 nRet;
+ ::std::map<wwFont, sal_uInt16>::const_iterator aIter = maFonts.find(rFont);
+ if (aIter != maFonts.end())
+ nRet = aIter->second;
+ else
+ {
+ nRet = static_cast< sal_uInt16 >(maFonts.size());
+ maFonts[rFont] = nRet;
+ }
+ return nRet;
+}
+
+void wwFontHelper::InitFontTable(bool bWrtWW8,const SwDoc& rDoc)
+{
+ mbWrtWW8 = bWrtWW8;
+
+ GetId(wwFont(CREATE_CONST_ASC("Times New Roman"), PITCH_VARIABLE,
+ FAMILY_ROMAN, RTL_TEXTENCODING_MS_1252,bWrtWW8));
+
+ GetId(wwFont(CREATE_CONST_ASC("Symbol"), PITCH_VARIABLE, FAMILY_ROMAN,
+ RTL_TEXTENCODING_SYMBOL,bWrtWW8));
+
+ GetId(wwFont(CREATE_CONST_ASC("Arial"), PITCH_VARIABLE, FAMILY_SWISS,
+ RTL_TEXTENCODING_MS_1252,bWrtWW8));
+
+ const SvxFontItem* pFont = (const SvxFontItem*)GetDfltAttr(RES_CHRATR_FONT);
+
+ GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(),
+ pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8));
+
+ const SfxItemPool& rPool = rDoc.GetAttrPool();
+ if (0 != (pFont = (const SvxFontItem*)rPool.GetPoolDefaultItem(RES_CHRATR_FONT)))
+ {
+ GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(),
+ pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8));
+ }
+
+ if (!bLoadAllFonts)
+ return;
+
+ const sal_uInt16 aTypes[] = { RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_FONT, 0 };
+ for (const sal_uInt16* pId = aTypes; *pId; ++pId)
+ {
+ sal_uInt32 const nMaxItem = rPool.GetItemCount2( *pId );
+ for (sal_uInt32 nGet = 0; nGet < nMaxItem; ++nGet)
+ {
+ pFont = (const SvxFontItem*)rPool.GetItem2( *pId, nGet );
+ if (0 != pFont)
+ {
+ GetId(wwFont(pFont->GetFamilyName(), pFont->GetPitch(),
+ pFont->GetFamily(), pFont->GetCharSet(),bWrtWW8));
+ }
+ }
+ }
+}
+
+sal_uInt16 wwFontHelper::GetId(const Font& rFont)
+{
+ wwFont aFont(rFont.GetName(), rFont.GetPitch(), rFont.GetFamily(),
+ rFont.GetCharSet(), mbWrtWW8);
+ return GetId(aFont);
+}
+
+sal_uInt16 wwFontHelper::GetId(const SvxFontItem& rFont)
+{
+ wwFont aFont(rFont.GetFamilyName(), rFont.GetPitch(), rFont.GetFamily(),
+ rFont.GetCharSet(), mbWrtWW8);
+ return GetId(aFont);
+}
+
+::std::vector< const wwFont* > wwFontHelper::AsVector() const
+{
+ ::std::vector<const wwFont *> aFontList( maFonts.size() );
+
+ typedef ::std::map<wwFont, sal_uInt16>::const_iterator myiter;
+ myiter aEnd = maFonts.end();
+ for ( myiter aIter = maFonts.begin(); aIter != aEnd; ++aIter )
+ aFontList[aIter->second] = &aIter->first;
+
+ return aFontList;
+}
+
+void wwFontHelper::WriteFontTable(SvStream *pTableStream, WW8Fib& rFib)
+{
+ rFib.fcSttbfffn = pTableStream->Tell();
+ /*
+ * Reserve some space to fill in the len after we know how big it is
+ */
+ if (mbWrtWW8)
+ SwWW8Writer::WriteLong(*pTableStream, 0);
+ else
+ SwWW8Writer::WriteShort(*pTableStream, 0);
+
+ /*
+ * Convert from fast insertion map to linear vector in the order that we
+ * want to write.
+ */
+ ::std::vector<const wwFont *> aFontList( AsVector() );
+
+ /*
+ * Write them all to pTableStream
+ */
+ ::std::for_each(aFontList.begin(), aFontList.end(),
+ ::std::bind2nd(::std::mem_fun(&wwFont::Write),pTableStream));
+
+ /*
+ * Write the position and len in the FIB
+ */
+ rFib.lcbSttbfffn = pTableStream->Tell() - rFib.fcSttbfffn;
+ if (mbWrtWW8)
+ SwWW8Writer::WriteLong( *pTableStream, rFib.fcSttbfffn, maFonts.size());
+ else
+ {
+ SwWW8Writer::WriteShort( *pTableStream, rFib.fcSttbfffn,
+ (sal_Int16)rFib.lcbSttbfffn );
+ }
+}
+
+void wwFontHelper::WriteFontTable( const DocxAttributeOutput& rAttrOutput )
+{
+ ::std::vector<const wwFont *> aFontList( AsVector() );
+
+ ::std::for_each( aFontList.begin(), aFontList.end(),
+ ::std::bind2nd( ::std::mem_fun( &wwFont::WriteDocx ), &rAttrOutput ) );
+}
+
+void wwFontHelper::WriteFontTable( const RtfAttributeOutput& rAttrOutput )
+{
+ ::std::vector<const wwFont *> aFontList( AsVector() );
+
+ ::std::for_each( aFontList.begin(), aFontList.end(),
+ ::std::bind2nd( ::std::mem_fun( &wwFont::WriteRtf ), &rAttrOutput ) );
+}
+
+
+WW8_WrPlc0::WW8_WrPlc0( sal_uLong nOffset )
+ : aPos( 4, 4 ), nOfs( nOffset )
+{
+}
+
+void WW8_WrPlc0::Append( sal_uLong nStartCpOrFc )
+{
+ aPos.Insert( nStartCpOrFc - nOfs, aPos.Count() );
+}
+
+void WW8_WrPlc0::Write( SvStream& rStrm )
+{
+ sal_uInt16 nLen = aPos.Count();
+ for( sal_uInt16 i = 0; i < nLen; ++i )
+ {
+ SVBT32 nP;
+ UInt32ToSVBT32( aPos[i], nP );
+ rStrm.Write( nP, 4 );
+ }
+}
+
+//------------------------------------------------------------------------------
+
+//------------------------------------------------------------------------------
+// class MSWordSections : Uebersetzung PageDescs in Sections
+// behandelt auch Header und Footer
+//------------------------------------------------------------------------------
+
+MSWordSections::MSWordSections( MSWordExportBase& rExport )
+ : mbDocumentIsProtected( false ),
+ aSects( 4, 4 )
+{
+ const SwSectionFmt *pFmt = 0;
+ rExport.pAktPageDesc = &const_cast<const SwDoc *>(rExport.pDoc)->GetPageDesc( 0 );
+
+ const SfxPoolItem* pI;
+ const SwNode* pNd = rExport.pCurPam->GetCntntNode();
+ const SfxItemSet* pSet = pNd ? &((SwCntntNode*)pNd)->GetSwAttrSet() : 0;
+
+ sal_uLong nRstLnNum = pSet ? ((SwFmtLineNumber&)pSet->Get( RES_LINENUMBER )).GetStartValue() : 0;
+
+ const SwTableNode* pTblNd = rExport.pCurPam->GetNode()->FindTableNode();
+ const SwSectionNode* pSectNd;
+ if ( pTblNd )
+ {
+ pSet = &pTblNd->GetTable().GetFrmFmt()->GetAttrSet();
+ pNd = pTblNd;
+ }
+ else if ( 0 != ( pSectNd = pNd->FindSectionNode() ) )
+ {
+ if ( TOX_HEADER_SECTION == pSectNd->GetSection().GetType() &&
+ pSectNd->StartOfSectionNode()->IsSectionNode() )
+ {
+ pSectNd = pSectNd->StartOfSectionNode()->GetSectionNode();
+ }
+
+ if ( TOX_CONTENT_SECTION == pSectNd->GetSection().GetType() )
+ {
+ pNd = pSectNd;
+ rExport.pCurPam->GetPoint()->nNode = *pNd;
+ }
+
+ if ( CONTENT_SECTION == pSectNd->GetSection().GetType() )
+ pFmt = pSectNd->GetSection().GetFmt();
+ }
+
+ // Hole evtl. Pagedesc des 1. Nodes
+ if ( pSet &&
+ SFX_ITEM_ON == pSet->GetItemState( RES_PAGEDESC, true, &pI ) &&
+ ( (SwFmtPageDesc*)pI )->GetPageDesc() )
+ {
+ AppendSection( *(SwFmtPageDesc*)pI, *pNd, pFmt, nRstLnNum );
+ }
+ else
+ AppendSection( rExport.pAktPageDesc, pFmt, nRstLnNum );
+}
+
+WW8_WrPlcSepx::WW8_WrPlcSepx( MSWordExportBase& rExport )
+ : MSWordSections( rExport ),
+ aCps( 4, 4 ),
+ pAttrs( 0 ),
+ pTxtPos( 0 ),
+ bNoMoreSections( false )
+{
+ // to be in sync with the AppendSection() call in the MSWordSections
+ // constructor
+ aCps.Insert( sal_uLong( 0 ), aCps.Count() );
+}
+
+MSWordSections::~MSWordSections()
+{
+}
+
+WW8_WrPlcSepx::~WW8_WrPlcSepx()
+{
+ sal_uInt16 nLen = aSects.Count();
+ if( pAttrs )
+ {
+ while( nLen )
+ delete[] pAttrs[ --nLen ].pData;
+ delete[] pAttrs;
+ }
+ delete pTxtPos;
+}
+
+sal_uInt16 MSWordSections::CurrentNumberOfColumns( const SwDoc &rDoc ) const
+{
+ OSL_ENSURE( aSects.Count(), "no segement inserted yet" );
+ if ( !aSects.Count() )
+ return 1;
+
+ return NumberOfColumns( rDoc, aSects[aSects.Count() - 1] );
+}
+
+sal_uInt16 MSWordSections::NumberOfColumns( const SwDoc &rDoc, const WW8_SepInfo& rInfo ) const
+{
+ const SwPageDesc* pPd = rInfo.pPageDesc;
+ if ( !pPd )
+ pPd = &rDoc.GetPageDesc( 0 );
+
+ if ( !pPd )
+ {
+ OSL_ENSURE( pPd, "totally impossible" );
+ return 1;
+ }
+
+ const SfxItemSet &rSet = pPd->GetMaster().GetAttrSet();
+ SfxItemSet aSet( *rSet.GetPool(), RES_COL, RES_COL );
+ aSet.SetParent( &rSet );
+
+ //0xffffffff, what the hell is going on with that!, fixme most terribly
+ if ( rInfo.pSectionFmt && (SwSectionFmt*)0xFFFFFFFF != rInfo.pSectionFmt )
+ aSet.Put( rInfo.pSectionFmt->GetFmtAttr( RES_COL ) );
+
+ const SwFmtCol& rCol = (const SwFmtCol&)aSet.Get( RES_COL );
+ const SwColumns& rColumns = rCol.GetColumns();
+ return rColumns.Count();
+}
+
+const WW8_SepInfo* MSWordSections::CurrentSectionInfo()
+{
+ if ( aSects.Count() > 0 )
+ return &aSects[aSects.Count() - 1];
+
+ return NULL;
+}
+
+void MSWordSections::AppendSection( const SwPageDesc* pPd,
+ const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo )
+{
+ aSects.Insert( WW8_SepInfo( pPd, pSectionFmt, nLnNumRestartNo ),
+ aSects.Count() );
+ NeedsDocumentProtected( aSects[aSects.Count()-1] );
+}
+
+void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwPageDesc* pPd,
+ const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo )
+{
+ if ( !bNoMoreSections )
+ {
+ aCps.Insert( nStartCp, aCps.Count() );
+
+ AppendSection( pPd, pSectionFmt, nLnNumRestartNo );
+ }
+}
+
+void MSWordSections::AppendSection( const SwFmtPageDesc& rPD,
+ const SwNode& rNd, const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo )
+{
+ WW8_SepInfo aI( rPD.GetPageDesc(), pSectionFmt, nLnNumRestartNo,
+ rPD.GetNumOffset(), &rNd );
+ aSects.Insert( aI, aSects.Count() );
+ NeedsDocumentProtected( aI );
+}
+
+void WW8_WrPlcSepx::AppendSep( WW8_CP nStartCp, const SwFmtPageDesc& rPD,
+ const SwNode& rNd, const SwSectionFmt* pSectionFmt, sal_uLong nLnNumRestartNo )
+{
+ if ( !bNoMoreSections )
+ {
+ aCps.Insert(nStartCp, aCps.Count());
+
+ AppendSection( rPD, rNd, pSectionFmt, nLnNumRestartNo );
+ }
+}
+
+// MSWordSections::SetNum() setzt in jeder Section beim 1. Aufruf den
+// Num-Pointer, alle folgenden Aufrufe werden ignoriert. Damit wird
+// die erste Aufzaehlung einer Section uebernommen.
+
+void MSWordSections::SetNum( const SwTxtNode* pNumNd )
+{
+ WW8_SepInfo& rInfo = aSects[ aSects.Count() - 1 ];
+ if ( !rInfo.pNumNd ) // noch nicht belegt
+ rInfo.pNumNd = pNumNd;
+}
+
+void WW8_WrPlcSepx::WriteFtnEndTxt( WW8Export& rWrt, sal_uLong nCpStt )
+{
+ sal_uInt8 nInfoFlags = 0;
+ const SwFtnInfo& rInfo = rWrt.pDoc->GetFtnInfo();
+ if( rInfo.aErgoSum.Len() ) nInfoFlags |= 0x02;
+ if( rInfo.aQuoVadis.Len() ) nInfoFlags |= 0x04;
+
+ sal_uInt8 nEmptyStt = rWrt.bWrtWW8 ? 0 : 6;
+ if( nInfoFlags )
+ {
+ if( rWrt.bWrtWW8 )
+ pTxtPos->Append( nCpStt ); // empty footenote separator
+
+ if( 0x02 & nInfoFlags ) // Footenote contiunation separator
+ {
+ pTxtPos->Append( nCpStt );
+ rWrt.WriteStringAsPara( rInfo.aErgoSum );
+ rWrt.WriteStringAsPara( aEmptyStr );
+ nCpStt = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+ }
+ else if( rWrt.bWrtWW8 )
+ pTxtPos->Append( nCpStt );
+
+ if( 0x04 & nInfoFlags ) // Footenote contiunation notice
+ {
+ pTxtPos->Append( nCpStt );
+ rWrt.WriteStringAsPara( rInfo.aQuoVadis );
+ rWrt.WriteStringAsPara( aEmptyStr );
+ nCpStt = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+ }
+ else if( rWrt.bWrtWW8 )
+ pTxtPos->Append( nCpStt );
+
+ if( rWrt.bWrtWW8 )
+ nEmptyStt = 3;
+ else
+ rWrt.pDop->grpfIhdt = nInfoFlags;
+ }
+
+ while( 6 > nEmptyStt++ )
+ pTxtPos->Append( nCpStt );
+
+ // gleich die Flags am Dop setzen
+ WW8Dop& rDop = *rWrt.pDop;
+ // Footnote Info
+ switch( rInfo.eNum )
+ {
+ case FTNNUM_PAGE: rDop.rncFtn = 2; break;
+ case FTNNUM_CHAPTER: rDop.rncFtn = 1; break;
+ default: rDop.rncFtn = 0; break;
+ } // rncFtn
+ rDop.nfcFtnRef = WW8Export::GetNumId( rInfo.aFmt.GetNumberingType() );
+ rDop.nFtn = rInfo.nFtnOffset + 1;
+ rDop.fpc = rWrt.bFtnAtTxtEnd ? 2 : 1;
+
+ // Endnote Info
+ rDop.rncEdn = 0; // rncEdn: Don't Restart
+ const SwEndNoteInfo& rEndInfo = rWrt.pDoc->GetEndNoteInfo();
+ rDop.nfcEdnRef = WW8Export::GetNumId( rEndInfo.aFmt.GetNumberingType() );
+ rDop.nEdn = rEndInfo.nFtnOffset + 1;
+ rDop.epc = rWrt.bEndAtTxtEnd ? 3 : 0;
+}
+
+void MSWordSections::SetHeaderFlag( sal_uInt8& rHeadFootFlags, const SwFmt& rFmt,
+ sal_uInt8 nFlag )
+{
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rFmt.GetItemState(RES_HEADER, true, &pItem)
+ && ((SwFmtHeader*)pItem)->IsActive() &&
+ ((SwFmtHeader*)pItem)->GetHeaderFmt() )
+ rHeadFootFlags |= nFlag;
+}
+
+void MSWordSections::SetFooterFlag( sal_uInt8& rHeadFootFlags, const SwFmt& rFmt,
+ sal_uInt8 nFlag )
+{
+ const SfxPoolItem* pItem;
+ if( SFX_ITEM_SET == rFmt.GetItemState(RES_FOOTER, true, &pItem)
+ && ((SwFmtFooter*)pItem)->IsActive() &&
+ ((SwFmtFooter*)pItem)->GetFooterFmt() )
+ rHeadFootFlags |= nFlag;
+}
+
+void WW8_WrPlcSepx::OutHeaderFooter( WW8Export& rWrt, bool bHeader,
+ const SwFmt& rFmt, sal_uLong& rCpPos, sal_uInt8 nHFFlags,
+ sal_uInt8 nFlag, sal_uInt8 nBreakCode)
+{
+ if ( nFlag & nHFFlags )
+ {
+ pTxtPos->Append( rCpPos );
+ rWrt.WriteHeaderFooterText( rFmt, bHeader);
+ rWrt.WriteStringAsPara( aEmptyStr ); // CR ans Ende ( sonst mault WW )
+ rCpPos = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+ }
+ else if ( rWrt.bWrtWW8 )
+ {
+ pTxtPos->Append( rCpPos );
+ if (rWrt.bHasHdr && nBreakCode!=0)
+ {
+ rWrt.WriteStringAsPara( aEmptyStr ); // Empty paragraph for empty header/footer
+ rWrt.WriteStringAsPara( aEmptyStr ); // a CR that WW8 needs for end of the stream
+ rCpPos = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+ }
+ }
+}
+
+void MSWordSections::NeedsDocumentProtected(const WW8_SepInfo &rInfo)
+{
+ if (rInfo.IsProtected())
+ mbDocumentIsProtected = true;
+}
+
+bool WW8_SepInfo::IsProtected() const
+{
+ bool bRet = false;
+ if (
+ pSectionFmt &&
+ ((SwSectionFmt*)0xFFFFFFFF != pSectionFmt)
+ )
+ {
+ const SwSection *pSection = pSectionFmt->GetSection();
+ if (pSection && pSection->IsProtect())
+ {
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+
+void MSWordSections::CheckForFacinPg( WW8Export& rWrt ) const
+{
+ // 2 Werte werden gesetzt
+ // Dop.fFacingPages == Kopf-/Fusszeilen unterschiedlich
+ // Dop.fSwapBordersFacingPgs == gespiegelte Raender
+ for( sal_uInt16 i = 0, nEnde = 0; i < aSects.Count(); ++i )
+ {
+ WW8_SepInfo& rSepInfo = aSects[i];
+ if( !rSepInfo.pSectionFmt )
+ {
+ const SwPageDesc* pPd = rSepInfo.pPageDesc;
+ if( pPd->GetFollow() && pPd != pPd->GetFollow() &&
+ pPd->GetFollow()->GetFollow() == pPd->GetFollow() &&
+ rSepInfo.pPDNd &&
+ pPd->IsFollowNextPageOfNode( *rSepInfo.pPDNd ) )
+ // das ist also 1.Seite und nachfolgende, also nur den
+ // follow beachten
+ pPd = pPd->GetFollow();
+
+ // left-/right chain of pagedescs ?
+ else if( !( 1 & nEnde ) &&
+ pPd->GetFollow() && pPd != pPd->GetFollow() &&
+ pPd->GetFollow()->GetFollow() == pPd &&
+ (( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
+ nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ||
+ ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
+ nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ))
+ {
+ rWrt.pDop->fFacingPages = rWrt.pDop->fMirrorMargins = true;
+ nEnde |= 1;
+ }
+
+ if( !( 1 & nEnde ) &&
+ ( !pPd->IsHeaderShared() || !pPd->IsFooterShared() ))
+ {
+ rWrt.pDop->fFacingPages = true;
+ nEnde |= 1;
+ }
+ if( !( 2 & nEnde ) &&
+ nsUseOnPage::PD_MIRROR == ( nsUseOnPage::PD_MIRROR & pPd->ReadUseOn() ))
+ {
+ rWrt.pDop->fSwapBordersFacingPgs =
+ rWrt.pDop->fMirrorMargins = true;
+ nEnde |= 2;
+ }
+
+ if( 3 == nEnde )
+ break; // weiter brauchen wird nicht
+ }
+ }
+}
+
+int MSWordSections::HasBorderItem( const SwFmt& rFmt )
+{
+ const SfxPoolItem* pItem;
+ return SFX_ITEM_SET == rFmt.GetItemState(RES_BOX, true, &pItem) &&
+ ( ((SvxBoxItem*)pItem)->GetTop() ||
+ ((SvxBoxItem*)pItem)->GetBottom() ||
+ ((SvxBoxItem*)pItem)->GetLeft() ||
+ ((SvxBoxItem*)pItem)->GetRight() );
+}
+
+void WW8AttributeOutput::StartSection()
+{
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
+}
+
+void WW8AttributeOutput::SectionFormProtection( bool bProtected )
+{
+ //If the document is to be exported as protected, then if a segment
+ //is not protected, set the unlocked flag
+ if ( m_rWW8Export.pSepx->DocumentIsProtected() && !bProtected )
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFProtected );
+ else
+ m_rWW8Export.pO->Insert( 139, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( 1 , m_rWW8Export.pO->Count() );
+ }
+}
+
+void WW8AttributeOutput::SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo )
+{
+ // sprmSNLnnMod - activate Line Numbering and define Modulo
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SNLnnMod );
+ else
+ m_rWW8Export.pO->Insert( 154, m_rWW8Export.pO->Count() );
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (sal_uInt16)rLnNumInfo.GetCountBy() );
+
+ // sprmSDxaLnn - xPosition of Line Number
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SDxaLnn );
+ else
+ m_rWW8Export.pO->Insert( 155, m_rWW8Export.pO->Count() );
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (sal_uInt16)rLnNumInfo.GetPosFromLeft() );
+
+ // sprmSLnc - restart number: 0 per page, 1 per section, 2 never restart
+ if ( nRestartNo || !rLnNumInfo.IsRestartEachPage() )
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SLnc );
+ else
+ m_rWW8Export.pO->Insert( 152, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( nRestartNo ? 1 : 2, m_rWW8Export.pO->Count() );
+ }
+
+ // sprmSLnnMin - Restart the Line Number with given value
+ if ( nRestartNo )
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SLnnMin );
+ else
+ m_rWW8Export.pO->Insert( 160, m_rWW8Export.pO->Count() );
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, (sal_uInt16)nRestartNo - 1 );
+ }
+}
+
+void WW8AttributeOutput::SectionTitlePage()
+{
+ // sprmSFTitlePage
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFTitlePage );
+ else
+ m_rWW8Export.pO->Insert( 143, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
+}
+
+void WW8AttributeOutput::SectionPageBorders( const SwFrmFmt* pPdFmt, const SwFrmFmt* pPdFirstPgFmt )
+{
+ if ( m_rWW8Export.bWrtWW8 ) // Seitenumrandung schreiben
+ {
+ sal_uInt16 nPgBorder = MSWordSections::HasBorderItem( *pPdFmt ) ? 0 : USHRT_MAX;
+ if ( pPdFmt != pPdFirstPgFmt )
+ {
+ if ( MSWordSections::HasBorderItem( *pPdFirstPgFmt ) )
+ {
+ if ( USHRT_MAX == nPgBorder )
+ {
+ nPgBorder = 1;
+ // nur die 1. Seite umrandet -> BoxItem aus dem
+ // richtigen Format besorgen
+ m_rWW8Export.pISet = &pPdFirstPgFmt->GetAttrSet();
+ OutputItem( pPdFirstPgFmt->GetFmtAttr( RES_BOX ) );
+ }
+ }
+ else if ( !nPgBorder )
+ nPgBorder = 2;
+ }
+
+ if ( USHRT_MAX != nPgBorder )
+ {
+ // Flag und das Border Attribut schreiben
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SPgbProp );
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, nPgBorder );
+ }
+ }
+}
+
+void WW8AttributeOutput::SectionBiDi( bool bBiDi )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFBiDi );
+ m_rWW8Export.pO->Insert( bBiDi? 1: 0, m_rWW8Export.pO->Count() );
+ }
+}
+
+void WW8AttributeOutput::SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber )
+{
+ // sprmSNfcPgn
+ sal_uInt8 nb = WW8Export::GetNumId( nNumType );
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SNfcPgn );
+ else
+ m_rWW8Export.pO->Insert( 147, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( nb, m_rWW8Export.pO->Count() );
+
+ if ( nPageRestartNumber )
+ {
+ // sprmSFPgnRestart
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SFPgnRestart );
+ else
+ m_rWW8Export.pO->Insert( 150, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
+
+ // sprmSPgnStart
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SPgnStart );
+ else
+ m_rWW8Export.pO->Insert( 161, m_rWW8Export.pO->Count() );
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, nPageRestartNumber );
+ }
+}
+
+void WW8AttributeOutput::SectionType( sal_uInt8 nBreakCode )
+{
+ if ( 2 != nBreakCode ) // new page is the default
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_SBkc );
+ else
+ m_rWW8Export.pO->Insert( 142, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( nBreakCode, m_rWW8Export.pO->Count() );
+ }
+}
+
+void WW8AttributeOutput::SectionWW6HeaderFooterFlags( sal_uInt8 nHeadFootFlags )
+{
+ if ( nHeadFootFlags && !m_rWW8Export.bWrtWW8 )
+ {
+ sal_uInt8 nTmpFlags = nHeadFootFlags;
+ if ( m_rWW8Export.pDop->fFacingPages )
+ {
+ if ( !(nTmpFlags & WW8_FOOTER_EVEN) && (nTmpFlags & WW8_FOOTER_ODD ) )
+ nTmpFlags |= WW8_FOOTER_EVEN;
+
+ if ( !(nTmpFlags & WW8_HEADER_EVEN) && (nTmpFlags & WW8_HEADER_ODD ) )
+ nTmpFlags |= WW8_HEADER_EVEN;
+ }
+
+ // sprmSGprfIhdt, wird nur noch im WW95 benoetigt
+ m_rWW8Export.pO->Insert( 153, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( nTmpFlags, m_rWW8Export.pO->Count() );
+ }
+}
+
+void WW8Export::SetupSectionPositions( WW8_PdAttrDesc* pA )
+{
+ if ( !pA )
+ return;
+
+ if ( pO->Count() )
+ { // waren Attrs vorhanden ?
+ pA->nLen = pO->Count();
+ pA->pData = new sal_uInt8 [pO->Count()];
+ memcpy( pA->pData, pO->GetData(), pO->Count() ); // -> merken
+ pO->Remove( 0, pO->Count() ); // leeren fuer HdFt-Text
+ }
+ else
+ { // keine Attrs da
+ pA->pData = 0;
+ pA->nLen = 0;
+ }
+}
+
+void WW8Export::WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
+ const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt, sal_uInt8 nBreakCode )
+{
+ sal_uLong nCpPos = Fc2Cp( Strm().Tell() );
+
+ IncrementHdFtIndex();
+ if ( !(nHeadFootFlags & WW8_HEADER_EVEN) && pDop->fFacingPages )
+ pSepx->OutHeaderFooter( *this, true, rFmt, nCpPos, nHeadFootFlags, WW8_HEADER_ODD, nBreakCode );
+ else
+ pSepx->OutHeaderFooter( *this, true, rLeftFmt, nCpPos, nHeadFootFlags, WW8_HEADER_EVEN, nBreakCode );
+ IncrementHdFtIndex();
+ pSepx->OutHeaderFooter( *this, true, rFmt, nCpPos, nHeadFootFlags, WW8_HEADER_ODD, nBreakCode );
+
+ IncrementHdFtIndex();
+ if ( !(nHeadFootFlags & WW8_FOOTER_EVEN) && pDop->fFacingPages )
+ pSepx->OutHeaderFooter( *this, false, rFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_ODD, nBreakCode );
+ else
+ pSepx->OutHeaderFooter( *this, false, rLeftFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_EVEN, nBreakCode );
+ IncrementHdFtIndex();
+ pSepx->OutHeaderFooter( *this, false, rFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_ODD, nBreakCode );
+
+ //#i24344# Drawing objects cannot be directly shared between main hd/ft
+ //and title hd/ft so we need to differenciate them
+ IncrementHdFtIndex();
+ pSepx->OutHeaderFooter( *this, true, rFirstPageFmt, nCpPos, nHeadFootFlags, WW8_HEADER_FIRST, nBreakCode );
+ pSepx->OutHeaderFooter( *this, false, rFirstPageFmt, nCpPos, nHeadFootFlags, WW8_FOOTER_FIRST, nBreakCode );
+}
+
+void MSWordExportBase::SectionProperties( const WW8_SepInfo& rSepInfo, WW8_PdAttrDesc* pA )
+{
+ const SwPageDesc* pPd = rSepInfo.pPageDesc;
+
+ if ( rSepInfo.pSectionFmt && !pPd )
+ pPd = &const_cast<const SwDoc *>( pDoc )->GetPageDesc( 0 );
+
+ pAktPageDesc = pPd;
+
+ if ( !pPd )
+ return;
+
+ bool bOldPg = bOutPageDescs;
+ bOutPageDescs = true;
+
+ AttrOutput().StartSection();
+
+ // forms
+ AttrOutput().SectionFormProtection( rSepInfo.IsProtected() );
+
+ // line numbers
+ const SwLineNumberInfo& rLnNumInfo = pDoc->GetLineNumberInfo();
+ if ( rLnNumInfo.IsPaintLineNumbers() )
+ AttrOutput().SectionLineNumbering( rSepInfo.nLnNumRestartNo, rLnNumInfo );
+
+ /* sprmSBkc, break code: 0 No break, 1 New column
+ 2 New page, 3 Even page, 4 Odd page
+ */
+ sal_uInt8 nBreakCode = 2; // default neue Seite beginnen
+ bool bOutPgDscSet = true, bLeftRightPgChain = false;
+ const SwFrmFmt* pPdFmt = &pPd->GetMaster();
+ const SwFrmFmt* pPdFirstPgFmt = pPdFmt;
+ if ( rSepInfo.pSectionFmt )
+ {
+ // ist pSectionFmt gesetzt, dann gab es einen SectionNode
+ // gueltiger Pointer -> Section beginnt,
+ // 0xfff -> Section wird beendet
+ nBreakCode = 0; // fortlaufender Abschnitt
+
+ if ( rSepInfo.pPDNd && rSepInfo.pPDNd->IsCntntNode() )
+ {
+ if ( !NoPageBreakSection( &rSepInfo.pPDNd->GetCntntNode()->GetSwAttrSet() ) )
+ {
+ nBreakCode = 2;
+ }
+ }
+
+ if ( (SwSectionFmt*)0xFFFFFFFF != rSepInfo.pSectionFmt )
+ {
+ if ( nBreakCode == 0 )
+ bOutPgDscSet = false;
+
+ // Itemset erzeugen, das das PgDesk-AttrSet beerbt:
+ // als Nachkomme wird bei 'deep'-OutputItemSet
+ // auch der Vorfahr abgeklappert
+ const SfxItemSet* pPdSet = &pPdFmt->GetAttrSet();
+ SfxItemSet aSet( *pPdSet->GetPool(), pPdSet->GetRanges() );
+ aSet.SetParent( pPdSet );
+
+ // am Nachkommen NUR die Spaltigkeit gemaess Sect-Attr.
+ // umsetzen
+ aSet.Put( rSepInfo.pSectionFmt->GetFmtAttr( RES_COL ) );
+
+ const SvxLRSpaceItem &rSectionLR =
+ ItemGet<SvxLRSpaceItem>( *(rSepInfo.pSectionFmt), RES_LR_SPACE );
+ const SvxLRSpaceItem &rPageLR =
+ ItemGet<SvxLRSpaceItem>( *pPdFmt, RES_LR_SPACE );
+
+ SvxLRSpaceItem aResultLR( rPageLR.GetLeft() +
+ rSectionLR.GetLeft(), rPageLR.GetRight() +
+ rSectionLR.GetRight(), 0, 0, RES_LR_SPACE );
+
+ aSet.Put( aResultLR );
+
+ // und raus damit ins WW-File
+ const SfxItemSet* pOldI = pISet;
+ pISet = &aSet;
+
+ // Switch off test on default item values, if page description
+ // set (value of <bOutPgDscSet>) isn't written.
+ AttrOutput().OutputStyleItemSet( aSet, true, bOutPgDscSet );
+
+ //Cannot export as normal page framedir, as continous sections
+ //cannot contain any grid settings like proper sections
+ AttrOutput().SectionBiDi( FRMDIR_HORI_RIGHT_TOP == TrueFrameDirection( *rSepInfo.pSectionFmt ) );
+
+ pISet = pOldI;
+ }
+ }
+
+ bool titlePage = false;
+ if ( bOutPgDscSet )
+ {
+ // es ist ein Follow gesetzt und dieser zeigt nicht auf sich
+ // selbst, so liegt eine Seitenverkettung vor.
+ // Falls damit eine "Erste Seite" simuliert werden soll, so
+ // koennen wir das auch als solches schreiben.
+ // Anders sieht es mit Links/Rechts wechseln aus. Dafuer muss
+ // erkannt werden, wo der Seitenwechsel statt findet. Hier ist
+ // es aber dafuer zuspaet!
+ if ( pPd->GetFollow() && pPd != pPd->GetFollow() &&
+ pPd->GetFollow()->GetFollow() == pPd->GetFollow() &&
+ ( !rSepInfo.pPDNd || pPd->IsFollowNextPageOfNode( *rSepInfo.pPDNd ) ) )
+ {
+ const SwPageDesc *pFollow = pPd->GetFollow();
+ const SwFrmFmt& rFollowFmt = pFollow->GetMaster();
+ if ( sw::util::IsPlausableSingleWordSection( *pPdFmt, rFollowFmt ) )
+ {
+ if (rSepInfo.pPDNd)
+ pPdFirstPgFmt = pPd->GetPageFmtOfNode( *rSepInfo.pPDNd );
+ else
+ pPdFirstPgFmt = &pPd->GetMaster();
+
+ pAktPageDesc = pPd = pFollow;
+ pPdFmt = &rFollowFmt;
+
+ // has different headers/footers for the title page
+ titlePage = true;
+ }
+ }
+
+ // The code above tries to detect if this is first page headers/footers,
+ // but it doesn't work even for quite trivial testcases. As I don't actually
+ // understand that code, I'll keep it. The simple and (at least for me) reliable way
+ // to detect for first page seems to be just RES_POOLPAGE_FIRST.
+ if( pPd->GetPoolFmtId() == RES_POOLPAGE_FIRST )
+ titlePage = true;
+ if( titlePage )
+ AttrOutput().SectionTitlePage();
+
+ const SfxItemSet* pOldI = pISet;
+
+ AttrOutput().SectionPageBorders( pPdFmt, pPdFirstPgFmt );
+
+ const SfxPoolItem* pItem;
+ if ( pPdFmt != pPdFirstPgFmt && SFX_ITEM_SET ==
+ pPdFirstPgFmt->GetItemState( RES_PAPER_BIN, true, &pItem ) )
+ {
+ pISet = &pPdFirstPgFmt->GetAttrSet();
+ bOutFirstPage = true;
+ AttrOutput().OutputItem( *pItem );
+ bOutFirstPage = false;
+ }
+
+ // left-/right chain of pagedescs ?
+ if ( pPd->GetFollow() && pPd != pPd->GetFollow() &&
+ pPd->GetFollow()->GetFollow() == pPd &&
+ (( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
+ nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ||
+ ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) &&
+ nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->GetFollow()->ReadUseOn() )) ))
+ {
+ bLeftRightPgChain = true;
+
+ // welches ist der Bezugspunkt ????? (links oder rechts?)
+ // annahme die rechte Seite!
+ if ( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) )
+ {
+ nBreakCode = 3;
+ pPd = pPd->GetFollow();
+ pPdFmt = &pPd->GetMaster();
+ }
+ else
+ nBreakCode = 4;
+ }
+
+ pISet = &pPdFmt->GetAttrSet();
+ AttrOutput().OutputStyleItemSet( pPdFmt->GetAttrSet(), true, false );
+ pISet = pOldI;
+
+ // dann noch die restlichen Einstellungen aus dem PageDesc
+
+ AttrOutput().SectionPageNumbering( pPd->GetNumType().GetNumberingType(), rSepInfo.nPgRestartNo );
+
+ // werden es nur linke oder nur rechte Seiten?
+ if ( 2 == nBreakCode )
+ {
+ if ( nsUseOnPage::PD_LEFT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) )
+ nBreakCode = 3;
+ else if ( nsUseOnPage::PD_RIGHT == ( nsUseOnPage::PD_ALL & pPd->ReadUseOn() ) )
+ nBreakCode = 4;
+ }
+ }
+
+ AttrOutput().SectionType( nBreakCode );
+
+ const SwTxtNode* pNd = rSepInfo.pNumNd;
+ if ( pNd )
+ {
+ const SwNumRule* pRule = pNd->GetNumRule();
+ if ( pRule )
+ OutputOlst( *pRule );
+ }
+
+ // Header oder Footer
+ sal_uInt8 nHeadFootFlags = 0;
+
+ const SwFrmFmt* pPdLeftFmt = bLeftRightPgChain
+ ? &pPd->GetFollow()->GetMaster()
+ : &pPd->GetLeft();
+
+ if ( nBreakCode != 0 )
+ {
+ if ( titlePage )
+ {
+ // es gibt eine ErsteSeite:
+ MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdFirstPgFmt, WW8_HEADER_FIRST );
+ MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdFirstPgFmt, WW8_FOOTER_FIRST );
+ }
+ // write other headers/footers only if it's not on the first page - I'm not quite sure
+ // this is technically correct, but it avoids first-page headers/footers
+ // extending to all pages (bnc#654230)
+ if( !titlePage || pPdFmt != pPdFirstPgFmt )
+ {
+ MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdFmt, WW8_HEADER_ODD );
+ MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdFmt, WW8_FOOTER_ODD );
+
+ if ( !pPd->IsHeaderShared() || bLeftRightPgChain )
+ MSWordSections::SetHeaderFlag( nHeadFootFlags, *pPdLeftFmt, WW8_HEADER_EVEN );
+
+ if ( !pPd->IsFooterShared() || bLeftRightPgChain )
+ MSWordSections::SetFooterFlag( nHeadFootFlags, *pPdLeftFmt, WW8_FOOTER_EVEN );
+ }
+ AttrOutput().SectionWW6HeaderFooterFlags( nHeadFootFlags );
+ }
+
+ // binary filters only
+ SetupSectionPositions( pA );
+
+ /*
+ !!!!!!!!!!!
+ // Umrandungen an Kopf- und Fusstexten muessten etwa so gehen:
+ // Dabei muss etwas wie pOut eingebaut werden,
+ // das bei jeder Spezialtext-Zeile wiederholt wird.
+ const SwFrmFmt* pFFmt = rFt.GetFooterFmt();
+ const SvxBoxItem& rBox = pFFmt->GetBox(false);
+ OutWW8_SwFmtBox1( m_rWW8Export.pOut, rBox, false);
+ !!!!!!!!!!!
+ Man koennt daraus Absatzattribute machen, die dann bei jedem Absatz
+ beachtet werden. Gilt fuer Hintergrund/Umrandung
+ !!!!!!!!!!!
+ */
+
+ const SwTxtNode *pOldPageRoot = GetHdFtPageRoot();
+ SetHdFtPageRoot( rSepInfo.pPDNd ? rSepInfo.pPDNd->GetTxtNode() : 0 );
+
+ WriteHeadersFooters( nHeadFootFlags, *pPdFmt, *pPdLeftFmt, *pPdFirstPgFmt, nBreakCode );
+
+ SetHdFtPageRoot( pOldPageRoot );
+
+ AttrOutput().EndSection();
+
+ // outside of the section properties again
+ bOutPageDescs = bOldPg;
+}
+
+bool WW8_WrPlcSepx::WriteKFTxt( WW8Export& rWrt )
+{
+ pAttrs = new WW8_PdAttrDesc[ aSects.Count() ];
+ sal_uLong nCpStart = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+
+ OSL_ENSURE( !pTxtPos, "wer hat den Pointer gesetzt?" );
+ pTxtPos = new WW8_WrPlc0( nCpStart );
+
+ WriteFtnEndTxt( rWrt, nCpStart );
+ CheckForFacinPg( rWrt );
+
+ unsigned int nOldIndex = rWrt.GetHdFtIndex();
+ rWrt.SetHdFtIndex( 0 );
+ for ( sal_uInt16 i = 0; i < aSects.Count(); ++i )
+ {
+ WW8_PdAttrDesc* pA = pAttrs + i;
+ pA->pData = 0;
+ pA->nLen = 0;
+ pA->nSepxFcPos = 0xffffffff; // Default: none
+
+ WW8_SepInfo& rSepInfo = aSects[i];
+ rWrt.SectionProperties( rSepInfo, pA );
+
+ bNoMoreSections = true;
+ }
+ rWrt.SetHdFtIndex( nOldIndex ); //0
+
+ if ( pTxtPos->Count() )
+ {
+ // HdFt vorhanden ?
+ sal_uLong nCpEnd = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+ pTxtPos->Append( nCpEnd ); // Ende letzter Hd/Ft fuer PlcfHdd
+
+ if ( nCpEnd > nCpStart )
+ {
+ ++nCpEnd;
+ pTxtPos->Append( nCpEnd + 1 ); // Ende letzter Hd/Ft fuer PlcfHdd
+
+ rWrt.WriteStringAsPara( aEmptyStr ); // CR ans Ende ( sonst mault WW )
+ }
+ rWrt.pFldHdFt->Finish( nCpEnd, rWrt.pFib->ccpText + rWrt.pFib->ccpFtn );
+ rWrt.pFib->ccpHdr = nCpEnd - nCpStart;
+ }
+ else
+ delete pTxtPos, pTxtPos = 0;
+
+ return rWrt.pFib->ccpHdr != 0;
+}
+
+void WW8_WrPlcSepx::WriteSepx( SvStream& rStrm ) const
+{
+ sal_uInt16 i;
+ for( i = 0; i < aSects.Count(); i++ ) // ueber alle Sections
+ {
+ WW8_PdAttrDesc* pA = pAttrs + i;
+ if( pA->nLen && pA->pData != NULL)
+ {
+ SVBT16 nL;
+ pA->nSepxFcPos = rStrm.Tell();
+ ShortToSVBT16( pA->nLen, nL );
+ rStrm.Write( nL, 2 );
+ rStrm.Write( pA->pData, pA->nLen );
+ }
+ }
+}
+
+void WW8_WrPlcSepx::WritePlcSed( WW8Export& rWrt ) const
+{
+ OSL_ENSURE( aCps.Count() == aSects.Count() + 1, "WrPlcSepx: DeSync" );
+ sal_uLong nFcStart = rWrt.pTableStrm->Tell();
+
+ sal_uInt16 i;
+ // ( ueber alle Sections )
+ for( i = 0; i <= aSects.Count(); i++ )
+ {
+ sal_uInt32 nP = aCps[i];
+ SVBT32 nPos;
+ UInt32ToSVBT32( nP, nPos );
+ rWrt.pTableStrm->Write( nPos, 4 );
+ }
+
+ static WW8_SED aSed = {{4, 0},{0, 0, 0, 0},{0, 0},{0xff, 0xff, 0xff, 0xff}};
+
+ // ( ueber alle Sections )
+ for( i = 0; i < aSects.Count(); i++ )
+ {
+ WW8_PdAttrDesc* pA = pAttrs + i;
+ UInt32ToSVBT32( pA->nSepxFcPos, aSed.fcSepx ); // Sepx-Pos
+ rWrt.pTableStrm->Write( &aSed, sizeof( aSed ) );
+ }
+ rWrt.pFib->fcPlcfsed = nFcStart;
+ rWrt.pFib->lcbPlcfsed = rWrt.pTableStrm->Tell() - nFcStart;
+}
+
+
+void WW8_WrPlcSepx::WritePlcHdd( WW8Export& rWrt ) const
+{
+ if( pTxtPos && pTxtPos->Count() )
+ {
+ rWrt.pFib->fcPlcfhdd = rWrt.pTableStrm->Tell();
+ pTxtPos->Write( *rWrt.pTableStrm ); // Plc0
+ rWrt.pFib->lcbPlcfhdd = rWrt.pTableStrm->Tell() -
+ rWrt.pFib->fcPlcfhdd;
+ }
+}
+
+void MSWordExportBase::WriteHeaderFooterText( const SwFmt& rFmt, bool bHeader )
+{
+ const SwFmtCntnt *pCntnt;
+ if ( bHeader )
+ {
+ bHasHdr = true;
+ const SwFmtHeader& rHd = rFmt.GetHeader();
+ OSL_ENSURE( rHd.GetHeaderFmt(), "Header text is not here" );
+ pCntnt = &rHd.GetHeaderFmt()->GetCntnt();
+ }
+ else
+ {
+ bHasFtr = true;
+ const SwFmtFooter& rFt = rFmt.GetFooter();
+ OSL_ENSURE( rFt.GetFooterFmt(), "Footer text is not here" );
+ pCntnt = &rFt.GetFooterFmt()->GetCntnt();
+ }
+
+ const SwNodeIndex* pSttIdx = pCntnt->GetCntntIdx();
+
+ if ( pSttIdx )
+ {
+ SwNodeIndex aIdx( *pSttIdx, 1 ),
+ aEnd( *pSttIdx->GetNode().EndOfSectionNode() );
+ sal_uLong nStart = aIdx.GetIndex();
+ sal_uLong nEnd = aEnd.GetIndex();
+
+ // Bereich also gueltiger Node
+ if ( nStart < nEnd )
+ {
+ bool bOldKF = bOutKF;
+ bOutKF = true;
+ WriteSpecialText( nStart, nEnd, TXT_HDFT );
+ bOutKF = bOldKF;
+ }
+ else
+ pSttIdx = 0;
+ }
+
+ if ( !pSttIdx )
+ {
+ // es gibt keine Kopf-/Fusszeile, aber ein CR ist immer noch noetig
+ OSL_ENSURE( pSttIdx, "K/F-Text nicht richtig da" );
+ AttrOutput().EmptyParagraph(); // CR ans Ende ( sonst mault WW )
+ }
+}
+
+//------------------------------------------------------------------------------
+// class WW8_WrPlcFtnEdn : Sammeln der Fuss/Endnoten und Ausgeben der Texte
+// und Plcs am Ende des Docs.
+// WW8_WrPlcFtnEdn ist die Klasse fuer Fuss- und Endnoten
+//------------------------------------------------------------------------------
+WW8_WrPlcSubDoc::WW8_WrPlcSubDoc()
+ : aCps( 0, 16 ), aCntnt( 0, 16 ), pTxtPos( 0 )
+{
+}
+
+WW8_WrPlcSubDoc::~WW8_WrPlcSubDoc()
+{
+ delete pTxtPos;
+}
+
+void WW8_WrPlcFtnEdn::Append( WW8_CP nCp, const SwFmtFtn& rFtn )
+{
+ aCps.Insert( nCp, aCps.Count() );
+ void* p = (void*)&rFtn;
+ aCntnt.Insert( p, aCntnt.Count() );
+}
+
+WW8_Annotation::WW8_Annotation(const SwPostItField* pPostIt)
+{
+ mpRichText = pPostIt->GetTextObject();
+ if (!mpRichText)
+ msSimpleText = pPostIt->GetTxt();
+ msOwner = pPostIt->GetPar1();
+ maDateTime = DateTime(pPostIt->GetDate(), pPostIt->GetTime());
+}
+
+WW8_Annotation::WW8_Annotation(const SwRedlineData* pRedline) : mpRichText(0)
+{
+ msSimpleText = pRedline->GetComment();
+ msOwner = SW_MOD()->GetRedlineAuthor(pRedline->GetAuthor());
+ maDateTime = pRedline->GetTimeStamp();
+}
+
+void WW8_WrPlcAnnotations::Append( WW8_CP nCp, const SwPostItField *pPostIt )
+{
+ aCps.Insert( nCp, aCps.Count() );
+ WW8_Annotation* p = new WW8_Annotation(pPostIt);
+ aCntnt.Insert( p, aCntnt.Count() );
+}
+
+void WW8_WrPlcAnnotations::Append( WW8_CP nCp, const SwRedlineData *pRedline )
+{
+ maProcessedRedlines.insert(pRedline);
+ aCps.Insert( nCp, aCps.Count() );
+ WW8_Annotation* p = new WW8_Annotation(pRedline);
+ aCntnt.Insert( p, aCntnt.Count() );
+}
+
+bool WW8_WrPlcAnnotations::IsNewRedlineComment( const SwRedlineData *pRedline )
+{
+ return maProcessedRedlines.find(pRedline) == maProcessedRedlines.end();
+}
+
+WW8_WrPlcAnnotations::~WW8_WrPlcAnnotations()
+{
+ for( sal_uInt16 n=0; n < aCntnt.Count(); n++ )
+ delete (WW8_Annotation*)aCntnt[n];
+}
+
+bool WW8_WrPlcSubDoc::WriteGenericTxt( WW8Export& rWrt, sal_uInt8 nTTyp,
+ WW8_CP& rCount )
+{
+ sal_uInt16 nLen = aCntnt.Count();
+ if ( !nLen )
+ return false;
+
+ sal_uLong nCpStart = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+ pTxtPos = new WW8_WrPlc0( nCpStart );
+ sal_uInt16 i;
+
+ switch ( nTTyp )
+ {
+ case TXT_ATN:
+ for ( i = 0; i < nLen; i++ )
+ {
+ // Anfaenge fuer PlcfAtnTxt
+ pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() ));
+
+ rWrt.WritePostItBegin();
+ const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i];
+ if (rAtn.mpRichText)
+ rWrt.WriteOutliner(*rAtn.mpRichText, nTTyp);
+ else
+ {
+ String sTxt(rAtn.msSimpleText);
+ sTxt.SearchAndReplaceAll(0x0A, 0x0B);
+ rWrt.WriteStringAsPara( sTxt );
+ }
+ }
+ break;
+
+ case TXT_TXTBOX:
+ case TXT_HFTXTBOX:
+ for ( i = 0; i < nLen; i++ )
+ {
+ // textbox - content
+ WW8_CP nCP = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+ aCps.Insert( nCP, i );
+ pTxtPos->Append( nCP );
+
+ // is it an writer or sdr - textbox?
+ const SdrObject& rObj = *(SdrObject*)aCntnt[ i ];
+ if (rObj.GetObjInventor() == FmFormInventor)
+ {
+ sal_uInt8 nOldTyp = rWrt.nTxtTyp;
+ rWrt.nTxtTyp = nTTyp;
+ rWrt.GetOCXExp().ExportControl(rWrt,&rObj);
+ rWrt.nTxtTyp = nOldTyp;
+ }
+ else if( rObj.ISA( SdrTextObj ) )
+ rWrt.WriteSdrTextObj(rObj, nTTyp);
+ else
+ {
+ const SwFrmFmt* pFmt = ::FindFrmFmt( &rObj );
+ OSL_ENSURE( pFmt, "wo ist das Format geblieben?" );
+
+ const SwNodeIndex* pNdIdx = pFmt->GetCntnt().GetCntntIdx();
+ OSL_ENSURE( pNdIdx, "wo ist der StartNode der Textbox?" );
+ rWrt.WriteSpecialText( pNdIdx->GetIndex() + 1,
+ pNdIdx->GetNode().EndOfSectionIndex(),
+ nTTyp );
+ {
+ SwNodeIndex aContentIdx = *pNdIdx;
+ ++aContentIdx;
+ if ( aContentIdx.GetNode().IsTableNode() )
+ {
+ bool bContainsOnlyTables = true;
+ do {
+ aContentIdx = *(aContentIdx.GetNode().EndOfSectionNode());
+ ++aContentIdx;
+ if ( !aContentIdx.GetNode().IsTableNode() &&
+ aContentIdx.GetIndex() != pNdIdx->GetNode().EndOfSectionIndex() )
+ {
+ bContainsOnlyTables = false;
+ }
+ } while ( aContentIdx.GetNode().IsTableNode() );
+ if ( bContainsOnlyTables )
+ {
+ // Additional paragraph containing a space to
+ // assure that by WW created RTF from written WW8
+ // does not crash WW.
+ rWrt.WriteStringAsPara( String::CreateFromAscii( " " ) );
+ }
+ }
+ }
+ }
+
+ // CR at end of one textbox text ( otherwise WW gpft :-( )
+ rWrt.WriteStringAsPara( aEmptyStr );
+ }
+ break;
+
+ case TXT_EDN:
+ case TXT_FTN:
+ for ( i = 0; i < nLen; i++ )
+ {
+ // Anfaenge fuer PlcfFtnTxt/PlcfEdnTxt
+ pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() ));
+
+ // Noten-Inhalt
+ const SwFmtFtn* pFtn = (SwFmtFtn*)aCntnt[ i ];
+ rWrt.WriteFtnBegin( *pFtn );
+ const SwNodeIndex* pIdx = pFtn->GetTxtFtn()->GetStartNode();
+ OSL_ENSURE( pIdx, "wo ist der StartNode der Fuss-/EndNote?" );
+ rWrt.WriteSpecialText( pIdx->GetIndex() + 1,
+ pIdx->GetNode().EndOfSectionIndex(),
+ nTTyp );
+ }
+ break;
+
+ default:
+ OSL_ENSURE( !this, "was ist das fuer ein SubDocType?" );
+ }
+
+ pTxtPos->Append( rWrt.Fc2Cp( rWrt.Strm().Tell() ));
+ // CR ans Ende ( sonst mault WW )
+ rWrt.WriteStringAsPara( aEmptyStr );
+
+ WW8_CP nCpEnd = rWrt.Fc2Cp( rWrt.Strm().Tell() );
+ pTxtPos->Append( nCpEnd );
+ rCount = nCpEnd - nCpStart;
+
+ return ( rCount != 0 );
+}
+
+void WW8_WrPlcSubDoc::WriteGenericPlc( WW8Export& rWrt, sal_uInt8 nTTyp,
+ WW8_FC& rTxtStart, sal_Int32& rTxtCount, WW8_FC& rRefStart, sal_Int32& rRefCount ) const
+{
+ typedef ::std::vector<String>::iterator myiter;
+
+ sal_uLong nFcStart = rWrt.pTableStrm->Tell();
+ sal_uInt16 nLen = aCps.Count();
+ if ( !nLen )
+ return;
+
+ OSL_ENSURE( aCps.Count() + 2 == pTxtPos->Count(), "WritePlc: DeSync" );
+
+ ::std::vector<String> aStrArr;
+ WW8Fib& rFib = *rWrt.pFib; // n+1-te CP-Pos nach Handbuch
+ sal_uInt16 i;
+ bool bWriteCP = true;
+
+ switch ( nTTyp )
+ {
+ case TXT_ATN:
+ {
+ // then write first the GrpXstAtnOwners
+ for ( i = 0; i < nLen; ++i )
+ {
+ const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i];
+ aStrArr.push_back(rAtn.msOwner);
+ }
+
+ //sort and remove duplicates
+ ::std::sort(aStrArr.begin(), aStrArr.end());
+ myiter aIter = ::std::unique(aStrArr.begin(), aStrArr.end());
+ aStrArr.erase(aIter, aStrArr.end());
+
+ if ( rWrt.bWrtWW8 )
+ {
+ for ( i = 0; i < aStrArr.size(); ++i )
+ {
+ const String& rStr = aStrArr[i];
+ SwWW8Writer::WriteShort(*rWrt.pTableStrm, rStr.Len());
+ SwWW8Writer::WriteString16(*rWrt.pTableStrm, rStr,
+ false);
+ }
+ }
+ else
+ {
+ for ( i = 0; i < aStrArr.size(); ++i )
+ {
+ const String& rStr = aStrArr[i];
+ *rWrt.pTableStrm << (sal_uInt8)rStr.Len();
+ SwWW8Writer::WriteString8(*rWrt.pTableStrm, rStr, false,
+ RTL_TEXTENCODING_MS_1252);
+ }
+ }
+
+ rFib.fcGrpStAtnOwners = nFcStart;
+ nFcStart = rWrt.pTableStrm->Tell();
+ rFib.lcbGrpStAtnOwners = nFcStart - rFib.fcGrpStAtnOwners;
+
+ // Write the extended >= Word XP ATLD records
+ if( rWrt.bWrtWW8 )
+ {
+ for( i = 0; i < nLen; ++i )
+ {
+ const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i];
+
+ sal_uInt32 nDTTM = sw::ms::DateTime2DTTM(rAtn.maDateTime);
+
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, nDTTM );
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
+ }
+
+ rFib.fcAtrdExtra = nFcStart;
+ nFcStart = rWrt.pTableStrm->Tell();
+ rFib.lcbAtrdExtra = nFcStart - rFib.fcAtrdExtra;
+ rFib.fcHplxsdr = 0x01010002; //WTF, but apparently necessary
+ rFib.lcbHplxsdr = 0;
+ }
+ }
+ break;
+ case TXT_TXTBOX:
+ case TXT_HFTXTBOX:
+ {
+ pTxtPos->Write( *rWrt.pTableStrm );
+ const SvULongs* pShapeIds = GetShapeIdArr();
+ OSL_ENSURE( pShapeIds, "wo sind die ShapeIds?" );
+
+ for ( i = 0; i < nLen; ++i )
+ {
+ // write textbox story - FTXBXS
+ // is it an writer or sdr - textbox?
+ const SdrObject* pObj = (SdrObject*)aCntnt[ i ];
+ sal_Int32 nCnt = 1;
+ if ( !pObj->ISA( SdrTextObj ) )
+ {
+ // find the "highest" SdrObject of this
+ const SwFrmFmt& rFmt = *::FindFrmFmt( pObj );
+
+ const SwFmtChain* pChn = &rFmt.GetChain();
+ while ( pChn->GetNext() )
+ {
+ // has a chain?
+ // then calc the cur pos in the chain
+ ++nCnt;
+ pChn = &pChn->GetNext()->GetChain();
+ }
+ }
+ // long cTxbx / iNextReuse
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, nCnt );
+ // long cReusable
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
+ // short fReusable
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
+ // long reserved
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, -1 );
+ // long lid
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm,
+ (*pShapeIds)[i]);
+ // long txidUndo
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 );
+ }
+ SwWW8Writer::FillCount( *rWrt.pTableStrm, 22 );
+ bWriteCP = false;
+ }
+ break;
+ }
+
+ if ( bWriteCP )
+ {
+ // Schreibe CP-Positionen
+ for ( i = 0; i < nLen; i++ )
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, aCps[ i ] );
+
+ // n+1-te CP-Pos nach Handbuch
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm,
+ rFib.ccpText + rFib.ccpFtn + rFib.ccpHdr + rFib.ccpEdn +
+ rFib.ccpTxbx + rFib.ccpHdrTxbx + 1 );
+
+ if ( TXT_ATN == nTTyp )
+ {
+ for ( i = 0; i < nLen; ++i )
+ {
+ const WW8_Annotation& rAtn = *(const WW8_Annotation*)aCntnt[i];
+
+ //aStrArr is sorted
+ myiter aIter = ::std::lower_bound(aStrArr.begin(),
+ aStrArr.end(), rAtn.msOwner);
+ OSL_ENSURE(aIter != aStrArr.end() && *aIter == rAtn.msOwner,
+ "Impossible");
+ sal_uInt16 nFndPos = static_cast< sal_uInt16 >(aIter - aStrArr.begin());
+ String sAuthor(*aIter);
+ sal_uInt8 nNameLen = (sal_uInt8)sAuthor.Len();
+ if ( nNameLen > 9 )
+ {
+ sAuthor.Erase( 9 );
+ nNameLen = 9;
+ }
+
+ // xstUsrInitl[ 10 ] pascal-style String holding initials
+ // of annotation author
+ if ( rWrt.bWrtWW8 )
+ {
+ SwWW8Writer::WriteShort(*rWrt.pTableStrm, nNameLen);
+ SwWW8Writer::WriteString16(*rWrt.pTableStrm, sAuthor,
+ false);
+ SwWW8Writer::FillCount( *rWrt.pTableStrm,
+ (9 - nNameLen) * 2 );
+
+ }
+ else
+ {
+ *rWrt.pTableStrm << nNameLen;
+ SwWW8Writer::WriteString8(*rWrt.pTableStrm, sAuthor,
+ false, RTL_TEXTENCODING_MS_1252);
+ SwWW8Writer::FillCount(*rWrt.pTableStrm, 9 - nNameLen);
+ }
+
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, nFndPos );
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, -1 );
+ }
+ }
+ else
+ {
+ sal_uInt16 nNo = 0;
+ for ( i = 0; i < nLen; ++i ) // Schreibe Flags
+ {
+ const SwFmtFtn* pFtn = (SwFmtFtn*)aCntnt[ i ];
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm,
+ pFtn->GetNumStr().Len() ? 0 : ++nNo );
+ }
+ }
+ }
+ rRefStart = nFcStart;
+ nFcStart = rWrt.pTableStrm->Tell();
+ rRefCount = nFcStart - rRefStart;
+
+ pTxtPos->Write( *rWrt.pTableStrm );
+
+ switch ( nTTyp )
+ {
+ case TXT_TXTBOX:
+ case TXT_HFTXTBOX:
+ for ( i = 0; i < nLen; ++i )
+ {
+ // write break descriptor (BKD)
+ // short itxbxs
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, i );
+ // short dcpDepend
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0 );
+ // short flags : icol/fTableBreak/fColumnBreak/fMarked/
+ // fUnk/fTextOverflow
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0x800 );
+ }
+ SwWW8Writer::FillCount( *rWrt.pTableStrm, 6 );
+ break;
+ }
+
+ rTxtStart = nFcStart;
+ rTxtCount = rWrt.pTableStrm->Tell() - nFcStart;
+}
+
+const SvULongs* WW8_WrPlcSubDoc::GetShapeIdArr() const
+{
+ return 0;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/wrtww8.cxx b/sw/source/filter/ww8/wrtww8.cxx
new file mode 100644
index 000000000000..81920922c145
--- /dev/null
+++ b/sw/source/filter/ww8/wrtww8.cxx
@@ -0,0 +1,3834 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <iostream>
+
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <unotools/ucbstreamhelper.hxx>
+
+#include <algorithm>
+
+#include <hintids.hxx>
+#include <string.h> // memcpy()
+#include <osl/endian.h>
+#include <docsh.hxx>
+
+#include <svl/svstdarr.hxx>
+
+#include <unotools/fltrcfg.hxx>
+#include <vcl/salbtype.hxx>
+#include <sot/storage.hxx>
+#include <svl/zformat.hxx>
+#include <sfx2/docinf.hxx>
+#include <editeng/tstpitem.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/hyznitem.hxx>
+#include <editeng/langitem.hxx>
+#include <filter/msfilter/msoleexp.hxx>
+#include <filter/msfilter/msocximex.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <swtypes.hxx>
+#include <swrect.hxx>
+#include <swtblfmt.hxx>
+#include <txatbase.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtrowsplt.hxx>
+#include <frmatr.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <pam.hxx>
+#include <ndtxt.hxx>
+#include <shellio.hxx>
+#include <docstat.hxx>
+#include <pagedesc.hxx>
+#include <IMark.hxx>
+#include <swtable.hxx>
+#include <wrtww8.hxx>
+#include <ww8par.hxx>
+#include <fltini.hxx>
+#include <swmodule.hxx>
+#include <section.hxx>
+#include <swfltopt.hxx>
+#include <fmtinfmt.hxx>
+#include <txtinet.hxx>
+#include <fmturl.hxx>
+#include <fesh.hxx>
+#include <svtools/imap.hxx>
+#include <svtools/imapobj.hxx>
+#include <tools/urlobj.hxx>
+#include <mdiexp.hxx> // Progress
+#include <statstr.hrc> // ResId fuer Statusleiste
+#include <fmtline.hxx>
+#include <fmtfsize.hxx>
+#include <comphelper/extract.hxx>
+#include <comphelper/stlunosequence.hxx>
+#include <writerfilter/doctok/sprmids.hxx>
+
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "ww8attributeoutput.hxx"
+
+#include <IDocumentMarkAccess.hxx>
+#include <xmloff/odffields.hxx>
+
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+
+#include "dbgoutsw.hxx"
+
+#include <sfx2/docfile.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/frame.hxx>
+#include <svl/stritem.hxx>
+#include <unotools/tempfile.hxx>
+#include <filter/msfilter/mscodec.hxx>
+#include <filter/msfilter/svxmsbas.hxx>
+#include <osl/time.h>
+#include <rtl/random.h>
+#include "WW8Sttbf.hxx"
+#include "WW8FibData.hxx"
+
+using namespace sw::util;
+using namespace sw::types;
+
+/** FKP - Formatted disK Page
+*/
+class WW8_WrFkp
+{
+ sal_uInt8* pFkp; // gesamter Fkp ( zuerst nur FCs und Sprms )
+ sal_uInt8* pOfs; // Pointer auf Offset-Bereich, spaeter nach pFkp kopiert
+ ePLCFT ePlc;
+ short nStartGrp; // ab hier grpprls
+ short nOldStartGrp;
+ sal_uInt8 nItemSize;
+ sal_uInt8 nIMax; // Anzahl der Eintrags-Paare
+ sal_uInt8 nOldVarLen;
+ sal_uInt8 nMark;
+ bool bCombined; // true : Einfuegen verboten
+
+ sal_uInt8 SearchSameSprm( sal_uInt16 nVarLen, const sal_uInt8* pSprms );
+public:
+ WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc, bool bWrtWW8);
+ ~WW8_WrFkp();
+ bool Append( WW8_FC nEndFc, sal_uInt16 nVarLen = 0, const sal_uInt8* pSprms = 0 );
+ bool Combine();
+ void Write( SvStream& rStrm, SwWW8WrGrf& rGrf );
+
+ bool IsEqualPos(WW8_FC nEndFc) const
+ { return !bCombined && nIMax && nEndFc == ((sal_Int32*)pFkp)[nIMax]; }
+ void MergeToNew( short& rVarLen, sal_uInt8 *& pNewSprms );
+ bool IsEmptySprm() const
+ { return !bCombined && nIMax && !nOldVarLen; }
+ void SetNewEnd( WW8_FC nEnd )
+ { ((sal_Int32*)pFkp)[nIMax] = nEnd; }
+
+#ifdef __WW8_NEEDS_COPY
+ WW8_FC GetStartFc() const;
+ WW8_FC GetEndFc() const;
+#else
+ WW8_FC GetStartFc() const { return ((sal_Int32*)pFkp)[0]; };
+ WW8_FC GetEndFc() const { return ((sal_Int32*)pFkp)[nIMax]; };
+#endif // defined __WW8_NEEDS_COPY
+
+ sal_uInt8 *CopyLastSprms(sal_uInt8 &rLen, bool bVer8);
+};
+
+
+// -------------------------------------------------------------------------
+// class WW8_WrPc sammelt alle Piece-Eintraege fuer ein Piece
+// -------------------------------------------------------------------------
+
+class WW8_WrPc
+{
+ WW8_CP nStartCp; // Start ZeichenPosition vom Text
+ WW8_FC nStartFc; // Start File Position vom Text
+ sal_uInt16 nStatus; // Absatzende im Piece ?
+
+public:
+ WW8_WrPc(WW8_FC nSFc, WW8_CP nSCp )
+ : nStartCp( nSCp ), nStartFc( nSFc ), nStatus( 0x0040 )
+ {}
+
+ void SetStatus() { nStatus = 0x0050; }
+ sal_uInt16 GetStatus() const { return nStatus; }
+ WW8_CP GetStartCp() const { return nStartCp; }
+ WW8_FC GetStartFc() const { return nStartFc; }
+};
+
+class WW8_WrtBookmarks
+{
+private:
+ //! Holds information about a single bookmark.
+ struct BookmarkInfo {
+ sal_uLong startPos; //!< Starting character position.
+ sal_uLong endPos; //!< Ending character position.
+ bool isField; //!< True if the bookmark is in a field result.
+ String name; //!< Name of this bookmark.
+ inline BookmarkInfo(sal_uLong start, sal_uLong end, bool isFld, const String& bkName) : startPos(start), endPos(end), isField(isFld), name(bkName) {};
+ //! Operator < is defined purely for sorting.
+ inline bool operator<(const BookmarkInfo &other) const { return startPos < other.startPos; }
+ };
+ std::vector<BookmarkInfo> aBookmarks;
+ typedef std::vector<BookmarkInfo>::iterator BkmIter;
+
+ //! Return the position in aBookmarks where the string rNm can be found.
+ BkmIter GetPos( const String& rNm );
+
+ //No copying
+ WW8_WrtBookmarks(const WW8_WrtBookmarks&);
+ WW8_WrtBookmarks& operator=(const WW8_WrtBookmarks&);
+public:
+ WW8_WrtBookmarks();
+ ~WW8_WrtBookmarks();
+
+ //! Add a new bookmark to the list OR add an end position to an existing bookmark.
+ void Append( WW8_CP nStartCp, const String& rNm, const ::sw::mark::IMark* pBkmk=NULL );
+ //! Write out bookmarks to file.
+ void Write( WW8Export& rWrt );
+ //! Move existing field marks from one position to another.
+ void MoveFieldMarks(sal_uLong nFrom,sal_uLong nTo);
+
+};
+
+#define ANZ_DEFAULT_STYLES 16
+
+// die Namen der StorageStreams
+#define sMainStream CREATE_CONST_ASC("WordDocument")
+#define sCompObj CREATE_CONST_ASC("\1CompObj")
+
+
+SV_IMPL_VARARR( WW8Bytes, sal_uInt8 )
+SV_IMPL_PTRARR( WW8_WrFkpPtrs, WW8_FkpPtr )
+
+typedef WW8_WrPc* WW8_WrPcPtr;
+SV_DECL_PTRARR_DEL( WW8_WrPcPtrs, WW8_WrPcPtr, 4, 4 )
+SV_IMPL_PTRARR( WW8_WrPcPtrs, WW8_WrPcPtr )
+
+static void WriteDop( WW8Export& rWrt )
+{
+ WW8Dop& rDop = *rWrt.pDop;
+
+ // i#78951#, store the value of unknown compatability options
+ rDop.SetCompatabilityOptions( rWrt.pDoc->Getn32DummyCompatabilityOptions1());
+ rDop.SetCompatabilityOptions2( rWrt.pDoc->Getn32DummyCompatabilityOptions2());
+
+ rDop.fNoLeading = !rWrt.pDoc->get(IDocumentSettingAccess::ADD_EXT_LEADING);
+ rDop.fUsePrinterMetrics = !rWrt.pDoc->get(IDocumentSettingAccess::USE_VIRTUAL_DEVICE);
+
+ // default TabStop schreiben
+ const SvxTabStopItem& rTabStop =
+ DefaultItemGet<SvxTabStopItem>(*rWrt.pDoc, RES_PARATR_TABSTOP);
+ rDop.dxaTab = (sal_uInt16)rTabStop[0].GetTabPos();
+
+
+ // Werte aus der DocStatistik (werden aufjedenfall fuer die
+ // DocStat-Felder benoetigt!)
+ rDop.fWCFtnEdn = true; // because they are included in StarWriter
+
+ const SwDocStat& rDStat = rWrt.pDoc->GetDocStat();
+ rDop.cWords = rDStat.nWord;
+ rDop.cCh = rDStat.nChar;
+ rDop.cPg = static_cast< sal_Int16 >(rDStat.nPage);
+ rDop.cParas = rDStat.nPara;
+ rDop.cLines = rDStat.nPara;
+
+ SwDocShell *pDocShell(rWrt.pDoc->GetDocShell());
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+ uno::Reference<document::XDocumentProperties> xDocProps;
+ uno::Reference<beans::XPropertySet> xProps;
+ if (pDocShell) {
+ uno::Reference<lang::XComponent> xModelComp(pDocShell->GetModel(),
+ uno::UNO_QUERY);
+ xProps = uno::Reference<beans::XPropertySet>(xModelComp,
+ uno::UNO_QUERY);
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ xModelComp, uno::UNO_QUERY_THROW);
+ xDocProps = xDPS->getDocumentProperties();
+ DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
+
+ rDop.lKeyProtDoc = pDocShell->GetModifyPasswordHash();
+ }
+
+ if ((rWrt.pSepx && rWrt.pSepx->DocumentIsProtected()) ||
+ rDop.lKeyProtDoc != 0)
+ {
+ rDop.fProtEnabled = 1;
+ }
+ else
+ {
+ rDop.fProtEnabled = 0;
+ }
+
+ if (!xDocProps.is()) {
+ rDop.dttmCreated = rDop.dttmRevised = rDop.dttmLastPrint = 0x45FBAC69;
+ } else {
+ ::util::DateTime uDT = xDocProps->getCreationDate();
+ Date aD(uDT.Day, uDT.Month, uDT.Year);
+ Time aT(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ rDop.dttmCreated = sw::ms::DateTime2DTTM(DateTime(aD,aT));
+ uDT = xDocProps->getModificationDate();
+ Date aD2(uDT.Day, uDT.Month, uDT.Year);
+ Time aT2(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ rDop.dttmRevised = sw::ms::DateTime2DTTM(DateTime(aD2,aT2));
+ uDT = xDocProps->getPrintDate();
+ Date aD3(uDT.Day, uDT.Month, uDT.Year);
+ Time aT3(uDT.Hours, uDT.Minutes, uDT.Seconds, uDT.HundredthSeconds);
+ rDop.dttmLastPrint = sw::ms::DateTime2DTTM(DateTime(aD3,aT3));
+
+ }
+
+// auch damit werden die DocStat-Felder in Kopf-/Fusszeilen nicht korrekt
+// berechnet.
+// ( we do not have this fields! )
+
+ // und noch fuer die Header und Footers
+ rDop.cWordsFtnEnd = rDStat.nWord;
+ rDop.cChFtnEdn = rDStat.nChar;
+ rDop.cPgFtnEdn = (sal_Int16)rDStat.nPage;
+ rDop.cParasFtnEdn = rDStat.nPara;
+ rDop.cLinesFtnEdn = rDStat.nPara;
+
+ rDop.fDontUseHTMLAutoSpacing = (rWrt.pDoc->get(IDocumentSettingAccess::PARA_SPACE_MAX) != 0);
+
+ rDop.fExpShRtn = !rWrt.pDoc->get(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK); // #i56856#
+
+ rDop.Write( *rWrt.pTableStrm, *rWrt.pFib );
+}
+
+const sal_Unicode *WW8DopTypography::GetJapanNotBeginLevel1()
+{
+ static const sal_Unicode aJapanNotBeginLevel1[nMaxFollowing] =
+ //Japanese Level 1
+ {
+ 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
+ 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
+ 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
+ 0x300f, 0x3011, 0x3015, 0x309b, 0x309c, 0x309d, 0x309e, 0x30fb,
+ 0x30fd, 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a,
+ 0xff1b, 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65,
+ 0xff9e, 0xff9f, 0xffe0
+ };
+ return &aJapanNotBeginLevel1[0];
+}
+
+const sal_Unicode *WW8DopTypography::GetJapanNotEndLevel1()
+{
+ static const sal_Unicode aJapanNotEndLevel1[nMaxLeading] =
+ //Japanese Level 1
+ {
+ 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
+ 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
+ 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
+ };
+ return &aJapanNotEndLevel1[0];
+}
+
+int lcl_CmpBeginEndChars( const rtl::OUString& rSWStr,
+ const sal_Unicode* pMSStr, int nMSStrByteLen )
+{
+ nMSStrByteLen /= sizeof( sal_Unicode );
+ if( nMSStrByteLen > rSWStr.getLength() )
+ nMSStrByteLen = rSWStr.getLength()+1;
+ nMSStrByteLen *= sizeof( sal_Unicode );
+
+ return memcmp( rSWStr.getStr(), pMSStr, nMSStrByteLen );
+}
+
+/*
+Converts the OOo Asian Typography into a best fit match for Microsoft
+Asian typography. This structure is actually dumped to disk within the
+Dop Writer. Assumption is that rTypo is cleared to 0 on entry
+*/
+void WW8Export::ExportDopTypography(WW8DopTypography &rTypo)
+{
+ static const sal_Unicode aLangNotBegin[4][WW8DopTypography::nMaxFollowing]=
+ {
+ //Japanese Level 1
+ {
+ 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
+ 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2030, 0x2032,
+ 0x2033, 0x2103, 0x3001, 0x3002, 0x3005, 0x3009, 0x300b, 0x300d,
+ 0x300f, 0x3011, 0x3015, 0x3041, 0x3043, 0x3045, 0x3047, 0x3049,
+ 0x3063, 0x3083, 0x3085, 0x3087, 0x308e, 0x309b, 0x309c, 0x309d,
+ 0x309e, 0x30a1, 0x30a3, 0x30a5, 0x30a7, 0x30a9, 0x30c3, 0x30e3,
+ 0x30e5, 0x30e7, 0x30ee, 0x30f5, 0x30f6, 0x30fb, 0x30fc, 0x30fd,
+ 0x30fe, 0xff01, 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b,
+ 0xff1f, 0xff3d, 0xff5d, 0xff61, 0xff63, 0xff64, 0xff65, 0xff67,
+ 0xff68, 0xff69, 0xff6a, 0xff6b, 0xff6c, 0xff6d, 0xff6e, 0xff6f,
+ 0xff70, 0xff9e, 0xff9f, 0xffe0
+ },
+ //Simplified Chinese
+ {
+ 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
+ 0x007d, 0x00a8, 0x00b7, 0x02c7, 0x02c9, 0x2015, 0x2016, 0x2019,
+ 0x201d, 0x2026, 0x2236, 0x3001, 0x3002, 0x3003, 0x3005, 0x3009,
+ 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x3017, 0xff01, 0xff02,
+ 0xff07, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
+ 0xff40, 0xff5c, 0xff5d, 0xff5e, 0xffe0
+ },
+ //Korean
+ {
+ 0x0021, 0x0025, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f,
+ 0x005d, 0x007d, 0x00a2, 0x00b0, 0x2019, 0x201d, 0x2032, 0x2033,
+ 0x2103, 0x3009, 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0xff01,
+ 0xff05, 0xff09, 0xff0c, 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff3d,
+ 0xff5d, 0xffe0
+ },
+ //Traditional Chinese
+ {
+ 0x0021, 0x0029, 0x002c, 0x002e, 0x003a, 0x003b, 0x003f, 0x005d,
+ 0x007d, 0x00a2, 0x00b7, 0x2013, 0x2014, 0x2019, 0x201d, 0x2022,
+ 0x2025, 0x2026, 0x2027, 0x2032, 0x2574, 0x3001, 0x3002, 0x3009,
+ 0x300b, 0x300d, 0x300f, 0x3011, 0x3015, 0x301e, 0xfe30, 0xfe31,
+ 0xfe33, 0xfe34, 0xfe36, 0xfe38, 0xfe3a, 0xfe3c, 0xfe3e, 0xfe40,
+ 0xfe42, 0xfe44, 0xfe4f, 0xfe50, 0xfe51, 0xfe52, 0xfe54, 0xfe55,
+ 0xfe56, 0xfe57, 0xfe5a, 0xfe5c, 0xfe5e, 0xff01, 0xff09, 0xff0c,
+ 0xff0e, 0xff1a, 0xff1b, 0xff1f, 0xff5c, 0xff5d, 0xff64
+ },
+ };
+
+ static const sal_Unicode aLangNotEnd[4][WW8DopTypography::nMaxLeading] =
+ {
+ //Japanese Level 1
+ {
+ 0x0024, 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018,
+ 0x201c, 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04,
+ 0xff08, 0xff3b, 0xff5b, 0xff62, 0xffe1, 0xffe5
+ },
+ //Simplified Chinese
+ {
+ 0x0028, 0x005b, 0x007b, 0x00b7, 0x2018, 0x201c, 0x3008, 0x300a,
+ 0x300c, 0x300e, 0x3010, 0x3014, 0x3016, 0xff08, 0xff0e, 0xff3b,
+ 0xff5b, 0xffe1, 0xffe5
+ },
+ //Korean
+ {
+ 0x0028, 0x005b, 0x005c, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c,
+ 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0xff04, 0xff08,
+ 0xff3b, 0xff5b, 0xffe6
+ },
+ //Traditional Chinese
+ {
+ 0x0028, 0x005b, 0x007b, 0x00a3, 0x00a5, 0x2018, 0x201c, 0x2035,
+ 0x3008, 0x300a, 0x300c, 0x300e, 0x3010, 0x3014, 0x301d, 0xfe35,
+ 0xfe37, 0xfe39, 0xfe3b, 0xfe3d, 0xfe3f, 0xfe41, 0xfe43, 0xfe59,
+ 0xfe5b, 0xfe5d, 0xff08, 0xff5b
+ },
+ };
+
+ const i18n::ForbiddenCharacters *pForbidden = 0;
+ const i18n::ForbiddenCharacters *pUseMe = 0;
+ sal_uInt8 nUseReserved=0;
+ int nNoNeeded=0;
+ /*
+ Now we have some minor difficult issues, to wit...
+ a. MicroSoft Office can only store one set of begin and end characters in
+ a given document, not one per language.
+ b. StarOffice has only a concept of one set of begin and end characters for
+ a given language, i.e. not the two levels of kinsoku in japanese
+
+ What is unknown as yet is if our default begin and end chars for
+ japanese, chinese tradition, chinese simplified and korean are different
+ in Word and Writer. I already suspect that they are different between
+ different version of word itself.
+
+ So what have come up with is to simply see if any of the four languages
+ in OOo have been changed away from OUR defaults, and if one has then
+ export that. If more than one has in the future we may hack in something
+ which examines our document properties to see which language is used the
+ most and choose that, for now we choose the first and throw an ASSERT
+ */
+
+ /*Our default Japanese Level is 2, this is a special MS hack to set this*/
+ rTypo.reserved2 = 1;
+
+ for (rTypo.reserved1=8;rTypo.reserved1>0;rTypo.reserved1-=2)
+ {
+ if (0 != (pForbidden = pDoc->getForbiddenCharacters(rTypo.GetConvertedLang(),
+ false)))
+ {
+ int nIdx = (rTypo.reserved1-2)/2;
+ if( lcl_CmpBeginEndChars( pForbidden->endLine,
+ aLangNotEnd[ nIdx ], sizeof(aLangNotEnd[ nIdx ]) ) ||
+ lcl_CmpBeginEndChars( pForbidden->beginLine,
+ aLangNotBegin[ nIdx ], sizeof(aLangNotBegin[ nIdx ]) ) )
+ {
+ //One exception for Japanese, if it matches a level 1 we
+ //can use one extra flag for that, rather than use a custom
+ if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESE)
+ {
+ if (
+ !lcl_CmpBeginEndChars
+ (
+ pForbidden->endLine,
+ rTypo.GetJapanNotEndLevel1(),
+ rTypo.nMaxLeading * sizeof(sal_Unicode)
+ )
+ &&
+ !lcl_CmpBeginEndChars
+ (
+ pForbidden->beginLine,
+ rTypo.GetJapanNotBeginLevel1(),
+ rTypo.nMaxFollowing * sizeof(sal_Unicode)
+ )
+ )
+ {
+ rTypo.reserved2 = 0;
+ continue;
+ }
+ }
+
+ if (!pUseMe)
+ {
+ pUseMe = pForbidden;
+ nUseReserved = rTypo.reserved1;
+ rTypo.iLevelOfKinsoku = 2;
+ }
+ nNoNeeded++;
+ }
+ }
+ }
+
+ OSL_ENSURE( nNoNeeded<=1, "Example of unexportable forbidden chars" );
+ rTypo.reserved1=nUseReserved;
+ if (rTypo.iLevelOfKinsoku)
+ {
+ rTypo.cchFollowingPunct = msword_cast<sal_Int16>
+ (pUseMe->beginLine.getLength());
+ if (rTypo.cchFollowingPunct > WW8DopTypography::nMaxFollowing - 1)
+ rTypo.cchFollowingPunct = WW8DopTypography::nMaxFollowing - 1;
+
+ rTypo.cchLeadingPunct = msword_cast<sal_Int16>
+ (pUseMe->endLine.getLength());
+ if (rTypo.cchLeadingPunct > WW8DopTypography::nMaxLeading - 1)
+ rTypo.cchLeadingPunct = WW8DopTypography::nMaxLeading -1;
+
+ memcpy(rTypo.rgxchFPunct,pUseMe->beginLine.getStr(),
+ (rTypo.cchFollowingPunct+1)*2);
+
+ memcpy(rTypo.rgxchLPunct,pUseMe->endLine.getStr(),
+ (rTypo.cchLeadingPunct+1)*2);
+ }
+
+ const IDocumentSettingAccess* pIDocumentSettingAccess = GetWriter().getIDocumentSettingAccess();
+
+ rTypo.fKerningPunct = pIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION);
+ rTypo.iJustification = pDoc->getCharacterCompressionType();
+}
+
+// HasItem ist fuer die Zusammenfassung der Doppel-Attribute
+// Underline / WordLineMode und Box / Shadow.
+// Es kann nur etwas gefunden werden, wenn diese Methode innerhalb
+// der aufgerufenen Methoden WW8_SwAttrIter::OutAttr() und
+// WW8Export::OutputItemSet() benutzt wird.
+const SfxPoolItem* MSWordExportBase::HasItem( sal_uInt16 nWhich ) const
+{
+ const SfxPoolItem* pItem=0;
+ if (pISet)
+ {
+ // if write a EditEngine text, then the WhichIds are greater as
+ // ourer own Ids. So the Id have to translate from our into the
+ // EditEngine Range
+ nWhich = sw::hack::GetSetWhichFromSwDocWhich(*pISet, *pDoc, nWhich);
+ if (nWhich && SFX_ITEM_SET != pISet->GetItemState(nWhich, true, &pItem))
+ pItem = 0;
+ }
+ else if( pChpIter )
+ pItem = pChpIter->HasTextItem( nWhich );
+ else
+ {
+ OSL_ENSURE( !this, "Wo ist mein ItemSet / pChpIter ?" );
+ pItem = 0;
+ }
+ return pItem;
+}
+
+const SfxPoolItem& MSWordExportBase::GetItem(sal_uInt16 nWhich) const
+{
+ const SfxPoolItem* pItem;
+ if (pISet)
+ {
+ // if write a EditEngine text, then the WhichIds are greater as
+ // ourer own Ids. So the Id have to translate from our into the
+ // EditEngine Range
+ nWhich = sw::hack::GetSetWhichFromSwDocWhich(*pISet, *pDoc, nWhich);
+ OSL_ENSURE(nWhich != 0, "All broken, Impossible");
+ pItem = &pISet->Get(nWhich, true);
+ }
+ else if( pChpIter )
+ pItem = &pChpIter->GetItem( nWhich );
+ else
+ {
+ OSL_ENSURE( !this, "Wo ist mein ItemSet / pChpIter ?" );
+ pItem = 0;
+ }
+ return *pItem;
+}
+
+//------------------------------------------------------------------------------
+
+WW8_WrPlc1::WW8_WrPlc1( sal_uInt16 nStructSz )
+ : aPos( 16, 16 ), nStructSiz( nStructSz )
+{
+ nDataLen = 16 * nStructSz;
+ pData = new sal_uInt8[ nDataLen ];
+}
+
+WW8_WrPlc1::~WW8_WrPlc1()
+{
+ delete[] pData;
+}
+
+WW8_CP WW8_WrPlc1::Prev() const
+{
+ sal_uInt16 nLen = aPos.Count();
+ OSL_ENSURE(nLen,"Prev called on empty list");
+ return nLen ? aPos[nLen-1] : 0;
+}
+
+void WW8_WrPlc1::Append( WW8_CP nCp, const void* pNewData )
+{
+ sal_uLong nInsPos = aPos.Count() * nStructSiz;
+ aPos.Insert( nCp, aPos.Count() );
+ if( nDataLen < nInsPos + nStructSiz )
+ {
+ sal_uInt8* pNew = new sal_uInt8[ 2 * nDataLen ];
+ memmove( pNew, pData, nDataLen );
+ delete[] pData;
+ pData = pNew;
+ nDataLen *= 2;
+ }
+ memcpy( pData + nInsPos, pNewData, nStructSiz );
+}
+
+void WW8_WrPlc1::Finish( sal_uLong nLastCp, sal_uLong nSttCp )
+{
+ if( aPos.Count() )
+ {
+ aPos.Insert( nLastCp, aPos.Count() );
+ if( nSttCp )
+ for( sal_uInt16 n = 0; n < aPos.Count(); ++n )
+ aPos[ n ] -= nSttCp;
+ }
+}
+
+
+void WW8_WrPlc1::Write( SvStream& rStrm )
+{
+ sal_uInt16 i;
+ for( i = 0; i < aPos.Count(); ++i )
+ SwWW8Writer::WriteLong( rStrm, aPos[i] );
+ if( i )
+ rStrm.Write( pData, (i-1) * nStructSiz );
+}
+
+//------------------------------------------------------------------------------
+// Klasse WW8_WrPlcFld fuer Felder
+//------------------------------------------------------------------------------
+
+
+bool WW8_WrPlcFld::Write( WW8Export& rWrt )
+{
+ if( WW8_WrPlc1::Count() <= 1 )
+ return false;
+
+ WW8_FC *pfc;
+ sal_Int32 *plc;
+ switch (nTxtTyp)
+ {
+ case TXT_MAINTEXT:
+ pfc = &rWrt.pFib->fcPlcffldMom;
+ plc = &rWrt.pFib->lcbPlcffldMom;
+ break;
+ case TXT_HDFT:
+ pfc = &rWrt.pFib->fcPlcffldHdr;
+ plc = &rWrt.pFib->lcbPlcffldHdr;
+ break;
+
+ case TXT_FTN:
+ pfc = &rWrt.pFib->fcPlcffldFtn;
+ plc = &rWrt.pFib->lcbPlcffldFtn;
+ break;
+
+ case TXT_EDN:
+ pfc = &rWrt.pFib->fcPlcffldEdn;
+ plc = &rWrt.pFib->lcbPlcffldEdn;
+ break;
+
+ case TXT_ATN:
+ pfc = &rWrt.pFib->fcPlcffldAtn;
+ plc = &rWrt.pFib->lcbPlcffldAtn;
+ break;
+
+ case TXT_TXTBOX:
+ pfc = &rWrt.pFib->fcPlcffldTxbx;
+ plc = &rWrt.pFib->lcbPlcffldTxbx;
+ break;
+
+ case TXT_HFTXTBOX:
+ pfc = &rWrt.pFib->fcPlcffldHdrTxbx;
+ plc = &rWrt.pFib->lcbPlcffldHdrTxbx;
+ break;
+
+ default:
+ pfc = plc = 0;
+ break;
+ }
+
+ if( pfc && plc )
+ {
+ sal_uLong nFcStart = rWrt.pTableStrm->Tell();
+ WW8_WrPlc1::Write( *rWrt.pTableStrm );
+ *pfc = nFcStart;
+ *plc = rWrt.pTableStrm->Tell() - nFcStart;
+ }
+ return true;
+}
+
+bool WW8_WrMagicTable::Write( WW8Export& rWrt )
+{
+ if( WW8_WrPlc1::Count() <= 1 )
+ return false;
+ sal_uLong nFcStart = rWrt.pTableStrm->Tell();
+ WW8_WrPlc1::Write( *rWrt.pTableStrm );
+ rWrt.pFib->fcPlcfTch = nFcStart;
+ rWrt.pFib->lcbPlcfTch = rWrt.pTableStrm->Tell() - nFcStart;
+ return true;
+}
+
+void WW8_WrMagicTable::Append( WW8_CP nCp, sal_uLong nData)
+{
+ SVBT32 nLittle;
+ /*
+ Tell the undocumented table hack that everything between here and the last
+ table position is nontable text, don't do it if the previous position is
+ the same as this one, as that would be a region of 0 length
+ */
+ if ((!Count()) || (Prev() != nCp))
+ {
+ UInt32ToSVBT32(nData,nLittle);
+ WW8_WrPlc1::Append(nCp, nLittle);
+ }
+}
+
+//--------------------------------------------------------------------------
+
+void SwWW8Writer::FillCount( SvStream& rStrm, sal_uLong nCount )
+{
+ static const sal_uInt32 aNulls[16] =
+ {
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 // 64 Byte
+ };
+
+ while (nCount > 64)
+ {
+ rStrm.Write( aNulls, 64 ); // in 64-Byte-Schritten
+ nCount -= 64;
+ }
+ rStrm.Write( aNulls, nCount ); // Rest ( 0 .. 64 Bytes ) schreiben
+}
+
+sal_uLong SwWW8Writer::FillUntil( SvStream& rStrm, sal_uLong nEndPos )
+{
+ sal_uLong nCurPos = rStrm.Tell();
+ if( !nEndPos ) // nEndPos == 0 -> next Page
+ nEndPos = (nCurPos + 0x1ff) & ~0x1ffUL;
+
+ if( nEndPos > nCurPos )
+ SwWW8Writer::FillCount( rStrm, nEndPos - nCurPos );
+#if OSL_DEBUG_LEVEL > 1
+ else
+ OSL_ENSURE( nEndPos == nCurPos, "Falsches FillUntil()" );
+#endif
+ return rStrm.Tell();
+}
+
+
+//--------------------------------------------------------------------------
+/* */
+
+WW8_WrPlcPn::WW8_WrPlcPn( WW8Export& rWr, ePLCFT ePl, WW8_FC nStartFc )
+ : rWrt(rWr), nFkpStartPage(0), ePlc(ePl), nMark(0)
+{
+ WW8_FkpPtr pF = new WW8_WrFkp( ePlc, nStartFc, rWrt.bWrtWW8 );
+ aFkps.Insert( pF, aFkps.Count() );
+}
+
+WW8_WrPlcPn::~WW8_WrPlcPn()
+{
+ aFkps.DeleteAndDestroy( 0, aFkps.Count() );
+}
+
+sal_uInt8 *WW8_WrPlcPn::CopyLastSprms(sal_uInt8 &rLen)
+{
+ WW8_FkpPtr pF = aFkps.GetObject(aFkps.Count() - 1);
+ return pF->CopyLastSprms(rLen, rWrt.bWrtWW8);
+}
+
+void WW8_WrPlcPn::AppendFkpEntry(WW8_FC nEndFc,short nVarLen,const sal_uInt8* pSprms)
+{
+ WW8_FkpPtr pF = aFkps.GetObject( aFkps.Count() - 1 );
+
+ // big sprm? build the sprmPHugePapx
+ sal_uInt8* pNewSprms = (sal_uInt8*)pSprms;
+ sal_uInt8 aHugePapx[ 8 ];
+ if( rWrt.bWrtWW8 && PAP == ePlc && 488 < nVarLen )
+ {
+ sal_uInt8* p = aHugePapx;
+ *p++ = *pSprms++; // set style Id
+ *p++ = *pSprms++;
+ nVarLen -= 2;
+
+ long nDataPos = rWrt.pDataStrm->Tell();
+ SwWW8Writer::WriteShort( *rWrt.pDataStrm, nVarLen );
+ rWrt.pDataStrm->Write( pSprms, nVarLen );
+
+ Set_UInt16( p, 0x6646 ); // set SprmCode
+ Set_UInt32( p, nDataPos ); // set startpos (FC) in the datastream
+ nVarLen = static_cast< short >(p - aHugePapx);
+ pSprms = pNewSprms = aHugePapx;
+ }
+ // if append at the same FC-EndPos and there are sprms, then get the old
+ // sprms and erase it; they will append now with the new sprms
+ else if( nVarLen && pF->IsEqualPos( nEndFc ))
+ pF->MergeToNew( nVarLen, pNewSprms );
+ // has the prev EndFC an empty sprm and the current is empty too, then
+ // expand only the old EndFc to the new EndFc
+ else if( !nVarLen && pF->IsEmptySprm() )
+ {
+ pF->SetNewEnd( nEndFc );
+ return ;
+ }
+
+ bool bOk = pF->Append(nEndFc, nVarLen, pNewSprms);
+ if( !bOk )
+ {
+ pF->Combine();
+ pF = new WW8_WrFkp( ePlc, pF->GetEndFc(), rWrt.bWrtWW8 );// Anfang neuer Fkp
+ // == Ende alter Fkp
+ aFkps.Insert( pF, aFkps.Count() );
+ if( !pF->Append( nEndFc, nVarLen, pNewSprms ) )
+ {
+ OSL_ENSURE( !this, "Sprm liess sich nicht einfuegen" );
+ }
+ }
+ if( pNewSprms != pSprms ) //Merge to new has created a new block
+ delete[] pNewSprms;
+}
+
+void WW8_WrPlcPn::WriteFkps()
+{
+ nFkpStartPage = (sal_uInt16) ( SwWW8Writer::FillUntil( rWrt.Strm() ) >> 9 );
+
+ for( sal_uInt16 i = 0; i < aFkps.Count(); i++ )
+ aFkps.GetObject( i )->Write( rWrt.Strm(), *rWrt.pGrf );
+
+ if( CHP == ePlc )
+ {
+ rWrt.pFib->pnChpFirst = nFkpStartPage;
+ rWrt.pFib->cpnBteChp = aFkps.Count();
+ }
+ else
+ {
+ rWrt.pFib->pnPapFirst = nFkpStartPage;
+ rWrt.pFib->cpnBtePap = aFkps.Count();
+ }
+}
+
+void WW8_WrPlcPn::WritePlc()
+{
+ sal_uLong nFcStart = rWrt.pTableStrm->Tell();
+ sal_uInt16 i;
+
+ for( i = 0; i < aFkps.Count(); i++ )
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm,
+ aFkps.GetObject( i )->GetStartFc() );
+
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm,
+ aFkps.GetObject( i - 1 )->GetEndFc() );
+
+ // fuer jedes FKP die Page ausgeben
+ if( rWrt.bWrtWW8) // fuer WW97 Long-Ausgabe
+ for ( i = 0; i < aFkps.Count(); i++)
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, i + nFkpStartPage );
+ else // fuer WW95 Short-Ausgabe
+ for ( i = 0; i < aFkps.Count(); i++)
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, i + nFkpStartPage );
+
+ if( CHP == ePlc )
+ {
+ rWrt.pFib->fcPlcfbteChpx = nFcStart;
+ rWrt.pFib->lcbPlcfbteChpx = rWrt.pTableStrm->Tell() - nFcStart;
+ }
+ else
+ {
+ rWrt.pFib->fcPlcfbtePapx = nFcStart;
+ rWrt.pFib->lcbPlcfbtePapx = rWrt.pTableStrm->Tell() - nFcStart;
+ }
+}
+
+//--------------------------------------------------------------------------
+/* */
+
+WW8_WrFkp::WW8_WrFkp(ePLCFT ePl, WW8_FC nStartFc, bool bWrtWW8)
+ : ePlc(ePl), nStartGrp(511), nOldStartGrp(511),
+ nItemSize( ( CHP == ePl ) ? 1 : ( bWrtWW8 ? 13 : 7 )),
+ nIMax(0), nOldVarLen(0), nMark(0), bCombined(false)
+{
+ pFkp = (sal_uInt8*)new sal_Int32[128]; // 512 Byte
+ pOfs = (sal_uInt8*)new sal_Int32[128]; // 512 Byte
+ memset( pFkp, 0, 4 * 128 );
+ memset( pOfs, 0, 4 * 128 );
+ ( (sal_Int32*)pFkp )[0] = nStartFc; // 0. FC-Eintrag auf nStartFc
+}
+
+WW8_WrFkp::~WW8_WrFkp()
+{
+ delete[] (sal_Int32 *)pFkp;
+ delete[] (sal_Int32 *)pOfs;
+}
+
+sal_uInt8 WW8_WrFkp::SearchSameSprm( sal_uInt16 nVarLen, const sal_uInt8* pSprms )
+{
+ if( 3 < nVarLen )
+ {
+ // if the sprms contained picture-references then never equal!
+ for( sal_uInt8 n = static_cast< sal_uInt8 >(nVarLen - 1); 3 < n; --n )
+ if( pSprms[ n ] == GRF_MAGIC_3 &&
+ pSprms[ n-1 ] == GRF_MAGIC_2 &&
+ pSprms[ n-2 ] == GRF_MAGIC_1 )
+ return 0;
+ }
+
+ short i;
+ for( i = 0; i < nIMax; i++ )
+ {
+ sal_uInt8 nStart = pOfs[i * nItemSize];
+ if( nStart )
+ { // Hat Sprms
+ const sal_uInt8* p = pFkp + ( (sal_uInt16)nStart << 1 );
+ if( ( CHP == ePlc
+ ? (*p++ == nVarLen)
+ : (((sal_uInt16)*p++ << 1 ) == (( nVarLen+1) & 0xfffe)) )
+ && !memcmp( p, pSprms, nVarLen ) )
+ return nStart; // gefunden
+ }
+ }
+ return 0; // nicht gefunden
+}
+
+sal_uInt8 *WW8_WrFkp::CopyLastSprms(sal_uInt8 &rLen, bool bVer8)
+{
+ rLen=0;
+ sal_uInt8 *pStart=0,*pRet=0;
+
+ if (!bCombined)
+ pStart = pOfs;
+ else
+ pStart = pFkp + ( nIMax + 1 ) * 4;
+
+ sal_uInt8 nStart = *(pStart + (nIMax-1) * nItemSize);
+
+ const sal_uInt8* p = pFkp + ( (sal_uInt16)nStart << 1 );
+
+ if (!*p && bVer8)
+ p++;
+
+ if (*p)
+ {
+ rLen = *p++;
+ if (PAP == ePlc)
+ rLen *= 2;
+ pRet = new sal_uInt8[rLen];
+ memcpy(pRet,p,rLen);
+ }
+ return pRet;
+}
+
+bool WW8_WrFkp::Append( WW8_FC nEndFc, sal_uInt16 nVarLen, const sal_uInt8* pSprms )
+{
+ OSL_ENSURE( !nVarLen || pSprms, "Item-Pointer fehlt" );
+ OSL_ENSURE( nVarLen < ( ( ePlc == PAP ) ? 497U : 502U ), "Sprms zu lang !" );
+
+ if( bCombined )
+ {
+ OSL_ENSURE( !this, "Fkp::Append: Fkp is already combined" );
+ return false;
+ }
+ sal_Int32 n = ((sal_Int32*)pFkp)[nIMax]; // letzter Eintrag
+ if( nEndFc <= n )
+ {
+ OSL_ENSURE( nEndFc >= n, "+Fkp: FC rueckwaerts" );
+ OSL_ENSURE( !nVarLen || !pSprms || nEndFc != n,
+ "+Fkp: selber FC mehrfach benutzt" );
+ // selber FC ohne Sprm wird ohne zu mosern ignoriert.
+
+ return true; // ignorieren, keinen neuen Fkp anlegen
+ }
+
+ sal_uInt8 nOldP = ( nVarLen ) ? SearchSameSprm( nVarLen, pSprms ) : 0;
+ // Kombinieren gleicher Eintraege
+ short nOffset=0, nPos = nStartGrp;
+ if (nVarLen && !nOldP)
+ {
+ nPos = PAP == ePlc
+ ? ( 13 == nItemSize // HACK: PAP und bWrtWW8 !!
+ ? (nStartGrp & 0xFFFE ) - nVarLen - 1
+ : (nStartGrp - (((nVarLen + 1) & 0xFFFE)+1)) & 0xFFFE )
+ : ((nStartGrp - nVarLen - 1) & 0xFFFE);
+ if( nPos < 0 )
+ return false; // Passt absolut nicht
+ nOffset = nPos; // Offset merken (kann auch ungerade sein!)
+ nPos &= 0xFFFE; // Pos fuer Sprms ( gerade Pos )
+ }
+
+ if( (sal_uInt16)nPos <= ( nIMax + 2U ) * 4U + ( nIMax + 1U ) * nItemSize )
+ // Passt hinter CPs und Offsets ?
+ return false; // Nein
+
+ ((sal_Int32*)pFkp)[nIMax + 1] = nEndFc; // FC eintragen
+
+ nOldVarLen = (sal_uInt8)nVarLen;
+ if( nVarLen && !nOldP )
+ { // echt eintragen
+ nOldStartGrp = nStartGrp;
+
+ nStartGrp = nPos;
+ pOfs[nIMax * nItemSize] = (sal_uInt8)( nStartGrp >> 1 );
+ // ( DatenAnfg >> 1 ) eintragen
+ sal_uInt8 nCnt = static_cast< sal_uInt8 >(CHP == ePlc
+ ? ( nVarLen < 256 ) ? (sal_uInt8) nVarLen : 255
+ : ( ( nVarLen + 1 ) >> 1 ));
+
+ pFkp[ nOffset ] = nCnt; // DatenLaenge eintragen
+ memcpy( pFkp + nOffset + 1, pSprms, nVarLen ); // Sprms speichern
+ }
+ else
+ {
+ // nicht echt eintragen ( keine Sprms oder Wiederholung )
+ // DatenAnfg 0 ( keine Daten ) oder Wiederholung
+ pOfs[nIMax * nItemSize] = nOldP;
+ }
+ nIMax++;
+ return true;
+}
+
+bool WW8_WrFkp::Combine()
+{
+ if( bCombined )
+ return false;
+ if( nIMax )
+ memcpy( pFkp + ( nIMax + 1 ) * 4, pOfs, nIMax * nItemSize );
+ delete[] pOfs;
+ pOfs = 0;
+ ((sal_uInt8*)pFkp)[511] = nIMax;
+ bCombined = true;
+
+#if defined OSL_BIGENDIAN // Hier werden nur die FCs gedreht, die
+ sal_uInt16 i; // Sprms muessen an anderer Stelle gedreht
+ // werden
+ sal_uInt32* p;
+ for( i = 0, p = (sal_uInt32*)pFkp; i <= nIMax; i++, p++ )
+ *p = SWAPLONG( *p );
+#endif // ifdef OSL_BIGENDIAN
+
+ return true;
+}
+
+void WW8_WrFkp::Write( SvStream& rStrm, SwWW8WrGrf& rGrf )
+{
+ Combine(); // Falls noch nicht Combined
+
+ sal_uInt8* p; // Suche Magic fuer nPicLocFc
+ sal_uInt8* pEnd = pFkp + nStartGrp;
+ for( p = pFkp + 511 - 4; p >= pEnd; p-- )
+ {
+ if( *p != GRF_MAGIC_1 ) // Suche nach Signatur 0x12 0x34 0x56 0xXX
+ continue;
+ if( *(p+1) != GRF_MAGIC_2 )
+ continue;
+ if( *(p+2) != GRF_MAGIC_3 )
+ continue;
+
+ SVBT32 nPos; // Signatur gefunden
+ UInt32ToSVBT32( rGrf.GetFPos(), nPos ); // FilePos der Grafik
+ memcpy( p, nPos, 4 ); // Patche FilePos ueber Signatur
+ }
+ rStrm.Write( pFkp, 512 );
+}
+
+void WW8_WrFkp::MergeToNew( short& rVarLen, sal_uInt8 *& rpNewSprms )
+{
+ sal_uInt8 nStart = pOfs[ (nIMax-1) * nItemSize ];
+ if( nStart )
+ { // Hat Sprms
+ sal_uInt8* p = pFkp + ( (sal_uInt16)nStart << 1 );
+
+ // old and new equal? Then copy only one into the new sprms
+ if( nOldVarLen == rVarLen && !memcmp( p+1, rpNewSprms, nOldVarLen ))
+ {
+ sal_uInt8* pNew = new sal_uInt8[ nOldVarLen ];
+ memcpy( pNew, p+1, nOldVarLen );
+ rpNewSprms = pNew;
+ }
+ else
+ {
+ sal_uInt8* pNew = new sal_uInt8[ nOldVarLen + rVarLen ];
+ memcpy( pNew, p+1, nOldVarLen );
+ memcpy( pNew + nOldVarLen, rpNewSprms, rVarLen );
+
+ rpNewSprms = pNew;
+ rVarLen = rVarLen + nOldVarLen;
+ }
+ --nIMax;
+ // if this sprms dont used from others, remove it
+ bool bFnd = false;
+ for (sal_uInt16 n = 0; n < nIMax; ++n)
+ {
+ if (nStart == pOfs[n * nItemSize])
+ {
+ bFnd = true;
+ break;
+ }
+ }
+ if (!bFnd)
+ {
+ nStartGrp = nOldStartGrp;
+ memset( p, 0, nOldVarLen+1 );
+ }
+ }
+}
+
+#ifdef __WW8_NEEDS_COPY
+
+WW8_FC WW8_WrFkp::GetStartFc() const
+{
+// wenn bCombined, dann ist das Array ab pFkp schon Bytemaessig auf LittleEndian
+// umgedreht, d.h. zum Herausholen der Anfangs- und Endpositionen muss
+// zurueckgedreht werden.
+ if( bCombined )
+ return SVBT32ToUInt32( pFkp ); // 0. Element
+ return ((sal_Int32*)pFkp)[0];
+}
+
+WW8_FC WW8_WrFkp::GetEndFc() const
+{
+ if( bCombined )
+ return SVBT32ToUInt32( &(pFkp[nIMax*4]) ); // nIMax-tes SVBT32-Element
+ return ((sal_Int32*)pFkp)[nIMax];
+}
+
+#endif // defined __WW8_NEEDS_COPY
+
+
+
+//--------------------------------------------------------------------------
+// Methoden fuer Piece-Table-Verwaltung
+//--------------------------------------------------------------------------
+
+WW8_WrPct::WW8_WrPct(WW8_FC nfcMin, bool bSaveUniCode)
+ : pPcts(new WW8_WrPcPtrs), nOldFc(nfcMin), bIsUni(bSaveUniCode)
+{
+ AppendPc( nOldFc, bIsUni );
+}
+
+WW8_WrPct::~WW8_WrPct()
+{
+ delete pPcts;
+}
+
+// Piece fuellen und neues Piece erzeugen
+void WW8_WrPct::AppendPc(WW8_FC nStartFc, bool bIsUnicode)
+{
+ WW8_CP nStartCp = nStartFc - nOldFc; // Textbeginn abziehen
+ if ( !nStartCp )
+ {
+ if ( 0 != pPcts->Count() )
+ {
+ OSL_ENSURE( 1 == pPcts->Count(), "Leeres Piece !!");
+ pPcts->DeleteAndDestroy( pPcts->Count() - 1 , 1);
+ }
+ }
+
+ nOldFc = nStartFc; // StartFc als alten merken
+
+ if( bIsUni )
+ nStartCp >>= 1; // Bei Unicode Anzahl der Zeichen / 2
+
+
+ if ( !bIsUnicode )
+ {
+ nStartFc <<= 1; // Adresse * 2
+ nStartFc |= 0x40000000; // Vorletztes Bit setzen fuer !Unicode
+ }
+
+ if( pPcts->Count() )
+ nStartCp += pPcts->GetObject( pPcts->Count()- 1 )->GetStartCp();
+
+ WW8_WrPcPtr pPc = new WW8_WrPc( nStartFc, nStartCp );
+ pPcts->Insert( pPc, pPcts->Count() );
+
+ bIsUni = bIsUnicode;
+}
+
+
+void WW8_WrPct::WritePc( WW8Export& rWrt )
+{
+ sal_uLong nPctStart;
+ sal_uLong nOldPos, nEndPos;
+ sal_uInt16 i;
+
+ nPctStart = rWrt.pTableStrm->Tell(); // Beginn Piece-Table
+ *rWrt.pTableStrm << ( char )0x02; // Statusbyte PCT
+ nOldPos = nPctStart + 1; // Position merken
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, 0 ); // Laenge folgt
+ for( i = 0; i < pPcts->Count(); ++i ) // Bereiche
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm,
+ pPcts->GetObject( i )->GetStartCp() );
+
+
+ // die letzte Pos noch errechnen
+ sal_uLong nStartCp = rWrt.pFib->fcMac - nOldFc;
+ if( bIsUni )
+ nStartCp >>= 1; // Bei Unicode Anzahl der Zeichen / 2
+ nStartCp += pPcts->GetObject( i-1 )->GetStartCp();
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, nStartCp );
+
+ // Pieceverweise
+ for ( i = 0; i < pPcts->Count(); ++i )
+ {
+ WW8_WrPcPtr pPc = pPcts->GetObject( i );
+
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, pPc->GetStatus());
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, pPc->GetStartFc());
+ SwWW8Writer::WriteShort( *rWrt.pTableStrm, 0); // PRM=0
+ }
+
+ // Eintraege im FIB
+ rWrt.pFib->fcClx = nPctStart;
+ nEndPos = rWrt.pTableStrm->Tell();
+ rWrt.pFib->lcbClx = nEndPos - nPctStart;
+
+ // und noch die Laenge eintragen
+ SwWW8Writer::WriteLong( *rWrt.pTableStrm, nOldPos,
+ nEndPos - nPctStart-5 );
+
+}
+
+void WW8_WrPct::SetParaBreak()
+{
+ OSL_ENSURE( pPcts->Count(),"SetParaBreak : aPcts.Count = 0" );
+ pPcts->GetObject( pPcts->Count() - 1)->SetStatus();
+}
+
+WW8_CP WW8_WrPct::Fc2Cp( sal_uLong nFc ) const
+{
+ OSL_ENSURE( nFc >= (sal_uLong)nOldFc, "FilePos liegt vorm letzten Piece" );
+ OSL_ENSURE( pPcts->Count(), "Fc2Cp noch kein Piece vorhanden" );
+
+ nFc -= nOldFc;
+ if( bIsUni )
+ nFc /= 2;
+ return nFc + pPcts->GetObject( pPcts->Count() - 1 )->GetStartCp();
+}
+
+//--------------------------------------------------------------------------
+/* */
+
+WW8_WrtBookmarks::WW8_WrtBookmarks()
+{
+}
+
+WW8_WrtBookmarks::~WW8_WrtBookmarks()
+{
+}
+
+void WW8_WrtBookmarks::Append( WW8_CP nStartCp, const String& rNm, const ::sw::mark::IMark* )
+{
+ BkmIter bkIter = GetPos( rNm );
+ if( bkIter == aBookmarks.end() )
+ {
+ // new bookmark -> insert with start==end
+ aBookmarks.push_back( BookmarkInfo(nStartCp, nStartCp, false, rNm) );
+ }
+ else
+ {
+ // old bookmark -> this should be the end position
+ OSL_ENSURE( bkIter->endPos == bkIter->startPos, "end position is valid" );
+
+ //If this bookmark was around a field in writer, then we want to move
+ //it to the field result in word. The end is therefore one cp
+ //backwards from the 0x15 end mark that was inserted.
+ if (bkIter->isField)
+ --nStartCp;
+ bkIter->endPos = nStartCp;
+ }
+}
+
+
+void WW8_WrtBookmarks::Write( WW8Export& rWrt )
+{
+ if (!aBookmarks.empty())
+ {
+ //Make sure the bookmarks are sorted in order of start position.
+ std::sort(aBookmarks.begin(), aBookmarks.end());
+
+ // First write the Bookmark Name Stringtable
+ std::vector<String> aNames;
+ aNames.reserve(aBookmarks.size());
+ for (BkmIter bIt = aBookmarks.begin(); bIt < aBookmarks.end(); ++bIt)
+ aNames.push_back(bIt->name);
+ rWrt.WriteAsStringTable(aNames, rWrt.pFib->fcSttbfbkmk, rWrt.pFib->lcbSttbfbkmk);
+
+ // Second write the Bookmark start positions as pcf of longs
+ SvStream& rStrm = rWrt.bWrtWW8 ? *rWrt.pTableStrm : rWrt.Strm();
+ rWrt.pFib->fcPlcfbkf = rStrm.Tell();
+ for (BkmIter bIt = aBookmarks.begin(); bIt < aBookmarks.end(); ++bIt)
+ SwWW8Writer::WriteLong( rStrm, bIt->startPos );
+ SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx);
+
+ //Lastly, need to write out the end positions (sorted by end position). But
+ //before that we need a lookup table (sorted by start position) to link
+ //start and end positions.
+ // Start by sorting the end positions.
+ std::vector<sal_uLong> aEndSortTab;
+ aEndSortTab.reserve(aBookmarks.size());
+ for (BkmIter bIt = aBookmarks.begin(); bIt < aBookmarks.end(); ++bIt)
+ aEndSortTab.push_back(bIt->endPos);
+ std::sort(aEndSortTab.begin(), aEndSortTab.end());
+
+ //Now write out the lookups.
+ //Note that in most cases, the positions in both vectors will be very close.
+ for( sal_uLong i = 0; i < aBookmarks.size(); ++i )
+ {
+ sal_uLong nEndCP = aBookmarks[ i ].endPos;
+ sal_uInt16 nPos = i;
+ if( aEndSortTab[ nPos ] > nEndCP )
+ {
+ while( aEndSortTab[ --nPos ] != nEndCP )
+ ;
+ }
+ else if( aEndSortTab[ nPos ] < nEndCP )
+ while( aEndSortTab[ ++nPos ] != nEndCP )
+ ;
+ SwWW8Writer::WriteLong( rStrm, nPos );
+ }
+ rWrt.pFib->lcbPlcfbkf = rStrm.Tell() - rWrt.pFib->fcPlcfbkf;
+
+ // Finally, the actual Bookmark end positions.
+ rWrt.pFib->fcPlcfbkl = rStrm.Tell();
+ for(sal_uLong i = 0; i < aEndSortTab.size(); ++i )
+ SwWW8Writer::WriteLong( rStrm, aEndSortTab[ i ] );
+ SwWW8Writer::WriteLong(rStrm, rWrt.pFib->ccpText + rWrt.pFib->ccpTxbx);
+ rWrt.pFib->lcbPlcfbkl = rStrm.Tell() - rWrt.pFib->fcPlcfbkl;
+ }
+}
+
+WW8_WrtBookmarks::BkmIter WW8_WrtBookmarks::GetPos( const String& rNm )
+{
+ for (BkmIter bIt = aBookmarks.begin(); bIt < aBookmarks.end(); ++bIt) {
+ if (rNm == bIt->name)
+ return bIt;
+ }
+ return aBookmarks.end();
+}
+
+void WW8_WrtBookmarks::MoveFieldMarks(sal_uLong nFrom, sal_uLong nTo)
+{
+ for (BkmIter i = aBookmarks.begin(); i < aBookmarks.end(); ++i)
+ {
+ if (i->startPos == nFrom)
+ {
+ i->startPos = nTo;
+ if (i->endPos == nFrom)
+ {
+ i->isField = true;
+ i->endPos = nTo;
+ }
+ }
+ }
+}
+
+void WW8Export::AppendBookmarks( const SwTxtNode& rNd,
+ xub_StrLen nAktPos, xub_StrLen nLen )
+{
+ SvPtrarr aArr( 8, 8 );
+ sal_uInt16 nCntnt;
+ xub_StrLen nAktEnd = nAktPos + nLen;
+ if( GetWriter().GetBookmarks( rNd, nAktPos, nAktEnd, aArr ))
+ {
+ sal_uLong nNd = rNd.GetIndex(), nSttCP = Fc2Cp( Strm().Tell() );
+ for( sal_uInt16 n = 0; n < aArr.Count(); ++n )
+ {
+ ::sw::mark::IMark& rBkmk = *(::sw::mark::IMark*)aArr[ n ];
+ if(dynamic_cast< ::sw::mark::IFieldmark *>(&rBkmk))
+ continue;
+
+ const SwPosition* pPos = &rBkmk.GetMarkPos();
+ const SwPosition* pOPos = 0;
+ if(rBkmk.IsExpanded())
+ pOPos = &rBkmk.GetOtherMarkPos();
+ if( pOPos && pOPos->nNode == pPos->nNode &&
+ pOPos->nContent < pPos->nContent )
+ {
+ pPos = pOPos;
+ pOPos = &rBkmk.GetMarkPos();
+ }
+
+ if( !pOPos || ( nNd == pPos->nNode.GetIndex() &&
+ ( nCntnt = pPos->nContent.GetIndex() ) >= nAktPos &&
+ nCntnt < nAktEnd ) )
+ {
+ sal_uLong nCp = nSttCP + pPos->nContent.GetIndex() - nAktPos;
+ pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()), &rBkmk);
+ }
+ if( pOPos && nNd == pOPos->nNode.GetIndex() &&
+ ( nCntnt = pOPos->nContent.GetIndex() ) >= nAktPos &&
+ nCntnt < nAktEnd )
+ {
+ sal_uLong nCp = nSttCP + pOPos->nContent.GetIndex() - nAktPos;
+ pBkmks->Append(nCp, BookmarkToWord(rBkmk.GetName()), &rBkmk);
+ }
+ }
+ }
+}
+
+void WW8Export::MoveFieldMarks(sal_uLong nFrom, sal_uLong nTo)
+{
+ pBkmks->MoveFieldMarks(nFrom, nTo);
+}
+
+void WW8Export::AppendBookmark( const rtl::OUString& rName, bool bSkip )
+{
+ sal_uLong nSttCP = Fc2Cp( Strm().Tell() ) + ( bSkip? 1: 0 );
+ pBkmks->Append( nSttCP, rName );
+}
+
+void MSWordExportBase::AppendWordBookmark( const String& rName )
+{
+ AppendBookmark( BookmarkToWord( rName ) );
+}
+
+
+//--------------------------------------------------------------------------
+/* */
+
+void WW8_WrtRedlineAuthor::Write( Writer& rWrt )
+{
+ WW8Export & rWW8Wrt = *(((SwWW8Writer&)rWrt).m_pExport);
+ rWW8Wrt.WriteAsStringTable(maAuthors, rWW8Wrt.pFib->fcSttbfRMark,
+ rWW8Wrt.pFib->lcbSttbfRMark, rWW8Wrt.bWrtWW8 ? 0 : 2);
+}
+
+sal_uInt16 WW8Export::AddRedlineAuthor( sal_uInt16 nId )
+{
+ if( !pRedlAuthors )
+ {
+ pRedlAuthors = new WW8_WrtRedlineAuthor;
+ pRedlAuthors->AddName(CREATE_CONST_ASC("Unknown"));
+ }
+ return pRedlAuthors->AddName( SW_MOD()->GetRedlineAuthor( nId ) );
+}
+
+//--------------------------------------------------------------------------
+/* */
+
+void WW8Export::WriteAsStringTable(const std::vector<String>& rStrings,
+ sal_Int32& rfcSttbf, sal_Int32& rlcbSttbf, sal_uInt16 nExtraLen)
+{
+ sal_uInt16 n, nCount = static_cast< sal_uInt16 >(rStrings.size());
+ if( nCount )
+ {
+ // we have some Redlines found in the document -> the
+ // Author Name Stringtable
+ SvStream& rStrm = bWrtWW8 ? *pTableStrm : Strm();
+ rfcSttbf = rStrm.Tell();
+ if( bWrtWW8 )
+ {
+ SwWW8Writer::WriteShort( rStrm, -1 );
+ SwWW8Writer::WriteLong( rStrm, nCount );
+ for( n = 0; n < nCount; ++n )
+ {
+ const String& rNm = rStrings[n];
+ SwWW8Writer::WriteShort( rStrm, rNm.Len() );
+ SwWW8Writer::WriteString16(rStrm, rNm, false);
+ if( nExtraLen )
+ SwWW8Writer::FillCount(rStrm, nExtraLen);
+ }
+ }
+ else
+ {
+ SwWW8Writer::WriteShort( rStrm, 0 );
+ for( n = 0; n < nCount; ++n )
+ {
+ const String aNm(rStrings[n].Copy(0, 255));
+ rStrm << (sal_uInt8)aNm.Len();
+ SwWW8Writer::WriteString8(rStrm, aNm, false,
+ RTL_TEXTENCODING_MS_1252);
+ if (nExtraLen)
+ SwWW8Writer::FillCount(rStrm, nExtraLen);
+ }
+ }
+ rlcbSttbf = rStrm.Tell() - rfcSttbf;
+ if( !bWrtWW8 )
+ SwWW8Writer::WriteShort( rStrm, rfcSttbf, (sal_uInt16)rlcbSttbf );
+ }
+}
+
+// WriteShort() traegt an FilePos nPos den Wert nVal ein und seekt auf die
+// alte FilePos zurueck. Benutzt zum Nachtragen von Laengen.
+void SwWW8Writer::WriteShort( SvStream& rStrm, sal_uLong nPos, sal_Int16 nVal )
+{
+ sal_uLong nOldPos = rStrm.Tell(); // Pos merken
+ rStrm.Seek( nPos );
+ SwWW8Writer::WriteShort( rStrm, nVal );
+ rStrm.Seek( nOldPos );
+}
+
+void SwWW8Writer::WriteLong( SvStream& rStrm, sal_uLong nPos, sal_Int32 nVal )
+{
+ sal_uLong nOldPos = rStrm.Tell(); // Pos merken
+ rStrm.Seek( nPos );
+ SwWW8Writer::WriteLong( rStrm, nVal );
+ rStrm.Seek( nOldPos );
+}
+
+void SwWW8Writer::InsUInt16(ww::bytes &rO, sal_uInt16 n)
+{
+ SVBT16 nL;
+ ShortToSVBT16( n, nL );
+ rO.push_back(nL[0]);
+ rO.push_back(nL[1]);
+}
+
+void SwWW8Writer::InsUInt32(ww::bytes &rO, sal_uInt32 n)
+{
+ SVBT32 nL;
+ UInt32ToSVBT32( n, nL );
+ rO.push_back(nL[0]);
+ rO.push_back(nL[1]);
+ rO.push_back(nL[2]);
+ rO.push_back(nL[3]);
+}
+
+void SwWW8Writer::InsAsString16(ww::bytes &rO, const String& rStr)
+{
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ for( xub_StrLen n = 0, nLen = rStr.Len(); n < nLen; ++n, ++pStr )
+ SwWW8Writer::InsUInt16( rO, *pStr );
+}
+
+void SwWW8Writer::InsAsString8(ww::bytes &rO, const String& rStr,
+ rtl_TextEncoding eCodeSet)
+{
+ ByteString sTmp(rStr, eCodeSet);
+ const sal_Char *pStart = sTmp.GetBuffer();
+ const sal_Char *pEnd = pStart + sTmp.Len();
+ rO.reserve(rO.size() + sTmp.Len());
+
+ std::copy(pStart, pEnd, std::inserter(rO, rO.end()));
+}
+
+#ifdef __WW8_NEEDS_COPY
+
+void SwWW8Writer::InsUInt16( WW8Bytes& rO, sal_uInt16 n )
+{
+ SVBT16 nL;
+ ShortToSVBT16( n, nL );
+ rO.Insert( nL, 2, rO.Count() );
+}
+void SwWW8Writer::InsUInt32( WW8Bytes& rO, sal_uInt32 n )
+{
+ SVBT32 nL;
+ UInt32ToSVBT32( n, nL );
+ rO.Insert( nL, 4, rO.Count() );
+}
+
+#else
+
+void SwWW8Writer::InsUInt16( WW8Bytes& rO, sal_uInt16 n )
+{
+ rO.Insert( (sal_uInt8*)&n, 2, rO.Count() );
+}
+void SwWW8Writer::InsUInt32( WW8Bytes& rO, sal_uInt32 n )
+{
+ rO.Insert( (sal_uInt8*)&n, 4, rO.Count() );
+}
+
+#endif // defined __WW8_NEEDS_COPY
+
+void SwWW8Writer::InsAsString16( WW8Bytes& rO, const String& rStr )
+{
+ const sal_Unicode* pStr = rStr.GetBuffer();
+ for( xub_StrLen n = 0, nLen = rStr.Len(); n < nLen; ++n, ++pStr )
+ SwWW8Writer::InsUInt16( rO, *pStr );
+}
+
+void SwWW8Writer::InsAsString8( WW8Bytes& rO, const String& rStr,
+ rtl_TextEncoding eCodeSet )
+{
+ ByteString sTmp( rStr, eCodeSet );
+ rO.Insert( (sal_uInt8*)sTmp.GetBuffer(), sTmp.Len(), rO.Count() );
+}
+
+void SwWW8Writer::WriteString16(SvStream& rStrm, const String& rStr,
+ bool bAddZero)
+{
+ ww::bytes aBytes;
+ SwWW8Writer::InsAsString16(aBytes, rStr);
+ if (bAddZero)
+ SwWW8Writer::InsUInt16(aBytes, 0);
+ //vectors are guaranteed to have contiguous memory, so we can do
+ //this while migrating away from WW8Bytes. Meyers Effective STL, item 16
+ if (!aBytes.empty())
+ rStrm.Write(&aBytes[0], aBytes.size());
+}
+
+void SwWW8Writer::WriteString_xstz(SvStream& rStrm, const String& rStr, bool bAddZero)
+{
+ ww::bytes aBytes;
+ SwWW8Writer::InsUInt16(aBytes, rStr.Len());
+ SwWW8Writer::InsAsString16(aBytes, rStr);
+ if (bAddZero)
+ SwWW8Writer::InsUInt16(aBytes, 0);
+ rStrm.Write(&aBytes[0], aBytes.size());
+}
+
+
+void SwWW8Writer::WriteString8(SvStream& rStrm, const String& rStr,
+ bool bAddZero, rtl_TextEncoding eCodeSet)
+{
+ ww::bytes aBytes;
+ SwWW8Writer::InsAsString8(aBytes, rStr, eCodeSet);
+ if (bAddZero)
+ aBytes.push_back(0);
+ //vectors are guaranteed to have contiguous memory, so we can do
+ ////this while migrating away from WW8Bytes. Meyers Effective STL, item 16
+ if (!aBytes.empty())
+ rStrm.Write(&aBytes[0], aBytes.size());
+}
+
+void WW8Export::WriteStringAsPara( const String& rTxt, sal_uInt16 nStyleId )
+{
+ if( rTxt.Len() )
+ OutSwString( rTxt, 0, rTxt.Len(), IsUnicode(), RTL_TEXTENCODING_MS_1252 );
+ WriteCR(); // CR danach
+
+ WW8Bytes aArr( 10, 10 );
+ SwWW8Writer::InsUInt16( aArr, nStyleId );
+ if( bOutTable )
+ { // Tab-Attr
+ // sprmPFInTable
+ if( bWrtWW8 )
+ SwWW8Writer::InsUInt16( aArr, NS_sprm::LN_PFInTable );
+ else
+ aArr.Insert( 24, aArr.Count() );
+ aArr.Insert( 1, aArr.Count() );
+ }
+
+ sal_uLong nPos = Strm().Tell();
+ pPapPlc->AppendFkpEntry( nPos, aArr.Count(), aArr.GetData() );
+ pChpPlc->AppendFkpEntry( nPos );
+}
+
+void MSWordExportBase::WriteSpecialText( sal_uLong nStart, sal_uLong nEnd, sal_uInt8 nTTyp )
+{
+ sal_uInt8 nOldTyp = nTxtTyp;
+ nTxtTyp = nTTyp;
+ SwPaM* pOldPam = pCurPam; //!! Einfaches Umsetzen des PaM ohne
+ SwPaM* pOldEnd = pOrigPam; // Wiederherstellen muesste es auch tun
+ bool bOldPageDescs = bOutPageDescs;
+ bOutPageDescs = false;
+ // bOutKF wird in WriteKF1 gemerkt / gesetzt
+ pCurPam = Writer::NewSwPaM( *pDoc, nStart, nEnd );
+
+ // Tabelle in Sonderbereichen erkennen
+ if ( ( nStart != pCurPam->GetMark()->nNode.GetIndex() ) &&
+ pDoc->GetNodes()[ nStart ]->IsTableNode() )
+ {
+ pCurPam->GetMark()->nNode = nStart;
+ }
+
+ pOrigPam = pCurPam;
+ pCurPam->Exchange();
+
+ WriteText();
+
+ bOutPageDescs = bOldPageDescs;
+ delete pCurPam; // Pam wieder loeschen
+ pCurPam = pOldPam;
+ pOrigPam = pOldEnd;
+ nTxtTyp = nOldTyp;
+}
+
+void WW8Export::OutSwString(const String& rStr, xub_StrLen nStt,
+ xub_StrLen nLen, bool bUnicode, rtl_TextEncoding eChrSet)
+
+{
+#ifdef DEBUG
+ ::std::clog << "<OutSwString>" << ::std::endl;
+#endif
+
+ if( nLen )
+ {
+ if ( bUnicode != pPiece->IsUnicode() )
+ pPiece->AppendPc ( Strm().Tell(), bUnicode );
+
+ if( nStt || nLen != rStr.Len() )
+ {
+ String sOut( rStr.Copy( nStt, nLen ) );
+
+#ifdef DEBUG
+ ::std::clog << ::rtl::OUStringToOString(sOut, RTL_TEXTENCODING_ASCII_US).getStr() << ::std::endl;
+#endif
+
+ if (bUnicode)
+ SwWW8Writer::WriteString16(Strm(), sOut, false);
+ else
+ SwWW8Writer::WriteString8(Strm(), sOut, false, eChrSet);
+ }
+ else
+ {
+#ifdef DEBUG
+ ::std::clog << ::rtl::OUStringToOString(rStr, RTL_TEXTENCODING_ASCII_US).getStr() << ::std::endl;
+#endif
+
+ if (bUnicode)
+ SwWW8Writer::WriteString16(Strm(), rStr, false);
+ else
+ SwWW8Writer::WriteString8(Strm(), rStr, false, eChrSet);
+ }
+ }
+
+#ifdef DEBUG
+ ::std::clog << "</OutSwString>" << ::std::endl;
+#endif
+}
+
+void WW8Export::WriteCR(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
+{
+ if (pTableTextNodeInfoInner.get() != NULL && pTableTextNodeInfoInner->getDepth() == 1 && pTableTextNodeInfoInner->isEndOfCell())
+ WriteChar('\007');
+ else
+ WriteChar( '\015' );
+
+ pPiece->SetParaBreak();
+}
+
+void WW8Export::WriteChar( sal_Unicode c )
+{
+ if( pPiece->IsUnicode() )
+ Strm() << c;
+ else
+ Strm() << (sal_uInt8)c;
+}
+
+void MSWordExportBase::SaveData( sal_uLong nStt, sal_uLong nEnd )
+{
+ MSWordSaveData aData;
+
+ // WW8Export only stuff - zeroed here not to issue warnings
+ aData.pOOld = NULL;
+ aData.mpTableAtOld = NULL;
+ aData.mnTableStdAtLenOld = 0;
+
+ // Common stuff
+ aData.pOldPam = pCurPam;
+ aData.pOldEnd = pOrigPam;
+ aData.pOldFlyFmt = mpParentFrame;
+ aData.pOldPageDesc = pAktPageDesc;
+
+ aData.pOldFlyOffset = pFlyOffset;
+ aData.eOldAnchorType = eNewAnchorType;
+
+ aData.bOldOutTable = bOutTable;
+ aData.bOldIsInTable = bIsInTable;
+ aData.bOldFlyFrmAttrs = bOutFlyFrmAttrs;
+ aData.bOldStartTOX = bStartTOX;
+ aData.bOldInWriteTOX = bInWriteTOX;
+
+ pCurPam = Writer::NewSwPaM( *pDoc, nStt, nEnd );
+
+ // Recognize tables in special cases
+ if ( nStt != pCurPam->GetMark()->nNode.GetIndex() &&
+ pDoc->GetNodes()[ nStt ]->IsTableNode() )
+ {
+ pCurPam->GetMark()->nNode = nStt;
+ }
+
+ pOrigPam = pCurPam;
+ pCurPam->Exchange();
+
+ bOutTable = false;
+ // Caution: bIsInTable should not be set here
+ bOutFlyFrmAttrs = false;
+ bStartTOX = false;
+ bInWriteTOX = false;
+
+ maSaveData.push( aData );
+}
+
+void MSWordExportBase::RestoreData()
+{
+ MSWordSaveData &rData = maSaveData.top();
+
+ delete pCurPam;
+ pCurPam = rData.pOldPam;
+ pOrigPam = rData.pOldEnd;
+
+ bOutTable = rData.bOldOutTable;
+ bIsInTable = rData.bOldIsInTable;
+ bOutFlyFrmAttrs = rData.bOldFlyFrmAttrs;
+ bStartTOX = rData.bOldStartTOX;
+ bInWriteTOX = rData.bOldInWriteTOX;
+
+ mpParentFrame = rData.pOldFlyFmt;
+ pAktPageDesc = rData.pOldPageDesc;
+
+ eNewAnchorType = rData.eOldAnchorType;
+ pFlyOffset = rData.pOldFlyOffset;
+
+ maSaveData.pop();
+}
+
+void WW8Export::SaveData( sal_uLong nStt, sal_uLong nEnd )
+{
+ MSWordExportBase::SaveData( nStt, nEnd );
+
+ MSWordSaveData &rData = maSaveData.top();
+
+ if ( pO->Count() )
+ {
+ rData.pOOld = pO;
+ pO = new WW8Bytes( 128, 128 );
+ }
+ else
+ rData.pOOld = 0; // reuse pO
+
+ rData.mpTableAtOld = mpTableAt;
+ mpTableAt = NULL;
+ rData.mnTableStdAtLenOld = mnTableStdAtLen;
+ mnTableStdAtLen = 0;
+
+ rData.bOldWriteAll = GetWriter().bWriteAll;
+ GetWriter().bWriteAll = true;
+}
+
+void WW8Export::RestoreData()
+{
+ MSWordSaveData &rData = maSaveData.top();
+
+ GetWriter().bWriteAll = rData.bOldWriteAll;
+
+ OSL_ENSURE( !pO->Count(), "pO is not empty in WW8Export::RestoreData()" );
+ if ( rData.pOOld )
+ {
+ delete pO;
+ pO = rData.pOOld;
+ }
+
+ OSL_ENSURE( !mpTableAt || !mpTableAt->Count(), "mpTableAt is not empty in WW8Export::RestoreData()" );
+ if ( mpTableAt )
+ delete mpTableAt;
+ mpTableAt = rData.mpTableAtOld;
+ mnTableStdAtLen = rData.mnTableStdAtLenOld;
+
+ MSWordExportBase::RestoreData();
+}
+
+void WW8AttributeOutput::TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
+
+ if ( nDepth > 0 )
+ {
+ /* Cell */
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFInTable );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PTableDepth );
+ m_rWW8Export.InsUInt32( nDepth );
+
+ if ( nDepth > 1 && pTableTextNodeInfoInner->isEndOfCell() )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PCell );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
+ }
+ }
+}
+
+void WW8AttributeOutput::TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ sal_uInt32 nDepth = pTableTextNodeInfoInner->getDepth();
+
+ if ( nDepth > 0 )
+ {
+ /* Row */
+ if ( pTableTextNodeInfoInner->isEndOfLine() )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFInTable );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
+
+ if ( nDepth == 1 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFTtp );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
+ }
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PTableDepth );
+ m_rWW8Export.InsUInt32( nDepth );
+
+ if ( nDepth > 1 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PCell );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PRow );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x1, m_rWW8Export.pO->Count() );
+ }
+
+ TableDefinition( pTableTextNodeInfoInner );
+ TableHeight( pTableTextNodeInfoInner );
+ TableBackgrounds( pTableTextNodeInfoInner );
+ TableDefaultBorders( pTableTextNodeInfoInner );
+ TableCanSplit( pTableTextNodeInfoInner );
+ TableBidi( pTableTextNodeInfoInner );
+ TableVerticalCell( pTableTextNodeInfoInner );
+ TableOrientation( pTableTextNodeInfoInner );
+ TableSpacing( pTableTextNodeInfoInner );
+ }
+ }
+}
+
+static sal_uInt16 lcl_TCFlags(const SwTableBox * pBox, long nRowSpan)
+{
+ sal_uInt16 nFlags = 0;
+
+ if (nRowSpan > 1)
+ nFlags |= (3 << 5);
+ else if (nRowSpan < 0)
+ nFlags |= (1 << 5);
+
+ if (pBox != NULL)
+ {
+ const SwFrmFmt * pFmt = pBox->GetFrmFmt();
+ switch (pFmt->GetVertOrient().GetVertOrient())
+ {
+ case text::VertOrientation::CENTER:
+ nFlags |= (1 << 7);
+ break;
+ case text::VertOrientation::BOTTOM:
+ nFlags |= (2 << 7);
+ break;
+ default:
+ break;
+ }
+ }
+
+ return nFlags;
+}
+
+void WW8AttributeOutput::TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwTableBoxes & rTblBoxes = pTabLine->GetTabBoxes();
+
+ sal_uInt8 nBoxes = rTblBoxes.Count();
+ for ( sal_uInt8 n = 0; n < nBoxes; n++ )
+ {
+ const SwTableBox * pTabBox1 = rTblBoxes[n];
+ const SwFrmFmt * pFrmFmt = pTabBox1->GetFrmFmt();
+
+ if ( FRMDIR_VERT_TOP_RIGHT == m_rWW8Export.TrueFrameDirection( *pFrmFmt ) )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TTextFlow );
+ m_rWW8Export.pO->Insert( sal_uInt8(n), m_rWW8Export.pO->Count() ); //start range
+ m_rWW8Export.pO->Insert( sal_uInt8(n + 1), m_rWW8Export.pO->Count() ); //end range
+ m_rWW8Export.InsUInt16( 5 ); //Equals vertical writing
+ }
+ }
+}
+
+void WW8AttributeOutput::TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
+
+ /*
+ By default the row can be split in word, and now in writer we have a
+ feature equivalent to this, Word stores 1 for fCantSplit if the row
+ cannot be split, we set true if we can split it. An example is #i4569#
+ */
+
+ const SwFmtRowSplit& rSplittable = pLineFmt->GetRowSplit();
+ sal_uInt8 nCantSplit = (!rSplittable.GetValue()) ? 1 : 0;
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TFCantSplit );
+ m_rWW8Export.pO->Insert( nCantSplit, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TFCantSplit90 ); // also write fCantSplit90
+ }
+ else
+ {
+ m_rWW8Export.pO->Insert( 185, m_rWW8Export.pO->Count() );
+ }
+ m_rWW8Export.pO->Insert( nCantSplit, m_rWW8Export.pO->Count() );
+}
+
+void WW8AttributeOutput::TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTable * pTable = pTableTextNodeInfoInner->getTable();
+ const SwFrmFmt * pFrmFmt = pTable->GetFrmFmt();
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ if ( m_rWW8Export.TrueFrameDirection(*pFrmFmt) == FRMDIR_HORI_RIGHT_TOP )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TFBiDi );
+ m_rWW8Export.InsUInt16( 1 );
+ }
+ }
+}
+
+void WW8AttributeOutput::TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwFrmFmt * pLineFmt = pTabLine->GetFrmFmt();
+
+ // Zeilenhoehe ausgeben sprmTDyaRowHeight
+ long nHeight = 0;
+ const SwFmtFrmSize& rLSz = pLineFmt->GetFrmSize();
+ if ( ATT_VAR_SIZE != rLSz.GetHeightSizeType() && rLSz.GetHeight() )
+ {
+ if ( ATT_MIN_SIZE == rLSz.GetHeightSizeType() )
+ nHeight = rLSz.GetHeight();
+ else
+ nHeight = -rLSz.GetHeight();
+ }
+
+ if ( nHeight )
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TDyaRowHeight );
+ else
+ m_rWW8Export.pO->Insert( 189, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( (sal_uInt16)nHeight );
+ }
+
+}
+
+void WW8AttributeOutput::TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTable * pTable = pTableTextNodeInfoInner->getTable();
+
+ const SwFrmFmt *pFmt = pTable->GetFrmFmt();
+ OSL_ENSURE(pFmt,"Impossible");
+ if (!pFmt)
+ return;
+
+ const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
+ const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
+
+ if (
+ (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
+ text::RelOrientation::FRAME == rHori.GetRelationOrient())
+ &&
+ (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
+ text::RelOrientation::FRAME == rVert.GetRelationOrient())
+ )
+ {
+ sal_Int16 eHOri = rHori.GetHoriOrient();
+ switch (eHOri)
+ {
+ case text::HoriOrientation::CENTER:
+ case text::HoriOrientation::RIGHT:
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TJc );
+ else
+ m_rWW8Export.pO->Insert( 182, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( text::HoriOrientation::RIGHT == eHOri ? 2 : 1 );
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void WW8AttributeOutput::TableSpacing(ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner)
+{
+ const SwTable * pTable = pTableTextNodeInfoInner->getTable();
+ const SwTableFmt * pTableFmt = pTable->GetTableFmt();
+
+ if (pTableFmt != NULL)
+ {
+ const SvxULSpaceItem & rUL = pTableFmt->GetULSpace();
+
+ if (rUL.GetUpper() > 0)
+ {
+ sal_uInt8 nPadding = 2;
+ sal_uInt8 nPcVert = 0;
+ sal_uInt8 nPcHorz = 0;
+
+ sal_uInt8 nTPc = (nPadding << 4) | (nPcVert << 2) | nPcHorz;
+
+ m_rWW8Export.InsUInt16(NS_sprm::LN_TPc);
+ m_rWW8Export.pO->Insert( nTPc, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16(NS_sprm::LN_TDyaAbs);
+ m_rWW8Export.InsUInt16(rUL.GetUpper());
+
+ m_rWW8Export.InsUInt16(NS_sprm::LN_TDyaFromText);
+ m_rWW8Export.InsUInt16(rUL.GetUpper());
+ }
+
+ if (rUL.GetLower() > 0)
+ {
+ m_rWW8Export.InsUInt16(NS_sprm::LN_TDyaFromTextBottom);
+ m_rWW8Export.InsUInt16(rUL.GetLower());
+ }
+ }
+}
+
+void WW8AttributeOutput::TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTable * pTable = pTableTextNodeInfoInner->getTable();
+
+ if ( pTable->GetRowsToRepeat() > pTableTextNodeInfoInner->getRow() )
+ {
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TTableHeader );
+ else
+ m_rWW8Export.pO->Insert( 186, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( 1, m_rWW8Export.pO->Count() );
+ }
+
+ ww8::TableBoxVectorPtr pTableBoxes =
+ pTableTextNodeInfoInner->getTableBoxesOfRow();
+ // number of cell written
+ sal_uInt32 nBoxes = pTableBoxes->size();
+
+ // sprm header
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTable );
+ sal_uInt16 nSprmSize = 2 + (nBoxes + 1) * 2 + nBoxes * 20;
+ m_rWW8Export.InsUInt16( nSprmSize ); // length
+
+ // number of boxes
+ m_rWW8Export.pO->Insert( static_cast<sal_uInt8>(nBoxes), m_rWW8Export.pO->Count() );
+
+ /* cellxs */
+ /*
+ ALWAYS relative when text::HoriOrientation::NONE (nPageSize + ( nPageSize / 10 )) < nTblSz,
+ in that case the cell width's and table width's are not real. The table
+ width is maxed and cells relative, so we need the frame (generally page)
+ width that the table is in to work out the true widths.
+ */
+ //const bool bNewTableModel = pTbl->IsNewModel();
+ const SwFrmFmt *pFmt = pTable->GetFrmFmt();
+ OSL_ENSURE(pFmt,"Impossible");
+ if (!pFmt)
+ return;
+
+ const SwFmtHoriOrient &rHori = pFmt->GetHoriOrient();
+ const SwFmtVertOrient &rVert = pFmt->GetVertOrient();
+
+ sal_uInt16 nTblOffset = 0;
+
+ if (
+ (text::RelOrientation::PRINT_AREA == rHori.GetRelationOrient() ||
+ text::RelOrientation::FRAME == rHori.GetRelationOrient())
+ &&
+ (text::RelOrientation::PRINT_AREA == rVert.GetRelationOrient() ||
+ text::RelOrientation::FRAME == rVert.GetRelationOrient())
+ )
+ {
+ sal_Int16 eHOri = rHori.GetHoriOrient();
+ switch ( eHOri )
+ {
+ case text::HoriOrientation::CENTER:
+ case text::HoriOrientation::RIGHT:
+ break;
+
+ default:
+ nTblOffset = rHori.GetPos();
+ const SvxLRSpaceItem& rLRSp = pFmt->GetLRSpace();
+ nTblOffset += rLRSp.GetLeft();
+ break;
+ }
+ }
+
+ m_rWW8Export.InsUInt16( nTblOffset );
+
+ ww8::GridColsPtr pGridCols = GetGridCols( pTableTextNodeInfoInner );
+ for ( ww8::GridCols::const_iterator it = pGridCols->begin(),
+ end = pGridCols->end(); it != end; ++it )
+ {
+ m_rWW8Export.InsUInt16( static_cast<sal_uInt16>( *it ) + nTblOffset );
+ }
+
+ /* TCs */
+ ww8::RowSpansPtr pRowSpans = pTableTextNodeInfoInner->getRowSpansOfRow();
+ ww8::RowSpans::const_iterator aItRowSpans = pRowSpans->begin();
+ ww8::TableBoxVector::const_iterator aIt;
+ ww8::TableBoxVector::const_iterator aItEnd = pTableBoxes->end();
+
+#ifdef DEBUG
+ size_t nRowSpans = pRowSpans->size();
+ size_t nTableBoxes = pTableBoxes->size();
+ (void) nRowSpans;
+ (void) nTableBoxes;
+#endif
+
+ for( aIt = pTableBoxes->begin(); aIt != aItEnd; ++aIt, ++aItRowSpans)
+ {
+#ifdef DEBUG
+ sal_uInt16 npOCount = m_rWW8Export.pO->Count();
+#endif
+
+ const SwTableBox * pTabBox1 = *aIt;
+ const SwFrmFmt * pBoxFmt = NULL;
+ if (pTabBox1 != NULL)
+ pBoxFmt = pTabBox1->GetFrmFmt();
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ sal_uInt16 nFlags =
+ lcl_TCFlags(pTabBox1, *aItRowSpans);
+ m_rWW8Export.InsUInt16( nFlags );
+ }
+
+ static sal_uInt8 aNullBytes[] = { 0x0, 0x0 };
+
+ m_rWW8Export.pO->Insert( aNullBytes, 2, m_rWW8Export.pO->Count() ); // dummy
+ if (pBoxFmt != NULL)
+ {
+ const SvxBoxItem & rBoxItem = pBoxFmt->GetBox();
+
+ m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, &rBoxItem ); // 8/16 Byte
+ }
+ else
+ m_rWW8Export.Out_SwFmtTableBox( *m_rWW8Export.pO, NULL); // 8/16 Byte
+
+#ifdef DEBUG
+ ::std::clog << "<tclength>" << m_rWW8Export.pO->Count() - npOCount << "</tclength>"
+ << ::std::endl;
+#endif
+ }
+}
+
+ww8::GridColsPtr AttributeOutputBase::GetGridCols( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ return pTableTextNodeInfoInner->getGridColsOfRow(*this);
+}
+
+void AttributeOutputBase::GetTablePageSize( ww8::WW8TableNodeInfoInner * pTableTextNodeInfoInner, sal_uInt32& rPageSize, bool& rRelBoxSize )
+{
+ sal_uInt32 nPageSize = 0;
+
+ const SwNode *pTxtNd = pTableTextNodeInfoInner->getNode( );
+ const SwTable *pTable = pTableTextNodeInfoInner->getTable( );
+
+ const SwFrmFmt *pFmt = pTable->GetFrmFmt();
+ OSL_ENSURE(pFmt,"Impossible");
+ if (!pFmt)
+ return;
+
+ const SwFmtFrmSize &rSize = pFmt->GetFrmSize();
+ int nWidthPercent = rSize.GetWidthPercent();
+ bool bManualAligned = pFmt->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::NONE;
+ if ( (pFmt->GetHoriOrient().GetHoriOrient() == text::HoriOrientation::FULL) || bManualAligned )
+ nWidthPercent = 100;
+ bool bRelBoxSize = nWidthPercent != 0;
+ unsigned long nTblSz = static_cast<unsigned long>(rSize.GetWidth());
+ if (nTblSz > USHRT_MAX/2 && !bRelBoxSize)
+ {
+ OSL_ENSURE(bRelBoxSize, "huge table width but not relative, suspicious");
+ bRelBoxSize = true;
+ }
+
+ if ( bRelBoxSize )
+ {
+ Point aPt;
+ SwRect aRect( pFmt->FindLayoutRect( false, &aPt ) );
+ if ( aRect.IsEmpty() )
+ {
+ // dann besorge mal die Seitenbreite ohne Raender !!
+ const SwFrmFmt* pParentFmt =
+ GetExport().mpParentFrame ?
+ &(GetExport().mpParentFrame->GetFrmFmt()) :
+ const_cast<const SwDoc *>(GetExport().pDoc)->GetPageDesc(0).GetPageFmtOfNode(*pTxtNd, false);
+ aRect = pParentFmt->FindLayoutRect(true);
+ if ( 0 == ( nPageSize = aRect.Width() ) )
+ {
+ const SvxLRSpaceItem& rLR = pParentFmt->GetLRSpace();
+ nPageSize = pParentFmt->GetFrmSize().GetWidth() - rLR.GetLeft()
+ - rLR.GetRight();
+ }
+ }
+ else
+ {
+ nPageSize = aRect.Width();
+ if ( bManualAligned )
+ {
+ // #i37571# For manually aligned tables
+ const SvxLRSpaceItem &rLR = pFmt->GetLRSpace();
+ nPageSize -= (rLR.GetLeft() + rLR.GetRight());
+ }
+
+ }
+
+ OSL_ENSURE(nWidthPercent, "Impossible");
+ if (nWidthPercent)
+ {
+ nPageSize *= nWidthPercent;
+ nPageSize /= 100;
+ }
+ }
+
+ rPageSize = nPageSize;
+ rRelBoxSize = bRelBoxSize;
+}
+
+void WW8AttributeOutput::TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwFrmFmt * pFrmFmt = pTabBox->GetFrmFmt();
+
+ //Set Default, just taken from the first cell of the first
+ //row
+ static sal_uInt16 aBorders[] =
+ {
+ BOX_LINE_TOP, BOX_LINE_LEFT,
+ BOX_LINE_BOTTOM, BOX_LINE_RIGHT
+ };
+
+ for ( int i = 0; i < 4; ++i )
+ {
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, 0xD634 );
+ m_rWW8Export.pO->Insert( sal_uInt8(6), m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( sal_uInt8(0), m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( sal_uInt8(1), m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( sal_uInt8(1 << i), m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( sal_uInt8(3), m_rWW8Export.pO->Count() );
+
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO,
+ pFrmFmt->GetBox().GetDistance( aBorders[i] ) );
+ }
+}
+
+void WW8AttributeOutput::TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner )
+{
+ const SwTableBox * pTabBox = pTableTextNodeInfoInner->getTableBox();
+ const SwTableLine * pTabLine = pTabBox->GetUpper();
+ const SwTableBoxes & rTabBoxes = pTabLine->GetTabBoxes();
+
+ sal_uInt8 nBoxes = rTabBoxes.Count();
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_TDefTableShd );
+ else
+ m_rWW8Export.pO->Insert( (sal_uInt8)191, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( (sal_uInt8)(nBoxes * 2), m_rWW8Export.pO->Count() ); // Len
+
+ for ( sal_uInt8 n = 0; n < nBoxes; n++ )
+ {
+ const SwTableBox * pBox1 = rTabBoxes[n];
+ const SwFrmFmt * pFrmFmt = pBox1->GetFrmFmt();
+ const SfxPoolItem * pI = NULL;
+ Color aColor;
+
+ if ( SFX_ITEM_ON == pFrmFmt->GetAttrSet().GetItemState( RES_BACKGROUND, false, &pI ) )
+ {
+ aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
+ }
+ else
+ aColor = COL_AUTO;
+
+ WW8_SHD aShd;
+ m_rWW8Export.TransBrush( aColor, aShd );
+ m_rWW8Export.InsUInt16( aShd.GetValue() );
+ }
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ sal_uInt32 aSprmIds[] = {NS_sprm::LN_TCellShd, NS_sprm::LN_TCellShadow};
+ sal_uInt8 nBoxes0 = rTabBoxes.Count();
+ if (nBoxes0 > 21)
+ nBoxes0 = 21;
+
+ for (sal_uInt32 m = 0; m < 2; m++)
+ {
+ m_rWW8Export.InsUInt16( aSprmIds[m] );
+ m_rWW8Export.pO->Insert( static_cast<sal_uInt8>(nBoxes0 * 10),
+ m_rWW8Export.pO->Count() );
+
+ for ( sal_uInt8 n = 0; n < nBoxes0; n++ )
+ {
+ const SwTableBox * pBox1 = rTabBoxes[n];
+ const SwFrmFmt * pFrmFmt = pBox1->GetFrmFmt();
+ const SfxPoolItem * pI = NULL;
+ Color aColor;
+
+ if ( SFX_ITEM_ON ==
+ pFrmFmt->GetAttrSet().
+ GetItemState( RES_BACKGROUND, false, &pI ) )
+ {
+ aColor = dynamic_cast<const SvxBrushItem *>(pI)->GetColor();
+ }
+ else
+ aColor = COL_AUTO;
+
+ WW8SHDLong aSHD;
+ aSHD.setCvFore( 0xFF000000 );
+
+ sal_uInt32 nBgColor = aColor.GetColor();
+ if ( nBgColor == COL_AUTO )
+ aSHD.setCvBack( 0xFF000000 );
+ else
+ aSHD.setCvBack( wwUtility::RGBToBGR( nBgColor ) );
+
+ aSHD.Write( m_rWW8Export );
+ }
+ }
+ }
+}
+
+void WW8Export::SectionBreaksAndFrames( const SwTxtNode& rNode )
+{
+ // output page/section breaks
+ OutputSectionBreaks( rNode.GetpSwAttrSet(), rNode );
+
+ // all textframes anchored as character for the winword 7- format
+ if ( !bWrtWW8 && !bIsInTable )
+ OutWW6FlyFrmsInCntnt( rNode );
+}
+
+#ifdef DEBUG
+struct SwNodeHash
+{
+ size_t operator()(SwNode * pNode) const { return reinterpret_cast<size_t>(pNode); }
+};
+
+typedef ::boost::unordered_set<SwNode *, SwNodeHash> SwNodeHashSet;
+typedef ::std::deque<SwNode *> SwNodeDeque;
+#endif
+
+void MSWordExportBase::WriteText()
+{
+ while( pCurPam->GetPoint()->nNode < pCurPam->GetMark()->nNode ||
+ ( pCurPam->GetPoint()->nNode == pCurPam->GetMark()->nNode &&
+ pCurPam->GetPoint()->nContent.GetIndex() <= pCurPam->GetMark()->nContent.GetIndex() ) )
+ {
+ SwNode * pNd = pCurPam->GetNode();
+
+ if ( pNd->IsTxtNode() )
+ SectionBreaksAndFrames( *pNd->GetTxtNode() );
+
+ // output the various types of nodes
+ if ( pNd->IsCntntNode() )
+ {
+ SwCntntNode* pCNd = (SwCntntNode*)pNd;
+
+ const SwPageDesc* pTemp = pCNd->GetSwAttrSet().GetPageDesc().GetPageDesc();
+ if ( pTemp )
+ pAktPageDesc = pTemp;
+
+ pCurPam->GetPoint()->nContent.Assign( pCNd, 0 );
+ OutputContentNode( *pCNd );
+ }
+ else if ( pNd->IsTableNode() )
+ {
+ mpTableInfo->processSwTable( &pNd->GetTableNode()->GetTable() );
+ }
+ else if ( pNd->IsSectionNode() && TXT_MAINTEXT == nTxtTyp )
+ OutputSectionNode( *pNd->GetSectionNode() );
+ else if ( TXT_MAINTEXT == nTxtTyp && pNd->IsEndNode() &&
+ pNd->StartOfSectionNode()->IsSectionNode() )
+ {
+ const SwSection& rSect = pNd->StartOfSectionNode()->GetSectionNode()
+ ->GetSection();
+ if ( bStartTOX && TOX_CONTENT_SECTION == rSect.GetType() )
+ bStartTOX = false;
+
+ SwNodeIndex aIdx( *pNd, 1 );
+ if ( aIdx.GetNode().IsEndNode() && aIdx.GetNode().StartOfSectionNode()->IsSectionNode() )
+ ;
+ else if ( aIdx.GetNode().IsSectionNode() )
+ ;
+ else if ( !bIsInTable ) //No sections in table
+ {
+ ReplaceCr( (char)0xc ); // Indikator fuer Page/Section-Break
+
+ const SwSectionFmt* pParentFmt = rSect.GetFmt()->GetParent();
+ if ( !pParentFmt )
+ pParentFmt = (SwSectionFmt*)0xFFFFFFFF;
+
+ sal_uLong nRstLnNum;
+ if ( aIdx.GetNode().IsCntntNode() )
+ nRstLnNum = ((SwCntntNode&)aIdx.GetNode()).GetSwAttrSet().
+ GetLineNumber().GetStartValue();
+ else
+ nRstLnNum = 0;
+
+ AppendSection( pAktPageDesc, pParentFmt, nRstLnNum );
+ }
+ }
+ else if ( pNd->IsStartNode() )
+ {
+ OutputStartNode( *pNd->GetStartNode() );
+ }
+ else if ( pNd->IsEndNode() )
+ {
+ OutputEndNode( *pNd->GetEndNode() );
+ }
+
+ if ( pNd == &pNd->GetNodes().GetEndOfContent() )
+ break;
+
+ SwNode * pCurrentNode = &pCurPam->GetPoint()->nNode.GetNode();
+ const SwNode * pNextNode = mpTableInfo->getNextNode(pCurrentNode);
+
+ if (pNextNode != NULL)
+ pCurPam->GetPoint()->nNode = SwNodeIndex(*pNextNode);
+ else
+ pCurPam->GetPoint()->nNode++;
+
+ sal_uLong nPos = pCurPam->GetPoint()->nNode.GetIndex();
+ ::SetProgressState( nPos, pCurPam->GetDoc()->GetDocShell() );
+ }
+
+#ifdef DEBUG
+ ::std::clog << "</WriteText>" << ::std::endl;
+#endif
+}
+
+void WW8Export::WriteMainText()
+{
+#ifdef DEBUG
+ ::std::clog << "<WriteMainText>" << ::std::endl;
+#endif
+
+ pFib->fcMin = Strm().Tell();
+
+ pCurPam->GetPoint()->nNode = pDoc->GetNodes().GetEndOfContent().StartOfSectionNode()->GetIndex();
+
+ WriteText();
+
+ if( 0 == Strm().Tell() - pFib->fcMin ) // kein Text ?
+ WriteCR(); // dann CR ans Ende ( sonst mault WW )
+
+ pFib->ccpText = Fc2Cp( Strm().Tell() );
+ pFldMain->Finish( pFib->ccpText, 0 );
+
+ // ccpText beinhaltet Ftn- und KF-Texte
+ // deshalb wird pFib->ccpText evtl. noch geupdated
+ // save the StyleId of the last paragraph. Because WW97 take the style
+ // from the last CR, that will be write after footer/Header/fontnotes/
+ // annotation usw.
+ const SwTxtNode* pLastNd = pCurPam->GetMark()->nNode.GetNode().GetTxtNode();
+ if( pLastNd )
+ nLastFmtId = GetId( (SwTxtFmtColl&)pLastNd->GetAnyFmtColl() );
+
+#ifdef DEBUG
+ ::std::clog << "</WriteMainText>" << ::std::endl;
+#endif
+}
+
+typedef ww8::WW8Sttb< ww8::WW8Struct > WW8SttbAssoc;
+
+void WW8Export::WriteFkpPlcUsw()
+{
+ if( !bWrtWW8 )
+ {
+ static const sal_uInt8 aSpec[2] =
+ {
+ 117, 1
+ };
+
+ pChpPlc->AppendFkpEntry( Strm().Tell() ); // Sepx mit fSpecial
+ pSepx->WriteSepx( Strm() ); // Slcx.Sepx
+ pGrf->Write(); // Grafiken
+ pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aSpec ), aSpec );
+
+ pChpPlc->WriteFkps(); // Fkp.Chpx
+ pPapPlc->WriteFkps(); // Fkp.Papx
+ pStyles->OutputStylesTable(); // Styles
+ pFtn->WritePlc( *this ); // Footnote-Ref & Text Plc
+ pEdn->WritePlc( *this ); // Endnote-Ref & Text Plc
+ pAtn->WritePlc( *this ); // Annotation-Ref & Text Plc
+ pSepx->WritePlcSed( *this ); // Slcx.PlcSed
+ pSepx->WritePlcHdd( *this ); // Slcx.PlcHdd
+ pChpPlc->WritePlc(); // Plcx.Chpx
+ pPapPlc->WritePlc(); // Plcx.Papx
+ maFontHelper.WriteFontTable(pTableStrm, *pFib); // FFNs
+ if( pRedlAuthors )
+ pRedlAuthors->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
+ pFldMain->Write( *this ); // Fields ( Main Text )
+ pFldHdFt->Write( *this ); // Fields ( Header/Footer )
+ pFldFtn->Write( *this ); // Fields ( FootNotes )
+ pFldEdn->Write( *this ); // Fields ( EndNotes )
+ pFldAtn->Write( *this ); // Fields ( Annotations )
+ pBkmks->Write( *this ); // Bookmarks - sttbfBkmk/
+ // plcfBkmkf/plcfBkmkl
+ WriteDop( *this ); // Document-Properties
+
+ }
+ else
+ {
+ // Grafiken in den Data-Tream
+ pGrf->Write(); // Grafiken
+
+ // Ausgabe in WordDocument-Stream
+ pChpPlc->WriteFkps(); // Fkp.Chpx
+ pPapPlc->WriteFkps(); // Fkp.Papx
+ pSepx->WriteSepx( Strm() ); // Sepx
+
+ // Ausagbe in Table-Stream
+ pStyles->OutputStylesTable(); // fuer WW8 StyleTab
+ pFtn->WritePlc( *this ); // Footnote-Ref & Text Plc
+ pEdn->WritePlc( *this ); // Endnote-Ref & Text Plc
+ pTxtBxs->WritePlc( *this ); // Textbox Text Plc
+ pHFTxtBxs->WritePlc( *this ); // Head/Foot-Textbox Text Plc
+ pAtn->WritePlc( *this ); // Annotation-Ref & Text Plc
+
+ pSepx->WritePlcSed( *this ); // Slcx.PlcSed
+ pSepx->WritePlcHdd( *this ); // Slcx.PlcHdd
+
+ pChpPlc->WritePlc(); // Plcx.Chpx
+ pPapPlc->WritePlc(); // Plcx.Papx
+
+ if( pRedlAuthors )
+ pRedlAuthors->Write( GetWriter() ); // sttbfRMark (RedlineAuthors)
+ pFldMain->Write( *this ); // Fields ( Main Text )
+ pFldHdFt->Write( *this ); // Fields ( Header/Footer )
+ pFldFtn->Write( *this ); // Fields ( FootNotes )
+ pFldEdn->Write( *this ); // Fields ( EndNotes )
+ pFldAtn->Write( *this ); // Fields ( Annotations )
+ pFldTxtBxs->Write( *this ); // Fields ( Textboxes )
+ pFldHFTxtBxs->Write( *this ); // Fields ( Head/Foot-Textboxes )
+
+ if (pEscher || pDoc->ContainsMSVBasic())
+ {
+ /*
+ Everytime MS 2000 creates an escher stream there is always
+ an ObjectPool dir (even if empty). It turns out that if a copy of
+ MS 2000 is used to open a document that contains escher graphics
+ exported from StarOffice without this empty dir then *if* that
+ copy of MS Office has never been used to open a MSOffice document
+ that has escher graphics (and an ObjectPool dir of course) and
+ that copy of office has not been used to draw escher graphics then
+ our exported graphics do not appear. Once you do open a ms
+ document with escher graphics or draw an escher graphic with that
+ copy of word, then all documents from staroffice that contain
+ escher work from then on. Tricky to track down, some sort of late
+ binding trickery in MS where solely for first time initialization
+ the existence of an ObjectPool dir is necessary for triggering
+ some magic. cmc
+ */
+ /* Similiarly having msvbasic storage seems to also trigger creating this stream */
+ GetWriter().GetStorage().OpenSotStorage(CREATE_CONST_ASC(SL::aObjectPool),
+ STREAM_READWRITE | STREAM_SHARE_DENYALL);
+ }
+
+ // dggInfo - escher stream
+ WriteEscher();
+
+ pSdrObjs->WritePlc( *this );
+ pHFSdrObjs->WritePlc( *this );
+ // spamom - office drawing table
+ // spahdr - header office drawing table
+
+ pBkmks->Write( *this ); // Bookmarks - sttbfBkmk/
+ // plcfBkmkf/plcfBkmkl
+
+ WriteNumbering();
+
+ RestoreMacroCmds();
+
+ pMagicTable->Write( *this );
+
+ pPiece->WritePc( *this ); // Piece-Table
+ maFontHelper.WriteFontTable(pTableStrm, *pFib); // FFNs
+
+ //Convert OOo asian typography into MS typography structure
+ ExportDopTypography(pDop->doptypography);
+
+ WriteDop( *this ); // Document-Properties
+
+ // Write SttbfAssoc
+ WW8SttbAssoc * pSttbfAssoc = dynamic_cast<WW8SttbAssoc *>
+ (pDoc->getExternalData(::sw::STTBF_ASSOC).get());
+
+ if ( pSttbfAssoc ) // #i106057#
+ // <--
+ {
+ ::std::vector<String> aStrings;
+
+ ::ww8::StringVector_t & aSttbStrings = pSttbfAssoc->getStrings();
+ ::ww8::StringVector_t::const_iterator aItEnd = aSttbStrings.end();
+ for (::ww8::StringVector_t::const_iterator aIt = aSttbStrings.begin();
+ aIt != aItEnd; aIt++)
+ {
+ String aStr(aIt->getStr());
+ aStrings.push_back(aStr);
+ }
+
+ WriteAsStringTable(aStrings, pFib->fcSttbfAssoc,
+ pFib->lcbSttbfAssoc);
+ }
+ }
+ Strm().Seek( 0 );
+
+ // Reclaim stored FIB data from document.
+ ::ww8::WW8FibData * pFibData = dynamic_cast<ww8::WW8FibData *>
+ (pDoc->getExternalData(::sw::FIB).get());
+
+ if ( pFibData )
+ // <--
+ {
+ pFib->fReadOnlyRecommended =
+ pFibData->getReadOnlyRecommended() ? 1 : 0;
+ pFib->fWriteReservation =
+ pFibData->getWriteReservation() ? 1 : 0;
+ }
+
+ pFib->Write( Strm() ); // FIB
+}
+
+void WW8Export::StoreDoc1()
+{
+ bool bNeedsFinalPara = false;
+ // Start of Text ( Mangel ueber )
+ SwWW8Writer::FillUntil( Strm(), pFib->fcMin );
+
+ WriteMainText(); // HauptText
+ sal_uInt8 nSprmsLen;
+ sal_uInt8 *pLastSprms = pPapPlc->CopyLastSprms(nSprmsLen);
+
+ bNeedsFinalPara |= pFtn->WriteTxt( *this ); // Footnote-Text
+ bNeedsFinalPara |= pSepx->WriteKFTxt( *this ); // K/F-Text
+ bNeedsFinalPara |= pAtn->WriteTxt( *this ); // Annotation-Text
+ bNeedsFinalPara |= pEdn->WriteTxt( *this ); // EndNote-Text
+
+ // create the escher streams
+ if( bWrtWW8 )
+ CreateEscher();
+
+ bNeedsFinalPara |= pTxtBxs->WriteTxt( *this ); //Textbox Text Plc
+ bNeedsFinalPara |= pHFTxtBxs->WriteTxt( *this );//Head/Foot-Textbox Text Plc
+
+ if (bNeedsFinalPara)
+ {
+ WriteCR();
+ pPapPlc->AppendFkpEntry(Strm().Tell(), nSprmsLen, pLastSprms);
+ }
+ delete[] pLastSprms;
+
+ pSepx->Finish( Fc2Cp( Strm().Tell() ));// Text + Ftn + HdFt als Section-Ende
+ pMagicTable->Finish( Fc2Cp( Strm().Tell() ),0);
+
+ pFib->fcMac = Strm().Tell(); // Ende aller Texte
+
+ WriteFkpPlcUsw(); // FKP, PLC, .....
+}
+
+void MSWordExportBase::AddLinkTarget(const String& rURL)
+{
+ if( !rURL.Len() || rURL.GetChar(0) != INET_MARK_TOKEN )
+ return;
+
+ String aURL( BookmarkToWriter( rURL.Copy( 1 ) ) );
+ xub_StrLen nPos = aURL.SearchBackward( cMarkSeperator );
+
+ if( nPos < 2 )
+ return;
+
+ String sCmp( aURL.Copy( nPos+1 ) );
+ sCmp.EraseAllChars();
+ if( !sCmp.Len() )
+ return;
+
+ sCmp.ToLowerAscii();
+
+ if( sCmp.EqualsAscii( pMarkToOutline ) )
+ {
+ SwPosition aPos( *pCurPam->GetPoint() );
+ String aOutline( BookmarkToWriter(aURL.Copy( 0, nPos )) );
+ // If we can find the outline this bookmark refers to
+ // save the name of the bookmark and the
+ // node index number of where it points to
+ if( pDoc->GotoOutline( aPos, aOutline ) )
+ {
+ sal_uLong nIdx = aPos.nNode.GetIndex();
+ aBookmarkPair aImplicitBookmark;
+ aImplicitBookmark.first = aOutline;
+ aImplicitBookmark.second = nIdx;
+ maImplicitBookmarks.push_back(aImplicitBookmark);
+ }
+ }
+}
+
+void MSWordExportBase::CollectOutlineBookmarks(const SwDoc &rDoc)
+{
+ const SwFmtINetFmt* pINetFmt;
+ const SwTxtINetFmt* pTxtAttr;
+ const SwTxtNode* pTxtNd;
+
+ sal_uInt32 n, nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_TXTATR_INETFMT );
+ for( n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 != (pINetFmt = (SwFmtINetFmt*)rDoc.GetAttrPool().GetItem2(
+ RES_TXTATR_INETFMT, n ) ) &&
+ 0 != ( pTxtAttr = pINetFmt->GetTxtINetFmt()) &&
+ 0 != ( pTxtNd = pTxtAttr->GetpTxtNode() ) &&
+ pTxtNd->GetNodes().IsDocNodes() )
+ {
+ AddLinkTarget( pINetFmt->GetValue() );
+ }
+ }
+
+ const SwFmtURL *pURL;
+ nMaxItems = rDoc.GetAttrPool().GetItemCount2( RES_URL );
+ for( n = 0; n < nMaxItems; ++n )
+ {
+ if( 0 != (pURL = (SwFmtURL*)rDoc.GetAttrPool().GetItem2(
+ RES_URL, n ) ) )
+ {
+ AddLinkTarget( pURL->GetURL() );
+ const ImageMap *pIMap = pURL->GetMap();
+ if( pIMap )
+ {
+ for( sal_uInt16 i=0; i<pIMap->GetIMapObjectCount(); i++ )
+ {
+ const IMapObject* pObj = pIMap->GetIMapObject( i );
+ if( pObj )
+ {
+ AddLinkTarget( pObj->GetURL() );
+ }
+ }
+ }
+ }
+ }
+}
+
+namespace
+{
+ const sal_uLong WW_BLOCKSIZE = 0x200;
+
+ void EncryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
+ {
+ rIn.Seek(STREAM_SEEK_TO_END);
+ sal_uLong nLen = rIn.Tell();
+ rIn.Seek(0);
+
+ sal_uInt8 in[WW_BLOCKSIZE];
+ for (sal_uLong nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
+ {
+ sal_uLong nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI;
+ rIn.Read(in, nBS);
+ rCtx.InitCipher(nBlock);
+ rCtx.Encode(in, nBS, in, nBS);
+ rOut.Write(in, nBS);
+ }
+ }
+}
+
+void MSWordExportBase::ExportDocument( bool bWriteAll )
+{
+ nCharFmtStart = ANZ_DEFAULT_STYLES;
+ nFmtCollStart = nCharFmtStart + pDoc->GetCharFmts()->Count() - 1;
+
+ bStyDef = bBreakBefore = bOutKF =
+ bOutFlyFrmAttrs = bOutPageDescs = bOutTable = bOutFirstPage =
+ bIsInTable = bOutGrf = bInWriteEscher = bStartTOX =
+ bInWriteTOX = false;
+
+ bFtnAtTxtEnd = bEndAtTxtEnd = true;
+
+ mpParentFrame = 0;
+ pFlyOffset = 0;
+ eNewAnchorType = FLY_AT_PAGE;
+ nTxtTyp = TXT_MAINTEXT;
+ nStyleBeforeFly = nLastFmtId = 0;
+ pStyAttr = 0;
+ pCurrentStyle = NULL;
+ pOutFmtNode = 0;
+ pEscher = 0;
+ pRedlAuthors = 0;
+ if ( aTOXArr.Count() )
+ aTOXArr.Remove( 0, aTOXArr.Count() );
+
+ if ( !pOLEExp )
+ {
+ sal_uInt32 nSvxMSDffOLEConvFlags = 0;
+ const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
+ if ( pOpt->IsMath2MathType() )
+ nSvxMSDffOLEConvFlags |= OLE_STARMATH_2_MATHTYPE;
+ if ( pOpt->IsWriter2WinWord() )
+ nSvxMSDffOLEConvFlags |= OLE_STARWRITER_2_WINWORD;
+ if ( pOpt->IsCalc2Excel() )
+ nSvxMSDffOLEConvFlags |= OLE_STARCALC_2_EXCEL;
+ if ( pOpt->IsImpress2PowerPoint() )
+ nSvxMSDffOLEConvFlags |= OLE_STARIMPRESS_2_POWERPOINT;
+
+ pOLEExp = new SvxMSExportOLEObjects( nSvxMSDffOLEConvFlags );
+ }
+
+ if ( !pOleMap)
+ pOleMap = new WW8OleMaps;
+
+ if ( !pOCXExp )
+ pOCXExp = new SwMSConvertControls( pDoc->GetDocShell(), pCurPam );
+
+ // #i81405# - Collect anchored objects before changing the redline mode.
+ maFrames = GetFrames( *pDoc, bWriteAll? NULL : pOrigPam );
+
+ mnRedlineMode = pDoc->GetRedlineMode();
+ if ( pDoc->GetRedlineTbl().Count() )
+ {
+ pDoc->SetRedlineMode( (RedlineMode_t)(mnRedlineMode | nsRedlineMode_t::REDLINE_SHOW_DELETE |
+ nsRedlineMode_t::REDLINE_SHOW_INSERT) );
+ }
+
+ maFontHelper.InitFontTable( SupportsUnicode(), *pDoc );
+ GatherChapterFields();
+
+ CollectOutlineBookmarks(*pDoc);
+
+ // make unique OrdNums (Z-Order) for all drawing-/fly Objects
+ if ( pDoc->GetDrawModel() )
+ pDoc->GetDrawModel()->GetPage( 0 )->RecalcObjOrdNums();
+
+ ExportDocument_Impl();
+
+ if ( mnRedlineMode != pDoc->GetRedlineMode() )
+ pDoc->SetRedlineMode( (RedlineMode_t)(mnRedlineMode) );
+}
+
+bool SwWW8Writer::InitStd97CodecUpdateMedium( ::msfilter::MSCodec_Std97& rCodec )
+{
+ uno::Sequence< beans::NamedValue > aEncryptionData;
+
+ if ( mpMedium )
+ {
+ SFX_ITEMSET_ARG( mpMedium->GetItemSet(), pEncryptionDataItem, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
+ if ( pEncryptionDataItem && ( pEncryptionDataItem->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
+ {
+ OSL_ENSURE( false, "Unexpected EncryptionData!" );
+ aEncryptionData.realloc( 0 );
+ }
+
+ if ( !aEncryptionData.getLength() )
+ {
+ // try to generate the encryption data based on password
+ SFX_ITEMSET_ARG( mpMedium->GetItemSet(), pPasswordItem, SfxStringItem, SID_PASSWORD, sal_False );
+ if ( pPasswordItem && pPasswordItem->GetValue().Len() && pPasswordItem->GetValue().Len() <= 15 )
+ {
+ // Generate random number with a seed of time as salt.
+ TimeValue aTime;
+ osl_getSystemTime( &aTime );
+ rtlRandomPool aRandomPool = rtl_random_createPool ();
+ rtl_random_addBytes ( aRandomPool, &aTime, 8 );
+
+ sal_uInt8 pDocId[ 16 ];
+ rtl_random_getBytes( aRandomPool, pDocId, 16 );
+
+ rtl_random_destroyPool( aRandomPool );
+
+ sal_Unicode aPassword[16];
+ memset( aPassword, 0, sizeof( aPassword ) );
+ for ( xub_StrLen nChar = 0; nChar < pPasswordItem->GetValue().Len(); ++nChar )
+ aPassword[nChar] = pPasswordItem->GetValue().GetChar(nChar);
+
+ rCodec.InitKey( aPassword, pDocId );
+ aEncryptionData = rCodec.GetEncryptionData();
+
+ mpMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
+ }
+ }
+
+ if ( aEncryptionData.getLength() )
+ mpMedium->GetItemSet()->ClearItem( SID_PASSWORD );
+ }
+
+ // nonempty encryption data means hier that the codec was successfuly initialized
+ return ( aEncryptionData.getLength() != 0 );
+}
+
+void WW8Export::ExportDocument_Impl()
+{
+ PrepareStorage();
+
+ pFib = new WW8Fib( bWrtWW8 ? 8 : 6 );
+
+ SvStorageStreamRef xWwStrm( GetWriter().GetStorage().OpenSotStream( aMainStg ) );
+ SvStorageStreamRef xTableStrm( xWwStrm ), xDataStrm( xWwStrm );
+ xWwStrm->SetBufferSize( 32768 );
+
+ if( bWrtWW8 )
+ {
+ pFib->fWhichTblStm = 1;
+ xTableStrm = GetWriter().GetStorage().OpenSotStream(CREATE_CONST_ASC(SL::a1Table),
+ STREAM_STD_WRITE );
+ xDataStrm = GetWriter().GetStorage().OpenSotStream(CREATE_CONST_ASC(SL::aData),
+ STREAM_STD_WRITE );
+
+ xDataStrm->SetBufferSize( 32768 ); // fuer Grafiken
+ xTableStrm->SetBufferSize( 16384 ); // fuer die Font-/Style-Table, usw.
+
+ xTableStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ xDataStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ }
+
+ GetWriter().SetStream( & *xWwStrm );
+ pTableStrm = &xTableStrm;
+ pDataStrm = &xDataStrm;
+
+ Strm().SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ utl::TempFile aTempMain;
+ aTempMain.EnableKillingFile();
+ utl::TempFile aTempTable;
+ aTempTable.EnableKillingFile();
+ utl::TempFile aTempData;
+ aTempData.EnableKillingFile();
+
+ msfilter::MSCodec_Std97 aCtx;
+ bool bEncrypt = m_pWriter ? m_pWriter->InitStd97CodecUpdateMedium( aCtx ) : false;
+ if ( bEncrypt )
+ {
+ GetWriter().SetStream(
+ aTempMain.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE ) );
+
+ pTableStrm = aTempTable.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
+
+ pDataStrm = aTempData.GetStream( STREAM_READWRITE | STREAM_SHARE_DENYWRITE );
+
+ sal_uInt8 aRC4EncryptionHeader[ 52 ] = {0};
+ pTableStrm->Write( aRC4EncryptionHeader, 52 );
+ }
+
+ // Default: "Standard"
+ pSepx = new WW8_WrPlcSepx( *this ); // Sections/headers/footers
+
+ pFtn = new WW8_WrPlcFtnEdn( TXT_FTN ); // Footnotes
+ pEdn = new WW8_WrPlcFtnEdn( TXT_EDN ); // Endnotes
+ pAtn = new WW8_WrPlcAnnotations; // PostIts
+ pTxtBxs = new WW8_WrPlcTxtBoxes( TXT_TXTBOX );
+ pHFTxtBxs = new WW8_WrPlcTxtBoxes( TXT_HFTXTBOX );
+
+ pSdrObjs = new MainTxtPlcDrawObj; // Draw-/Fly-Objects for main text
+ pHFSdrObjs = new HdFtPlcDrawObj; // Draw-/Fly-Objects for header/footer
+
+ pBkmks = new WW8_WrtBookmarks; // Bookmarks
+ GetWriter().CreateBookmarkTbl();
+
+ pPapPlc = new WW8_WrPlcPn( *this, PAP, pFib->fcMin );
+ pChpPlc = new WW8_WrPlcPn( *this, CHP, pFib->fcMin );
+ pO = new WW8Bytes( 128, 128 );
+ pStyles = new MSWordStyles( *this );
+ pFldMain = new WW8_WrPlcFld( 2, TXT_MAINTEXT );
+ pFldHdFt = new WW8_WrPlcFld( 2, TXT_HDFT );
+ pFldFtn = new WW8_WrPlcFld( 2, TXT_FTN );
+ pFldEdn = new WW8_WrPlcFld( 2, TXT_EDN );
+ pFldAtn = new WW8_WrPlcFld( 2, TXT_ATN );
+ pFldTxtBxs = new WW8_WrPlcFld( 2, TXT_TXTBOX );
+ pFldHFTxtBxs = new WW8_WrPlcFld( 2, TXT_HFTXTBOX );
+
+ pMagicTable = new WW8_WrMagicTable;
+
+ pGrf = new SwWW8WrGrf( *this );
+ pPiece = new WW8_WrPct( pFib->fcMin, bWrtWW8 );
+ pDop = new WW8Dop;
+
+
+ pDop->fRevMarking = 0 != ( nsRedlineMode_t::REDLINE_ON & mnRedlineMode );
+ pDop->fRMView = 0 != ( nsRedlineMode_t::REDLINE_SHOW_DELETE & mnRedlineMode );
+ pDop->fRMPrint = pDop->fRMView;
+
+ // set AutoHyphenation flag if found in default para style
+ const SfxPoolItem* pItem;
+ SwTxtFmtColl* pStdTxtFmtColl =
+ pDoc->GetTxtCollFromPool(RES_POOLCOLL_STANDARD, false);
+ if (pStdTxtFmtColl && SFX_ITEM_SET == pStdTxtFmtColl->GetItemState(
+ RES_PARATR_HYPHENZONE, false, &pItem))
+ {
+ pDop->fAutoHyphen = ((const SvxHyphenZoneItem*)pItem)->IsHyphen();
+ }
+
+ StoreDoc1();
+
+ if ( bEncrypt )
+ {
+ SvStream *pStrmTemp, *pTableStrmTemp, *pDataStrmTemp;
+ pStrmTemp = &xWwStrm;
+ pTableStrmTemp = &xTableStrm;
+ pDataStrmTemp = &xDataStrm;
+
+ if ( pDataStrmTemp && pDataStrmTemp != pStrmTemp)
+ EncryptRC4(aCtx, *pDataStrm, *pDataStrmTemp);
+
+ EncryptRC4(aCtx, *pTableStrm, *pTableStrmTemp);
+
+ // Write Unencrypted Header 52 bytes to the start of the table stream
+ // EncryptionVersionInfo (4 bytes): A Version structure where Version.vMajor MUST be 0x0001, and Version.vMinor MUST be 0x0001.
+ pTableStrmTemp->Seek( 0 );
+ sal_uInt32 nEncType = 0x10001;
+ *pTableStrmTemp << nEncType;
+
+ sal_uInt8 pDocId[16];
+ aCtx.GetDocId( pDocId );
+
+ sal_uInt8 pSaltData[16];
+ sal_uInt8 pSaltDigest[16];
+ aCtx.GetEncryptKey( pDocId, pSaltData, pSaltDigest );
+
+ pTableStrmTemp->Write( pDocId, 16 );
+ pTableStrmTemp->Write( pSaltData, 16 );
+ pTableStrmTemp->Write( pSaltDigest, 16 );
+
+ EncryptRC4(aCtx, GetWriter().Strm(), *pStrmTemp);
+
+ // Write Unencrypted Fib 68 bytes to the start of the workdocument stream
+ pFib->fEncrypted = 1; // fEncrypted indicates the document is encrypted.
+ pFib->fObfuscated = 0; // Must be 0 for RC4.
+ pFib->nHash = 0x34; // encrypt header bytes count of table stream.
+ pFib->nKey = 0; // lkey2 must be 0 for RC4.
+
+ pStrmTemp->Seek( 0 );
+ pFib->WriteHeader( *pStrmTemp );
+ }
+
+ if (pUsedNumTbl) // all used NumRules
+ {
+ // clear the part of the list array that was copied from the document
+ // - it's an auto delete array, so the rest of the array which are
+ // duplicated lists that were added during the export will be deleted.
+ pUsedNumTbl->Remove(0, pUsedNumTbl->Count()-nUniqueList);
+ delete pUsedNumTbl;
+ }
+
+ DELETEZ( pGrf );
+ DELETEZ( pMagicTable );
+ DELETEZ( pFldFtn );
+ DELETEZ( pFldTxtBxs );
+ DELETEZ( pFldHFTxtBxs );
+ DELETEZ( pFldAtn );
+ DELETEZ( pFldEdn );
+ DELETEZ( pFldHdFt );
+ DELETEZ( pFldMain );
+ DELETEZ( pStyles );
+ DELETEZ( pO );
+ DELETEZ( pChpPlc );
+ DELETEZ( pPapPlc );
+ DELETEZ( pSepx );
+
+ delete pRedlAuthors;
+ delete pSdrObjs;
+ delete pHFSdrObjs;
+ delete pTxtBxs;
+ delete pHFTxtBxs;
+ delete pAtn;
+ delete pEdn;
+ delete pFtn;
+ delete pBkmks;
+ delete pPiece;
+ delete pDop;
+ delete pFib;
+ GetWriter().SetStream( 0 );
+
+
+ xWwStrm->SetBufferSize( 0 );
+ if( bWrtWW8 )
+ {
+ xTableStrm->SetBufferSize( 0 );
+ xDataStrm->SetBufferSize( 0 );
+ if( 0 == pDataStrm->Seek( STREAM_SEEK_TO_END ))
+ {
+ xDataStrm.Clear();
+ pDataStrm = 0;
+ GetWriter().GetStorage().Remove(CREATE_CONST_ASC(SL::aData));
+ }
+ }
+}
+
+
+void WW8Export::PrepareStorage()
+{
+ sal_uLong nLen;
+ const sal_uInt8* pData;
+ const char* pName;
+ sal_uInt32 nId1;
+
+ if (bWrtWW8)
+ {
+ static const char aUserName[] = "Microsoft Word-Document";
+ static const sal_uInt8 aCompObj[] =
+ {
+ 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x09, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x18, 0x00, 0x00, 0x00,
+ 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
+ 0x74, 0x20, 0x57, 0x6F, 0x72, 0x64, 0x2D, 0x44,
+ 0x6F, 0x6B, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x00,
+ 0x0A, 0x00, 0x00, 0x00, 0x4D, 0x53, 0x57, 0x6F,
+ 0x72, 0x64, 0x44, 0x6F, 0x63, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x57, 0x6F, 0x72, 0x64, 0x2E, 0x44,
+ 0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E,
+ 0x38, 0x00, 0xF4, 0x39, 0xB2, 0x71, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+ };
+
+ pName = aUserName;
+ pData = aCompObj;
+ nLen = sizeof( aCompObj );
+ nId1 = 0x00020906L;
+ }
+ else
+ {
+ static const char aUserName[] = "Microsoft Word 6.0 Document";
+ static const sal_uInt8 aCompObj[] =
+ {
+ 0x01, 0x00, 0xFE, 0xFF, 0x03, 0x0A, 0x00, 0x00,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x09, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46, 0x1C, 0x00, 0x00, 0x00,
+ 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66,
+ 0x74, 0x20, 0x57, 0x6F, 0x72, 0x64, 0x20, 0x36,
+ 0x2E, 0x30, 0x2D, 0x44, 0x6F, 0x6B, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x00, 0x0A, 0x00, 0x00, 0x00,
+ 0x4D, 0x53, 0x57, 0x6F, 0x72, 0x64, 0x44, 0x6F,
+ 0x63, 0x00, 0x10, 0x00, 0x00, 0x00, 0x57, 0x6F,
+ 0x72, 0x64, 0x2E, 0x44, 0x6F, 0x63, 0x75, 0x6D,
+ 0x65, 0x6E, 0x74, 0x2E, 0x36, 0x00, 0x00, 0x00,
+ 0x00, 0x00
+ };
+
+ pName = aUserName;
+ pData = aCompObj;
+ nLen = sizeof( aCompObj );
+ nId1 = 0x00020900L;
+ }
+
+ SvGlobalName aGName( nId1, 0x0000, 0x0000, 0xc0, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x46 );
+ GetWriter().GetStorage().SetClass( aGName, 0, String::CreateFromAscii( pName ));
+ SvStorageStreamRef xStor( GetWriter().GetStorage().OpenSotStream(sCompObj) );
+ xStor->Write( pData, nLen );
+
+ SwDocShell* pDocShell = pDoc->GetDocShell ();
+ DBG_ASSERT(pDocShell, "no SwDocShell");
+
+ if (pDocShell) {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ pDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
+
+ if (xDocProps.is())
+ {
+ if ( SvtFilterOptions::Get()->IsEnableWordPreview() )
+ {
+ ::boost::shared_ptr<GDIMetaFile> pMetaFile =
+ pDocShell->GetPreviewMetaFile (sal_False);
+ uno::Sequence<sal_uInt8> metaFile(
+ sfx2::convertMetaFile(pMetaFile.get()));
+ sfx2::SaveOlePropertySet(xDocProps, &GetWriter().GetStorage(), &metaFile);
+ }
+ else
+ sfx2::SaveOlePropertySet( xDocProps, &GetWriter().GetStorage() );
+ }
+ }
+}
+
+sal_uLong SwWW8Writer::WriteStorage()
+{
+ // #i34818# - update layout (if present), for SwWriteTable
+ ViewShell* pViewShell = NULL;
+ pDoc->GetEditShell( &pViewShell );
+ if( pViewShell != NULL )
+ pViewShell->CalcLayout();
+
+ long nMaxNode = pDoc->GetNodes().Count();
+ ::StartProgress( STR_STATSTR_W4WWRITE, 0, nMaxNode, pDoc->GetDocShell() );
+
+ // Tabelle am Doc.-Anfang beachten
+ {
+ SwTableNode * pTNd = pCurPam->GetNode()->FindTableNode();
+ if( pTNd && bWriteAll )
+ // mit dem TabellenNode anfangen !!
+ pCurPam->GetPoint()->nNode = *pTNd;
+ }
+
+ // Do the actual export
+ {
+ WW8Export aExport( this, pDoc, pCurPam, pOrigPam, m_bWrtWW8 );
+ m_pExport = &aExport;
+ aExport.ExportDocument( bWriteAll );
+ m_pExport = NULL;
+ }
+
+ ::EndProgress( pDoc->GetDocShell() );
+ return 0;
+}
+
+sal_uLong SwWW8Writer::WriteMedium( SfxMedium& )
+{
+ return WriteStorage();
+}
+
+sal_uLong SwWW8Writer::Write( SwPaM& rPaM, SfxMedium& rMed,
+ const String* pFileName )
+{
+ mpMedium = &rMed;
+ sal_uLong nRet = StgWriter::Write( rPaM, rMed, pFileName );
+ mpMedium = NULL;
+ return nRet;
+}
+
+MSWordExportBase::MSWordExportBase( SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam )
+ : aMainStg(sMainStream), pISet(0), pUsedNumTbl(0), mpTopNodeOfHdFtPage(0),
+ pBmpPal(0), pKeyMap(0), pOLEExp(0), pOCXExp(0), pOleMap(0),
+ mpTableInfo(new ww8::WW8TableInfo()), nUniqueList(0),
+ mnHdFtIndex(0), pAktPageDesc(0), pPapPlc(0), pChpPlc(0), pChpIter(0),
+ pStyles( NULL ),
+ bHasHdr(false), bHasFtr(false), bSubstituteBullets(true),
+ mbExportModeRTF( false ),
+ mbOutOutlineOnly( false ),
+ pDoc( pDocument ),
+ pCurPam( pCurrentPam ),
+ pOrigPam( pOriginalPam )
+{
+}
+
+MSWordExportBase::~MSWordExportBase()
+{
+ delete pBmpPal;
+ if (pKeyMap)
+ delete[] (NfKeywordTable*)pKeyMap;
+ delete pOLEExp;
+ delete pOCXExp;
+ delete pOleMap;
+}
+
+WW8Export::WW8Export( SwWW8Writer *pWriter,
+ SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam,
+ bool bIsWW8 )
+ : MSWordExportBase( pDocument, pCurrentPam, pOriginalPam ),
+ pO( NULL ),
+ mpTableAt( NULL ),
+ mnTableStdAtLen( 0 ),
+ pSepx( NULL ),
+ bWrtWW8( bIsWW8 ),
+ m_pWriter( pWriter ),
+ m_pAttrOutput( new WW8AttributeOutput( *this ) )
+{
+}
+
+WW8Export::~WW8Export()
+{
+ delete m_pAttrOutput, m_pAttrOutput = NULL;
+}
+
+AttributeOutputBase& WW8Export::AttrOutput() const
+{
+ return *m_pAttrOutput;
+}
+
+MSWordSections& WW8Export::Sections() const
+{
+ return *pSepx;
+}
+
+SwWW8Writer::SwWW8Writer(const String& rFltName, const String& rBaseURL)
+ : StgWriter(),
+ m_bWrtWW8( rFltName.EqualsAscii( FILTER_WW8 ) ),
+ m_pExport( NULL ),
+ mpMedium( 0 )
+{
+ SetBaseURL( rBaseURL );
+}
+
+SwWW8Writer::~SwWW8Writer()
+{
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT sal_uLong SAL_CALL SaveOrDelMSVBAStorage_ww8( SfxObjectShell& rDoc, SotStorage& rStor, sal_Bool bSaveInto, const String& rStorageName )
+{
+ SvxImportMSVBasic aTmp( rDoc, rStor );
+ return aTmp.SaveOrDelMSVBAStorage( bSaveInto, rStorageName );
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT void SAL_CALL ExportDOC( const String& rFltName, const String& rBaseURL, WriterRef& xRet )
+{
+ xRet = new SwWW8Writer( rFltName, rBaseURL );
+}
+
+
+extern "C" SAL_DLLPUBLIC_EXPORT sal_uLong SAL_CALL GetSaveWarningOfMSVBAStorage_ww8( SfxObjectShell &rDocS )
+{
+ return SvxImportMSVBasic::GetSaveWarningOfMSVBAStorage( rDocS );
+}
+
+bool WW8_WrPlcFtnEdn::WriteTxt( WW8Export& rWrt )
+{
+ bool bRet = false;
+ if (TXT_FTN == nTyp)
+ {
+ bRet = WriteGenericTxt( rWrt, TXT_FTN, rWrt.pFib->ccpFtn );
+ rWrt.pFldFtn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
+ rWrt.pFib->ccpText );
+ }
+ else
+ {
+ bRet = WriteGenericTxt( rWrt, TXT_EDN, rWrt.pFib->ccpEdn );
+ rWrt.pFldEdn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
+ rWrt.pFib->ccpText + rWrt.pFib->ccpFtn
+ + rWrt.pFib->ccpHdr + rWrt.pFib->ccpAtn );
+ }
+ return bRet;
+}
+
+void WW8_WrPlcFtnEdn::WritePlc( WW8Export& rWrt ) const
+{
+ if( TXT_FTN == nTyp )
+ {
+ WriteGenericPlc( rWrt, TXT_FTN, rWrt.pFib->fcPlcffndTxt,
+ rWrt.pFib->lcbPlcffndTxt, rWrt.pFib->fcPlcffndRef,
+ rWrt.pFib->lcbPlcffndRef );
+ }
+ else
+ {
+ WriteGenericPlc( rWrt, TXT_EDN, rWrt.pFib->fcPlcfendTxt,
+ rWrt.pFib->lcbPlcfendTxt, rWrt.pFib->fcPlcfendRef,
+ rWrt.pFib->lcbPlcfendRef );
+ }
+}
+
+
+bool WW8_WrPlcAnnotations::WriteTxt( WW8Export& rWrt )
+{
+ bool bRet = WriteGenericTxt( rWrt, TXT_ATN, rWrt.pFib->ccpAtn );
+ rWrt.pFldAtn->Finish( rWrt.Fc2Cp( rWrt.Strm().Tell() ),
+ rWrt.pFib->ccpText + rWrt.pFib->ccpFtn
+ + rWrt.pFib->ccpHdr );
+ return bRet;
+}
+
+void WW8_WrPlcAnnotations::WritePlc( WW8Export& rWrt ) const
+{
+ WriteGenericPlc( rWrt, TXT_ATN, rWrt.pFib->fcPlcfandTxt,
+ rWrt.pFib->lcbPlcfandTxt, rWrt.pFib->fcPlcfandRef,
+ rWrt.pFib->lcbPlcfandRef );
+}
+
+void WW8_WrPlcTxtBoxes::WritePlc( WW8Export& rWrt ) const
+{
+ if( TXT_TXTBOX == nTyp )
+ {
+ WriteGenericPlc( rWrt, nTyp, rWrt.pFib->fcPlcftxbxBkd,
+ rWrt.pFib->lcbPlcftxbxBkd, rWrt.pFib->fcPlcftxbxTxt,
+ rWrt.pFib->lcbPlcftxbxTxt );
+ }
+ else
+ {
+ WriteGenericPlc( rWrt, nTyp, rWrt.pFib->fcPlcfHdrtxbxBkd,
+ rWrt.pFib->lcbPlcfHdrtxbxBkd, rWrt.pFib->fcPlcfHdrtxbxTxt,
+ rWrt.pFib->lcbPlcfHdrtxbxTxt );
+ }
+}
+
+void WW8Export::RestoreMacroCmds()
+{
+ pFib->fcCmds = pTableStrm->Tell();
+
+ uno::Reference < embed::XStorage > xSrcRoot(pDoc->GetDocShell()->GetStorage());
+ try
+ {
+ uno::Reference < io::XStream > xSrcStream =
+ xSrcRoot->openStreamElement( CREATE_CONST_ASC(SL::aMSMacroCmds), embed::ElementModes::READ );
+ SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xSrcStream );
+
+ if ( pStream && SVSTREAM_OK == pStream->GetError())
+ {
+ pStream->Seek(STREAM_SEEK_TO_END);
+ pFib->lcbCmds = pStream->Tell();
+ pStream->Seek(0);
+
+ sal_uInt8 *pBuffer = new sal_uInt8[pFib->lcbCmds];
+ pStream->Read(pBuffer, pFib->lcbCmds);
+ pTableStrm->Write(pBuffer, pFib->lcbCmds);
+ delete[] pBuffer;
+
+ }
+
+ delete pStream;
+ }
+ catch ( uno::Exception& )
+ {
+ }
+
+ // set len to FIB
+ pFib->lcbCmds = pTableStrm->Tell() - pFib->fcCmds;
+}
+
+void WW8SHDLong::Write( WW8Export& rExport )
+{
+ rExport.InsUInt32( m_cvFore );
+ rExport.InsUInt32( m_cvBack );
+ rExport.InsUInt16( m_ipat );
+}
+
+void WW8Export::WriteFormData( const ::sw::mark::IFieldmark& rFieldmark )
+{
+ OSL_ENSURE( bWrtWW8, "No 95 export yet" );
+ if ( !bWrtWW8 )
+ return;
+
+ const ::sw::mark::IFieldmark* pFieldmark = &rFieldmark;
+ const ::sw::mark::ICheckboxFieldmark* pAsCheckbox = NULL;
+ if ( rFieldmark.GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) ) )
+ pAsCheckbox = reinterpret_cast< const ::sw::mark::ICheckboxFieldmark* >( pFieldmark );
+
+
+ OSL_ENSURE(rFieldmark.GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMTEXT ) ) ||
+ rFieldmark.GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMDROPDOWN ) ) ||
+ rFieldmark.GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) ), "Unknown field type!!!");
+ if ( ! ( rFieldmark.GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMTEXT ) ) ||
+ rFieldmark.GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMDROPDOWN ) ) ||
+ rFieldmark.GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMCHECKBOX ) ) ) )
+ return;
+
+ int type = 0; // TextFieldmark
+ if ( pAsCheckbox )
+ type = 1;
+ if ( rFieldmark.GetFieldname().equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ODF_FORMDROPDOWN ) ) )
+ type=2;
+
+ ::sw::mark::IFieldmark::parameter_map_t::const_iterator pNameParameter = rFieldmark.GetParameters()->find(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("name")));
+ ::rtl::OUString ffname;
+ if(pNameParameter != rFieldmark.GetParameters()->end())
+ pNameParameter->second >>= ffname;
+
+ sal_uLong nDataStt = pDataStrm->Tell();
+ pChpPlc->AppendFkpEntry(Strm().Tell());
+
+ WriteChar(0x01);
+ static sal_uInt8 aArr1[] =
+ {
+ 0x03, 0x6a, 0,0,0,0, // sprmCPicLocation
+
+ 0x06, 0x08, 0x01, // sprmCFData
+ 0x55, 0x08, 0x01, // sprmCFSpec
+ 0x02, 0x08, 0x01 // sprmCFFldVanish
+ };
+ sal_uInt8* pDataAdr = aArr1 + 2;
+ Set_UInt32(pDataAdr, nDataStt);
+
+ pChpPlc->AppendFkpEntry( Strm().Tell(), sizeof( aArr1 ), aArr1 );
+
+ struct FFDataHeader
+ {
+ sal_uInt32 version;
+ sal_uInt16 bits;
+ sal_uInt16 cch;
+ sal_uInt16 hps;
+ FFDataHeader() : version( 0xFFFFFFFF ), bits(0), cch(0), hps(0) {}
+ };
+
+
+ FFDataHeader aFldHeader;
+ aFldHeader.bits |= (type & 0x03);
+
+ sal_Int32 ffres = 0; // rFieldmark.GetFFRes();
+ if ( pAsCheckbox && pAsCheckbox->IsChecked() )
+ ffres = 1;
+ else if ( type == 2 )
+ {
+ ::sw::mark::IFieldmark::parameter_map_t::const_iterator pResParameter = rFieldmark.GetParameters()->find(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_RESULT)));
+ if(pResParameter != rFieldmark.GetParameters()->end())
+ pResParameter->second >>= ffres;
+ else
+ ffres = 0;
+ }
+ aFldHeader.bits |= ( (ffres<<2) & 0x7C );
+
+ std::vector< ::rtl::OUString > aListItems;
+ if (type==2)
+ {
+ aFldHeader.bits |= 0x8000; // ffhaslistbox
+ const ::sw::mark::IFieldmark::parameter_map_t* const pParameters = rFieldmark.GetParameters();
+ ::sw::mark::IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_LISTENTRY)));
+ if(pListEntries != pParameters->end())
+ {
+ uno::Sequence< ::rtl::OUString > vListEntries;
+ pListEntries->second >>= vListEntries;
+ copy(::comphelper::stl_begin(vListEntries), ::comphelper::stl_end(vListEntries), back_inserter(aListItems));
+ }
+ }
+
+ const ::rtl::OUString ffdeftext;
+ const ::rtl::OUString ffformat;
+ const ::rtl::OUString ffhelptext;
+ const ::rtl::OUString ffstattext;
+ const ::rtl::OUString ffentrymcr;
+ const ::rtl::OUString ffexitmcr;
+
+
+ const sal_uInt8 aFldData[] =
+ {
+ 0x44,0, // the start of "next" data
+ 0,0,0,0,0,0,0,0,0,0, // PIC-Structure! /10
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, // | /16
+ 0,0,0,0, // / /4
+ };
+ sal_uInt32 slen = sizeof(sal_uInt32)
+ + sizeof(aFldData)
+ + sizeof( aFldHeader.version ) + sizeof( aFldHeader.bits ) + sizeof( aFldHeader.cch ) + sizeof( aFldHeader.hps )
+ + 2*ffname.getLength() + 4
+ + 2*ffformat.getLength() + 4
+ + 2*ffhelptext.getLength() + 4
+ + 2*ffstattext.getLength() + 4
+ + 2*ffentrymcr.getLength() + 4
+ + 2*ffexitmcr.getLength() + 4;
+ if ( type )
+ slen += 2; // wDef
+ else
+ slen += 2*ffdeftext.getLength() + 4; //xstzTextDef
+ if ( type==2 ) {
+ slen += 2; // sttb ( fExtend )
+ slen += 4; // for num of list items
+ const int items = aListItems.size();
+ for( int i = 0; i < items; i++ ) {
+ rtl::OUString item = aListItems[i];
+ slen += 2 * item.getLength() + 2;
+ }
+ }
+
+ *pDataStrm << slen;
+
+ int len = sizeof( aFldData );
+ OSL_ENSURE( len == 0x44-sizeof(sal_uInt32), "SwWW8Writer::WriteFormData(..) - wrong aFldData length" );
+ pDataStrm->Write( aFldData, len );
+
+ *pDataStrm << aFldHeader.version << aFldHeader.bits << aFldHeader.cch << aFldHeader.hps;
+
+ SwWW8Writer::WriteString_xstz( *pDataStrm, ffname, true ); // Form field name
+
+ if ( !type )
+ SwWW8Writer::WriteString_xstz( *pDataStrm, ffdeftext, true );
+ if ( type )
+ *pDataStrm << sal_uInt16(0);
+
+
+ SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffformat ), true );
+ SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffhelptext ), true );
+ SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffstattext ), true );
+ SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffentrymcr ), true );
+ SwWW8Writer::WriteString_xstz( *pDataStrm, String( ffexitmcr ), true );
+ if (type==2) {
+ *pDataStrm<<(sal_uInt16)0xFFFF;
+ const int items=aListItems.size();
+ *pDataStrm<<(sal_uInt32)items;
+ for(int i=0;i<items;i++) {
+ rtl::OUString item=aListItems[i];
+ SwWW8Writer::WriteString_xstz( *pDataStrm, item, false );
+ }
+ }
+}
+
+void WW8Export::WriteHyperlinkData( const sw::mark::IFieldmark& /*rFieldmark*/ )
+{
+ //@TODO implement me !!!
+}
+
+void WW8AttributeOutput::TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner )
+{
+ SVBT16 nStyle;
+ ShortToSVBT16( m_rWW8Export.nStyleBeforeFly, nStyle );
+
+#ifdef DEBUG
+ ::std::clog << "<OutWW8_TableNodeInfoInner>" << pNodeInfoInner->toString();
+#endif
+
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
+
+ sal_uInt32 nShadowsBefore = pNodeInfoInner->getShadowsBefore();
+ if (nShadowsBefore > 0)
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t
+ pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(NULL));
+
+ pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
+ pTmpNodeInfoInner->setEndOfCell(true);
+
+ for (sal_uInt32 n = 0; n < nShadowsBefore; ++n)
+ {
+ m_rWW8Export.WriteCR(pTmpNodeInfoInner);
+
+ m_rWW8Export.pO->Insert( (sal_uInt8*)&nStyle, 2,
+ m_rWW8Export.pO->Count() ); // Style #
+ TableInfoCell(pTmpNodeInfoInner);
+ m_rWW8Export.pPapPlc->AppendFkpEntry
+ ( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
+ m_rWW8Export.pO->GetData() );
+
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
+ }
+ }
+
+ if (pNodeInfoInner->isEndOfCell())
+ {
+#ifdef DEBUG
+ ::std::clog << "<endOfCell/>" << ::std::endl;
+#endif
+ m_rWW8Export.WriteCR(pNodeInfoInner);
+
+ m_rWW8Export.pO->Insert( (sal_uInt8*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
+ TableInfoCell(pNodeInfoInner);
+ m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
+ m_rWW8Export.pO->GetData() );
+
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
+ }
+
+ sal_uInt32 nShadowsAfter = pNodeInfoInner->getShadowsAfter();
+ if (nShadowsAfter > 0)
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t
+ pTmpNodeInfoInner(new ww8::WW8TableNodeInfoInner(NULL));
+
+ pTmpNodeInfoInner->setDepth(pNodeInfoInner->getDepth());
+ pTmpNodeInfoInner->setEndOfCell(true);
+
+ for (sal_uInt32 n = 0; n < nShadowsAfter; ++n)
+ {
+ m_rWW8Export.WriteCR(pTmpNodeInfoInner);
+
+ m_rWW8Export.pO->Insert( (sal_uInt8*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
+ TableInfoCell(pTmpNodeInfoInner);
+ m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
+ m_rWW8Export.pO->GetData() );
+
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
+ }
+ }
+
+ if (pNodeInfoInner->isEndOfLine())
+ {
+#ifdef DEBUG
+ ::std::clog << "<endOfLine/>" << ::std::endl;
+#endif
+ TableRowEnd(pNodeInfoInner->getDepth());
+
+ ShortToSVBT16(0, nStyle);
+ m_rWW8Export.pO->Insert( (sal_uInt8*)&nStyle, 2, m_rWW8Export.pO->Count() ); // Style #
+ TableInfoRow(pNodeInfoInner);
+ m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
+ m_rWW8Export.pO->GetData() );
+
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // leeren
+ }
+#ifdef DEBUG
+ ::std::clog << "</OutWW8_TableNodeInfoInner>" << ::std::endl;
+#endif
+}
+
+void MSWordExportBase::OutputStartNode( const SwStartNode & rNode)
+{
+
+ ww8::WW8TableNodeInfo::Pointer_t pNodeInfo =
+ mpTableInfo->getTableNodeInfo( &rNode );
+
+ if (pNodeInfo.get() != NULL)
+ {
+#ifdef DEBUG
+ ::std::clog << pNodeInfo->toString() << ::std::endl;
+#endif
+
+ const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
+ ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aIt(aInners.rbegin());
+ ww8::WW8TableNodeInfo::Inners_t::const_reverse_iterator aEnd(aInners.rend());
+ while (aIt != aEnd)
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
+
+ AttrOutput().TableNodeInfoInner(pInner);
+ ++aIt;
+ }
+ }
+#ifdef DEBUG
+ ::std::clog << "</OutWW8_SwStartNode>" << ::std::endl;
+#endif
+}
+
+void MSWordExportBase::OutputEndNode( const SwEndNode &rNode )
+{
+#ifdef DEBUG
+// whoever has need of the missing function should go and implement it!
+// This piece of code always breaks builds...
+// ::std::clog << "<OutWW8_SwEndNode>" << dbg_out(&rNode) << ::std::endl;
+#endif
+
+ ww8::WW8TableNodeInfo::Pointer_t pNodeInfo = mpTableInfo->getTableNodeInfo( &rNode );
+
+ if (pNodeInfo.get() != NULL)
+ {
+#ifdef DEBUG
+ ::std::clog << pNodeInfo->toString() << ::std::endl;
+#endif
+
+ const ww8::WW8TableNodeInfo::Inners_t aInners = pNodeInfo->getInners();
+ ww8::WW8TableNodeInfo::Inners_t::const_iterator aIt(aInners.begin());
+ ww8::WW8TableNodeInfo::Inners_t::const_iterator aEnd(aInners.end());
+ while (aIt != aEnd)
+ {
+ ww8::WW8TableNodeInfoInner::Pointer_t pInner = aIt->second;
+ AttrOutput().TableNodeInfoInner(pInner);
+ ++aIt;
+ }
+ }
+#ifdef DEBUG
+ ::std::clog << "</OutWW8_SwEndNode>" << ::std::endl;
+#endif
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/wrtww8.hxx b/sw/source/filter/ww8/wrtww8.hxx
new file mode 100644
index 000000000000..2a8b22f4447c
--- /dev/null
+++ b/sw/source/filter/ww8/wrtww8.hxx
@@ -0,0 +1,1574 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WRTWW8_HXX
+#define _WRTWW8_HXX
+
+#include <tools/solar.h> // UINTXX
+#include <tools/gen.hxx>
+#ifndef _SVSTDARR_HXX
+#define _SVSTDARR_ULONGS
+#include <svl/svstdarr.hxx>
+#endif
+#include <editeng/editdata.hxx>
+
+#include <map>
+#include <vector>
+
+#include <shellio.hxx>
+#include <wrt_fn.hxx>
+#include <filter/msfilter/msocximex.hxx>
+
+#include "ww8struc.hxx"
+#include "ww8scan.hxx"
+#include "fields.hxx"
+#include "types.hxx"
+#include "writerhelper.hxx"
+#include "../inc/msfilter.hxx"
+#include <expfld.hxx>
+
+// einige Forward Deklarationen
+class SwWW8AttrIter;
+namespace msfilter
+{
+ class MSCodec_Std97;
+}
+
+namespace editeng { class SvxBorderLine; }
+
+class AttributeOutputBase;
+class DocxAttributeOutput;
+class RtfAttributeOutput;
+class BitmapPalette;
+class SwEscherEx;
+class DateTime;
+class Font;
+class MSWordExportBase;
+class SdrObject;
+class SfxItemSet;
+class SvStream;
+class SvxFontItem;
+class SvxBoxItem;
+class SwAttrSet;
+class SwCharFmt;
+class SwCntntNode;
+class SwField;
+class SwFmt;
+class SwFmtCntnt;
+class SwFmtFtn;
+class SwFrmFmt;
+class SwGrfNode;
+class SwModify;
+class SwNumFmt;
+class SwNumRule;
+class SwNumRuleTbl;
+class SwPageDesc;
+class SwFmtPageDesc;
+class SwOLENode;
+class SwPostItField;
+class SwRedlineData;
+class SwSection;
+class SwSectionFmt;
+class SwSectionNode;
+class SwTableNode;
+class SwTOXType;
+class SwTxtAttr;
+class SwTxtFmtColl;
+class SwTxtNode;
+class SwWW8WrGrf;
+class SwWW8Writer;
+class MSWordStyles;
+class WW8AttributeOutput;
+class WW8Bytes;
+class WW8Export;
+class MSWordAttrIter;
+class WW8_WrFkp;
+class WW8_WrPlc0;
+class WW8_WrPlc1;
+class WW8_WrPlcFld;
+class WW8_WrMagicTable;
+class WW8_WrPlcFtnEdn;
+class WW8_WrPlcPn;
+class WW8_WrPlcAnnotations;
+class MSWordSections;
+class WW8_WrPlcTxtBoxes;
+class WW8_WrPct; // Verwaltung
+class WW8_WrPcPtrs;
+class WW8_WrtBookmarks;
+class WW8_WrtRedlineAuthor;
+class SvxMSExportOLEObjects;
+class SwMSConvertControls;
+class WW8OleMaps;
+class SvStorageRef;
+struct WW8_PdAttrDesc;
+class SvxBrushItem;
+
+#include "WW8TableInfo.hxx"
+
+#define GRF_MAGIC_1 0x12 // 3 magic Bytes fuer PicLocFc-Attribute
+#define GRF_MAGIC_2 0x34
+#define GRF_MAGIC_3 0x56
+#define GRF_MAGIC_321 0x563412L
+
+#define OLE_PREVIEW_AS_EMF //If we want to export ole2 previews as emf in ww8+
+
+typedef sal_uInt8 FieldFlags;
+namespace nsFieldFlags // for InsertField- Method
+{
+ const FieldFlags WRITEFIELD_START = 0x01;
+ const FieldFlags WRITEFIELD_CMD_START = 0x02;
+ const FieldFlags WRITEFIELD_CMD_END = 0x04;
+ const FieldFlags WRITEFIELD_END = 0x10;
+ const FieldFlags WRITEFIELD_CLOSE = 0x20;
+ const FieldFlags WRITEFIELD_ALL = 0xFF;
+}
+
+enum TxtTypes //enums for TextTypes
+{
+ TXT_MAINTEXT = 0, /*TXT_FTNEDN = 1,*/ TXT_HDFT = 2, TXT_FTN = 3,
+ TXT_EDN = 4, TXT_ATN = 5, TXT_TXTBOX = 6, TXT_HFTXTBOX= 7
+};
+
+SV_DECL_VARARR( WW8Bytes, sal_uInt8, 128, 128 )
+
+struct WW8_SepInfo
+{
+ const SwPageDesc* pPageDesc;
+ const SwSectionFmt* pSectionFmt;
+ const SwNode* pPDNd;
+ const SwTxtNode* pNumNd;
+ sal_uLong nLnNumRestartNo;
+ sal_uInt16 nPgRestartNo;
+
+ WW8_SepInfo()
+ : pPageDesc(0), pSectionFmt(0), pPDNd(0), pNumNd(0), nLnNumRestartNo(0), nPgRestartNo(0)
+
+ {}
+
+ WW8_SepInfo( const SwPageDesc* pPD, const SwSectionFmt* pFmt,
+ sal_uLong nLnRestart, sal_uInt16 nPgRestart = 0, const SwNode* pNd = NULL )
+ : pPageDesc( pPD ), pSectionFmt( pFmt ), pPDNd( pNd ), pNumNd( 0 ),
+ nLnNumRestartNo( nLnRestart ), nPgRestartNo( nPgRestart )
+ {}
+
+ bool IsProtected() const;
+};
+
+SV_DECL_VARARR( WW8_WrSepInfoPtrs, WW8_SepInfo, 4, 4 )
+
+/// Class to collect and output the sections/headers/footers.
+// Plc fuer PageDescs -> Sepx ( Section Extensions )
+class MSWordSections
+{
+protected:
+ bool mbDocumentIsProtected;
+ WW8_WrSepInfoPtrs aSects; // PTRARR von SwPageDesc und SwSectionFmt
+
+ void CheckForFacinPg( WW8Export& rWrt ) const;
+ void WriteOlst( WW8Export& rWrt, const WW8_SepInfo& rSectionInfo );
+ void NeedsDocumentProtected(const WW8_SepInfo &rInfo);
+
+ //No copy, no assign
+ MSWordSections( const MSWordSections& );
+ MSWordSections& operator=( const MSWordSections& );
+public:
+ MSWordSections( MSWordExportBase& rExport );
+ virtual ~MSWordSections();
+
+ void AppendSection( const SwPageDesc* pPd,
+ const SwSectionFmt* pSectionFmt = 0,
+ sal_uLong nLnNumRestartNo = 0 );
+ void AppendSection( const SwFmtPageDesc& rPd,
+ const SwNode& rNd,
+ const SwSectionFmt* pSectionFmt,
+ sal_uLong nLnNumRestartNo );
+ void SetNum( const SwTxtNode* pNumNd );
+
+ /// Number of columns based on the most recent WW8_SepInfo.
+ sal_uInt16 CurrentNumberOfColumns( const SwDoc &rDoc ) const;
+
+ /// Number of columns of the provided WW8_SepInfo.
+ sal_uInt16 NumberOfColumns( const SwDoc &rDoc, const WW8_SepInfo& rInfo ) const;
+
+ bool DocumentIsProtected() const { return mbDocumentIsProtected; }
+
+ /// The most recent WW8_SepInfo.
+ const WW8_SepInfo* CurrentSectionInfo();
+
+ static void SetHeaderFlag( sal_uInt8& rHeadFootFlags, const SwFmt& rFmt,
+ sal_uInt8 nFlag );
+ static void SetFooterFlag( sal_uInt8& rHeadFootFlags, const SwFmt& rFmt,
+ sal_uInt8 nFlag );
+
+ /// Should we output borders?
+ static int HasBorderItem( const SwFmt& rFmt );
+};
+
+class WW8_WrPlcSepx : public MSWordSections
+{
+ SvULongs aCps; // PTRARR von CPs
+ WW8_PdAttrDesc* pAttrs;
+ WW8_WrPlc0* pTxtPos; // Pos der einzelnen Header / Footer
+ bool bNoMoreSections;
+
+ // No copy, no assign
+ WW8_WrPlcSepx( const WW8_WrPlcSepx& );
+ WW8_WrPlcSepx& operator=( const WW8_WrPlcSepx& );
+
+public:
+ WW8_WrPlcSepx( MSWordExportBase& rExport );
+ ~WW8_WrPlcSepx();
+
+ void AppendSep( WW8_CP nStartCp,
+ const SwPageDesc* pPd,
+ const SwSectionFmt* pSectionFmt = 0,
+ sal_uLong nLnNumRestartNo = 0 );
+ void AppendSep( WW8_CP nStartCp, const SwFmtPageDesc& rPd,
+ const SwNode& rNd,
+ const SwSectionFmt* pSectionFmt,
+ sal_uLong nLnNumRestartNo );
+ void Finish( WW8_CP nEndCp ) { aCps.Insert( nEndCp, aCps.Count() ); }
+
+ bool WriteKFTxt( WW8Export& rWrt );
+ void WriteSepx( SvStream& rStrm ) const;
+ void WritePlcSed( WW8Export& rWrt ) const;
+ void WritePlcHdd( WW8Export& rWrt ) const;
+
+private:
+ void WriteFtnEndTxt( WW8Export& rWrt, sal_uLong nCpStt );
+public:
+ void OutHeaderFooter(WW8Export& rWrt, bool bHeader,
+ const SwFmt& rFmt, sal_uLong& rCpPos, sal_uInt8 nHFFlags, sal_uInt8 nFlag, sal_uInt8 nBreakCode);
+};
+
+//--------------------------------------------------------------------------
+// class WW8_WrPct zum Aufbau der Piece-Table
+//--------------------------------------------------------------------------
+class WW8_WrPct
+{
+ WW8_WrPcPtrs* pPcts;
+ WW8_FC nOldFc;
+ bool bIsUni;
+public:
+ WW8_WrPct(WW8_FC nStartFc, bool bSaveUniCode);
+ ~WW8_WrPct();
+ void AppendPc(WW8_FC nStartFc, bool bIsUnicode);
+ void WritePc( WW8Export& rWrt );
+ void SetParaBreak();
+ bool IsUnicode() const { return bIsUni; }
+ WW8_CP Fc2Cp( sal_uLong nFc ) const;
+};
+
+/// Collects and outputs fonts.
+class wwFont
+{
+//In some future land the stream could be converted to a nice stream interface
+//and we could have harmony
+private:
+ sal_uInt8 maWW8_FFN[6];
+ String msFamilyNm;
+ String msAltNm;
+ bool mbAlt;
+ bool mbWrtWW8;
+ FontPitch mePitch;
+ FontFamily meFamily;
+ rtl_TextEncoding meChrSet;
+public:
+ wwFont( const String &rFamilyName, FontPitch ePitch, FontFamily eFamily,
+ rtl_TextEncoding eChrSet, bool bWrtWW8 );
+ bool Write( SvStream *pTableStram ) const;
+ void WriteDocx( const DocxAttributeOutput* rAttrOutput ) const;
+ void WriteRtf( const RtfAttributeOutput* rAttrOutput ) const;
+ rtl::OUString GetFamilyName() const { return rtl::OUString( msFamilyNm ); }
+ friend bool operator < (const wwFont &r1, const wwFont &r2);
+};
+
+class wwFontHelper
+{
+private:
+ /// Keep track of fonts that need to be exported.
+ ::std::map<wwFont, sal_uInt16> maFonts;
+ bool mbWrtWW8;
+
+ /// Convert from fast insertion map to linear vector in the order that we want to write.
+ ::std::vector< const wwFont* > AsVector() const;
+
+public:
+ wwFontHelper() : mbWrtWW8(false), bLoadAllFonts(false) {}
+ /// rDoc used only to get the initial standard font(s) in use.
+ void InitFontTable(bool bWrtWW8, const SwDoc& rDoc);
+ sal_uInt16 GetId(const Font& rFont);
+ sal_uInt16 GetId(const SvxFontItem& rFont);
+ sal_uInt16 GetId(const wwFont& rFont);
+ void WriteFontTable( SvStream *pTableStream, WW8Fib& pFib );
+ void WriteFontTable( const DocxAttributeOutput& rAttrOutput );
+ void WriteFontTable( const RtfAttributeOutput& rAttrOutput );
+
+ /// If true, all fonts are loaded before processing the document.
+ sal_uInt8 bLoadAllFonts: 1;
+};
+
+class DrawObj
+{
+public:
+ WW8_CP mnCp; // CP-Pos der Verweise
+ sal_uInt32 mnShapeId; // ShapeId for the SwFrmFmts
+ sw::Frame maCntnt; // the frame itself
+ Point maParentPos; // Points
+ sal_Int32 mnThick; // Border Thicknesses
+ short mnDirection; // If BiDi or not
+ unsigned int mnHdFtIndex; // 0 for main text, +1 for each subsequent
+ // msword hd/ft
+
+ DrawObj(const sw::Frame &rCntnt, WW8_CP nCp, Point aParentPos, short nDir,
+ unsigned int nHdFtIndex)
+ : mnCp(nCp), mnShapeId(0), maCntnt(rCntnt), maParentPos(aParentPos),
+ mnThick(0), mnDirection(nDir), mnHdFtIndex(nHdFtIndex) {}
+ void SetShapeDetails(sal_uInt32 nId, sal_Int32 nThick);
+ DrawObj& operator=(const DrawObj &rOther);
+};
+
+typedef std::vector<DrawObj> DrawObjVector;
+typedef DrawObjVector::iterator DrawObjIter;
+typedef DrawObjVector::const_iterator cDrawObjIter;
+
+typedef std::vector<DrawObj *> DrawObjPointerVector;
+typedef DrawObjPointerVector::iterator DrawObjPointerIter;
+
+class PlcDrawObj // PC for DrawObjects and Text-/OLE-/GRF-Boxes
+{
+private:
+ DrawObjVector maDrawObjs; // vector of drawobjs
+protected:
+ virtual void RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
+ sal_uInt32 nLen) const = 0;
+ virtual WW8_CP GetCpOffset(const WW8Fib &rFib) const = 0;
+public:
+ PlcDrawObj() {}
+ void WritePlc( WW8Export& rWrt ) const;
+ bool Append( WW8Export&, WW8_CP nCp, const sw::Frame& rFmt,
+ const Point& rNdTopLeft );
+ int size() { return maDrawObjs.size(); };
+ DrawObjVector &GetObjArr() { return maDrawObjs; }
+ virtual ~PlcDrawObj();
+private:
+ //No copying
+ PlcDrawObj(const PlcDrawObj&);
+ PlcDrawObj& operator=(const PlcDrawObj&);
+};
+
+class MainTxtPlcDrawObj : public PlcDrawObj
+{
+public:
+ MainTxtPlcDrawObj() {}
+private:
+ virtual void RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
+ sal_uInt32 nLen) const;
+ virtual WW8_CP GetCpOffset(const WW8Fib &) const;
+private:
+ //No copying
+ MainTxtPlcDrawObj(const MainTxtPlcDrawObj&);
+ MainTxtPlcDrawObj& operator=(const MainTxtPlcDrawObj&);
+};
+
+class HdFtPlcDrawObj : public PlcDrawObj
+{
+public:
+ HdFtPlcDrawObj() {}
+private:
+ virtual void RegisterWithFib(WW8Fib &rFib, sal_uInt32 nStart,
+ sal_uInt32 nLen) const;
+ virtual WW8_CP GetCpOffset(const WW8Fib &rFib) const;
+private:
+ //No copying
+ HdFtPlcDrawObj(const HdFtPlcDrawObj&);
+ HdFtPlcDrawObj& operator=(const HdFtPlcDrawObj&);
+};
+
+typedef ::std::pair<String, sal_uLong> aBookmarkPair;
+typedef std::vector<aBookmarkPair> SwImplBookmarks;
+typedef std::vector<aBookmarkPair>::iterator SwImplBookmarksIter;
+
+class WW8_WrtRedlineAuthor : public sw::util::WrtRedlineAuthor
+{
+ public:
+ virtual void Write(Writer &rWrt);
+};
+
+/** Structure that is used to save some of the WW8Export/DocxExport data.
+
+ It is used to be able to recurse inside of the WW8Export/DocxExport (eg.
+ for the needs of the tables) - you need to tall WriteText() from there with
+ new values of PaM etc.
+
+ It must contain all the stuff that might be saved either in WW8Export or in
+ DocxExport, because it makes no sense to do it abstract, and specialize it
+ for each of the cases. If you implement other *Export, just add the needed
+ members here, and store them in the appropriate SaveData() method.
+ */
+struct MSWordSaveData
+{
+ Point* pOldFlyOffset;
+ RndStdIds eOldAnchorType;
+ WW8Bytes* pOOld; ///< WW8Export only
+ WW8Bytes* mpTableAtOld; ///< WW8Export only: Additional buffer for the output of the tables
+ sal_uInt16 mnTableStdAtLenOld; ///< WW8Export only: Standard length of mpTableAt
+ SwPaM* pOldPam, *pOldEnd;
+ const sw::Frame* pOldFlyFmt;
+ const SwPageDesc* pOldPageDesc;
+
+ sal_uInt8 bOldWriteAll : 1; ///< WW8Export only
+ sal_uInt8 bOldOutTable : 1;
+ sal_uInt8 bOldIsInTable: 1;
+ sal_uInt8 bOldFlyFrmAttrs : 1;
+ sal_uInt8 bOldStartTOX : 1;
+ sal_uInt8 bOldInWriteTOX : 1;
+ // bOutPageDesc muss nicht gesichert werden, da es nur nicht waehrend der
+ // Ausgabe von Spezial-Texten veraendert wird.
+};
+
+/// Base class for WW8Export and DocxExport
+class MSWordExportBase
+{
+public:
+ wwFontHelper maFontHelper;
+ std::vector<sal_uLong> maChapterFieldLocs;
+ typedef std::vector<sal_uLong>::const_iterator mycCFIter;
+ String aMainStg;
+ SvPtrarr aTOXArr;
+ const SfxItemSet* pISet; // fuer Doppel-Attribute
+ WW8_WrPct* pPiece; // Pointer auf Piece-Table
+ SwNumRuleTbl* pUsedNumTbl; // alle used NumRules
+ const SwTxtNode *mpTopNodeOfHdFtPage; ///< Top node of host page when in hd/ft
+ std::map< sal_uInt16, sal_uInt16 > aRuleDuplicates; //map to Duplicated numrules
+ std::stack< xub_StrLen > m_aCurrentCharPropStarts; ///< To remember the position in a run.
+ WW8_WrtBookmarks* pBkmks;
+ WW8_WrtRedlineAuthor* pRedlAuthors;
+ BitmapPalette* pBmpPal;
+ void* pKeyMap;
+ SvxMSExportOLEObjects* pOLEExp;
+ SwMSConvertControls* pOCXExp;
+ WW8OleMaps* pOleMap;
+ ww8::WW8TableInfo::Pointer_t mpTableInfo;
+
+ sal_uInt16 nCharFmtStart;
+ sal_uInt16 nFmtCollStart;
+ sal_uInt16 nStyleBeforeFly; ///< Style-Nummer des Nodes,
+ ///< in/an dem ein Fly verankert ist
+ sal_uInt16 nLastFmtId; ///< Style of last TxtNode in normal range
+ sal_uInt16 nUniqueList; ///< current number for creating unique list names
+ unsigned int mnHdFtIndex;
+
+ sal_uInt16 mnRedlineMode; ///< Remember the original redline mode
+
+public:
+ /* implicit bookmark vector containing pairs of node indexes and bookmark names */
+ SwImplBookmarks maImplicitBookmarks;
+ sw::Frames maFrames; // The floating frames in this document
+ const SwPageDesc *pAktPageDesc;
+ WW8_WrPlcPn* pPapPlc;
+ WW8_WrPlcPn* pChpPlc;
+ MSWordAttrIter* pChpIter;
+ MSWordStyles* pStyles;
+ WW8_WrPlcAnnotations* pAtn;
+ WW8_WrPlcTxtBoxes *pTxtBxs, *pHFTxtBxs;
+
+ const sw::Frame *mpParentFrame; //If set we are exporting content inside
+ //a frame, e.g. a graphic node
+
+ Point* pFlyOffset; // zur Justierung eines im Writer als
+ RndStdIds eNewAnchorType; // Zeichen gebundenen Flys, der im WW
+ // Absatzgebunden wird.
+
+ WW8_WrPlcFld* pFldMain; // Felder im Haupttext
+ WW8_WrPlcFld* pFldHdFt; // Felder in Header/Footer
+ WW8_WrPlcFld* pFldFtn; // Felder in FootNotes
+ WW8_WrPlcFld* pFldEdn; // Felder in EndNotes
+ WW8_WrPlcFld* pFldAtn; // Felder in Annotations
+ WW8_WrPlcFld* pFldTxtBxs; // fields in textboxes
+ WW8_WrPlcFld* pFldHFTxtBxs; // fields in header/footer textboxes
+ WW8_WrMagicTable *pMagicTable; // keeps track of table cell positions, and
+ // marks those that contain graphics,
+ // which is required to make word display
+ // graphics inside tables
+ SwWW8WrGrf* pGrf;
+ const SwAttrSet* pStyAttr; // StyleAttr fuer Tabulatoren
+ const SwModify* pOutFmtNode; // write Format or Node
+ const SwFmt *pCurrentStyle; // iff bStyDef=true, then this store the current style
+
+ MainTxtPlcDrawObj *pSdrObjs; // Draw-/Fly-Objects
+ HdFtPlcDrawObj *pHFSdrObjs; // Draw-/Fly-Objects in header or footer
+
+ SwEscherEx* pEscher; // escher export class
+ // #i43447# - removed
+// SwTwips nFlyWidth, nFlyHeight; // Fuer Anpassung Graphic
+ // <--
+
+ sal_uInt8 nTxtTyp;
+
+ sal_uInt8 bStyDef : 1; // wird Style geschrieben ?
+ sal_uInt8 bBreakBefore : 1; // Breaks werden 2mal ausgegeben
+ sal_uInt8 bOutKF : 1; // Kopf/Fusstexte werden ausgegeben
+ sal_uInt8 bOutFlyFrmAttrs : 1; // Rahmen-Attr von Flys werden ausgegeben
+ sal_uInt8 bOutPageDescs : 1; ///< PageDescs (section properties) are being written
+ sal_uInt8 bOutFirstPage : 1; // write Attrset of FirstPageDesc
+ sal_uInt8 bOutTable : 1; // Tabelle wird ausgegeben
+ // ( wird zB bei Flys in Tabelle zurueckgesetzt )
+ sal_uInt8 bIsInTable : 1; // wird sind innerhalb der Ausgabe einer Tabelle
+ // ( wird erst nach der Tabelle zurueckgesetzt )
+ sal_uInt8 bOutGrf : 1; // Grafik wird ausgegeben
+ sal_uInt8 bInWriteEscher : 1; // in write textboxes
+ sal_uInt8 bStartTOX : 1; // true: a TOX is startet
+ sal_uInt8 bInWriteTOX : 1; // true: all content are in a TOX
+ sal_uInt8 bFtnAtTxtEnd : 1; // true: all FTN at Textend
+ sal_uInt8 bEndAtTxtEnd : 1; // true: all END at Textend
+ sal_uInt8 bHasHdr : 1;
+ sal_uInt8 bHasFtr : 1;
+ sal_uInt8 bSubstituteBullets : 1; // true: SubstituteBullet() gets called
+
+ bool mbExportModeRTF;
+ bool mbOutOutlineOnly; // export outline nodes, only (send outline to clipboard/presentation)
+
+ SwDoc *pDoc;
+ SwPaM *pCurPam, *pOrigPam;
+
+ /// Stack to remember the nesting (see MSWordSaveData for more)
+ ::std::stack< MSWordSaveData > maSaveData;
+
+ /// Used to split the runs according to the bookmarks start and ends
+ typedef std::vector< ::sw::mark::IMark* > IMarkVector;
+ IMarkVector m_rSortedMarksStart;
+ IMarkVector m_rSortedMarksEnd;
+
+public:
+ /// The main function to export the document.
+ void ExportDocument( bool bWriteAll );
+
+ /// Iterate through the nodes and call the appropriate OutputNode() on them.
+ void WriteText();
+
+ /// Set the pCurPam appropriately and call WriteText().
+ ///
+ /// Used to export paragraphs in footnotes/endnotes/etc.
+ void WriteSpecialText( sal_uLong nStart, sal_uLong nEnd, sal_uInt8 nTTyp );
+
+ /// Export the pool items to attributes (through an attribute output class).
+ void ExportPoolItemsToCHP( sw::PoolItems &rItems, sal_uInt16 nScript );
+
+ /// Return the numeric id of the numbering rule
+ sal_uInt16 GetId( const SwNumRule& rNumRule );
+
+ /// Return the numeric id of the style.
+ sal_uInt16 GetId( const SwTxtFmtColl& rColl ) const;
+
+ /// Return the numeric id of the style.
+ sal_uInt16 GetId( const SwCharFmt& rFmt ) const;
+
+ sal_uInt16 GetId( const SwTOXType& rTOXType );
+
+ /// Return the numeric id of the font (and add it to the font list if needed)
+ sal_uInt16 GetId( const SvxFontItem& rFont)
+ {
+ return maFontHelper.GetId(rFont);
+ }
+ /// @overload
+ sal_uInt16 GetId( const wwFont& rFont)
+ {
+ return maFontHelper.GetId(rFont);
+ }
+
+ const SfxPoolItem& GetItem( sal_uInt16 nWhich ) const;
+
+ /// Find the reference.
+ bool HasRefToObject( sal_uInt16 nTyp, const String* pName, sal_uInt16 nSeqNo );
+
+ /// Find the bookmark name.
+ String GetBookmarkName( sal_uInt16 nTyp, const String* pName, sal_uInt16 nSeqNo );
+
+ /// Add a bookmark converted to a Word name.
+ void AppendWordBookmark( const String& rName );
+
+ /// Use OutputItem() on an item set according to the parameters.
+ void OutputItemSet( const SfxItemSet& rSet, bool bPapFmt, bool bChpFmt, sal_uInt16 nScript, bool bExportParentItemSet );
+
+ short GetDefaultFrameDirection( ) const;
+
+ /// Right to left?
+ short TrueFrameDirection( const SwFrmFmt& rFlyFmt ) const;
+
+ /// Right to left?
+ short GetCurrentPageDirection() const;
+
+ /// In case of numbering restart.
+
+ /// List is set to restart at a particular value so for export make a
+ /// completely new list based on this one and export that instead,
+ /// which duplicates words behaviour in this respect.
+ sal_uInt16 DuplicateNumRule( const SwNumRule *pRule, sal_uInt8 nLevel, sal_uInt16 nVal );
+
+ /// Access to the attribute output class.
+ virtual AttributeOutputBase& AttrOutput() const = 0;
+
+ /// Access to the sections/headers/footres.
+ virtual MSWordSections& Sections() const = 0;
+
+ /// Determines if the format is expected to support unicode.
+ virtual bool SupportsUnicode() const = 0;
+
+ /// Used to filter out attributes that can be e.g. written to .doc but not to .docx
+ virtual bool ignoreAttributeForStyles( sal_uInt16 /*nWhich*/ ) const { return false; }
+
+ /// Guess the script (asian/western).
+ ///
+ /// Sadly word does not have two different sizes for asian font size and
+ /// western font size, it has two different fonts, but not sizes, so we
+ /// have to use our guess as to the script used and disable the export of
+ /// one type. The same occurs for font weight and posture (bold and
+ /// italic).
+ ///
+ /// In addition WW7- has only one character language identifier while WW8+
+ /// has two
+ virtual bool CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich ) = 0;
+
+ virtual void AppendBookmarks( const SwTxtNode& rNd, xub_StrLen nAktPos, xub_StrLen nLen ) = 0;
+
+ virtual void AppendBookmark( const rtl::OUString& rName, bool bSkip = false ) = 0;
+
+ // FIXME probably a hack...
+ virtual void WriteCR( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner = ww8::WW8TableNodeInfoInner::Pointer_t() ) = 0;
+
+ // FIXME definitely a hack, must not be here - it can't do anything
+ // sensible for docx
+ virtual void WriteChar( sal_Unicode c ) = 0;
+
+ /// Output attributes.
+ void OutputFormat( const SwFmt& rFmt, bool bPapFmt, bool bChpFmt, bool bFlyFmt = false );
+
+ /// Getter for pISet.
+ const SfxItemSet* GetCurItemSet() const { return pISet; }
+
+ /// Setter for pISet.
+ void SetCurItemSet( const SfxItemSet* pS ) { pISet = pS; }
+
+ /// Remember some of the memebers so that we can recurse in WriteText().
+ virtual void SaveData( sal_uLong nStt, sal_uLong nEnd );
+
+ /// Restore what was saved in SaveData().
+ virtual void RestoreData();
+
+ /// The return value indicates, if a follow page desc is written.
+ bool OutputFollowPageDesc( const SfxItemSet* pSet,
+ const SwTxtNode* pNd );
+
+ /// Write header/footer text.
+ void WriteHeaderFooterText( const SwFmt& rFmt, bool bHeader);
+
+ /// Format of the section.
+ const SwSectionFmt* GetSectionFormat( const SwNode& rNd ) const;
+
+ /// Line number of the section start.
+ sal_uLong GetSectionLineNo( const SfxItemSet* pSet, const SwNode& rNd ) const;
+
+ /// Start new section.
+ void OutputSectionBreaks( const SfxItemSet *pSet, const SwNode& rNd );
+
+ /// Write section properties.
+ ///
+ /// pA is ignored for docx.
+ void SectionProperties( const WW8_SepInfo& rSectionInfo, WW8_PdAttrDesc* pA = NULL );
+
+ /// Output the numbering table.
+ virtual void WriteNumbering() = 0;
+
+ /// Write static data of SwNumRule - LSTF
+ void NumberingDefinitions();
+
+ /// Write all Levels for all SwNumRules - LVLF
+ void AbstractNumberingDefinitions();
+
+ // Convert the bullet according to the font.
+ void SubstituteBullet( String& rNumStr, rtl_TextEncoding& rChrSet,
+ String& rFontName ) const;
+
+ /// No-op for the newer WW versions.
+ virtual void OutputOlst( const SwNumRule& /*rRule*/ ) {}
+
+ /// Setup the pA's info.
+ virtual void SetupSectionPositions( WW8_PdAttrDesc* /*pA*/ ) {}
+
+ /// Top node of host page when in header/footer.
+ void SetHdFtPageRoot( const SwTxtNode *pNd ) { mpTopNodeOfHdFtPage = pNd; }
+
+ /// Top node of host page when in header/footer.
+ const SwTxtNode *GetHdFtPageRoot() const { return mpTopNodeOfHdFtPage; }
+
+ /// Output the actual headers and footers.
+ virtual void WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
+ const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt,
+ sal_uInt8 nBreakCode) = 0;
+
+ /// Write the field
+ virtual void OutputField( const SwField* pFld, ww::eField eFldType,
+ const String& rFldCmd, sal_uInt8 nMode = nsFieldFlags::WRITEFIELD_ALL ) = 0;
+
+ /// Write the data of the form field
+ virtual void WriteFormData( const ::sw::mark::IFieldmark& rFieldmark ) = 0;
+ virtual void WriteHyperlinkData( const ::sw::mark::IFieldmark& rFieldmark ) = 0;
+
+ virtual void DoComboBox(const rtl::OUString &rName,
+ const rtl::OUString &rHelp,
+ const rtl::OUString &ToolTip,
+ const rtl::OUString &rSelected,
+ com::sun::star::uno::Sequence<rtl::OUString> &rListItems) = 0;
+
+ virtual void DoFormText(const SwInputField * pFld) = 0;
+
+ static bool NoPageBreakSection( const SfxItemSet *pSet );
+
+ // Compute the number format for WW dates
+ bool GetNumberFmt(const SwField& rFld, String& rStr);
+
+ virtual sal_uLong ReplaceCr( sal_uInt8 nChar ) = 0;
+
+ const SfxPoolItem* HasItem( sal_uInt16 nWhich ) const;
+
+
+protected:
+ /// Format-dependant part of the actual export.
+ virtual void ExportDocument_Impl() = 0;
+
+ /// Get the next position in the text node to output
+ virtual xub_StrLen GetNextPos( SwWW8AttrIter* pAttrIter, const SwTxtNode& rNode, xub_StrLen nAktPos );
+
+ /// Update the information for GetNextPos().
+ virtual void UpdatePosition( SwWW8AttrIter* pAttrIter, xub_StrLen nAktPos, xub_StrLen nEnd );
+
+ /// Output SwTxtNode
+ virtual void OutputTextNode( const SwTxtNode& );
+
+ /// Output SwTableNode
+ void OutputTableNode( const SwTableNode& );
+
+ /// Setup the chapter fields (maChapterFieldLocs).
+ void GatherChapterFields();
+
+ void AddLinkTarget( const String& rURL );
+ void CollectOutlineBookmarks( const SwDoc &rDoc );
+
+ bool SetAktPageDescFromNode(const SwNode &rNd);
+ bool CntntContainsChapterField(const SwFmtCntnt &rCntnt) const;
+ bool FmtHdFtContainsChapterField(const SwFrmFmt &rFmt) const;
+
+ virtual void SectionBreaksAndFrames( const SwTxtNode& rNode ) = 0;
+
+ virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
+ const SwNode& rNd,
+ const SwFmtPageDesc* pNewPgDescFmt = 0,
+ const SwPageDesc* pNewPgDesc = 0 ) = 0;
+
+ /// Return value indicates if an inherited outline numbering is suppressed.
+ virtual bool DisallowInheritingOutlineNumbering(const SwFmt &rFmt) = 0;
+
+protected:
+ /// Output SwStartNode
+ virtual void OutputStartNode( const SwStartNode& );
+
+ /// Output SwEndNode
+ virtual void OutputEndNode( const SwEndNode& );
+
+ /// Output SwGrfNode
+ virtual void OutputGrfNode( const SwGrfNode& ) = 0;
+
+ /// Output SwOLENode
+ virtual void OutputOLENode( const SwOLENode& ) = 0;
+
+ virtual void OutputLinkedOLE( const rtl::OUString& ) = 0;
+
+
+ /// Output SwSectionNode
+ virtual void OutputSectionNode( const SwSectionNode& );
+
+ virtual void AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum ) = 0;
+
+ /// Call the right (virtual) function according to the type of the item.
+ ///
+ /// One of OutputTextNode(), OutputGrfNode(), or OutputOLENode()
+ void OutputContentNode( const SwCntntNode& );
+
+ /// Find the nearest bookmark from the current position.
+ ///
+ /// Returns false when there is no bookmark.
+ bool NearestBookmark( xub_StrLen& rNearest, const xub_StrLen nAktPos, bool bNextPositionOnly );
+
+ void GetSortedBookmarks( const SwTxtNode& rNd, xub_StrLen nAktPos,
+ xub_StrLen nLen );
+
+ bool GetBookmarks( const SwTxtNode& rNd, xub_StrLen nStt, xub_StrLen nEnd,
+ IMarkVector& rArr );
+
+public:
+ MSWordExportBase( SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam );
+ virtual ~MSWordExportBase();
+
+ // TODO move as much as possible here from WW8Export! ;-)
+
+ static void CorrectTabStopInSet( SfxItemSet& rSet, sal_uInt16 nAbsLeft );
+
+private:
+ /// No copying.
+ MSWordExportBase( const MSWordExportBase& );
+ /// No copying.
+ MSWordExportBase& operator=( const MSWordExportBase& );
+};
+
+/// The writer class that gets called for the WW8 filter.
+class SwWW8Writer: public StgWriter
+{
+// friends to get access to m_pExport
+// FIXME avoid that, this is probably not what we want
+// (if yes, remove the friends, and provide here a GetExport() method)
+friend void WW8_WrtRedlineAuthor::Write(Writer &rWrt);
+
+ bool m_bWrtWW8;
+ WW8Export *m_pExport;
+ SfxMedium *mpMedium;
+
+public:
+ SwWW8Writer( const String& rFltName, const String& rBaseURL );
+ virtual ~SwWW8Writer();
+
+ virtual sal_uLong WriteStorage();
+ virtual sal_uLong WriteMedium( SfxMedium& );
+
+ // TODO most probably we want to be able to get these in
+ // MSExportFilterBase
+ using Writer::getIDocumentSettingAccess;
+
+public:
+#if 1
+ /// Prefer ww::bytes to WW8Bytes, migrate away from the other ones.
+ static void InsUInt16(ww::bytes &rO, sal_uInt16 n);
+ static void InsUInt32(ww::bytes &rO, sal_uInt32 n);
+ static void InsAsString16(ww::bytes &rO, const String& rStr);
+ static void InsAsString8(ww::bytes & O, const String& rStr,
+ rtl_TextEncoding eCodeSet);
+#endif
+
+ static void InsUInt16( WW8Bytes& rO, sal_uInt16 );
+ static void InsUInt32( WW8Bytes& rO, sal_uInt32 );
+ static void InsAsString16( WW8Bytes& rO, const String& );
+ static void InsAsString8( WW8Bytes& rO, const String& rStr,
+ rtl_TextEncoding eCodeSet );
+
+ static sal_uLong FillUntil( SvStream& rStrm, sal_uLong nEndPos = 0 );
+ static void FillCount( SvStream& rStrm, sal_uLong nCount );
+
+ static void WriteShort( SvStream& rStrm, sal_Int16 nVal ) { rStrm << nVal; }
+ static void WriteShort( SvStream& rStrm, sal_uLong nPos, sal_Int16 nVal );
+
+ static void WriteLong( SvStream& rStrm, sal_Int32 nVal ) { rStrm << nVal; }
+ static void WriteLong( SvStream& rStrm, sal_uLong nPos, sal_Int32 nVal );
+
+ static void WriteString16(SvStream& rStrm, const String& rStr,
+ bool bAddZero);
+ static void WriteString8(SvStream& rStrm, const String& rStr,
+ bool bAddZero, rtl_TextEncoding eCodeSet);
+
+ static void WriteString_xstz(SvStream& rStrm, const String& rStr, bool bAddZero);
+
+ bool InitStd97CodecUpdateMedium( ::msfilter::MSCodec_Std97& rCodec );
+
+ using StgWriter::Write;
+ virtual sal_uLong Write( SwPaM&, SfxMedium&, const String* = 0 );
+
+private:
+ /// No copying.
+ SwWW8Writer(const SwWW8Writer&);
+ /// No copying.
+ SwWW8Writer& operator=(const SwWW8Writer&);
+};
+
+/// Exporter of the binary Word file formats.
+class WW8Export : public MSWordExportBase
+{
+public:
+ WW8Bytes* pO; ///< Buffer
+ WW8Bytes* mpTableAt; ///< Additional buffer for the output of the tables
+ sal_uInt16 mnTableStdAtLen; ///< Standard length of mpTableAt
+
+ SvStream *pTableStrm, *pDataStrm; ///< Streams for WW97 Export
+
+ WW8Fib* pFib; ///< File Information Block
+ WW8Dop* pDop; ///< DOcument Properties
+ WW8_WrPlcFtnEdn *pFtn; ///< Footnotes - structure to remember them, and output
+ WW8_WrPlcFtnEdn *pEdn; ///< Endnotes - structure to remember them, and output
+ WW8_WrPlcSepx* pSepx; ///< Sections/headers/footers
+
+ sal_uInt8 bWrtWW8 : 1; ///< Write WW95 (false) or WW97 (true) file format
+
+protected:
+ SwWW8Writer *m_pWriter; ///< Pointer to the writer
+ WW8AttributeOutput *m_pAttrOutput; ///< Converting attributes to stream data
+
+public:
+ /// Access to the attribute output class.
+ virtual AttributeOutputBase& AttrOutput() const;
+
+ /// Access to the sections/headers/footres.
+ virtual MSWordSections& Sections() const;
+
+ /// False for WW6, true for WW8.
+ virtual bool SupportsUnicode() const { return bWrtWW8; }
+
+private:
+ /// Format-dependant part of the actual export.
+ virtual void ExportDocument_Impl();
+
+ void PrepareStorage();
+ void WriteFkpPlcUsw();
+ void WriteMainText();
+ void StoreDoc1();
+ void Out_WwNumLvl( sal_uInt8 nWwLevel );
+ void BuildAnlvBulletBase( WW8_ANLV& rAnlv, sal_uInt8*& rpCh, sal_uInt16& rCharLen,
+ const SwNumFmt& rFmt );
+ static void BuildAnlvBase( WW8_ANLV& rAnlv, sal_uInt8*& rpCh, sal_uInt16& rCharLen,
+ const SwNumRule& rRul, const SwNumFmt& rFmt, sal_uInt8 nSwLevel );
+
+ void Out_BorderLine(WW8Bytes& rO, const ::editeng::SvxBorderLine* pLine,
+ sal_uInt16 nDist, sal_uInt16 nSprmNo, bool bShadow);
+
+ /// Output the numbering table.
+ virtual void WriteNumbering();
+
+ void OutOverrideListTab();
+ void OutListNamesTab();
+
+ void RestoreMacroCmds();
+
+ void InitFontTable();
+
+ void DoComboBox(com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet> xPropSet);
+ void DoCheckBox(com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet> xPropSet);
+
+public:
+ virtual void OutputOlst( const SwNumRule& rRule );
+
+ /// Setup the pA's info.
+ virtual void SetupSectionPositions( WW8_PdAttrDesc* pA );
+
+ void Out_SwNumLvl( sal_uInt8 nSwLevel );
+ void Out_NumRuleAnld( const SwNumRule& rRul, const SwNumFmt& rFmt,
+ sal_uInt8 nSwLevel );
+
+ bool MiserableFormFieldExportHack(const SwFrmFmt& rFrmFmt);
+
+ SvxMSExportOLEObjects& GetOLEExp() { return *pOLEExp; }
+ SwMSConvertControls& GetOCXExp() { return *pOCXExp; }
+ WW8OleMaps& GetOLEMap() { return *pOleMap; }
+ void ExportDopTypography(WW8DopTypography &rTypo);
+
+ sal_uInt16 AddRedlineAuthor( sal_uInt16 nId );
+
+ void WriteFtnBegin( const SwFmtFtn& rFtn, WW8Bytes* pO = 0 );
+ void WritePostItBegin( WW8Bytes* pO = 0 );
+ const SvxBrushItem* GetCurrentPageBgBrush() const;
+ SvxBrushItem TrueFrameBgBrush(const SwFrmFmt &rFlyFmt) const;
+
+ /// Output all textframes anchored as character for the winword 7- format.
+ void OutWW6FlyFrmsInCntnt( const SwTxtNode& rNd );
+
+ void AppendFlyInFlys(const sw::Frame& rFrmFmt, const Point& rNdTopLeft);
+ void WriteOutliner(const OutlinerParaObject& rOutliner, sal_uInt8 nTyp);
+ void WriteSdrTextObj(const SdrObject& rObj, sal_uInt8 nTyp);
+
+ sal_uInt32 GetSdrOrdNum( const SwFrmFmt& rFmt ) const;
+ void CreateEscher();
+ void WriteEscher();
+
+ bool Out_SwNum(const SwTxtNode* pNd);
+
+ /// Write the field
+ virtual void OutputField( const SwField* pFld, ww::eField eFldType,
+ const String& rFldCmd, sal_uInt8 nMode = nsFieldFlags::WRITEFIELD_ALL );
+
+ void StartCommentOutput( const String& rName );
+ void EndCommentOutput( const String& rName );
+ void OutGrf(const sw::Frame &rFrame);
+ bool TestOleNeedsGraphic(const SwAttrSet& rSet, SvStorageRef xOleStg,
+ SvStorageRef xObjStg, String &rStorageName, SwOLENode *pOLENd);
+
+ virtual void AppendBookmarks( const SwTxtNode& rNd, xub_StrLen nAktPos, xub_StrLen nLen );
+ virtual void AppendBookmark( const rtl::OUString& rName, bool bSkip = false );
+ void MoveFieldMarks(sal_uLong nFrom, sal_uLong nTo);
+
+ void WriteAsStringTable(const ::std::vector<String>&, sal_Int32& rfcSttbf,
+ sal_Int32& rlcbSttbf, sal_uInt16 nExtraLen = 0);
+
+ virtual sal_uLong ReplaceCr( sal_uInt8 nChar );
+
+ virtual void WriteCR( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner = ww8::WW8TableNodeInfoInner::Pointer_t() );
+ void WriteChar( sal_Unicode c );
+
+ void OutSwString(const String&, xub_StrLen nStt, xub_StrLen nLen,
+ bool bUnicode, rtl_TextEncoding eChrSet);
+
+ WW8_CP Fc2Cp( sal_uLong nFc ) const { return pPiece->Fc2Cp( nFc ); }
+
+ // einige z.T. static halb-interne Funktions-Deklarationen
+
+ void OutSprmBytes( sal_uInt8* pBytes, sal_uInt16 nSiz )
+ { pO->Insert( pBytes, nSiz, pO->Count() ); }
+
+ inline bool IsUnicode() const { return pPiece->IsUnicode(); }
+
+ virtual void SectionBreaksAndFrames( const SwTxtNode& rNode );
+
+ /// Helper method for OutputSectionBreaks() and OutputFollowPageDesc().
+ // #i76300#
+ virtual void PrepareNewPageDesc( const SfxItemSet* pSet,
+ const SwNode& rNd,
+ const SwFmtPageDesc* pNewPgDescFmt = 0,
+ const SwPageDesc* pNewPgDesc = 0 );
+
+ void Out_SwFmtBox(const SvxBoxItem& rBox, bool bShadow);
+ void Out_SwFmtTableBox( WW8Bytes& rO, const SvxBoxItem * rBox );
+ sal_uInt8 TransCol( const Color& rCol );
+ bool TransBrush(const Color& rCol, WW8_SHD& rShd);
+ WW8_BRC TranslateBorderLine(const ::editeng::SvxBorderLine& pLine,
+ sal_uInt16 nDist, bool bShadow);
+
+ // #i77805# - new return value indicates, if an inherited outline numbering is suppressed
+ virtual bool DisallowInheritingOutlineNumbering(const SwFmt &rFmt);
+
+ unsigned int GetHdFtIndex() const { return mnHdFtIndex; }
+ void SetHdFtIndex(unsigned int nHdFtIndex) { mnHdFtIndex = nHdFtIndex; }
+ void IncrementHdFtIndex() { ++mnHdFtIndex; }
+
+ static long GetDTTM( const DateTime& rDT );
+
+ /// Convert the SVX numbering type to id
+ static sal_uInt8 GetNumId( sal_uInt16 eNumType );
+
+ /// Guess the script (asian/western).
+ virtual bool CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich );
+
+ sal_uInt16 DupNumRuleWithLvlStart(const SwNumRule *pRule,sal_uInt8 nLvl,sal_uInt16 nVal);
+
+ SwTwips CurrentPageWidth(SwTwips &rLeft, SwTwips &rRight) const;
+
+ /// Nasty swap for bidi if neccessary
+ bool MiserableRTLFrmFmtHack(SwTwips &rLeft, SwTwips &rRight,
+ const sw::Frame &rFrmFmt);
+
+ void InsUInt16( sal_uInt16 n ) { SwWW8Writer::InsUInt16( *pO, n ); }
+ void InsUInt32( sal_uInt32 n ) { SwWW8Writer::InsUInt32( *pO, n ); }
+ void InsAsString16( const String& rStr )
+ { SwWW8Writer::InsAsString16( *pO, rStr ); }
+ void InsAsString8( const String& rStr, rtl_TextEncoding eCodeSet )
+ { SwWW8Writer::InsAsString8( *pO, rStr, eCodeSet ); }
+ void WriteStringAsPara( const String& rTxt, sal_uInt16 nStyleId = 0 );
+
+ /// Setup the exporter.
+ WW8Export( SwWW8Writer *pWriter,
+ SwDoc *pDocument, SwPaM *pCurrentPam, SwPaM *pOriginalPam,
+ bool bIsWW8 );
+ virtual ~WW8Export();
+
+ virtual void DoComboBox(const rtl::OUString &rName,
+ const rtl::OUString &rHelp,
+ const rtl::OUString &ToolTip,
+ const rtl::OUString &rSelected,
+ com::sun::star::uno::Sequence<rtl::OUString> &rListItems);
+
+ virtual void DoFormText(const SwInputField * pFld);
+
+ void GetCurrentItems(WW8Bytes &rItems) const;
+
+ /// Write the data of the form field
+ virtual void WriteFormData( const ::sw::mark::IFieldmark& rFieldmark );
+ virtual void WriteHyperlinkData( const ::sw::mark::IFieldmark& rFieldmark );
+
+ /// Fields.
+ WW8_WrPlcFld* CurrentFieldPlc() const;
+
+ SwWW8Writer& GetWriter() const { return *m_pWriter; }
+ SvStream& Strm() const { return m_pWriter->Strm(); }
+
+ /// Remember some of the memebers so that we can recurse in WriteText().
+ virtual void SaveData( sal_uLong nStt, sal_uLong nEnd );
+
+ /// Restore what was saved in SaveData().
+ virtual void RestoreData();
+
+ /// Output the actual headers and footers.
+ virtual void WriteHeadersFooters( sal_uInt8 nHeadFootFlags,
+ const SwFrmFmt& rFmt, const SwFrmFmt& rLeftFmt, const SwFrmFmt& rFirstPageFmt,
+ sal_uInt8 nBreakCode);
+
+protected:
+ /// Output SwGrfNode
+ virtual void OutputGrfNode( const SwGrfNode& );
+
+ /// Output SwOLENode
+ virtual void OutputOLENode( const SwOLENode& );
+
+ virtual void OutputLinkedOLE( const rtl::OUString& );
+
+ virtual void AppendSection( const SwPageDesc *pPageDesc, const SwSectionFmt* pFmt, sal_uLong nLnNum );
+
+private:
+ /// No copying.
+ WW8Export(const WW8Export&);
+ /// No copying.
+ WW8Export& operator=(const WW8Export&);
+};
+
+class WW8_WrPlcSubDoc // Doppel-Plc fuer Foot-/Endnotes und Postits
+{
+private:
+ //No copying
+ WW8_WrPlcSubDoc(const WW8_WrPlcSubDoc&);
+ WW8_WrPlcSubDoc& operator=(const WW8_WrPlcSubDoc&);
+protected:
+ SvULongs aCps; // PTRARR CP-Pos der Verweise
+ SvPtrarr aCntnt; // PTRARR von SwFmtFtn/PostIts/..
+ WW8_WrPlc0* pTxtPos; // Pos der einzelnen Texte
+
+ WW8_WrPlcSubDoc();
+ virtual ~WW8_WrPlcSubDoc();
+
+ bool WriteGenericTxt( WW8Export& rWrt, sal_uInt8 nTTyp, WW8_CP& rCount );
+ void WriteGenericPlc( WW8Export& rWrt, sal_uInt8 nTTyp, WW8_FC& rTxtStt,
+ sal_Int32& rTxtCnt, WW8_FC& rRefStt, sal_Int32& rRefCnt ) const;
+
+ virtual const SvULongs* GetShapeIdArr() const;
+};
+
+// Doppel-Plc fuer Footnotes/Endnotes
+class WW8_WrPlcFtnEdn : public WW8_WrPlcSubDoc
+{
+private:
+ sal_uInt8 nTyp;
+
+ //No copying
+ WW8_WrPlcFtnEdn(const WW8_WrPlcFtnEdn&);
+ WW8_WrPlcFtnEdn& operator=(WW8_WrPlcFtnEdn &);
+public:
+ WW8_WrPlcFtnEdn( sal_uInt8 nTTyp ) : nTyp( nTTyp ) {}
+
+ bool WriteTxt( WW8Export& rWrt );
+ void WritePlc( WW8Export& rWrt ) const;
+
+ void Append( WW8_CP nCp, const SwFmtFtn& rFtn );
+};
+
+struct WW8_Annotation
+{
+ const OutlinerParaObject* mpRichText;
+ String msSimpleText;
+ String msOwner;
+ DateTime maDateTime;
+ WW8_Annotation(const SwPostItField* pPostIt);
+ WW8_Annotation(const SwRedlineData* pRedline);
+};
+
+class WW8_WrPlcAnnotations : public WW8_WrPlcSubDoc // Doppel-Plc fuer PostIts
+{
+private:
+ //No copying
+ WW8_WrPlcAnnotations(const WW8_WrPlcAnnotations&);
+ WW8_WrPlcAnnotations& operator=(WW8_WrPlcAnnotations&);
+ std::set<const SwRedlineData*> maProcessedRedlines;
+public:
+ WW8_WrPlcAnnotations() {}
+ ~WW8_WrPlcAnnotations();
+
+ void Append( WW8_CP nCp, const SwPostItField* pPostIt );
+ void Append( WW8_CP nCp, const SwRedlineData* pRedLine );
+ bool IsNewRedlineComment( const SwRedlineData* pRedLine );
+ bool WriteTxt( WW8Export& rWrt );
+ void WritePlc( WW8Export& rWrt ) const;
+};
+
+class WW8_WrPlcTxtBoxes : public WW8_WrPlcSubDoc // Doppel-Plc fuer Textboxen
+{ // Rahmen/DrawTextboxes!
+private:
+ sal_uInt8 nTyp;
+ SvULongs aShapeIds; // VARARR of ShapeIds for the SwFrmFmts
+ virtual const SvULongs* GetShapeIdArr() const;
+
+ //No copying
+ WW8_WrPlcTxtBoxes(const WW8_WrPlcTxtBoxes&);
+ WW8_WrPlcTxtBoxes& operator=(WW8_WrPlcTxtBoxes&);
+public:
+ WW8_WrPlcTxtBoxes( sal_uInt8 nTTyp ) : nTyp( nTTyp ) {}
+
+ bool WriteTxt( WW8Export& rWrt );
+ void WritePlc( WW8Export& rWrt ) const;
+ void Append( const SdrObject& rObj, sal_uInt32 nShapeId );
+ sal_uInt16 Count() const { return aCntnt.Count(); }
+ sal_uInt16 GetPos( const VoidPtr& p ) const { return aCntnt.GetPos( p ); }
+};
+
+typedef WW8_WrFkp* WW8_FkpPtr; // Plc fuer Chpx und Papx ( incl PN-Plc )
+SV_DECL_PTRARR( WW8_WrFkpPtrs, WW8_FkpPtr, 4, 4 )
+
+class WW8_WrPlcPn // Plc fuer Page Numbers
+{
+private:
+ WW8Export& rWrt;
+ WW8_WrFkpPtrs aFkps; // PTRARR
+ sal_uInt16 nFkpStartPage;
+ ePLCFT ePlc;
+ bool bWrtWW8; // Fuer Writererkennung
+ sal_uInt16 nMark;
+
+ //No copying
+ WW8_WrPlcPn(const WW8_WrPlcPn&);
+ WW8_WrPlcPn& operator=(const WW8_WrPlcPn&);
+public:
+ WW8_WrPlcPn( WW8Export& rWrt, ePLCFT ePl, WW8_FC nStartFc );
+ ~WW8_WrPlcPn();
+ void AppendFkpEntry(WW8_FC nEndFc,short nVarLen = 0,const sal_uInt8* pSprms = 0);
+ void WriteFkps();
+ void WritePlc();
+ sal_uInt8 *CopyLastSprms(sal_uInt8 &rLen);
+};
+
+// class WW8_WrPlc1 ist erstmal nur fuer Felder
+class WW8_WrPlc1
+{
+private:
+ SvULongs aPos; // PTRARR von CPs
+ sal_uInt8* pData; // Inhalte ( Strukturen )
+ sal_uLong nDataLen;
+ sal_uInt16 nStructSiz;
+
+ //No copying
+ WW8_WrPlc1(const WW8_WrPlc1&);
+ WW8_WrPlc1& operator=(const WW8_WrPlc1&);
+protected:
+ sal_uInt16 Count() const { return aPos.Count(); }
+ void Write( SvStream& rStrm );
+ WW8_CP Prev() const;
+public:
+ WW8_WrPlc1( sal_uInt16 nStructSz );
+ ~WW8_WrPlc1();
+ void Append( WW8_CP nCp, const void* pData );
+ void Finish( sal_uLong nLastCp, sal_uLong nStartCp );
+};
+
+// class WW8_WrPlcFld ist fuer Felder
+class WW8_WrPlcFld : public WW8_WrPlc1
+{
+private:
+ sal_uInt8 nTxtTyp;
+ sal_uInt16 nResults;
+
+ //No copying
+ WW8_WrPlcFld(const WW8_WrPlcFld&);
+ WW8_WrPlcFld& operator=(const WW8_WrPlcFld&);
+public:
+ WW8_WrPlcFld( sal_uInt16 nStructSz, sal_uInt8 nTTyp )
+ : WW8_WrPlc1( nStructSz ), nTxtTyp( nTTyp ), nResults(0)
+ {}
+ bool Write( WW8Export& rWrt );
+ void ResultAdded() { ++nResults; }
+ sal_uInt16 ResultCount() const { return nResults; }
+};
+
+class WW8_WrMagicTable : public WW8_WrPlc1
+{
+private:
+ //No copying
+ WW8_WrMagicTable(const WW8_WrMagicTable&);
+ WW8_WrMagicTable& operator=(const WW8_WrMagicTable&);
+public:
+ WW8_WrMagicTable() : WW8_WrPlc1( 4 ) {Append(0,0);}
+ void Append( WW8_CP nCp, sal_uLong nData );
+ bool Write( WW8Export& rWrt );
+};
+
+class GraphicDetails
+{
+public:
+ sw::Frame maFly; // Umgebende FlyFrms dazu
+ sal_uLong mnPos; // FilePos der Grafiken
+ sal_uInt16 mnWid; // Breite der Grafiken
+ sal_uInt16 mnHei; // Hoehe der Grafiken
+
+ GraphicDetails(const sw::Frame &rFly, sal_uInt16 nWid, sal_uInt16 nHei)
+ : maFly(rFly), mnPos(0), mnWid(nWid), mnHei(nHei)
+ {}
+ GraphicDetails& operator=(const GraphicDetails& rOther);
+
+ bool operator==(const GraphicDetails& rIn) const
+ {
+ return (
+ (mnWid == rIn.mnWid) && (mnHei == rIn.mnHei) &&
+ (maFly.RefersToSameFrameAs(rIn.maFly))
+ );
+ }
+};
+
+// class SwWW8WrGrf sammelt Grafiken und gibt sie aus
+class SwWW8WrGrf
+{
+private:
+ /// for access to the variables
+ WW8Export& rWrt;
+
+ std::vector<GraphicDetails> maDetails;
+ typedef std::vector<GraphicDetails>::iterator myiter;
+ sal_uInt16 mnIdx; // Index in File-Positionen
+
+ void WritePICFHeader(SvStream& rStrm, const sw::Frame &rFly,
+ sal_uInt16 mm, sal_uInt16 nWidth, sal_uInt16 nHeight,
+ const SwAttrSet* pAttrSet = 0);
+ void WriteGraphicNode(SvStream& rStrm, const GraphicDetails &rItem);
+ void WriteGrfFromGrfNode(SvStream& rStrm, const SwGrfNode &rNd,
+ const sw::Frame &rFly, sal_uInt16 nWidth, sal_uInt16 nHeight);
+
+ //No copying
+ SwWW8WrGrf(const SwWW8WrGrf&);
+ SwWW8WrGrf& operator=(const SwWW8WrGrf&);
+public:
+ SwWW8WrGrf( WW8Export& rW ) : rWrt( rW ), mnIdx( 0 ) {}
+ void Insert(const sw::Frame &rFly);
+ void Write();
+ sal_uLong GetFPos()
+ { return (mnIdx < maDetails.size()) ? maDetails[mnIdx++].mnPos : 0; }
+};
+
+/** The class MSWordAttrIter is a helper class to build the Fkp.chpx.
+ This class may be overloaded for output the SwTxtAttrs and the
+ EditEngineTxtAttrs.
+*/
+class MSWordAttrIter
+{
+private:
+ MSWordAttrIter* pOld;
+ //No copying
+ MSWordAttrIter(const MSWordAttrIter&);
+ MSWordAttrIter& operator=(const MSWordAttrIter&);
+protected:
+ MSWordExportBase& m_rExport;
+public:
+ MSWordAttrIter( MSWordExportBase& rExport );
+ virtual ~MSWordAttrIter();
+
+ virtual const SfxPoolItem* HasTextItem( sal_uInt16 nWhich ) const = 0;
+ virtual const SfxPoolItem& GetItem( sal_uInt16 nWhich ) const = 0;
+};
+
+/// Used to export formatted text associated to drawings.
+class MSWord_SdrAttrIter : public MSWordAttrIter
+{
+private:
+ const EditTextObject* pEditObj;
+ const SfxItemPool* pEditPool;
+ EECharAttribArray aTxtAtrArr;
+ SvPtrarr aChrTxtAtrArr;
+ SvUShorts aChrSetArr;
+ sal_uInt16 nPara;
+ xub_StrLen nAktSwPos;
+ xub_StrLen nTmpSwPos; // for HasItem()
+ rtl_TextEncoding eNdChrSet;
+ sal_uInt16 nScript;
+ sal_uInt8 mnTyp;
+
+ xub_StrLen SearchNext( xub_StrLen nStartPos );
+ void SetCharSet(const EECharAttrib& rTxtAttr, bool bStart);
+
+ //No copying
+ MSWord_SdrAttrIter(const MSWord_SdrAttrIter&);
+ MSWord_SdrAttrIter& operator=(const MSWord_SdrAttrIter&);
+public:
+ MSWord_SdrAttrIter( MSWordExportBase& rWr, const EditTextObject& rEditObj,
+ sal_uInt8 nType );
+ void NextPara( sal_uInt16 nPar );
+ void OutParaAttr(bool bCharAttr);
+ void OutEEField(const SfxPoolItem& rHt);
+
+ bool IsTxtAttr(xub_StrLen nSwPos);
+
+ void NextPos() { if ( nAktSwPos < STRING_NOTFOUND ) nAktSwPos = SearchNext( nAktSwPos + 1 ); }
+
+ void OutAttr( xub_StrLen nSwPos );
+ virtual const SfxPoolItem* HasTextItem( sal_uInt16 nWhich ) const;
+ virtual const SfxPoolItem& GetItem( sal_uInt16 nWhich ) const;
+ bool OutAttrWithRange(xub_StrLen nPos);
+ xub_StrLen WhereNext() const { return nAktSwPos; }
+ rtl_TextEncoding GetNextCharSet() const;
+ rtl_TextEncoding GetNodeCharSet() const { return eNdChrSet; }
+};
+
+// Die Klasse SwWW8AttrIter ist eine Hilfe zum Aufbauen der Fkp.chpx.
+// Dabei werden nur Zeichen-Attribute beachtet; Absatz-Attribute brauchen
+// diese Behandlung nicht.
+// Die Absatz- und Textattribute des Writers kommen rein, und es wird
+// mit Where() die naechste Position geliefert, an der sich die Attribute
+// aendern. IsTxtAtr() sagt, ob sich an der mit Where() gelieferten Position
+// ein Attribut ohne Ende und mit \xff im Text befindet.
+// Mit OutAttr() werden die Attribute an der angegebenen SwPos
+// ausgegeben.
+class SwWW8AttrIter : public MSWordAttrIter
+{
+private:
+ const SwTxtNode& rNd;
+
+ sw::util::CharRuns maCharRuns;
+ sw::util::cCharRunIter maCharRunIter;
+
+ rtl_TextEncoding meChrSet;
+ sal_uInt16 mnScript;
+ bool mbCharIsRTL;
+
+ const SwRedline* pCurRedline;
+ xub_StrLen nAktSwPos;
+ sal_uInt16 nCurRedlinePos;
+
+ bool mbParaIsRTL;
+
+ const SwFmtDrop &mrSwFmtDrop;
+
+ sw::Frames maFlyFrms; // #i2916#
+ sw::FrameIter maFlyIter;
+
+ xub_StrLen SearchNext( xub_StrLen nStartPos );
+ void FieldVanish( const String& rTxt );
+
+ void OutSwFmtRefMark(const SwFmtRefMark& rAttr, bool bStart);
+
+ void IterToCurrent();
+
+ //No copying
+ SwWW8AttrIter(const SwWW8AttrIter&);
+ SwWW8AttrIter& operator=(const SwWW8AttrIter&);
+public:
+ SwWW8AttrIter( MSWordExportBase& rWr, const SwTxtNode& rNd );
+
+ bool IsTxtAttr( xub_StrLen nSwPos );
+ bool IsRedlineAtEnd( xub_StrLen nPos ) const;
+ bool IsDropCap( int nSwPos );
+ bool RequiresImplicitBookmark();
+
+ void NextPos() { if ( nAktSwPos < STRING_NOTFOUND ) nAktSwPos = SearchNext( nAktSwPos + 1 ); }
+
+ void OutAttr( xub_StrLen nSwPos, bool bRuby = false );
+ virtual const SfxPoolItem* HasTextItem( sal_uInt16 nWhich ) const;
+ virtual const SfxPoolItem& GetItem( sal_uInt16 nWhich ) const;
+ int OutAttrWithRange(xub_StrLen nPos);
+ const SwRedlineData* GetRedline( xub_StrLen nPos );
+ void OutFlys(xub_StrLen nSwPos);
+
+ xub_StrLen WhereNext() const { return nAktSwPos; }
+ sal_uInt16 GetScript() const { return mnScript; }
+ bool IsCharRTL() const { return mbCharIsRTL; }
+ bool IsParaRTL() const { return mbParaIsRTL; }
+ rtl_TextEncoding GetCharSet() const { return meChrSet; }
+ String GetSnippet(const String &rStr, xub_StrLen nAktPos,
+ xub_StrLen nLen) const;
+ const SwFmtDrop& GetSwFmtDrop() const { return mrSwFmtDrop; }
+};
+
+/// Class to collect and output the styles table.
+class MSWordStyles
+{
+ MSWordExportBase& m_rExport;
+ SwFmt** pFmtA;
+ sal_uInt16 nUsedSlots;
+
+ /// Create the style table, called from the constructor.
+ void BuildStylesTable();
+
+ /// Get slot number during building the style table.
+ sal_uInt16 BuildGetSlot( const SwFmt& rFmt );
+
+ /// Return information about one style.
+ void GetStyleData( SwFmt* pFmt, bool& bFmtColl, sal_uInt16& nBase, sal_uInt16& nNext );
+
+ /// Outputs attributes of one style.
+ void WriteProperties( const SwFmt* pFmt, bool bPap, sal_uInt16 nPos, bool bInsDefCharSiz );
+
+ sal_uInt16 GetWWId( const SwFmt& rFmt ) const;
+
+ void SetStyleDefaults( const SwFmt& rFmt, bool bPap );
+
+ /// Outputs one style - called (in a loop) from OutputStylesTable().
+ void OutputStyle( SwFmt* pFmt, sal_uInt16 nPos );
+
+ // No copying
+ MSWordStyles( const MSWordStyles& );
+ MSWordStyles& operator=( const MSWordStyles& );
+
+public:
+ MSWordStyles( MSWordExportBase& rExport );
+ ~MSWordStyles();
+
+ /// Output the styles table.
+ void OutputStylesTable();
+
+ /// Get id of the style (rFmt).
+ sal_uInt16 GetSlot( const SwFmt& rFmt ) const;
+
+ SwFmt* GetSwFmt() { return (*pFmtA); }
+};
+
+sal_Int16 GetWordFirstLineOffset(const SwNumFmt &rFmt);
+//A bit of a bag on the side for now
+String FieldString(ww::eField eIndex);
+String BookmarkToWord(const String &rBookmark);
+
+class WW8SHDLong
+{
+ sal_uInt32 m_cvFore;
+ sal_uInt32 m_cvBack;
+ sal_uInt16 m_ipat;
+
+public:
+ WW8SHDLong() : m_cvFore(0), m_cvBack(0), m_ipat(0) {}
+ virtual ~WW8SHDLong() {}
+
+ void Write(WW8Export & rExport);
+ void setCvFore(sal_uInt32 cvFore) { m_cvFore = cvFore; }
+ void setCvBack(sal_uInt32 cvBack) { m_cvBack = cvBack; }
+ void setIPat(sal_uInt16 ipat) { m_ipat = ipat; }
+};
+
+/// For the output of sections.
+struct WW8_PdAttrDesc
+{
+ sal_uInt8* pData;
+ sal_uInt16 nLen;
+ WW8_FC nSepxFcPos;
+};
+
+#endif // _WRTWW8_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/wrtww8gr.cxx b/sw/source/filter/ww8/wrtww8gr.cxx
new file mode 100644
index 000000000000..5c72d15ea799
--- /dev/null
+++ b/sw/source/filter/ww8/wrtww8gr.cxx
@@ -0,0 +1,905 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#if OSL_DEBUG_LEVEL > 1
+#include <cstdio>
+#endif
+
+#include <com/sun/star/embed/XEmbedPersist.hpp>
+#include <com/sun/star/embed/Aspects.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <rtl/math.hxx>
+#include <svtools/filter.hxx>
+#include <svl/itemiter.hxx>
+#include "svl/urihelper.hxx"
+
+#include <svtools/embedhlp.hxx>
+
+#include <vcl/virdev.hxx>
+#include <vcl/svapp.hxx>
+
+#include <hintids.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <filter/msfilter/msoleexp.hxx>
+#include <editeng/lrspitem.hxx> // SvxLRSpaceItem
+#include <editeng/ulspitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <svx/svdoole2.hxx>
+
+#include <unotools/ucbstreamhelper.hxx>
+#include <fmtanchr.hxx>
+#include <ndgrf.hxx>
+#include <frmfmt.hxx> // class SwFlyFrmFmt
+#include <grfatr.hxx> // class SwCropGrf
+#include <ndole.hxx>
+#include <ndtxt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+
+#include <writerfilter/doctok/sprmids.hxx>
+
+#include <doc.hxx>
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "ww8struc.hxx"
+#include "wrtww8.hxx"
+#include "ww8par.hxx"
+#include "escher.hxx"
+
+#include "docsh.hxx"
+#include <cstdio>
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+using namespace ::com::sun::star;
+using namespace nsFieldFlags;
+
+// ToDo:
+// 5. Die MapModes, die Win nicht kann, umrechnen
+
+// OutGrf() wird fuer jeden GrafNode im Doc gerufen. Es wird ein PicLocFc-Sprm
+// eingefuegt, der statt Adresse ein Magic sal_uLong enthaelt. Ausserdem wird
+// in der Graf-Klasse der GrfNode-Ptr gemerkt ( fuers spaetere Ausgeben der
+// Grafiken und Patchen der PicLocFc-Attribute )
+
+void WW8Export::OutputGrfNode( const SwGrfNode& /*rNode*/ )
+{
+ OSL_TRACE("WW8Export::OutputGrfNode( const SwGrfNode& )\n" );
+ OSL_ENSURE( mpParentFrame, "frame not set!" );
+ if ( mpParentFrame )
+ {
+ OutGrf( *mpParentFrame );
+ pFib->fHasPic = 1;
+ }
+}
+
+bool WW8Export::TestOleNeedsGraphic(const SwAttrSet& rSet,
+ SvStorageRef xOleStg, SvStorageRef xObjStg, String &rStorageName,
+ SwOLENode *pOLENd)
+{
+ bool bGraphicNeeded = false;
+ SfxItemIter aIter( rSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+
+ do {
+ switch (pItem->Which())
+ {
+ /*
+ For an inline object these properties are irrelevent because they
+ will be the same as the defaults that msword applies in their
+ absence, so if that is all that there is for these inline objects
+ then if there turns out to be enough information in the object
+ itself to regenerate the correct size and preview of the object
+ then we will not need to provide an additional graphics preview in
+ the data stream, which can save a lot of disk space.
+ */
+ case RES_FRM_SIZE:
+ case RES_CNTNT:
+ case RES_VERT_ORIENT:
+ case RES_ANCHOR:
+ break;
+ default:
+ bGraphicNeeded = true;
+ }
+ } while( !bGraphicNeeded && !aIter.IsAtEnd() &&
+ 0 != ( pItem = aIter.NextItem() ) );
+
+ /*
+ Now we must see if the object contains a preview itself which is equal to
+ the preview that we are currently using. If the graphics are equal then we
+ dont need to store another preview
+ */
+ GDIMetaFile aWMF;
+ long nX=0,nY=0;
+ if (!bGraphicNeeded && SwWW8ImplReader::ImportOleWMF(xOleStg,aWMF,nX,nY))
+ {
+ // bGraphicNeeded set to true is right / fixes #i51670#.
+ bGraphicNeeded = true;
+ Point aTmpPoint;
+ Rectangle aRect( aTmpPoint, Size( nX, nY ) );
+ Graphic aGraph(aWMF);
+
+ ErrCode nErr = ERRCODE_NONE;
+ Rectangle aVisArea;
+ sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
+ if ( pOLENd )
+ nAspect = pOLENd->GetAspect();
+ SdrOle2Obj *pRet = SvxMSDffManager::CreateSdrOLEFromStorage(
+ rStorageName,xObjStg,pDoc->GetDocStorage(),aGraph,aRect,aVisArea,0,nErr,0,nAspect);
+
+ if (pRet)
+ {
+ uno::Reference< embed::XEmbeddedObject > xObj = pOLENd->GetOLEObj().GetOleRef();
+ if ( xObj.is() )
+ {
+ SvStream* pGraphicStream = NULL;
+ comphelper::EmbeddedObjectContainer aCnt( pDoc->GetDocStorage() );
+ try
+ {
+ uno::Reference< embed::XEmbedPersist > xPersist(
+ xObj,
+ uno::UNO_QUERY_THROW );
+
+ // it makes no sence to search the object in the container by reference since the object was created
+ // outside of the container and was not inserted there, only the name makes sence
+ pGraphicStream =
+ ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( xPersist->getEntryName() ) );
+ }
+ catch( uno::Exception& )
+ {}
+
+ DBG_ASSERT( pGraphicStream && !pGraphicStream->GetError(), "No graphic stream available!" );
+ if ( pGraphicStream && !pGraphicStream->GetError() )
+ {
+ Graphic aGr1;
+ GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
+ if( pGF->ImportGraphic( aGr1, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
+ {
+ Graphic aGr2;
+ delete pGraphicStream;
+ pGraphicStream =
+ ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( pRet->GetObjRef() ) );
+ if( pGF->ImportGraphic( aGr2, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
+ {
+ if ( aGr1 == aGr2 )
+ bGraphicNeeded = false;
+ }
+ }
+ }
+ else
+ delete pGraphicStream;
+ }
+
+ delete pRet;
+ }
+ }
+ else
+ bGraphicNeeded = true;
+ return bGraphicNeeded;
+}
+
+void WW8Export::OutputOLENode( const SwOLENode& rOLENode )
+{
+ OSL_TRACE("WW8Export::OutputOLENode( const SwOLENode& rOLENode )\n" );
+ sal_uInt8 *pSpecOLE;
+ sal_uInt8 *pDataAdr;
+ short nSize;
+ static sal_uInt8 aSpecOLE_WW8[] = {
+ 0x03, 0x6a, 0, 0, 0, 0, // sprmCPicLocation
+ 0x0a, 0x08, 1, // sprmCFOLE2
+ 0x56, 0x08, 1 // sprmCFObj
+ };
+ static sal_uInt8 aSpecOLE_WW6[] = {
+ 68, 4, 0, 0, 0, 0, // sprmCPicLocation (len is 4)
+ 75, 1, // sprmCFOLE2
+ 118, 1 // sprmCFObj
+ };
+
+ if ( bWrtWW8 )
+ {
+ pSpecOLE = aSpecOLE_WW8;
+ nSize = sizeof( aSpecOLE_WW8 );
+ }
+ else
+ {
+ pSpecOLE = aSpecOLE_WW6;
+ nSize = sizeof( aSpecOLE_WW6 );
+ }
+ pDataAdr = pSpecOLE + 2; //WW6 sprm is 1 but has 1 byte len as well.
+
+ SvStorageRef xObjStg = GetWriter().GetStorage().OpenSotStorage(
+ CREATE_CONST_ASC(SL::aObjectPool), STREAM_READWRITE |
+ STREAM_SHARE_DENYALL );
+
+ if( xObjStg.Is() )
+ {
+ uno::Reference < embed::XEmbeddedObject > xObj(const_cast<SwOLENode&>(rOLENode).GetOLEObj().GetOleRef());
+ if( xObj.is() )
+ {
+ embed::XEmbeddedObject *pObj = xObj.get();
+ sal_uInt32 nPictureId = (sal_uInt32)(sal_uIntPtr)pObj;
+ Set_UInt32(pDataAdr, nPictureId);
+
+ WW8OleMap *pMap = new WW8OleMap(nPictureId);
+ bool bDuplicate = false;
+ WW8OleMaps &rOleMap = GetOLEMap();
+ sal_uInt16 nPos;
+ if ( rOleMap.Seek_Entry(pMap, &nPos) )
+ {
+ bDuplicate = true;
+ delete pMap;
+ }
+ else if( 0 == rOleMap.Insert( pMap) )
+ delete pMap;
+
+ String sStorageName( '_' );
+ sStorageName += String::CreateFromInt32( nPictureId );
+ SvStorageRef xOleStg = xObjStg->OpenSotStorage( sStorageName,
+ STREAM_READWRITE| STREAM_SHARE_DENYALL );
+ if( xOleStg.Is() )
+ {
+ /*
+ If this object storage has been written already don't
+ waste time rewriting it
+ */
+ if (!bDuplicate)
+ {
+ sal_Int64 nAspect = rOLENode.GetAspect();
+ svt::EmbeddedObjectRef aObjRef( xObj, nAspect );
+ GetOLEExp().ExportOLEObject( aObjRef, *xOleStg );
+ if ( nAspect == embed::Aspects::MSOLE_ICON )
+ {
+ ::rtl::OUString aObjInfo( RTL_CONSTASCII_USTRINGPARAM( "\3ObjInfo" ) );
+ if ( !xOleStg->IsStream( aObjInfo ) )
+ {
+ const sal_uInt8 pObjInfoData[] = { 0x40, 0x00, 0x03, 0x00 };
+ SvStorageStreamRef rObjInfoStream = xOleStg->OpenSotStream( aObjInfo );
+ if ( rObjInfoStream.Is() && !rObjInfoStream->GetError() )
+ {
+ rObjInfoStream->Write( pObjInfoData, sizeof( pObjInfoData ) );
+ xOleStg->Commit();
+ }
+ }
+ }
+ }
+
+ // write as embedded field - the other things will be done
+ // in the escher export
+ String sServer(FieldString(ww::eEMBED));
+ sServer += xOleStg->GetUserName();
+ sServer += ' ';
+
+ OutputField(0, ww::eEMBED, sServer, WRITEFIELD_START |
+ WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
+
+ pChpPlc->AppendFkpEntry( Strm().Tell(),
+ nSize, pSpecOLE );
+
+ bool bEndCR = true;
+ /*
+ In the word filter we only need a preview image for
+ floating images, and then only (the usual case) if the
+ object doesn't contain enough information to reconstruct
+ what we need.
+
+ We don't need a graphic for inline objects, so we don't
+ even need the overhead of a graphic in that case.
+ */
+ bool bGraphicNeeded = false;
+
+ if (mpParentFrame)
+ {
+ bGraphicNeeded = true;
+
+ if (mpParentFrame->IsInline())
+ {
+ const SwAttrSet& rSet =
+ mpParentFrame->GetFrmFmt().GetAttrSet();
+ bEndCR = false;
+ bGraphicNeeded = TestOleNeedsGraphic(rSet,
+ xOleStg, xObjStg, sStorageName, const_cast<SwOLENode*>(&rOLENode));
+ }
+ }
+
+ if (!bGraphicNeeded)
+ WriteChar(0x1);
+ else
+ {
+ /*
+ ##897##
+ We need to insert the graphic representation of
+ this object for the inline case, otherwise word
+ has no place to find the dimensions of the ole
+ object, and will not be able to draw it
+ */
+ OutGrf(*mpParentFrame);
+ }
+
+ OutputField(0, ww::eEMBED, aEmptyStr,
+ WRITEFIELD_END | WRITEFIELD_CLOSE);
+
+ if (bEndCR) //No newline in inline case
+ WriteCR();
+ }
+ }
+ }
+}
+
+void WW8Export::OutputLinkedOLE( const rtl::OUString& rOleId )
+{
+ uno::Reference< embed::XStorage > xDocStg = pDoc->GetDocStorage();
+ uno::Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OLELinks")), embed::ElementModes::READ );
+ SotStorageRef xObjSrc = SotStorage::OpenOLEStorage( xOleStg, rOleId, STREAM_READ );
+
+ SotStorageRef xObjStg = GetWriter().GetStorage().OpenSotStorage(
+ CREATE_CONST_ASC(SL::aObjectPool), STREAM_READWRITE |
+ STREAM_SHARE_DENYALL );
+
+ if( xObjStg.Is() && xObjSrc.Is() )
+ {
+ SotStorageRef xOleDst = xObjStg->OpenSotStorage( rOleId,
+ STREAM_READWRITE | STREAM_SHARE_DENYALL );
+ if ( xOleDst.Is() )
+ xObjSrc->CopyTo( xOleDst );
+
+ if ( !xOleDst->GetError( ) )
+ {
+ xOleDst->Commit();
+
+ // Ouput the cPicLocation attribute
+ WW8Bytes* pBuf = new WW8Bytes( 128, 128 );
+ GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CPicLocation );
+ GetWriter().InsUInt32( *pBuf, rOleId.copy( 1 ).toInt32() );
+
+ GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFOle2 );
+ pBuf->Insert( 1, pBuf->Count() );
+
+ GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFSpec );
+ pBuf->Insert( 1, pBuf->Count() );
+
+ GetWriter().InsUInt16( *pBuf, NS_sprm::LN_CFObj );
+ pBuf->Insert( 1, pBuf->Count() );
+
+ pChpPlc->AppendFkpEntry( Strm().Tell(), pBuf->Count(), pBuf->GetData() );
+ delete pBuf;
+ }
+ }
+}
+
+void WW8Export::OutGrf(const sw::Frame &rFrame)
+{
+ // GrfNode fuer spaeteres rausschreiben der Grafik merken
+ pGrf->Insert(rFrame);
+
+ pChpPlc->AppendFkpEntry( Strm().Tell(), pO->Count(), pO->GetData() );
+ pO->Remove( 0, pO->Count() ); // leeren
+
+ // #i29408#
+ // linked, as-character anchored graphics have to be exported as fields.
+ const SwGrfNode* pGrfNd = rFrame.IsInline() && rFrame.GetContent()
+ ? rFrame.GetContent()->GetGrfNode() : 0;
+ if ( pGrfNd && pGrfNd->IsLinkedFile() )
+ {
+ String sStr( FieldString(ww::eINCLUDEPICTURE) );
+ sStr.APPEND_CONST_ASC(" \"");
+ {
+ if ( pGrfNd )
+ {
+ String aFileURL;
+ pGrfNd->GetFileFilterNms( &aFileURL, 0 );
+ sStr += aFileURL;
+ }
+ }
+ sStr.APPEND_CONST_ASC("\" \\d");
+
+ OutputField( 0, ww::eINCLUDEPICTURE, sStr,
+ WRITEFIELD_START | WRITEFIELD_CMD_START | WRITEFIELD_CMD_END );
+ }
+ // <--
+
+ WriteChar( (char)1 ); // Grafik-Sonderzeichen in Haupttext einfuegen
+
+ sal_uInt8 aArr[ 18 ];
+ sal_uInt8* pArr = aArr;
+
+ const SwFrmFmt &rFlyFmt = rFrame.GetFrmFmt();
+ const RndStdIds eAn = rFlyFmt.GetAttrSet().GetAnchor(false).GetAnchorId();
+ if (eAn == FLY_AS_CHAR)
+ {
+ sal_Int16 eVert = rFlyFmt.GetVertOrient().GetVertOrient();
+ if ((eVert == text::VertOrientation::CHAR_CENTER) || (eVert == text::VertOrientation::LINE_CENTER))
+ {
+ bool bVert = false;
+ //The default for word in vertical text mode is to center,
+ //otherwise a sub/super script hack is employed
+ if (pOutFmtNode && pOutFmtNode->ISA(SwCntntNode) )
+ {
+ const SwTxtNode* pTxtNd = (const SwTxtNode*)pOutFmtNode;
+ SwPosition aPos(*pTxtNd);
+ bVert = pDoc->IsInVerticalText(aPos) ? true : false;
+ }
+ if (!bVert)
+ {
+ SwTwips nHeight = rFlyFmt.GetFrmSize().GetHeight();
+ nHeight/=20; //nHeight was in twips, want it in half points, but
+ //then half of total height.
+ long nFontHeight = ((const SvxFontHeightItem&)
+ GetItem(RES_CHRATR_FONTSIZE)).GetHeight();
+ nHeight-=nFontHeight/20;
+
+ if (bWrtWW8)
+ Set_UInt16( pArr, NS_sprm::LN_CHpsPos );
+ else
+ Set_UInt8( pArr, 101 );
+ Set_UInt16( pArr, -((sal_Int16)nHeight));
+ }
+ }
+ }
+
+ // sprmCFSpec
+ if( bWrtWW8 )
+ Set_UInt16( pArr, 0x855 );
+ else
+ Set_UInt8( pArr, 117 );
+ Set_UInt8( pArr, 1 );
+
+ // sprmCPicLocation
+ if( bWrtWW8 )
+ Set_UInt16( pArr, NS_sprm::LN_CPicLocation );
+ else
+ {
+ Set_UInt8( pArr, 68 );
+ Set_UInt8( pArr, 4 );
+ }
+ Set_UInt32( pArr, GRF_MAGIC_321 );
+
+ // Magic variieren, damit verschiedene Grafik-Attribute nicht
+ // gemerged werden
+ static sal_uInt8 nAttrMagicIdx = 0;
+ --pArr;
+ Set_UInt8( pArr, nAttrMagicIdx++ );
+ pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
+
+ // #i75464#
+ // Check, if graphic isn't exported as-character anchored.
+ // Otherwise, an additional paragraph is exported for a graphic, which is
+ // forced to be treated as inline, because it's anchored inside another frame.
+ if ( !rFrame.IsInline() &&
+ ( ((eAn == FLY_AT_PARA) && ( bWrtWW8 || !bIsInTable )) ||
+ (eAn == FLY_AT_PAGE)) )
+ // <--
+ {
+ WriteChar( (char)0x0d ); // umgebenden Rahmen mit CR abschliessen
+
+ static sal_uInt8 nSty[2] = { 0, 0 };
+ pO->Insert( nSty, 2, pO->Count() ); // Style #0
+ bool bOldGrf = bOutGrf;
+ bOutGrf = true;
+
+ OutputFormat( rFrame.GetFrmFmt(), false, false, true ); // Fly-Attrs
+
+ bOutGrf = bOldGrf;
+ pPapPlc->AppendFkpEntry( Strm().Tell(), pO->Count(), pO->GetData() );
+ pO->Remove( 0, pO->Count() ); // leeren
+ }
+ // #i29408#
+ // linked, as-character anchored graphics have to be exported as fields.
+ else if ( pGrfNd && pGrfNd->IsLinkedFile() )
+ {
+ OutputField( 0, ww::eINCLUDEPICTURE, String(), WRITEFIELD_CLOSE );
+ }
+ // <--
+}
+
+GraphicDetails& GraphicDetails::operator=(const GraphicDetails &rOther)
+{
+ maFly = rOther.maFly;
+ mnPos = rOther.mnPos;
+ mnWid = rOther.mnWid;
+ mnHei = rOther.mnHei;
+ return *this;
+}
+
+void SwWW8WrGrf::Insert(const sw::Frame &rFly)
+{
+ const Size aSize( rFly.GetLayoutSize() );
+ const sal_uInt16 nWidth = static_cast< sal_uInt16 >(aSize.Width());
+ const sal_uInt16 nHeight = static_cast< sal_uInt16 >(aSize.Height());
+ maDetails.push_back(GraphicDetails(rFly, nWidth, nHeight));
+}
+
+void SwWW8WrGrf::WritePICFHeader(SvStream& rStrm, const sw::Frame &rFly,
+ sal_uInt16 mm, sal_uInt16 nWidth, sal_uInt16 nHeight, const SwAttrSet* pAttrSet)
+{
+ sal_Int16 nXSizeAdd = 0, nYSizeAdd = 0;
+ sal_Int16 nCropL = 0, nCropR = 0, nCropT = 0, nCropB = 0;
+
+ // Crop-AttributInhalt in Header schreiben ( falls vorhanden )
+ const SfxPoolItem* pItem;
+ if (pAttrSet && (SFX_ITEM_ON
+ == pAttrSet->GetItemState(RES_GRFATR_CROPGRF, false, &pItem)))
+ {
+ const SwCropGrf& rCr = *(SwCropGrf*)pItem;
+ nCropL = (sal_Int16)rCr.GetLeft();
+ nCropR = (sal_Int16)rCr.GetRight();
+ nCropT = (sal_Int16)rCr.GetTop();
+ nCropB = (sal_Int16)rCr.GetBottom();
+ nXSizeAdd = nXSizeAdd - (sal_Int16)( rCr.GetLeft() + rCr.GetRight() );
+ nYSizeAdd = nYSizeAdd - (sal_Int16)( rCr.GetTop() + rCr.GetBottom() );
+ }
+
+ Size aGrTwipSz(rFly.GetSize());
+ bool bWrtWW8 = rWrt.bWrtWW8;
+ sal_uInt16 nHdrLen = bWrtWW8 ? 0x44 : 0x3A;
+
+ sal_uInt8 aArr[ 0x44 ] = { 0 };
+
+ sal_uInt8* pArr = aArr + 0x2E; //Do borders first
+
+ const SwAttrSet& rAttrSet = rFly.GetFrmFmt().GetAttrSet();
+ if (SFX_ITEM_ON == rAttrSet.GetItemState(RES_BOX, false, &pItem))
+ {
+ const SvxBoxItem* pBox = (const SvxBoxItem*)pItem;
+ if( pBox )
+ {
+ bool bShadow = false; // Shadow ?
+ const SvxShadowItem* pSI =
+ sw::util::HasItem<SvxShadowItem>(rAttrSet, RES_SHADOW);
+ if (pSI)
+ {
+ bShadow = (pSI->GetLocation() != SVX_SHADOW_NONE) &&
+ (pSI->GetWidth() != 0);
+ }
+
+ sal_uInt8 aLnArr[4] = { BOX_LINE_TOP, BOX_LINE_LEFT,
+ BOX_LINE_BOTTOM, BOX_LINE_RIGHT };
+ for( sal_uInt8 i = 0; i < 4; ++i )
+ {
+ const ::editeng::SvxBorderLine* pLn = pBox->GetLine( aLnArr[ i ] );
+ WW8_BRC aBrc;
+ if (pLn)
+ {
+ aBrc = rWrt.TranslateBorderLine( *pLn,
+ pBox->GetDistance( aLnArr[ i ] ), bShadow );
+ }
+
+ //use importer logic to determine how large the exported
+ //border will really be in word and adjust accordingly
+ short nSpacing;
+ short nThick = aBrc.DetermineBorderProperties(!bWrtWW8,
+ &nSpacing);
+ switch (aLnArr[ i ])
+ {
+ case BOX_LINE_TOP:
+ case BOX_LINE_BOTTOM:
+ nHeight -= bShadow ? nThick*2 : nThick;
+ nHeight = nHeight - nSpacing;
+ break;
+ case BOX_LINE_LEFT:
+ case BOX_LINE_RIGHT:
+ default:
+ nWidth -= bShadow ? nThick*2 : nThick;
+ nWidth = nWidth - nSpacing;
+ break;
+ }
+ memcpy( pArr, &aBrc.aBits1, 2);
+ pArr+=2;
+
+ if( bWrtWW8 )
+ {
+ memcpy( pArr, &aBrc.aBits2, 2);
+ pArr+=2;
+ }
+ }
+ }
+ }
+
+ pArr = aArr + 4; //skip lcb
+ Set_UInt16( pArr, nHdrLen ); // set cbHeader
+
+ Set_UInt16( pArr, mm ); // set mm
+
+ /*
+ Just in case our original size is too big to fit inside a ushort we can
+ substitute the final size and loose on retaining the scaling factor but
+ still keep the correct display size anyway.
+ */
+ if ( (aGrTwipSz.Width() > SHRT_MAX) || (aGrTwipSz.Height() > SHRT_MAX)
+ || (aGrTwipSz.Width() < 0 ) || (aGrTwipSz.Height() < 0) )
+ {
+ aGrTwipSz.Width() = nWidth;
+ aGrTwipSz.Height() = nHeight;
+ }
+ using namespace sw::types;
+ // set xExt & yExt
+ Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Width() * 254L / 144));
+ Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Height() * 254L / 144));
+ pArr += 16;
+ // skip hMF & rcWinMF
+ // set dxaGoal & dyaGoal
+ Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Width()));
+ Set_UInt16(pArr, msword_cast<sal_uInt16>(aGrTwipSz.Height()));
+
+ if( aGrTwipSz.Width() + nXSizeAdd ) // set mx
+ {
+ double fVal = nWidth * 1000.0 / (aGrTwipSz.Width() + nXSizeAdd);
+ Set_UInt16( pArr, (sal_uInt16)::rtl::math::round(fVal) );
+ }
+ else
+ pArr += 2;
+
+ if( aGrTwipSz.Height() + nYSizeAdd ) // set my
+ {
+ double fVal = nHeight * 1000.0 / (aGrTwipSz.Height() + nYSizeAdd);
+ Set_UInt16( pArr, (sal_uInt16)::rtl::math::round(fVal) );
+ }
+ else
+ pArr += 2;
+
+ Set_UInt16( pArr, nCropL ); // set dxaCropLeft
+ Set_UInt16( pArr, nCropT ); // set dyaCropTop
+ Set_UInt16( pArr, nCropR ); // set dxaCropRight
+ Set_UInt16( pArr, nCropB ); // set dyaCropBottom
+
+ rStrm.Write( aArr, nHdrLen );
+}
+
+void SwWW8WrGrf::WriteGrfFromGrfNode(SvStream& rStrm, const SwGrfNode &rGrfNd,
+ const sw::Frame &rFly, sal_uInt16 nWidth, sal_uInt16 nHeight)
+{
+ if (rGrfNd.IsLinkedFile()) // Linked File
+ {
+ String aFileN;
+ rGrfNd.GetFileFilterNms( &aFileN, 0 );
+
+ sal_uInt16 mm = 94; // 94 = BMP, GIF
+
+ WritePICFHeader(rStrm, rFly, mm, nWidth, nHeight,
+ rGrfNd.GetpSwAttrSet());
+ rStrm << (sal_uInt8)aFileN.Len(); // Pascal-String schreiben
+ SwWW8Writer::WriteString8(rStrm, aFileN, false,
+ RTL_TEXTENCODING_MS_1252);
+ }
+ else // Embedded File oder DDE oder so was
+ {
+ if (rWrt.bWrtWW8)
+ {
+ WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight,
+ rGrfNd.GetpSwAttrSet());
+ SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
+ aInlineEscher.WriteGrfFlyFrame(rFly.GetFrmFmt(), 0x401);
+ aInlineEscher.WritePictures();
+ }
+ else
+ {
+ Graphic& rGrf = const_cast<Graphic&>(rGrfNd.GetGrf());
+ bool bSwapped = rGrf.IsSwapOut() ? true : false;
+ // immer ueber den Node einswappen!
+ const_cast<SwGrfNode&>(rGrfNd).SwapIn();
+
+ GDIMetaFile aMeta;
+ switch (rGrf.GetType())
+ {
+ case GRAPHIC_BITMAP: // Bitmap -> in Metafile abspielen
+ {
+ VirtualDevice aVirt;
+ aMeta.Record(&aVirt);
+ aVirt.DrawBitmap( Point( 0,0 ), rGrf.GetBitmap() );
+ aMeta.Stop();
+ aMeta.WindStart();
+ aMeta.SetPrefMapMode( rGrf.GetPrefMapMode());
+ aMeta.SetPrefSize( rGrf.GetPrefSize());
+ }
+ break;
+ case GRAPHIC_GDIMETAFILE : // GDI ( =SV ) Metafile
+ aMeta = rGrf.GetGDIMetaFile();
+ break;
+ default:
+ return;
+ }
+
+ WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
+ rGrfNd.GetpSwAttrSet());
+ WriteWindowMetafileBits(rStrm, aMeta);
+
+ if (bSwapped)
+ rGrf.SwapOut();
+ }
+ }
+}
+
+void SwWW8WrGrf::WriteGraphicNode(SvStream& rStrm, const GraphicDetails &rItem)
+{
+ sal_uInt16 nWidth = rItem.mnWid;
+ sal_uInt16 nHeight = rItem.mnHei;
+ sal_uInt32 nPos = rStrm.Tell(); // Grafik-Anfang merken
+
+ const sw::Frame &rFly = rItem.maFly;
+ switch (rFly.GetWriterType())
+ {
+ case sw::Frame::eGraphic:
+ {
+ const SwNode *pNode = rItem.maFly.GetContent();
+ const SwGrfNode *pNd = pNode ? pNode->GetGrfNode() : 0;
+ OSL_ENSURE(pNd, "Impossible");
+ if (pNd)
+ WriteGrfFromGrfNode(rStrm, *pNd, rItem.maFly, nWidth, nHeight);
+ }
+ break;
+ case sw::Frame::eOle:
+ {
+#ifdef OLE_PREVIEW_AS_EMF
+ const SwNode *pNode = rItem.maFly.GetContent();
+ const SwOLENode *pNd = pNode ? pNode->GetOLENode() : 0;
+ OSL_ENSURE(pNd, "Impossible");
+ if (!rWrt.bWrtWW8)
+ {
+ SwOLENode *pOleNd = const_cast<SwOLENode*>(pNd);
+ OSL_ENSURE( pOleNd, " Wer hat den OleNode versteckt ?" );
+ SwOLEObj& rSObj= pOleNd->GetOLEObj();
+ uno::Reference < embed::XEmbeddedObject > rObj( rSObj.GetOleRef() );
+
+ comphelper::EmbeddedObjectContainer aCnt( pOleNd->GetDoc()->GetDocStorage() );
+
+ SvStream* pGraphicStream = ::utl::UcbStreamHelper::CreateStream( aCnt.GetGraphicStream( rObj ) );
+ DBG_ASSERT( pGraphicStream && !pGraphicStream->GetError(), "No graphic stream available!" );
+ if ( pGraphicStream && !pGraphicStream->GetError() )
+ {
+ Graphic aGr;
+ GraphicFilter* pGF = GraphicFilter::GetGraphicFilter();
+ if( pGF->ImportGraphic( aGr, aEmptyStr, *pGraphicStream, GRFILTER_FORMAT_DONTKNOW ) == GRFILTER_OK )
+ {
+ //TODO/LATER: do we really want to use GDIMetafile?!
+ GDIMetaFile aMtf;
+ aMtf = aGr.GetGDIMetaFile();
+ aMtf.WindStart();
+ aMtf.Play(Application::GetDefaultDevice(), Point(0, 0),
+ Size(2880, 2880));
+ WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
+ pNd->GetpSwAttrSet());
+ WriteWindowMetafileBits(rStrm, aMtf);
+ }
+ }
+ else
+ delete pGraphicStream;
+ }
+ else
+ {
+ //Convert this ole2 preview in ww8+ to an EMF for better unicode
+ //support (note that at this moment this breaks StarSymbol
+ //using graphics because I need to embed starsymbol in exported
+ //documents.
+ WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight,
+ pNd->GetpSwAttrSet());
+ SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
+ aInlineEscher.WriteOLEFlyFrame(rFly.GetFrmFmt(), 0x401);
+ aInlineEscher.WritePictures();
+ }
+#else
+ // cast away const
+ SwOLENode *pOleNd = const_cast<SwOLENode*>(pNd);
+ OSL_ENSURE( pOleNd, " Wer hat den OleNode versteckt ?" );
+ SwOLEObj& rSObj= pOleNd->GetOLEObj();
+
+ // TODO/LATER: do we need to load object?
+ Graphic* pGr = SdrOle2Obj::GetGraphicFromObject( pOleNd->GetDoc()->GetDocStorage(), rObj );
+
+ //TODO/LATER: do we really want to use GDIMetafile?!
+ GDIMetaFile aMtf;
+ if ( pGr )
+ aMtf = pGr->GetGDIMetaFile();
+
+ Size aS(aMtf.GetPrefSize());
+ aMtf.WindStart();
+ aMtf.Play(Application::GetDefaultDevice(), Point(0, 0),
+ Size(2880, 2880));
+
+ WritePICFHeader(rStrm, rFly, 8, nWidth, nHeight,
+ pNd->GetpSwAttrSet());
+ WriteWindowMetafileBits(rStrm, aMtf);
+ delete pGr;
+#endif
+ }
+ break;
+ case sw::Frame::eDrawing:
+ case sw::Frame::eTxtBox:
+ case sw::Frame::eFormControl:
+ OSL_ENSURE(rWrt.bWrtWW8,
+ "You can't try and export these in WW8 format, a filter bug");
+ /*
+ #i3958# We only export an empty dummy picture frame here, this is
+ what word does the escher export should contain an anchored to
+ character element which is drawn over this dummy and the whole
+ shebang surrounded with a SHAPE field. This isn't *my* hack :-),
+ its what word does.
+ */
+ if (rWrt.bWrtWW8)
+ {
+ WritePICFHeader(rStrm, rFly, 0x64, nWidth, nHeight);
+ SwBasicEscherEx aInlineEscher(&rStrm, rWrt);
+ aInlineEscher.WriteEmptyFlyFrame(rFly.GetFrmFmt(), 0x401);
+ }
+ break;
+ default:
+ OSL_ENSURE(!this,
+ "Some inline export not implemented, remind cmc before we ship :-)");
+ break;
+ }
+
+ sal_uInt32 nPos2 = rStrm.Tell(); // Ende merken
+ rStrm.Seek( nPos );
+ SVBT32 nLen;
+ UInt32ToSVBT32( nPos2 - nPos, nLen ); // Grafik-Laenge ausrechnen
+ rStrm.Write( nLen, 4 ); // im Header einpatchen
+ rStrm.Seek( nPos2 ); // Pos wiederherstellen
+}
+
+// SwWW8WrGrf::Write() wird nach dem Text gerufen. Es schreibt die alle
+// Grafiken raus und merkt sich die File-Positionen der Grafiken, damit
+// beim Schreiben der Attribute die Positionen in die PicLocFc-Sprms
+// eingepatcht werden koennen.
+// Das Suchen in den Attributen nach dem Magic sal_uLong und das Patchen
+// passiert beim Schreiben der Attribute. Die SwWW8WrGrf-Klasse liefert
+// hierfuer nur mit GetFPos() sequentiell die Positionen.
+void SwWW8WrGrf::Write()
+{
+ SvStream& rStrm = *rWrt.pDataStrm;
+ myiter aEnd = maDetails.end();
+ for (myiter aIter = maDetails.begin(); aIter != aEnd; ++aIter)
+ {
+ sal_uInt32 nPos = rStrm.Tell(); // auf 4 Bytes alignen
+ if( nPos & 0x3 )
+ SwWW8Writer::FillCount( rStrm, 4 - ( nPos & 0x3 ) );
+
+ bool bDuplicated = false;
+ for (myiter aIter2 = maDetails.begin(); aIter2 != aIter; ++aIter2)
+ {
+ if (*aIter2 == *aIter)
+ {
+ aIter->mnPos = aIter2->mnPos;
+ bDuplicated = true;
+ break;
+ }
+ }
+
+ if (!bDuplicated)
+ {
+ aIter->mnPos = rStrm.Tell();
+ WriteGraphicNode(rStrm, *aIter);
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8atr.cxx b/sw/source/filter/ww8/ww8atr.cxx
new file mode 100644
index 000000000000..9448cca6b6e8
--- /dev/null
+++ b/sw/source/filter/ww8/ww8atr.cxx
@@ -0,0 +1,5247 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+/*
+ * This file contains methods for the WW8 output
+ * (nodes, attributes, formats und chars).
+ */
+
+#include <hintids.hxx>
+
+#include <vcl/svapp.hxx>
+#include <vcl/salbtype.hxx>
+#include <svl/zformat.hxx>
+#include <svl/itemiter.hxx>
+#include <svl/whiter.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/hyznitem.hxx>
+#include <editeng/brkitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/paravertalignitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/blnkitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <editeng/paperinf.hxx>
+#include <fmtfld.hxx>
+#include <fchrfmt.hxx>
+#include <fmtfsize.hxx>
+#include <fmtpdsc.hxx>
+#include <fmtornt.hxx>
+#include <fmtanchr.hxx>
+#include <fmtclds.hxx>
+#include <fmtsrnd.hxx>
+#include <fmtftn.hxx>
+#include <fmtflcnt.hxx>
+#include <frmatr.hxx>
+#include <swtable.hxx>
+#include <fmtinfmt.hxx>
+#include <txtfld.hxx>
+#include <txtftn.hxx>
+#include <poolfmt.hxx>
+#include <doc.hxx> // Doc for footnotes
+#include <pam.hxx>
+#include <paratr.hxx>
+#include <fldbas.hxx> // for SwField
+#include <docufld.hxx> // for SwField
+#include <expfld.hxx>
+#include <pagedesc.hxx> // for SwPageDesc
+#include <flddat.hxx> // for Date fields
+#include <ndtxt.hxx> // for Numrules
+#include <swrect.hxx>
+#include <reffld.hxx>
+#include <ftninfo.hxx>
+#include <charfmt.hxx>
+#include <section.hxx>
+#include <lineinfo.hxx>
+#include <fmtline.hxx>
+#include <tox.hxx>
+#include <fmtftntx.hxx>
+#include <breakit.hxx>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <unotools/localedatawrapper.hxx>
+#include <tgrditem.hxx>
+#include <flddropdown.hxx>
+#include <chpfld.hxx>
+#include <fmthdft.hxx>
+
+#include <writerfilter/doctok/sprmids.hxx>
+
+#include <fmtcntnt.hxx>
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "wrtww8.hxx"
+#include "ww8par.hxx"
+#include "ww8attributeoutput.hxx"
+#include "fields.hxx"
+#include <vcl/outdev.hxx>
+#include <i18npool/mslangid.hxx>
+
+using ::editeng::SvxBorderLine;
+using namespace ::com::sun::star;
+using namespace nsFieldFlags;
+using namespace nsSwDocInfoSubType;
+
+/*
+ * um nicht immer wieder nach einem Update festzustellen, das irgendwelche
+ * Hint-Ids dazugekommen sind, wird hier definiert, die Groesse der Tabelle
+ * definiert und mit der akt. verglichen. Bei unterschieden wird der
+ * Compiler schon meckern.
+ *
+ * diese Section und die dazugeherigen Tabellen muessen in folgenden Files
+ * gepflegt werden: rtf\rtfatr.cxx, sw6\sw6atr.cxx, w4w\w4watr.cxx
+*/
+
+#if !defined(MSC) && !defined(UNX) && !defined(PPC) && !defined(__MINGW32__) && !defined(OS2)
+
+#define ATTRFNTAB_SIZE 130
+#if ATTRFNTAB_SIZE != POOLATTR_END - POOLATTR_BEGIN
+# error "Attribut-Tabelle ist ungueltigt. Wurden neue Hint-ID's zugefuegt ??"
+#endif
+
+#define NODETAB_SIZE 3
+#if NODETAB_SIZE != RES_NODE_END - RES_NODE_BEGIN
+# error "Node-Tabelle ist ungueltigt. Wurden neue Hint-ID's zugefuegt ??"
+#endif
+
+#endif
+
+using namespace sw::util;
+using namespace sw::types;
+
+bool WW8Export::CollapseScriptsforWordOk( sal_uInt16 nScript, sal_uInt16 nWhich )
+{
+ bool bRet = true;
+ if ( nScript == i18n::ScriptType::ASIAN )
+ {
+ //for asian in ww8, there is only one fontsize
+ //and one fontstyle (posture/weight) for ww6
+ //there is the additional problem that there
+ //is only one font setting for all three scripts
+ switch ( nWhich )
+ {
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_POSTURE:
+ case RES_CHRATR_WEIGHT:
+ bRet = false;
+ break;
+ case RES_CHRATR_LANGUAGE:
+ case RES_CHRATR_CTL_FONT:
+ case RES_CHRATR_CTL_FONTSIZE:
+ case RES_CHRATR_CTL_LANGUAGE:
+ case RES_CHRATR_CTL_POSTURE:
+ case RES_CHRATR_CTL_WEIGHT:
+ if (bWrtWW8 == 0)
+ bRet = false;
+ default:
+ break;
+ }
+ }
+ else if ( nScript == i18n::ScriptType::COMPLEX )
+ {
+ //Complex is ok in ww8, but for ww6 there is only
+ //one font, one fontsize, one fontsize (weight/posture)
+ //and only one language
+ if ( bWrtWW8 == 0 )
+ {
+ switch ( nWhich )
+ {
+ case RES_CHRATR_CJK_FONT:
+ case RES_CHRATR_CJK_FONTSIZE:
+ case RES_CHRATR_CJK_POSTURE:
+ case RES_CHRATR_CJK_WEIGHT:
+ case RES_CHRATR_CJK_LANGUAGE:
+ case RES_CHRATR_FONT:
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_POSTURE:
+ case RES_CHRATR_WEIGHT:
+ case RES_CHRATR_LANGUAGE:
+ bRet = false;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ else
+ {
+ //for western in ww8, there is only one fontsize
+ //and one fontstyle (posture/weight) for ww6
+ //there is the additional problem that there
+ //is only one font setting for all three scripts
+ switch ( nWhich )
+ {
+ case RES_CHRATR_CJK_FONTSIZE:
+ case RES_CHRATR_CJK_POSTURE:
+ case RES_CHRATR_CJK_WEIGHT:
+ bRet = false;
+ break;
+ case RES_CHRATR_CJK_LANGUAGE:
+ case RES_CHRATR_CTL_FONT:
+ case RES_CHRATR_CTL_FONTSIZE:
+ case RES_CHRATR_CTL_LANGUAGE:
+ case RES_CHRATR_CTL_POSTURE:
+ case RES_CHRATR_CTL_WEIGHT:
+ if ( bWrtWW8 == 0 )
+ bRet = false;
+ default:
+ break;
+ }
+ }
+ return bRet;
+}
+
+//------------------------------------------------------------
+// Hilfsroutinen fuer Styles
+//------------------------------------------------------------
+
+void MSWordExportBase::ExportPoolItemsToCHP( sw::PoolItems &rItems, sal_uInt16 nScript )
+{
+ sw::cPoolItemIter aEnd = rItems.end();
+ for ( sw::cPoolItemIter aI = rItems.begin(); aI != aEnd; ++aI )
+ {
+ const SfxPoolItem *pItem = aI->second;
+ sal_uInt16 nWhich = pItem->Which();
+ if ( ( isCHRATR( nWhich ) || isTXTATR( nWhich ) ) && CollapseScriptsforWordOk( nScript, nWhich ) )
+ {
+ AttrOutput().OutputItem( *pItem );
+ }
+ }
+}
+
+/*
+ * Format wie folgt ausgeben:
+ * - gebe die Attribute aus; ohne Parents!
+ */
+
+void MSWordExportBase::OutputItemSet( const SfxItemSet& rSet, bool bPapFmt, bool bChpFmt, sal_uInt16 nScript,
+ bool bExportParentItemSet )
+{
+ if( bExportParentItemSet || rSet.Count() )
+ {
+ const SfxPoolItem* pItem;
+ pISet = &rSet; // fuer Doppel-Attribute
+
+ // If frame dir is set, but not adjust, then force adjust as well
+ if ( bPapFmt && SFX_ITEM_SET == rSet.GetItemState( RES_FRAMEDIR, bExportParentItemSet ) )
+ {
+ // No explicit adjust set ?
+ if ( SFX_ITEM_SET != rSet.GetItemState( RES_PARATR_ADJUST, bExportParentItemSet ) )
+ {
+ if ( 0 != ( pItem = rSet.GetItem( RES_PARATR_ADJUST, bExportParentItemSet ) ) )
+ {
+ // then set the adjust used by the parent format
+ AttrOutput().OutputItem( *pItem );
+ }
+ }
+ }
+
+ if ( bPapFmt && SFX_ITEM_SET == rSet.GetItemState( RES_PARATR_NUMRULE, bExportParentItemSet, &pItem ) )
+ {
+ AttrOutput().OutputItem( *pItem );
+
+ // switch off the numerbering?
+ if ( !( (SwNumRuleItem*)pItem )->GetValue().Len() &&
+ SFX_ITEM_SET != rSet.GetItemState( RES_LR_SPACE, false) &&
+ SFX_ITEM_SET == rSet.GetItemState( RES_LR_SPACE, true, &pItem ) )
+ {
+ // the set the LR-Space of the parentformat!
+ AttrOutput().OutputItem( *pItem );
+ }
+ }
+
+ sw::PoolItems aItems;
+ GetPoolItems( rSet, aItems, bExportParentItemSet );
+ if ( bChpFmt )
+ ExportPoolItemsToCHP(aItems, nScript);
+
+ if ( bPapFmt )
+ {
+ sw::cPoolItemIter aEnd = aItems.end();
+ for ( sw::cPoolItemIter aI = aItems.begin(); aI != aEnd; ++aI )
+ {
+ pItem = aI->second;
+ sal_uInt16 nWhich = pItem->Which();
+ if ( nWhich >= RES_PARATR_BEGIN && nWhich < RES_FRMATR_END && nWhich != RES_PARATR_NUMRULE)
+ AttrOutput().OutputItem( *pItem );
+ }
+ }
+ pISet = 0; // fuer Doppel-Attribute
+ }
+}
+#include "switerator.hxx"
+void MSWordExportBase::GatherChapterFields()
+{
+ //If the header/footer contains a chapter field
+ SwFieldType* pType = pDoc->GetSysFldType( RES_CHAPTERFLD );
+ SwIterator<SwFmtFld,SwFieldType> aFmtFlds( *pType );
+ for ( SwFmtFld* pFld = aFmtFlds.First(); pFld; pFld = aFmtFlds.Next() )
+ {
+ if (const SwTxtFld *pTxtFld = pFld->GetTxtFld())
+ {
+ const SwTxtNode &rTxtNode = pTxtFld->GetTxtNode();
+ maChapterFieldLocs.push_back(rTxtNode.GetIndex());
+ }
+ }
+}
+
+bool MSWordExportBase::CntntContainsChapterField(const SwFmtCntnt &rCntnt) const
+{
+ bool bRet = false;
+ if ( const SwNodeIndex* pSttIdx = rCntnt.GetCntntIdx() )
+ {
+ SwNodeIndex aIdx( *pSttIdx, 1 );
+ SwNodeIndex aEnd( *pSttIdx->GetNode().EndOfSectionNode() );
+ sal_uLong nStart = aIdx.GetIndex();
+ sal_uLong nEnd = aEnd.GetIndex();
+ //If the header/footer contains a chapter field
+ mycCFIter aIEnd = maChapterFieldLocs.end();
+ for ( mycCFIter aI = maChapterFieldLocs.begin(); aI != aIEnd; ++aI )
+ {
+ if ( ( nStart <= *aI ) && ( *aI <= nEnd ) )
+ {
+ bRet = true;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+bool MSWordExportBase::FmtHdFtContainsChapterField(const SwFrmFmt &rFmt) const
+{
+ if ( maChapterFieldLocs.empty() )
+ return false;
+
+ const SwFrmFmt *pFmt = 0;
+
+ pFmt = rFmt.GetHeader().GetHeaderFmt();
+ if ( pFmt && CntntContainsChapterField( pFmt->GetCntnt() ) )
+ return true;
+
+ pFmt = rFmt.GetFooter().GetFooterFmt();
+ if ( pFmt && CntntContainsChapterField( pFmt->GetCntnt() ) )
+ return true;
+
+ return false;
+}
+
+bool MSWordExportBase::SetAktPageDescFromNode(const SwNode &rNd)
+{
+ bool bNewPageDesc = false;
+ const SwPageDesc* pCurrent = SwPageDesc::GetPageDescOfNode(rNd);
+ OSL_ENSURE(pCurrent && pAktPageDesc, "Not possible surely");
+ if (pAktPageDesc && pCurrent)
+ {
+ if (pCurrent != pAktPageDesc)
+ {
+ if (pAktPageDesc->GetFollow() != pCurrent)
+ bNewPageDesc = true;
+ else
+ {
+ const SwFrmFmt& rTitleFmt = pAktPageDesc->GetMaster();
+ const SwFrmFmt& rFollowFmt = pCurrent->GetMaster();
+
+ bNewPageDesc = !IsPlausableSingleWordSection(rTitleFmt,
+ rFollowFmt);
+ }
+ pAktPageDesc = pCurrent;
+ }
+ else
+ {
+ const SwFrmFmt &rFmt = pCurrent->GetMaster();
+ bNewPageDesc = FmtHdFtContainsChapterField(rFmt);
+ }
+ }
+ return bNewPageDesc;
+}
+
+// Da WW nur Break-After ( Pagebreak und Sectionbreaks ) kennt, im SW aber
+// Bagebreaks "vor" und "nach" und Pagedescs nur "vor" existieren, werden
+// die Breaks 2* durchgeklimpert, naemlich vor und hinter jeder Zeile.
+// Je nach BreakTyp werden sie vor oder nach der Zeile gesetzt.
+// Es duerfen nur Funktionen gerufen werden, die nicht in den
+// Ausgabebereich pO schreiben, da dieser nur einmal fuer CHP und PAP existiert
+// und damit im falschen landen wuerden.
+void MSWordExportBase::OutputSectionBreaks( const SfxItemSet *pSet, const SwNode& rNd )
+{
+ if ( bStyDef || bOutKF || bInWriteEscher || bOutPageDescs )
+ return;
+
+ bBreakBefore = true;
+
+ bool bNewPageDesc = false;
+ const SfxPoolItem* pItem=0;
+ const SwFmtPageDesc *pPgDesc=0;
+
+ //Output a sectionbreak if theres a new pagedesciptor. otherwise output a
+ //pagebreak if there is a pagebreak here, unless the new page (follow
+ //style) is different to the current one, in which case plump for a
+ //section.
+ bool bBreakSet = false;
+
+ if ( pSet && pSet->Count() )
+ {
+ if ( SFX_ITEM_SET == pSet->GetItemState( RES_PAGEDESC, false, &pItem )
+ && ( (SwFmtPageDesc*)pItem )->KnowsPageDesc() )
+ {
+ bBreakSet = true;
+ bNewPageDesc = true;
+ pPgDesc = (const SwFmtPageDesc*)pItem;
+ pAktPageDesc = pPgDesc->GetPageDesc();
+ }
+ else if ( SFX_ITEM_SET == pSet->GetItemState( RES_BREAK, false, &pItem ) )
+ {
+ // Word does not like hard break attributes in some table cells
+ bool bRemoveHardBreakInsideTable = false;
+ if ( bOutTable )
+ {
+ const SwTableNode* pTableNode = rNd.FindTableNode();
+ if ( pTableNode )
+ {
+ const SwTableBox* pBox = rNd.GetTblBox();
+ const SwTableLine* pLine = pBox ? pBox->GetUpper() : 0;
+ // but only for non-complex tables
+ if ( pLine && !pLine->GetUpper() )
+ {
+ // check if box is not first in that line:
+ if ( 0 < pLine->GetTabBoxes().GetPos( pBox ) && pBox->GetSttNd() )
+ {
+ bRemoveHardBreakInsideTable = true;
+ }
+ }
+ }
+ }
+ // <--
+
+ bBreakSet = true;
+
+ if ( !bRemoveHardBreakInsideTable )
+ {
+ OSL_ENSURE(pAktPageDesc, "should not be possible");
+ /*
+ If because of this pagebreak the page desc following the page
+ break is the follow style of the current page desc then output a
+ section break using that style instead. At least in those cases
+ we end up with the same style in word and writer, nothing can be
+ done when it happens when we get a new pagedesc because we
+ overflow from the first page style.
+ */
+ if ( pAktPageDesc )
+ {
+ // #i76301# - assure that there is a page break before set at the node.
+ const SvxFmtBreakItem* pBreak = dynamic_cast<const SvxFmtBreakItem*>(pItem);
+ if ( pBreak &&
+ pBreak->GetBreak() == SVX_BREAK_PAGE_BEFORE )
+ {
+ bNewPageDesc = SetAktPageDescFromNode( rNd );
+ }
+ // <--
+ }
+ if ( !bNewPageDesc )
+ AttrOutput().OutputItem( *pItem );
+ }
+ }
+ }
+
+ /*
+ #i9301#
+ No explicit page break, lets see if the style had one and we've moved to a
+ new page style because of it, if we have to then we take the opportunity to
+ set the equivalent word section here. We *could* do it for every paragraph
+ that moves onto a new page because of layout, but that would be insane.
+ */
+ bool bHackInBreak = false;
+ if ( !bBreakSet )
+ {
+ if ( const SwCntntNode *pNd = rNd.GetCntntNode() )
+ {
+ const SvxFmtBreakItem &rBreak =
+ ItemGet<SvxFmtBreakItem>( *pNd, RES_BREAK );
+ if ( rBreak.GetBreak() == SVX_BREAK_PAGE_BEFORE )
+ bHackInBreak = true;
+ else
+ { // Even a pagedesc item is set, the break item can be set 'NONE',
+ // but a pagedesc item is an implicit page break before...
+ const SwFmtPageDesc &rPageDesc =
+ ItemGet<SwFmtPageDesc>( *pNd, RES_PAGEDESC );
+ if ( rPageDesc.KnowsPageDesc() )
+ bHackInBreak = true;
+ }
+ }
+ }
+
+ if ( bHackInBreak )
+ {
+ OSL_ENSURE( pAktPageDesc, "should not be possible" );
+ if ( pAktPageDesc )
+ bNewPageDesc = SetAktPageDescFromNode( rNd );
+ }
+
+ if ( bNewPageDesc && pAktPageDesc )
+ {
+ PrepareNewPageDesc( pSet, rNd, pPgDesc, pAktPageDesc );
+ }
+ bBreakBefore = false;
+}
+
+// #i76300#
+bool MSWordExportBase::OutputFollowPageDesc( const SfxItemSet* pSet, const SwTxtNode* pNd )
+{
+ bool bRet = false;
+
+ if ( pNd &&
+ pAktPageDesc &&
+ pAktPageDesc != pAktPageDesc->GetFollow() )
+ {
+ PrepareNewPageDesc( pSet, *pNd, 0, pAktPageDesc->GetFollow() );
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+const SwSectionFmt* MSWordExportBase::GetSectionFormat( const SwNode& rNd ) const
+{
+ const SwSectionFmt* pFmt = NULL;
+ const SwSectionNode* pSect = rNd.FindSectionNode();
+ if ( pSect &&
+ CONTENT_SECTION == pSect->GetSection().GetType() )
+ {
+ pFmt = pSect->GetSection().GetFmt();
+ }
+
+ return pFmt;
+}
+
+sal_uLong MSWordExportBase::GetSectionLineNo( const SfxItemSet* pSet, const SwNode& rNd ) const
+{
+ const SwFmtLineNumber* pNItem = 0;
+ if ( pSet )
+ {
+ pNItem = &( ItemGet<SwFmtLineNumber>( *pSet, RES_LINENUMBER ) );
+ }
+ else if ( const SwCntntNode *pNd = rNd.GetCntntNode() )
+ {
+ pNItem = &( ItemGet<SwFmtLineNumber>( *pNd, RES_LINENUMBER ) );
+ }
+
+ return pNItem? pNItem->GetStartValue() : 0;
+}
+
+void WW8Export::PrepareNewPageDesc( const SfxItemSet*pSet,
+ const SwNode& rNd,
+ const SwFmtPageDesc* pNewPgDescFmt,
+ const SwPageDesc* pNewPgDesc )
+{
+ // Die PageDescs werden beim Auftreten von PageDesc-Attributen nur in
+ // WW8Writer::pSepx mit der entsprechenden Position eingetragen. Das
+ // Aufbauen und die Ausgabe der am PageDesc haengenden Attribute und
+ // Kopf/Fusszeilen passiert nach dem Haupttext und seinen Attributen.
+
+ sal_uLong nFcPos = ReplaceCr( msword::PageBreak ); // Page/Section-Break
+
+ // tatsaechlich wird hier NOCH NICHTS ausgegeben, sondern
+ // nur die Merk-Arrays aCps, aSects entsprechend ergaenzt
+ if ( !nFcPos )
+ return;
+
+ const SwSectionFmt* pFmt = GetSectionFormat( rNd );
+ const sal_uLong nLnNm = GetSectionLineNo( pSet, rNd );
+
+ OSL_ENSURE( pNewPgDescFmt || pNewPgDesc, "Neither page desc format nor page desc provided." );
+
+ if ( pNewPgDescFmt )
+ {
+ pSepx->AppendSep( Fc2Cp( nFcPos ), *pNewPgDescFmt, rNd, pFmt, nLnNm );
+ }
+ else if ( pNewPgDesc )
+ {
+ pSepx->AppendSep( Fc2Cp( nFcPos ), pNewPgDesc, rNd, pFmt, nLnNm );
+ }
+}
+
+void MSWordExportBase::CorrectTabStopInSet( SfxItemSet& rSet, sal_uInt16 nAbsLeft )
+{
+ const SvxTabStopItem *pItem =
+ sw::util::HasItem<SvxTabStopItem>( rSet, RES_PARATR_TABSTOP );
+
+ if ( pItem )
+ {
+ // dann muss das fuer die Ausgabe korrigiert werden
+ SvxTabStopItem aTStop(*pItem);
+ for ( sal_uInt16 nCnt = 0; nCnt < aTStop.Count(); ++nCnt )
+ {
+ SvxTabStop& rTab = (SvxTabStop&)aTStop[ nCnt ];
+ if ( SVX_TAB_ADJUST_DEFAULT != rTab.GetAdjustment() &&
+ rTab.GetTabPos() >= nAbsLeft )
+ {
+ rTab.GetTabPos() -= nAbsLeft;
+ }
+ else
+ {
+ aTStop.Remove( nCnt );
+ --nCnt;
+ }
+ }
+ rSet.Put( aTStop );
+ }
+}
+
+sal_uInt8 WW8Export::GetNumId( sal_uInt16 eNumType )
+{
+ sal_uInt8 nRet = 0;
+ switch( eNumType )
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ case SVX_NUM_CHARS_UPPER_LETTER_N: nRet = 3; break;
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ case SVX_NUM_CHARS_LOWER_LETTER_N: nRet = 4; break;
+ case SVX_NUM_ROMAN_UPPER: nRet = 1; break;
+ case SVX_NUM_ROMAN_LOWER: nRet = 2; break;
+
+ case SVX_NUM_BITMAP:
+ case SVX_NUM_CHAR_SPECIAL: nRet = 23; break;
+
+ // nix, macht WW undokumentiert auch so
+ case SVX_NUM_NUMBER_NONE: nRet = 0xff; break;
+ }
+ return nRet;
+}
+
+void WW8AttributeOutput::OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt &rNFmt, const SwFmt &rFmt )
+{
+ if ( nLvl >= WW8ListManager::nMaxLevel )
+ nLvl = WW8ListManager::nMaxLevel-1;
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ // write sprmPOutLvl sprmPIlvl and sprmPIlfo
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_POutLvl );
+ m_rWW8Export.pO->Insert( nLvl, m_rWW8Export.pO->Count() );
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_PIlvl );
+ m_rWW8Export.pO->Insert( nLvl, m_rWW8Export.pO->Count() );
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_PIlfo );
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO,
+ 1 + m_rWW8Export.GetId( *m_rWW8Export.pDoc->GetOutlineNumRule() ) );
+ }
+ else
+ {
+ m_rWW8Export.Out_SwNumLvl( nLvl );
+ if ( rNFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION &&
+ rNFmt.GetAbsLSpace() )
+ {
+ SwNumFmt aNumFmt( rNFmt );
+ const SvxLRSpaceItem& rLR =
+ ItemGet<SvxLRSpaceItem>( rFmt, RES_LR_SPACE );
+
+ aNumFmt.SetAbsLSpace( writer_cast<short>(
+ aNumFmt.GetAbsLSpace() + rLR.GetLeft() ) );
+ m_rWW8Export.Out_NumRuleAnld(
+ *m_rWW8Export.pDoc->GetOutlineNumRule(),
+ aNumFmt, nLvl );
+ }
+ else
+ m_rWW8Export.Out_NumRuleAnld(
+ *m_rWW8Export.pDoc->GetOutlineNumRule(),
+ rNFmt, nLvl );
+ }
+}
+
+// #i77805#
+bool WW8Export::DisallowInheritingOutlineNumbering(const SwFmt &rFmt)
+{
+ bool bRet( false );
+
+ //If there is no numbering on this fmt, but its parent was outline
+ //numbered, then in writer this is no inheritied, but in word it would
+ //be, so we must export "no numbering" and "body level" to make word
+ //behave like writer (see #i25755)
+ if (SFX_ITEM_SET != rFmt.GetItemState(RES_PARATR_NUMRULE, false))
+ {
+ if (const SwFmt *pParent = rFmt.DerivedFrom())
+ {
+ if (((const SwTxtFmtColl*)pParent)->IsAssignedToListLevelOfOutlineStyle())
+ {
+ if (bWrtWW8)
+ {
+ SwWW8Writer::InsUInt16(*pO, NS_sprm::LN_POutLvl);
+ pO->Insert(sal_uInt8(9), pO->Count());
+ SwWW8Writer::InsUInt16(*pO, NS_sprm::LN_PIlfo);
+ SwWW8Writer::InsUInt16(*pO, 0);
+
+ bRet = true;
+ }
+ /*whats the winword 6 way to do this ?*/
+ }
+ }
+ }
+
+ return bRet;
+}
+// <--
+
+void MSWordExportBase::OutputFormat( const SwFmt& rFmt, bool bPapFmt, bool bChpFmt, bool bFlyFmt )
+{
+ bool bCallOutSet = true;
+ const SwModify* pOldMod = pOutFmtNode;
+ pOutFmtNode = &rFmt;
+
+ switch( rFmt.Which() )
+ {
+ case RES_CONDTXTFMTCOLL:
+ case RES_TXTFMTCOLL:
+ if( bPapFmt )
+ {
+ if (((const SwTxtFmtColl&)rFmt).IsAssignedToListLevelOfOutlineStyle())
+ {
+ int nLvl = ((const SwTxtFmtColl&)rFmt).GetAssignedOutlineStyleLevel();
+
+ //if outline numbered
+ // if Write StyleDefinition then write the OutlineRule
+ const SwNumFmt& rNFmt = pDoc->GetOutlineNumRule()->Get( static_cast<sal_uInt16>( nLvl ) );
+ if ( bStyDef )
+ AttrOutput().OutlineNumbering( static_cast< sal_uInt8 >( nLvl ), rNFmt, rFmt );
+
+ if ( rNFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION &&
+ rNFmt.GetAbsLSpace() )
+ {
+ SfxItemSet aSet( rFmt.GetAttrSet() );
+ SvxLRSpaceItem aLR(
+ ItemGet<SvxLRSpaceItem>(aSet, RES_LR_SPACE));
+
+ aLR.SetTxtLeft( aLR.GetTxtLeft() + rNFmt.GetAbsLSpace() );
+ aLR.SetTxtFirstLineOfst( GetWordFirstLineOffset(rNFmt));
+
+ aSet.Put( aLR );
+ CorrectTabStopInSet( aSet, rNFmt.GetAbsLSpace() );
+ OutputItemSet( aSet, bPapFmt, bChpFmt,
+ i18n::ScriptType::LATIN, mbExportModeRTF);
+ bCallOutSet = false;
+ }
+ }
+ else
+ {
+ //otherwise we might have to remove outline numbering from
+ //what gets exported if the parent style was outline numbered
+ // #i77805#
+ // If inherited outline numbering is suppress, the left/right
+ // margins has to be exported explicitly.
+ if ( bStyDef && DisallowInheritingOutlineNumbering(rFmt) )
+ {
+ SfxItemSet aSet( rFmt.GetAttrSet() );
+ SvxLRSpaceItem aLR(
+ ItemGet<SvxLRSpaceItem>(aSet, RES_LR_SPACE));
+ aSet.Put( aLR );
+ OutputItemSet( aSet, bPapFmt, bChpFmt,
+ com::sun::star::i18n::ScriptType::LATIN, mbExportModeRTF);
+ bCallOutSet = false;
+ }
+ // <--
+ }
+ }
+ break;
+
+ case RES_CHRFMT:
+ break;
+ case RES_FLYFRMFMT:
+ if (bFlyFmt)
+ {
+ OSL_ENSURE(mpParentFrame, "No parent frame, all broken");
+
+ if (mpParentFrame)
+ {
+ const SwFrmFmt &rFrmFmt = mpParentFrame->GetFrmFmt();
+
+ SfxItemSet aSet(pDoc->GetAttrPool(), RES_FRMATR_BEGIN,
+ RES_FRMATR_END-1);
+ aSet.Set(rFrmFmt.GetAttrSet());
+
+ // Fly als Zeichen werden bei uns zu Absatz-gebundenen
+ // jetzt den Abstand vom Absatz-Rand setzen
+ if (pFlyOffset)
+ {
+ aSet.Put(SwFmtHoriOrient(pFlyOffset->X()));
+ aSet.Put(SwFmtVertOrient(pFlyOffset->Y()));
+ SwFmtAnchor aAnchor(rFrmFmt.GetAnchor());
+ aAnchor.SetType(eNewAnchorType);
+ aSet.Put(aAnchor);
+ }
+
+ if (SFX_ITEM_SET != aSet.GetItemState(RES_SURROUND))
+ aSet.Put(SwFmtSurround(SURROUND_NONE));
+
+ bOutFlyFrmAttrs = true;
+ //script doesn't matter if not exporting chp
+ OutputItemSet(aSet, true, false,
+ i18n::ScriptType::LATIN, mbExportModeRTF);
+ bOutFlyFrmAttrs = false;
+
+ bCallOutSet = false;
+ }
+ }
+ break;
+ default:
+ OSL_ENSURE( !this, "Was wird hier ausgegeben ??? " );
+ break;
+ }
+
+ if( bCallOutSet )
+ OutputItemSet( rFmt.GetAttrSet(), bPapFmt, bChpFmt,
+ i18n::ScriptType::LATIN, mbExportModeRTF);
+ pOutFmtNode = pOldMod;
+}
+
+bool MSWordExportBase::HasRefToObject( sal_uInt16 nTyp, const String* pName, sal_uInt16 nSeqNo )
+{
+ const SwTxtNode* pNd;
+
+ SwFieldType* pType = pDoc->GetSysFldType( RES_GETREFFLD );
+ SwIterator<SwFmtFld, SwFieldType> aFmtFlds( *pType );
+ for ( SwFmtFld* pFld = aFmtFlds.First(); pFld; pFld = aFmtFlds.Next() )
+ {
+ if ( pFld->GetTxtFld() && nTyp == pFld->GetFld()->GetSubType() &&
+ 0 != ( pNd = pFld->GetTxtFld()->GetpTxtNode() ) &&
+ pNd->GetNodes().IsDocNodes() )
+ {
+ const SwGetRefField& rRFld = *static_cast< SwGetRefField* >( pFld->GetFld() );
+ switch ( nTyp )
+ {
+ case REF_BOOKMARK:
+ case REF_SETREFATTR:
+ if ( pName && *pName == rRFld.GetSetRefName() )
+ return true;
+ break;
+ case REF_FOOTNOTE:
+ case REF_ENDNOTE:
+ if ( nSeqNo == rRFld.GetSeqNo() )
+ return true;
+ break;
+ case REF_SEQUENCEFLD:
+ break; // ???
+ case REF_OUTLINE:
+ break; // ???
+ }
+ }
+ }
+
+ return false;
+}
+
+String MSWordExportBase::GetBookmarkName( sal_uInt16 nTyp, const String* pName, sal_uInt16 nSeqNo )
+{
+ String sRet;
+ switch ( nTyp )
+ {
+ case REF_SETREFATTR:
+ if ( pName )
+ {
+ sRet.APPEND_CONST_ASC( "Ref_" );
+ sRet += *pName;
+ }
+ break;
+ case REF_SEQUENCEFLD:
+ break; // ???
+ case REF_BOOKMARK:
+ if ( pName )
+ sRet = *pName;
+ break;
+ case REF_OUTLINE:
+ break; // ???
+ case REF_FOOTNOTE:
+ sRet.APPEND_CONST_ASC( "_RefF" );
+ sRet += String::CreateFromInt32( nSeqNo );
+ break;
+ case REF_ENDNOTE:
+ sRet.APPEND_CONST_ASC( "_RefE" );
+ sRet += String::CreateFromInt32( nSeqNo );
+ break;
+ }
+ return BookmarkToWord( sRet ); // #i43956# - encode bookmark accordingly
+}
+
+//-----------------------------------------------------------------------
+/* */
+/* File CHRATR.HXX: */
+void WW8AttributeOutput::RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript )
+{
+ if ( m_rWW8Export.bWrtWW8 && bIsRTL )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CFBiDi );
+ m_rWW8Export.pO->Insert( (sal_uInt8)1, m_rWW8Export.pO->Count() );
+ }
+
+ // #i46087# patch from james_clark; complex texts needs the undocumented SPRM CComplexScript with param 0x81.
+ if ( m_rWW8Export.bWrtWW8 && nScript == i18n::ScriptType::COMPLEX && !bIsRTL )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CComplexScript );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x81, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pDop->bUseThaiLineBreakingRules = true;
+ }
+}
+
+void WW8AttributeOutput::EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner )
+{
+ m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() );
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // delete
+
+ if ( pTextNodeInfoInner.get() != NULL )
+ {
+ if ( pTextNodeInfoInner->isEndOfLine() )
+ {
+ TableRowEnd( pTextNodeInfoInner->getDepth() );
+
+ SVBT16 nSty;
+ ShortToSVBT16( 0, nSty );
+ m_rWW8Export.pO->Insert( (sal_uInt8*)&nSty, 2, m_rWW8Export.pO->Count() ); // Style #
+ TableInfoRow( pTextNodeInfoInner );
+ m_rWW8Export.pPapPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(), m_rWW8Export.pO->Count(),
+ m_rWW8Export.pO->GetData() );
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // delete
+ }
+ }
+}
+
+void WW8AttributeOutput::StartRunProperties()
+{
+ WW8_WrPlcFld* pCurrentFields = m_rWW8Export.CurrentFieldPlc();
+ m_nFieldResults = pCurrentFields ? pCurrentFields->ResultCount() : 0;
+}
+
+
+void WW8AttributeOutput::StartRun( const SwRedlineData* pRedlineData )
+{
+ if (pRedlineData)
+ {
+ const String &rComment = pRedlineData->GetComment();
+ //Only possible to export to main text
+ if (rComment.Len() && (m_rWW8Export.nTxtTyp == TXT_MAINTEXT))
+ {
+ if (m_rWW8Export.pAtn->IsNewRedlineComment(pRedlineData))
+ {
+ m_rWW8Export.pAtn->Append( m_rWW8Export.Fc2Cp( m_rWW8Export.Strm().Tell() ), pRedlineData );
+ m_rWW8Export.WritePostItBegin( m_rWW8Export.pO );
+ }
+ }
+ }
+}
+
+void WW8AttributeOutput::EndRunProperties( const SwRedlineData* pRedlineData )
+{
+ Redline( pRedlineData );
+
+ WW8_WrPlcFld* pCurrentFields = m_rWW8Export.CurrentFieldPlc();
+ sal_uInt16 nNewFieldResults = pCurrentFields ? pCurrentFields->ResultCount() : 0;
+
+ bool bExportedFieldResult = ( m_nFieldResults != nNewFieldResults );
+
+ // If we have exported a field result, then we will have been forced to
+ // split up the text into a 0x13, 0x14, <result> 0x15 sequence with the
+ // properties forced out at the end of the result, so the 0x15 itself
+ // should remain clean of all other attributes to avoid #iXXXXX#
+ if ( !bExportedFieldResult )
+ {
+ m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(),
+ m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() );
+ }
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // delete
+}
+
+void WW8AttributeOutput::RunText( const String& rText, rtl_TextEncoding eCharSet )
+{
+ RawText( rText, m_rWW8Export.bWrtWW8, eCharSet );
+}
+
+void WW8AttributeOutput::RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet )
+{
+ m_rWW8Export.OutSwString( rText, 0, rText.Len(), bForceUnicode, eCharSet );
+}
+
+void WW8AttributeOutput::OutputFKP()
+{
+ if ( m_rWW8Export.pO->Count() )
+ {
+ m_rWW8Export.pChpPlc->AppendFkpEntry( m_rWW8Export.Strm().Tell(),
+ m_rWW8Export.pO->Count(), m_rWW8Export.pO->GetData() );
+ m_rWW8Export.pO->Remove( 0, m_rWW8Export.pO->Count() ); // delete
+ }
+}
+
+void WW8AttributeOutput::ParagraphStyle( sal_uInt16 nStyle )
+{
+ OSL_ENSURE( !m_rWW8Export.pO->Count(), " pO ist am ZeilenEnde nicht leer" );
+
+ SVBT16 nSty;
+ ShortToSVBT16( nStyle, nSty );
+ m_rWW8Export.pO->Insert( (sal_uInt8*)&nSty, 2, m_rWW8Export.pO->Count() ); // Style #
+}
+
+void WW8AttributeOutput::OutputWW8Attribute( sal_uInt8 nId, bool bVal )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( 8 == nId ? NS_sprm::LN_CFDStrike : NS_sprm::LN_CFBold + nId );
+ else if (8 == nId )
+ return; // no such attribute in WW6
+ else
+ m_rWW8Export.pO->Insert( 85 + nId, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.pO->Insert( bVal ? 1 : 0, m_rWW8Export.pO->Count() );
+}
+
+void WW8AttributeOutput::OutputWW8AttributeCTL( sal_uInt8 nId, bool bVal )
+{
+ OSL_ENSURE( nId <= 1, "out of range" );
+ if ( !m_rWW8Export.bWrtWW8 || nId > 1 )
+ return;
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CFBoldBi + nId );
+ m_rWW8Export.pO->Insert( bVal ? 1 : 0, m_rWW8Export.pO->Count() );
+}
+
+void WW8AttributeOutput::CharFont( const SvxFontItem& rFont )
+{
+ sal_uInt16 nFontID = m_rWW8Export.GetId( rFont );
+
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc0 );
+ m_rWW8Export.InsUInt16( nFontID );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc2 );
+ }
+ else
+ m_rWW8Export.pO->Insert( 93, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( nFontID );
+}
+
+void WW8AttributeOutput::CharFontCTL( const SvxFontItem& rFont )
+{
+ //Can only export in 8+, in 7- export as normal varient and expect that
+ //upperlevel code has blocked exporting clobbering attributes
+ sal_uInt16 nFontID = m_rWW8Export.GetId( rFont );
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CFtcBi );
+ else
+ m_rWW8Export.pO->Insert( 93, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( nFontID );
+}
+
+void WW8AttributeOutput::CharFontCJK( const SvxFontItem& rFont )
+{
+ //Can only export in 8+, in 7- export as normal varient and expect that
+ //upperlevel code has blocked exporting clobbering attributes
+ sal_uInt16 nFontID = m_rWW8Export.GetId( rFont );
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CRgFtc1 );
+ else
+ m_rWW8Export.pO->Insert( 93, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( nFontID );
+}
+
+void WW8AttributeOutput::CharWeightCTL( const SvxWeightItem& rWeight )
+{
+ //Can only export in 8+, in 7- export as normal varient and expect that
+ //upperlevel code has blocked exporting clobbering attributes
+ if (m_rWW8Export.bWrtWW8)
+ {
+ OutputWW8AttributeCTL( 0, WEIGHT_BOLD == rWeight.GetWeight());
+ }
+ else
+ {
+ OutputWW8Attribute( 0, WEIGHT_BOLD == rWeight.GetWeight());
+ }
+}
+
+void WW8AttributeOutput::CharPostureCTL( const SvxPostureItem& rPosture )
+{
+ // Can only export in 8+, in 7- export as normal varient and expect that
+ // upperlevel code has blocked exporting clobbering attributes
+ if (m_rWW8Export.bWrtWW8)
+ {
+ OutputWW8AttributeCTL( 1, ITALIC_NONE != rPosture.GetPosture() );
+ }
+ else
+ {
+ OutputWW8Attribute( 1, ITALIC_NONE != rPosture.GetPosture() );
+ }
+}
+
+void WW8AttributeOutput::CharPosture( const SvxPostureItem& rPosture )
+{
+ OutputWW8Attribute( 1, ITALIC_NONE != rPosture.GetPosture() );
+}
+
+void WW8AttributeOutput::CharWeight( const SvxWeightItem& rWeight )
+{
+ OutputWW8Attribute( 0, WEIGHT_BOLD == rWeight.GetWeight() );
+}
+
+// Shadowed und Contour are not in WW-UI. JP: ??
+void WW8AttributeOutput::CharContour( const SvxContourItem& rContour )
+{
+ OutputWW8Attribute( 3, rContour.GetValue() ? true : false);
+}
+
+void WW8AttributeOutput::CharShadow( const SvxShadowedItem& rShadow )
+{
+ OutputWW8Attribute( 4, rShadow.GetValue() ? true : false);
+}
+
+void WW8AttributeOutput::CharKerning( const SvxKerningItem& rKerning )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CDxaSpace );
+ else
+ m_rWW8Export.pO->Insert( 96, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( rKerning.GetValue() );
+}
+
+void WW8AttributeOutput::CharAutoKern( const SvxAutoKernItem& rAutoKern )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CHpsKern );
+ else
+ m_rWW8Export.pO->Insert( 107, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( rAutoKern.GetValue() ? 1 : 0 );
+}
+
+void WW8AttributeOutput::CharAnimatedText( const SvxBlinkItem& rBlink )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CSfxText );
+ // At the moment the only animated text effect we support is blinking
+ m_rWW8Export.InsUInt16( rBlink.GetValue() ? 2 : 0 );
+ }
+}
+
+void WW8AttributeOutput::CharCrossedOut( const SvxCrossedOutItem& rCrossed )
+{
+ FontStrikeout eSt = rCrossed.GetStrikeout();
+ if ( STRIKEOUT_DOUBLE == eSt )
+ {
+ OutputWW8Attribute( 8, true );
+ return;
+ }
+ if ( STRIKEOUT_NONE != eSt )
+ {
+ OutputWW8Attribute( 2, true );
+ return;
+ }
+
+ // otherwise both off
+ OutputWW8Attribute( 8, false );
+ OutputWW8Attribute( 2, false );
+}
+
+void WW8AttributeOutput::CharCaseMap( const SvxCaseMapItem& rCaseMap )
+{
+ sal_uInt16 eSt = rCaseMap.GetValue();
+ switch ( eSt )
+ {
+ case SVX_CASEMAP_KAPITAELCHEN:
+ OutputWW8Attribute( 5, true );
+ return;
+ case SVX_CASEMAP_VERSALIEN:
+ OutputWW8Attribute( 6, true );
+ return;
+ case SVX_CASEMAP_TITEL:
+ // no such feature in word
+ break;
+ default:
+ // otherwise both off
+ OutputWW8Attribute( 5, false );
+ OutputWW8Attribute( 6, false );
+ return;
+ }
+}
+
+void WW8AttributeOutput::CharHidden( const SvxCharHiddenItem& rHidden )
+{
+ OutputWW8Attribute( 7, rHidden.GetValue() );
+}
+
+void WW8AttributeOutput::CharUnderline( const SvxUnderlineItem& rUnderline )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CKul );
+ else
+ m_rWW8Export.pO->Insert( 94, m_rWW8Export.pO->Count() );
+
+ const SfxPoolItem* pItem = m_rWW8Export.HasItem( RES_CHRATR_WORDLINEMODE );
+ bool bWord = false;
+ if (pItem)
+ bWord = ((const SvxWordLineModeItem*)pItem)->GetValue() ? true : false;
+
+ // WW95 - parameters: 0 = none, 1 = single, 2 = by Word,
+ // 3 = double, 4 = dotted, 5 = hidden
+ // WW97 - additional parameters:
+ // 6 = thick, 7 = dash, 8 = dot(not used)
+ // 9 = dotdash 10 = dotdotdash, 11 = wave
+ sal_uInt8 b = 0;
+ switch ( rUnderline.GetLineStyle() )
+ {
+ case UNDERLINE_SINGLE:
+ b = ( bWord ) ? 2 : 1;
+ break;
+ case UNDERLINE_BOLD:
+ b = m_rWW8Export.bWrtWW8 ? 6 : 1;
+ break;
+ case UNDERLINE_DOUBLE:
+ b = 3;
+ break;
+ case UNDERLINE_DOTTED:
+ b = 4;
+ break;
+ case UNDERLINE_DASH:
+ b = m_rWW8Export.bWrtWW8 ? 7 : 4;
+ break;
+ case UNDERLINE_DASHDOT:
+ b = m_rWW8Export.bWrtWW8 ? 9 : 4;
+ break;
+ case UNDERLINE_DASHDOTDOT:
+ b = m_rWW8Export.bWrtWW8 ? 10 : 4;
+ break;
+ case UNDERLINE_WAVE:
+ b = m_rWW8Export.bWrtWW8 ? 11 : 3;
+ break;
+ // ------------ new in WW2000 -------------------------------------
+ case UNDERLINE_BOLDDOTTED:
+ b = m_rWW8Export.bWrtWW8 ? 20 : 4;
+ break;
+ case UNDERLINE_BOLDDASH:
+ b = m_rWW8Export.bWrtWW8 ? 23 : 4;
+ break;
+ case UNDERLINE_LONGDASH:
+ b = m_rWW8Export.bWrtWW8 ? 39 : 4;
+ break;
+ case UNDERLINE_BOLDLONGDASH:
+ b = m_rWW8Export.bWrtWW8 ? 55 : 4;
+ break;
+ case UNDERLINE_BOLDDASHDOT:
+ b = m_rWW8Export.bWrtWW8 ? 25 : 4;
+ break;
+ case UNDERLINE_BOLDDASHDOTDOT:
+ b = m_rWW8Export.bWrtWW8 ? 26 : 4;
+ break;
+ case UNDERLINE_BOLDWAVE:
+ b = m_rWW8Export.bWrtWW8 ? 27 : 3;
+ break;
+ case UNDERLINE_DOUBLEWAVE:
+ b = m_rWW8Export.bWrtWW8 ? 43 : 3;
+ break;
+ case UNDERLINE_NONE:
+ b = 0;
+ break;
+ default:
+ OSL_ENSURE( rUnderline.GetLineStyle() == UNDERLINE_NONE, "Unhandled underline type" );
+ break;
+ }
+
+ m_rWW8Export.pO->Insert( b, m_rWW8Export.pO->Count() );
+}
+
+void WW8AttributeOutput::CharLanguage( const SvxLanguageItem& rLanguage )
+{
+ sal_uInt16 nId = 0;
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ switch ( rLanguage.Which() )
+ {
+ case RES_CHRATR_LANGUAGE:
+ nId = NS_sprm::LN_CRgLid0_80;
+ break;
+ case RES_CHRATR_CJK_LANGUAGE:
+ nId = NS_sprm::LN_CRgLid1_80;
+ break;
+ case RES_CHRATR_CTL_LANGUAGE:
+ nId = NS_sprm::LN_CLidBi;
+ break;
+ }
+ }
+ else
+ nId = 97;
+
+ if ( nId )
+ {
+ if ( m_rWW8Export.bWrtWW8 ) // use sprmCRgLid0_80 rather than sprmCLid
+ m_rWW8Export.InsUInt16( nId );
+ else
+ m_rWW8Export.pO->Insert( (sal_uInt8)nId, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( rLanguage.GetLanguage() );
+
+ // Word 2000 and above apparently require both old and new versions of
+ // these sprms to be set, without it spellchecking doesn't work
+ if ( nId == NS_sprm::LN_CRgLid0_80 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CRgLid0 );
+ m_rWW8Export.InsUInt16( rLanguage.GetLanguage() );
+ }
+ else if ( nId == NS_sprm::LN_CRgLid1_80 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CRgLid1 );
+ m_rWW8Export.InsUInt16( rLanguage.GetLanguage() );
+ }
+ }
+}
+
+void WW8AttributeOutput::CharEscapement( const SvxEscapementItem& rEscapement )
+{
+ sal_uInt8 b = 0xFF;
+ short nEsc = rEscapement.GetEsc(), nProp = rEscapement.GetProp();
+ if ( !nEsc )
+ {
+ b = 0;
+ nEsc = 0;
+ nProp = 100;
+ }
+ else if ( DFLT_ESC_PROP == nProp )
+ {
+ if ( DFLT_ESC_SUB == nEsc || DFLT_ESC_AUTO_SUB == nEsc )
+ b = 2;
+ else if ( DFLT_ESC_SUPER == nEsc || DFLT_ESC_AUTO_SUPER == nEsc )
+ b = 1;
+ }
+
+ if ( 0xFF != b )
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CIss );
+ else
+ m_rWW8Export.pO->Insert( 104, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.pO->Insert( b, m_rWW8Export.pO->Count() );
+ }
+
+ if ( 0 == b || 0xFF == b )
+ {
+ long nHeight = ((SvxFontHeightItem&)m_rWW8Export.GetItem(
+ RES_CHRATR_FONTSIZE )).GetHeight();
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CHpsPos );
+ else
+ m_rWW8Export.pO->Insert( 101, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( (short)(( nHeight * nEsc + 500 ) / 1000 ));
+
+ if( 100 != nProp || !b )
+ {
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CHps );
+ else
+ m_rWW8Export.pO->Insert( 99, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16(
+ msword_cast<sal_uInt16>((nHeight * nProp + 500 ) / 1000));
+ }
+ }
+}
+
+void WW8AttributeOutput::CharFontSize( const SvxFontHeightItem& rHeight )
+{
+ sal_uInt16 nId = 0;
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ switch ( rHeight.Which() )
+ {
+ case RES_CHRATR_FONTSIZE:
+ case RES_CHRATR_CJK_FONTSIZE:
+ nId = NS_sprm::LN_CHps;
+ break;
+ case RES_CHRATR_CTL_FONTSIZE:
+ nId = NS_sprm::LN_CHpsBi;
+ break;
+ }
+ }
+ else
+ nId = 99;
+
+ if ( nId )
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( nId );
+ else
+ m_rWW8Export.pO->Insert( (sal_uInt8)nId, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( (sal_uInt16)(( rHeight.GetHeight() + 5 ) / 10 ) );
+ }
+}
+
+void WW8AttributeOutput::CharScaleWidth( const SvxCharScaleWidthItem& rScaleWidth )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CCharScale );
+ m_rWW8Export.InsUInt16( rScaleWidth.GetValue() );
+ }
+}
+
+void WW8AttributeOutput::CharRelief( const SvxCharReliefItem& rRelief )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ sal_uInt16 nId;
+ switch ( rRelief.GetValue() )
+ {
+ case RELIEF_EMBOSSED: nId = NS_sprm::LN_CFEmboss; break;
+ case RELIEF_ENGRAVED: nId = NS_sprm::LN_CFImprint; break;
+ default: nId = 0; break;
+ }
+
+ if( nId )
+ {
+ m_rWW8Export.InsUInt16( nId );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x81, m_rWW8Export.pO->Count() );
+ }
+ else
+ {
+ // switch both flags off
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CFEmboss );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x0, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CFImprint );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x0, m_rWW8Export.pO->Count() );
+ }
+ }
+}
+
+void WW8AttributeOutput::CharRotate( const SvxCharRotateItem& rRotate )
+{
+ // #i28331# - check that a Value is set
+ if ( !rRotate.GetValue() )
+ return;
+
+ if ( m_rWW8Export.bWrtWW8 && !m_rWW8Export.bIsInTable )
+ {
+ // #i36867 In word the text in a table is rotated via the TC or NS_sprm::LN_TTextFlow
+ // This means you can only rotate all or none of the text adding NS_sprm::LN_CEastAsianLayout
+ // here corrupts the table, hence !m_rWW8Export.bIsInTable
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CEastAsianLayout );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x06, m_rWW8Export.pO->Count() ); //len 6
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x01, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( rRotate.IsFitToLine() ? 1 : 0 );
+ static const sal_uInt8 aZeroArr[ 3 ] = { 0, 0, 0 };
+ m_rWW8Export.pO->Insert( aZeroArr, 3, m_rWW8Export.pO->Count() );
+ }
+}
+
+void WW8AttributeOutput::CharEmphasisMark( const SvxEmphasisMarkItem& rEmphasisMark )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ sal_uInt8 nVal;
+ switch ( rEmphasisMark.GetValue() )
+ {
+ case EMPHASISMARK_NONE: nVal = 0; break;
+ case EMPHASISMARK_SIDE_DOTS: nVal = 2; break;
+ case EMPHASISMARK_CIRCLE_ABOVE: nVal = 3; break;
+ case EMPHASISMARK_DOTS_BELOW: nVal = 4; break;
+ // case 1:
+ default: nVal = 1; break;
+ }
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CKcd );
+ m_rWW8Export.pO->Insert( nVal, m_rWW8Export.pO->Count() );
+ }
+}
+
+// TransCol uebersetzt SW-Farben in WW. Heraus kommt die bei WW fuer
+// Text- und Hintergrundfarbe benutzte Codierung.
+// Gibt es keine direkte Entsprechung, dann wird versucht, eine moeglichst
+// aehnliche WW-Farbe zu finden.
+// return: 5-Bit-Wert ( 0..16 )
+sal_uInt8 WW8Export::TransCol( const Color& rCol )
+{
+ sal_uInt8 nCol = 0; // ->Auto
+ switch( rCol.GetColor() )
+ {
+ case COL_BLACK: nCol = 1; break;
+ case COL_BLUE: nCol = 9; break;
+ case COL_GREEN: nCol = 11; break;
+ case COL_CYAN: nCol = 10; break;
+ case COL_RED: nCol = 13; break;
+ case COL_MAGENTA: nCol = 12; break;
+ case COL_BROWN: nCol = 14; break;
+ case COL_GRAY: nCol = 15; break;
+ case COL_LIGHTGRAY: nCol = 16; break;
+ case COL_LIGHTBLUE: nCol = 2; break;
+ case COL_LIGHTGREEN: nCol = 4; break;
+ case COL_LIGHTCYAN: nCol = 3; break;
+ case COL_LIGHTRED: nCol = 6; break;
+ case COL_LIGHTMAGENTA: nCol = 5; break;
+ case COL_YELLOW: nCol = 7; break;
+ case COL_WHITE: nCol = 8; break;
+ case COL_AUTO: nCol = 0; break;
+
+ default:
+ if( !pBmpPal )
+ {
+ pBmpPal = new BitmapPalette( 16 );
+ static const ColorData aColArr[ 16 ] = {
+ COL_BLACK, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_LIGHTGREEN,
+ COL_LIGHTMAGENTA,COL_LIGHTRED, COL_YELLOW, COL_WHITE,
+ COL_BLUE, COL_CYAN, COL_GREEN, COL_MAGENTA,
+ COL_RED, COL_BROWN, COL_GRAY, COL_LIGHTGRAY
+ };
+
+ for( sal_uInt16 i = 0; i < 16; ++i )
+ pBmpPal->operator[]( i ) = Color( aColArr[ i ] );
+ }
+ nCol = static_cast< sal_uInt8 >(pBmpPal->GetBestIndex( rCol ) + 1);
+ break;
+ }
+ return nCol;
+}
+
+// TransBrush uebersetzt SW-Brushes in WW. Heraus kommt WW8_SHD.
+// Nicht-Standardfarben des SW werden noch nicht in die
+// Misch-Werte ( 0 .. 95% ) vom WW uebersetzt.
+// Return: Echte Brush ( nicht transparent )
+// auch bei Transparent wird z.B. fuer Tabellen eine transparente Brush
+// geliefert
+bool WW8Export::TransBrush(const Color& rCol, WW8_SHD& rShd)
+{
+ if( rCol.GetTransparency() )
+ rShd = WW8_SHD(); // alles Nullen : transparent
+ else
+ {
+ rShd.SetFore( 0);
+ rShd.SetBack( TransCol( rCol ) );
+ rShd.SetStyle( bWrtWW8, 0 );
+ }
+ return !rCol.GetTransparency();
+}
+
+sal_uInt32 SuitableBGColor(sal_uInt32 nIn)
+{
+ if (nIn == COL_AUTO)
+ return 0xFF000000;
+ return wwUtility::RGBToBGR(nIn);
+}
+
+void WW8AttributeOutput::CharColor( const SvxColorItem& rColor )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CIco );
+ else
+ m_rWW8Export.pO->Insert( 98, m_rWW8Export.pO->Count() );
+
+ sal_uInt8 nColor = m_rWW8Export.TransCol( rColor.GetValue() );
+ m_rWW8Export.pO->Insert( nColor, m_rWW8Export.pO->Count() );
+
+ if ( m_rWW8Export.bWrtWW8 && nColor )
+ {
+ m_rWW8Export.InsUInt16( 0x6870 );
+ m_rWW8Export.InsUInt32( wwUtility::RGBToBGR( rColor.GetValue().GetColor() ) );
+ }
+}
+
+void WW8AttributeOutput::CharBackground( const SvxBrushItem& rBrush )
+{
+ if( m_rWW8Export.bWrtWW8 ) // nur WW8 kann ZeichenHintergrund
+ {
+ WW8_SHD aSHD;
+
+ m_rWW8Export.TransBrush( rBrush.GetColor(), aSHD );
+ // sprmCShd
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CShd );
+ m_rWW8Export.InsUInt16( aSHD.GetValue() );
+
+ //Quite a few unknowns, some might be transparency or something
+ //of that nature...
+ m_rWW8Export.InsUInt16( 0xCA71 );
+ m_rWW8Export.pO->Insert( 10, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt32( 0xFF000000 );
+ m_rWW8Export.InsUInt32( SuitableBGColor( rBrush.GetColor().GetColor() ) );
+ m_rWW8Export.InsUInt16( 0x0000);
+ }
+}
+
+void WW8AttributeOutput::TextINetFormat( const SwFmtINetFmt& rINet )
+{
+ if ( rINet.GetValue().Len() )
+ {
+ sal_uInt16 nId;
+ const String& rStr = rINet.GetINetFmt();
+ if ( rStr.Len() )
+ nId = rINet.GetINetFmtId();
+ else
+ nId = RES_POOLCHR_INET_NORMAL;
+
+ const SwCharFmt* pFmt = IsPoolUserFmt( nId )
+ ? m_rWW8Export.pDoc->FindCharFmtByName( rStr )
+ : m_rWW8Export.pDoc->GetCharFmtFromPool( nId );
+
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CIstd );
+ else
+ m_rWW8Export.pO->Insert( 80, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *pFmt ) );
+ }
+}
+
+// #i43956# - add optional parameter <pLinkStr>
+// It's needed to write the hyperlink data for a certain cross-reference
+// - it contains the name of the link target, which is a bookmark.
+// add optional parameter <bIncludeEmptyPicLocation>
+// It is needed to write an empty picture location for page number field separators
+static void InsertSpecialChar( WW8Export& rWrt, sal_uInt8 c,
+ String* pLinkStr = 0L,
+ bool bIncludeEmptyPicLocation = false )
+{
+ WW8Bytes aItems;
+ rWrt.GetCurrentItems(aItems);
+
+ if (c == 0x13)
+ rWrt.pChpPlc->AppendFkpEntry(rWrt.Strm().Tell());
+ else
+ rWrt.pChpPlc->AppendFkpEntry(rWrt.Strm().Tell(), aItems.Count(),
+ aItems.GetData());
+
+ rWrt.WriteChar(c);
+
+ // store empty sprmCPicLocation for field separator
+ if ( bIncludeEmptyPicLocation &&
+ ( c == 0x13 || c == 0x14 || c == 0x15 ) )
+ {
+ SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CPicLocation );
+ SwWW8Writer::InsUInt32( aItems, 0x00000000 );
+ }
+
+ // #i43956# - write hyperlink data and attributes
+ if ( rWrt.bWrtWW8 && c == 0x01 && pLinkStr )
+ {
+ // write hyperlink data to data stream
+ SvStream& rStrm = *rWrt.pDataStrm;
+ // position of hyperlink data
+ const sal_uInt32 nLinkPosInDataStrm = rStrm.Tell();
+ // write empty header
+ const sal_uInt16 nEmptyHdrLen = 0x44;
+ sal_uInt8 aEmptyHeader[ nEmptyHdrLen ] = { 0 };
+ aEmptyHeader[ 4 ] = 0x44;
+ rStrm.Write( aEmptyHeader, nEmptyHdrLen );
+ // writer fixed header
+ const sal_uInt16 nFixHdrLen = 0x19;
+ sal_uInt8 aFixHeader[ nFixHdrLen ] =
+ {
+ 0x08, 0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE,
+ 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9,
+ 0x0B, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
+ 0x00,
+ };
+ rStrm.Write( aFixHeader, nFixHdrLen );
+ // write reference string including length+1
+ sal_uInt32 nStrLen( pLinkStr->Len() + 1 );
+ SwWW8Writer::WriteLong( rStrm, nStrLen );
+ SwWW8Writer::WriteString16( rStrm, *(pLinkStr), false );
+ // write additional two NULL Bytes
+ SwWW8Writer::WriteLong( rStrm, 0 );
+ // write length of hyperlink data
+ const sal_uInt32 nCurrPos = rStrm.Tell();
+ rStrm.Seek( nLinkPosInDataStrm );
+ SVBT32 nLen;
+ UInt32ToSVBT32( nCurrPos - nLinkPosInDataStrm, nLen );
+ rStrm.Write( nLen, 4 );
+ rStrm.Seek( nCurrPos );
+
+ // write attributes of hyperlink character 0x01
+ SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFFldVanish );
+ aItems.Insert( (sal_uInt8)0x81, aItems.Count() );
+ SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CPicLocation );
+ SwWW8Writer::InsUInt32( aItems, nLinkPosInDataStrm );
+ SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFData );
+ aItems.Insert( (sal_uInt8)0x01, aItems.Count() );
+ }
+
+ //Technically we should probably Remove all attribs
+ //here for the 0x13, 0x14, 0x15, but our import
+ //is slightly lacking
+ //aItems.Remove(0, aItems.Count());
+ // fSpec-Attribute true
+ if( rWrt.bWrtWW8 )
+ {
+ SwWW8Writer::InsUInt16( aItems, NS_sprm::LN_CFSpec );
+ aItems.Insert( 1, aItems.Count() );
+ }
+ else
+ {
+ aItems.Insert( 117, aItems.Count() ); //sprmCFSpec
+ aItems.Insert( 1, aItems.Count() );
+ }
+
+ rWrt.pChpPlc->AppendFkpEntry(rWrt.Strm().Tell(), aItems.Count(),
+ aItems.GetData());
+}
+
+String lcl_GetExpandedField(const SwField &rFld)
+{
+ String sRet(rFld.ExpandField(true));
+
+ //replace LF 0x0A with VT 0x0B
+ sRet.SearchAndReplaceAll(0x0A, 0x0B);
+
+ return sRet;
+}
+
+WW8_WrPlcFld* WW8Export::CurrentFieldPlc() const
+{
+ WW8_WrPlcFld* pFldP = NULL;
+ switch (nTxtTyp)
+ {
+ case TXT_MAINTEXT:
+ pFldP = pFldMain;
+ break;
+ case TXT_HDFT:
+ pFldP = pFldHdFt;
+ break;
+ case TXT_FTN:
+ pFldP = pFldFtn;
+ break;
+ case TXT_EDN:
+ pFldP = pFldEdn;
+ break;
+ case TXT_ATN:
+ pFldP = pFldAtn;
+ break;
+ case TXT_TXTBOX:
+ pFldP = pFldTxtBxs;
+ break;
+ case TXT_HFTXTBOX:
+ pFldP = pFldHFTxtBxs;
+ break;
+ default:
+ OSL_ENSURE( !this, "was ist das fuer ein SubDoc-Type?" );
+ }
+ return pFldP;
+}
+
+void WW8Export::OutputField( const SwField* pFld, ww::eField eFldType,
+ const String& rFldCmd, sal_uInt8 nMode )
+{
+ bool bUnicode = IsUnicode();
+ WW8_WrPlcFld* pFldP = CurrentFieldPlc();
+
+ const bool bIncludeEmptyPicLocation = ( eFldType == ww::ePAGE );
+
+ if (WRITEFIELD_START & nMode)
+ {
+ sal_uInt8 aFld13[2] = { 0x13, 0x00 }; // will change
+ //#i3958#, Needed to make this field work correctly in Word 2000
+ if (eFldType == ww::eSHAPE)
+ aFld13[0] |= 0x80;
+ aFld13[1] = static_cast< sal_uInt8 >(eFldType); // Typ nachtragen
+ pFldP->Append( Fc2Cp( Strm().Tell() ), aFld13 );
+ InsertSpecialChar( *this, 0x13, 0, bIncludeEmptyPicLocation );
+ }
+ if (WRITEFIELD_CMD_START & nMode)
+ {
+ if (bUnicode)
+ SwWW8Writer::WriteString16(Strm(), rFldCmd, false);
+ else
+ {
+ SwWW8Writer::WriteString8(Strm(), rFldCmd, false,
+ RTL_TEXTENCODING_MS_1252);
+ }
+ // #i43956# - write hyperlink character including
+ // attributes and corresponding binary data for certain reference fields.
+ bool bHandleBookmark = false;
+
+ if (pFld)
+ {
+ if (pFld->GetTyp()->Which() == RES_GETREFFLD &&
+ ( eFldType == ww::ePAGEREF || eFldType == ww::eREF ||
+ eFldType == ww::eNOTEREF || eFldType == ww::eFOOTREF ))
+ bHandleBookmark = true;
+
+ }
+
+ if ( bHandleBookmark )
+ {
+ // retrieve reference destionation - the name of the bookmark
+ String aLinkStr;
+ const sal_uInt16 nSubType = pFld->GetSubType();
+ const SwGetRefField& rRFld = *(static_cast<const SwGetRefField*>(pFld));
+ if ( nSubType == REF_SETREFATTR ||
+ nSubType == REF_BOOKMARK )
+ {
+ aLinkStr = GetBookmarkName( nSubType, &rRFld.GetSetRefName(), 0 );
+ }
+ else if ( nSubType == REF_FOOTNOTE ||
+ nSubType == REF_ENDNOTE )
+ {
+ aLinkStr = GetBookmarkName( nSubType, 0, rRFld.GetSeqNo() );
+ }
+ else if ( nSubType == REF_SEQUENCEFLD )
+ {
+ aLinkStr = pFld->GetPar2();
+ }
+ // insert hyperlink character including attributes and data.
+ InsertSpecialChar( *this, 0x01, &aLinkStr );
+ }
+ // <--
+ }
+ if (WRITEFIELD_CMD_END & nMode)
+ {
+ static const sal_uInt8 aFld14[2] = { 0x14, 0xff };
+ pFldP->Append( Fc2Cp( Strm().Tell() ), aFld14 );
+ pFldP->ResultAdded();
+ InsertSpecialChar( *this, 0x14, 0, bIncludeEmptyPicLocation );
+ }
+ if (WRITEFIELD_END & nMode)
+ {
+ String sOut;
+ if( pFld )
+ sOut = lcl_GetExpandedField(*pFld);
+ else
+ sOut = rFldCmd;
+ if( sOut.Len() )
+ {
+ if( bUnicode )
+ SwWW8Writer::WriteString16(Strm(), sOut, false);
+ else
+ {
+ SwWW8Writer::WriteString8(Strm(), sOut, false,
+ RTL_TEXTENCODING_MS_1252);
+ }
+
+ if (pFld)
+ {
+ if (pFld->GetTyp()->Which() == RES_INPUTFLD &&
+ eFldType == ww::eFORMTEXT)
+ {
+ sal_uInt8 aArr[12];
+ sal_uInt8 *pArr = aArr;
+
+ if ( bWrtWW8 )
+ {
+ Set_UInt16( pArr, NS_sprm::LN_CPicLocation );
+ Set_UInt32( pArr, 0x0 );
+
+ Set_UInt16( pArr, NS_sprm::LN_CFSpec );
+ Set_UInt8( pArr, 1 );
+
+ Set_UInt16( pArr, NS_sprm::LN_CFNoProof );
+ Set_UInt8( pArr, 1 );
+ }
+ else
+ {
+ Set_UInt8(pArr, 0x68); //sprmCPicLocation
+ Set_UInt32(pArr, 0x0);
+
+ Set_UInt8( pArr, 117 ); //sprmCFSpec
+ Set_UInt8( pArr, 1 );
+ }
+ pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
+ }
+ }
+ }
+ }
+ if (WRITEFIELD_CLOSE & nMode)
+ {
+ sal_uInt8 aFld15[2] = { 0x15, 0x80 };
+
+ if (pFld)
+ {
+ if (pFld->GetTyp()->Which() == RES_INPUTFLD &&
+ eFldType == ww::eFORMTEXT)
+ {
+ sal_uInt16 nSubType = pFld->GetSubType();
+
+ if (nSubType == REF_SEQUENCEFLD)
+ aFld15[0] |= (0x4 << 5);
+ }
+ }
+
+ pFldP->Append( Fc2Cp( Strm().Tell() ), aFld15 );
+ InsertSpecialChar( *this, 0x15, 0, bIncludeEmptyPicLocation );
+ }
+}
+
+void WW8Export::StartCommentOutput(const String& rName)
+{
+ String sStr(FieldString(ww::eQUOTE));
+ sStr.APPEND_CONST_ASC("[");
+ sStr += rName;
+ sStr.APPEND_CONST_ASC("] ");
+ OutputField(0, ww::eQUOTE, sStr, WRITEFIELD_START | WRITEFIELD_CMD_START);
+}
+
+void WW8Export::EndCommentOutput(const String& rName)
+{
+ String sStr(CREATE_CONST_ASC(" ["));
+ sStr += rName;
+ sStr.APPEND_CONST_ASC("] ");
+ OutputField(0, ww::eQUOTE, sStr, WRITEFIELD_CMD_END | WRITEFIELD_END |
+ WRITEFIELD_CLOSE);
+}
+
+sal_uInt16 MSWordExportBase::GetId( const SwTOXType& rTOXType )
+{
+ void* p = (void*)&rTOXType;
+ sal_uInt16 nRet = aTOXArr.GetPos( p );
+ if( USHRT_MAX == nRet )
+ aTOXArr.Insert( p, nRet = aTOXArr.Count() );
+ return nRet;
+}
+
+// return values: 1 - no PageNum,
+// 2 - TabStop before PageNum,
+// 3 - Text before PageNum - rTxt hold the text
+// 4 - no Text and no TabStop before PageNum
+int lcl_CheckForm( const SwForm& rForm, sal_uInt8 nLvl, String& rText )
+{
+ int nRet = 4;
+ rText.Erase();
+
+ // #i21237#
+ SwFormTokens aPattern = rForm.GetPattern(nLvl);
+ SwFormTokens::iterator aIt = aPattern.begin();
+ bool bPgNumFnd = false;
+ FormTokenType eTType;
+
+ // #i61362#
+ if (! aPattern.empty())
+ {
+ // #i21237#
+ while( ++aIt != aPattern.end() && !bPgNumFnd )
+ {
+ eTType = aIt->eTokenType;
+
+ switch( eTType )
+ {
+ case TOKEN_PAGE_NUMS:
+ bPgNumFnd = true;
+ break;
+
+ case TOKEN_TAB_STOP:
+ nRet = 2;
+ break;
+ case TOKEN_TEXT:
+ nRet = 3;
+ rText = aIt->sText.Copy( 0, 5 ); // #i21237#
+ break;
+
+ case TOKEN_LINK_START:
+ case TOKEN_LINK_END:
+ break;
+
+ default:
+ nRet = 4;
+ break;
+ }
+ }
+
+ if( !bPgNumFnd )
+ nRet = 1;
+ }
+
+ return nRet;
+}
+
+bool lcl_IsHyperlinked(const SwForm& rForm, sal_uInt16 nTOXLvl)
+{
+ bool bRes = false;
+ for (sal_uInt16 nI = 1; nI < nTOXLvl; ++nI)
+ {
+ // #i21237#
+ SwFormTokens aPattern = rForm.GetPattern(nI);
+
+ if ( !aPattern.empty() )
+ {
+ SwFormTokens::iterator aIt = aPattern.begin();
+
+ FormTokenType eTType;
+
+ // #i21237#
+ while ( ++aIt != aPattern.end() )
+ {
+ eTType = aIt->eTokenType;
+ switch (eTType)
+ {
+ case TOKEN_LINK_START:
+ case TOKEN_LINK_END:
+ bRes = true;
+ break;
+ default:
+ ;
+ }
+ }
+ }
+ }
+ return bRes;
+}
+
+void AttributeOutputBase::StartTOX( const SwSection& rSect )
+{
+ if ( const SwTOXBase* pTOX = rSect.GetTOXBase() )
+ {
+ static const sal_Char sEntryEnd[] = "\" ";
+
+ ww::eField eCode = ww::eTOC;
+ String sStr;
+ switch (pTOX->GetType())
+ {
+ case TOX_INDEX:
+ eCode = ww::eINDEX;
+ sStr = FieldString(eCode);
+
+ if (pTOX->GetTOXForm().IsCommaSeparated())
+ sStr.APPEND_CONST_ASC("\\r ");
+
+ if (nsSwTOIOptions::TOI_ALPHA_DELIMITTER & pTOX->GetOptions())
+ sStr.APPEND_CONST_ASC("\\h \"A\" ");
+
+ {
+ String aFillTxt;
+ for (sal_uInt8 n = 1; n <= 3; ++n)
+ {
+ String aTxt;
+ int nRet = ::lcl_CheckForm(pTOX->GetTOXForm(), n, aTxt);
+
+ if( 3 == nRet )
+ aFillTxt = aTxt;
+ else if ((4 == nRet) || (2 == nRet))
+ aFillTxt = '\t';
+ else
+ aFillTxt.Erase();
+ }
+ sStr.APPEND_CONST_ASC("\\e \"");
+ sStr += aFillTxt;
+ sStr.AppendAscii(sEntryEnd);
+ }
+ break;
+
+ case TOX_ILLUSTRATIONS:
+ case TOX_OBJECTS:
+ case TOX_TABLES:
+ if (!pTOX->IsFromObjectNames())
+ {
+ sStr = FieldString(eCode);
+
+ sStr.APPEND_CONST_ASC("\\c \"");
+ sStr += pTOX->GetSequenceName();
+ sStr.AppendAscii(sEntryEnd);
+
+ String aTxt;
+ int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(), 1, aTxt );
+ if (1 == nRet)
+ sStr.APPEND_CONST_ASC("\\n ");
+ else if( 3 == nRet || 4 == nRet )
+ {
+ sStr.APPEND_CONST_ASC("\\p \"");
+ sStr += aTxt;
+ sStr.AppendAscii(sEntryEnd);
+ }
+ }
+ break;
+
+ default:
+ {
+ sStr = FieldString(eCode);
+
+ String sTOption;
+ sal_uInt16 n, nTOXLvl = pTOX->GetLevel();
+ if( !nTOXLvl )
+ ++nTOXLvl;
+
+ if( nsSwTOXElement::TOX_MARK & pTOX->GetCreateType() )
+ {
+ sStr.APPEND_CONST_ASC( "\\f " );
+
+ if( TOX_USER == pTOX->GetType() )
+ {
+ sStr += '\"';
+ sStr += (sal_Char)( 'A' + GetExport( ).GetId( *pTOX->GetTOXType() ) );
+ sStr.AppendAscii( sEntryEnd );
+ }
+
+ if( nsSwTOXElement::TOX_OUTLINELEVEL & pTOX->GetCreateType() )
+ {
+ const int nMinLvl = nTOXLvl;
+
+ if ( nMinLvl > 0 )
+ {
+ int nTmpLvl = nMinLvl;
+ if (nTmpLvl > WW8ListManager::nMaxLevel)
+ nTmpLvl = WW8ListManager::nMaxLevel;
+
+ sStr.APPEND_CONST_ASC( "\\o \"1-" );
+ sStr += String::CreateFromInt32( nTmpLvl );
+ sStr.AppendAscii(sEntryEnd);
+
+ }
+
+ }
+
+
+ if( nsSwTOXElement::TOX_OUTLINELEVEL & pTOX->GetCreateType() )
+ {
+ // Take the TOC value of the max level to evaluate to as
+ // the starting point for the \o flag, but reduce it to the
+ // value of the highest outline level filled by a *standard*
+ // Heading 1 - 9 style because \o "Builds a table of
+ // contents from paragraphs formatted with built-in heading
+ // styles". And afterward fill in any outline styles left
+ // uncovered by that range to the \t flag
+ //
+ // i.e. for
+ // Heading 1
+ // Heading 2
+ // custom-style
+ // Heading 4
+ // output
+ // \o 1-2 \tcustom-style,3,Heading 3,4
+
+ // Search over all the outline styles used and figure out
+ // what is the minimum outline level (if any) filled by a
+ // non-standard style for that level, i.e. ignore headline
+ // styles 1-9 and find the lowest valid outline level
+ sal_uInt8 nPosOfLowestNonStandardLvl = MAXLEVEL;
+ const SwTxtFmtColls& rColls = *GetExport().pDoc->GetTxtFmtColls();
+ for( n = rColls.Count(); n; )
+ {
+ const SwTxtFmtColl* pColl = rColls[ --n ];
+ sal_uInt16 nPoolId = pColl->GetPoolFmtId();
+ if (
+ //Is a Non-Standard Outline Style
+ (RES_POOLCOLL_HEADLINE1 > nPoolId || RES_POOLCOLL_HEADLINE9 < nPoolId) &&
+ //Has a valid outline level
+ (pColl->IsAssignedToListLevelOfOutlineStyle()) &&
+ // Is less than the lowest known non-standard level
+ (pColl->GetAssignedOutlineStyleLevel() < nPosOfLowestNonStandardLvl)
+ )
+ {
+ nPosOfLowestNonStandardLvl = ::sal::static_int_cast<sal_uInt8>(pColl->GetAssignedOutlineStyleLevel());
+ }
+ }
+
+ sal_uInt8 nMaxMSAutoEvaluate = nPosOfLowestNonStandardLvl < nTOXLvl ? nPosOfLowestNonStandardLvl : (sal_uInt8)nTOXLvl;
+
+ //output \o 1-X where X is the highest normal outline style to be included in the toc
+ if ( nMaxMSAutoEvaluate )
+ {
+ if (nMaxMSAutoEvaluate > WW8ListManager::nMaxLevel)
+ nMaxMSAutoEvaluate = WW8ListManager::nMaxLevel;
+
+ sStr.APPEND_CONST_ASC( "\\o \"1-" );
+ sStr += String::CreateFromInt32( nMaxMSAutoEvaluate );
+ sStr.AppendAscii(sEntryEnd);
+ }
+
+ //collect up any other styles in the writer TOC which will
+ //not already appear in the MS TOC and place then into the
+ //\t option
+ if( nMaxMSAutoEvaluate < nTOXLvl )
+ {
+ // collect this templates into the \t otion
+ for( n = rColls.Count(); n;)
+ {
+ const SwTxtFmtColl* pColl = rColls[ --n ];
+ if (!pColl->IsAssignedToListLevelOfOutlineStyle())
+ continue;
+ sal_uInt8 nTestLvl = ::sal::static_int_cast<sal_uInt8>(pColl->GetAssignedOutlineStyleLevel());
+ if (nTestLvl < nTOXLvl && nTestLvl >= nMaxMSAutoEvaluate)
+ {
+ if( sTOption.Len() )
+ sTOption += ',';
+ (( sTOption += pColl->GetName() ) += ',' )
+ += String::CreateFromInt32( nTestLvl + 1 );
+ }
+ }
+ }
+ }
+
+ if( nsSwTOXElement::TOX_TEMPLATE & pTOX->GetCreateType() )
+ // #i99641# - Consider additional styles regardless of TOX-outlinelevel
+ for( n = 0; n < MAXLEVEL; ++n )
+ {
+ const String& rStyles = pTOX->GetStyleNames( n );
+ if( rStyles.Len() )
+ {
+ xub_StrLen nPos = 0;
+ String sLvl( ',' );
+ sLvl += String::CreateFromInt32( n + 1 );
+ do {
+ String sStyle( rStyles.GetToken( 0,
+ TOX_STYLE_DELIMITER, nPos ));
+ if( sStyle.Len() )
+ {
+ SwTxtFmtColl* pColl = GetExport().pDoc->FindTxtFmtCollByName(sStyle);
+ if (!pColl || !pColl->IsAssignedToListLevelOfOutlineStyle() || pColl->GetAssignedOutlineStyleLevel() < nTOXLvl)
+ {
+ if( sTOption.Len() )
+ sTOption += ',';
+ ( sTOption += sStyle ) += sLvl;
+ }
+ }
+ } while( STRING_NOTFOUND != nPos );
+ }
+ }
+
+ {
+ String aFillTxt;
+ sal_uInt8 nNoPgStt = MAXLEVEL, nNoPgEnd = MAXLEVEL;
+ bool bFirstFillTxt = true, bOnlyText = true;
+ for( n = 0; n < nTOXLvl; ++n )
+ {
+ String aTxt;
+ int nRet = ::lcl_CheckForm( pTOX->GetTOXForm(),
+ static_cast< sal_uInt8 >(n+1), aTxt );
+ if( 1 == nRet )
+ {
+ bOnlyText = false;
+ if( MAXLEVEL == nNoPgStt )
+ nNoPgStt = static_cast< sal_uInt8 >(n+1);
+ }
+ else
+ {
+ if( MAXLEVEL != nNoPgStt &&
+ MAXLEVEL == nNoPgEnd )
+ nNoPgEnd = sal_uInt8(n);
+
+ bOnlyText = bOnlyText && 3 == nRet;
+ if( 3 == nRet || 4 == nRet )
+ {
+ if( bFirstFillTxt )
+ aFillTxt = aTxt;
+ else if( aFillTxt != aTxt )
+ aFillTxt.Erase();
+ bFirstFillTxt = false;
+ }
+ }
+ }
+ if( MAXLEVEL != nNoPgStt )
+ {
+ if (WW8ListManager::nMaxLevel < nNoPgEnd)
+ nNoPgEnd = WW8ListManager::nMaxLevel;
+ sStr.APPEND_CONST_ASC( "\\n " );
+ sStr += String::CreateFromInt32( nNoPgStt );
+ sStr += '-';
+ sStr += String::CreateFromInt32( nNoPgEnd );
+ sStr += ' ';
+ }
+ if( bOnlyText )
+ {
+ sStr.APPEND_CONST_ASC( "\\p \"" );
+ sStr += aFillTxt;
+ sStr.AppendAscii(sEntryEnd);
+ }
+ }
+
+ if( sTOption.Len() )
+ {
+ sStr.APPEND_CONST_ASC( "\\t \"" );
+ sStr += sTOption;
+ sStr.AppendAscii(sEntryEnd);
+ }
+
+ if (lcl_IsHyperlinked(pTOX->GetTOXForm(), nTOXLvl))
+ sStr.APPEND_CONST_ASC("\\h");
+ }
+ break;
+ }
+ }
+
+ if( sStr.Len() )
+ {
+ GetExport( ).bInWriteTOX = true;
+ GetExport( ).OutputField( 0, eCode, sStr, WRITEFIELD_START | WRITEFIELD_CMD_START |
+ WRITEFIELD_CMD_END );
+ }
+ }
+
+ GetExport( ).bStartTOX = false;
+}
+
+void AttributeOutputBase::EndTOX( const SwSection& rSect )
+{
+ const SwTOXBase* pTOX = rSect.GetTOXBase();
+ if ( pTOX )
+ {
+ ww::eField eCode = TOX_INDEX == pTOX->GetType() ? ww::eINDEX : ww::eTOC;
+ GetExport( ).OutputField( 0, eCode, aEmptyStr, WRITEFIELD_CLOSE );
+ }
+ GetExport( ).bInWriteTOX = false;
+}
+
+bool MSWordExportBase::GetNumberFmt(const SwField& rFld, String& rStr)
+{
+ // Returns a date or time format string by using the US NfKeywordTable
+ bool bHasFmt = false;
+ SvNumberFormatter* pNFmtr = pDoc->GetNumberFormatter();
+ sal_uInt32 nFmtIdx = rFld.GetFormat();
+ const SvNumberformat* pNumFmt = pNFmtr->GetEntry( nFmtIdx );
+ if( pNumFmt )
+ {
+ LocaleDataWrapper aLocDat( pNFmtr->GetServiceManager(),
+ MsLangId::convertLanguageToLocale( LANGUAGE_ENGLISH_US ) );
+
+ if( !pKeyMap )
+ {
+ pKeyMap = new NfKeywordTable;
+ NfKeywordTable& rKeyMap = *(NfKeywordTable*)pKeyMap;
+ pNFmtr->FillKeywordTable( rKeyMap, LANGUAGE_ENGLISH_US );
+ }
+
+ String sFmt(pNumFmt->GetMappedFormatstring(*(NfKeywordTable*)pKeyMap,
+ aLocDat));
+ if (sFmt.Len())
+ {
+ sw::ms::SwapQuotesInField(sFmt);
+
+ rStr.APPEND_CONST_ASC( "\\@\"" );
+ rStr += sFmt;
+ rStr.APPEND_CONST_ASC( "\" " );
+ bHasFmt = true;
+ }
+ }
+ return bHasFmt;
+}
+
+void AttributeOutputBase::GetNumberPara( String& rStr, const SwField& rFld )
+{
+ switch(rFld.GetFormat())
+ {
+ case SVX_NUM_CHARS_UPPER_LETTER:
+ case SVX_NUM_CHARS_UPPER_LETTER_N:
+ rStr.APPEND_CONST_ASC( "\\*ALPHABETIC ");
+ break;
+ case SVX_NUM_CHARS_LOWER_LETTER:
+ case SVX_NUM_CHARS_LOWER_LETTER_N:
+ rStr.APPEND_CONST_ASC("\\*alphabetic ");
+ break;
+ case SVX_NUM_ROMAN_UPPER:
+ rStr.APPEND_CONST_ASC("\\*ROMAN ");
+ break;
+ case SVX_NUM_ROMAN_LOWER:
+ rStr.APPEND_CONST_ASC("\\*roman ");
+ break;
+ default:
+ OSL_ENSURE(rFld.GetFormat() == SVX_NUM_ARABIC,
+ "Unknown numbering type exported as default\n");
+ case SVX_NUM_ARABIC:
+ rStr.APPEND_CONST_ASC("\\*Arabic ");
+ break;
+ case SVX_NUM_PAGEDESC:
+ //Nothing, use word's default
+ break;
+ }
+}
+
+void WW8Export::WritePostItBegin( WW8Bytes* pOut )
+{
+ sal_uInt8 aArr[ 3 ];
+ sal_uInt8* pArr = aArr;
+
+ // sprmCFSpec true
+ if( bWrtWW8 )
+ Set_UInt16( pArr, NS_sprm::LN_CFSpec );
+ else
+ Set_UInt8( pArr, 117 ); //sprmCFSpec
+ Set_UInt8( pArr, 1 );
+
+ pChpPlc->AppendFkpEntry( Strm().Tell() );
+ WriteChar( 0x05 ); // Annotation reference
+
+ if( pOut )
+ pOut->Insert( aArr, static_cast< sal_uInt16 >(pArr - aArr), pOut->Count() );
+ else
+ pChpPlc->AppendFkpEntry( Strm().Tell(), static_cast< short >(pArr - aArr), aArr );
+}
+
+String FieldString(ww::eField eIndex)
+{
+ String sRet(CREATE_CONST_ASC(" "));
+ if (const char *pField = ww::GetEnglishFieldName(eIndex))
+ sRet.InsertAscii(pField, 1);
+ return sRet;
+}
+
+void WW8AttributeOutput::HiddenField( const SwField& rFld )
+{
+ String sExpand(rFld.GetPar2());
+
+ //replace LF 0x0A with VT 0x0B
+ sExpand.SearchAndReplaceAll(0x0A, 0x0B);
+ m_rWW8Export.pChpPlc->AppendFkpEntry(m_rWW8Export.Strm().Tell());
+ if (m_rWW8Export.IsUnicode())
+ {
+ SwWW8Writer::WriteString16(m_rWW8Export.Strm(), sExpand, false);
+ static sal_uInt8 aArr[] =
+ {
+ 0x3C, 0x08, 0x1
+ };
+ m_rWW8Export.pChpPlc->AppendFkpEntry(m_rWW8Export.Strm().Tell(), sizeof(aArr), aArr);
+ }
+ else
+ {
+ SwWW8Writer::WriteString8(m_rWW8Export.Strm(), sExpand, false,
+ RTL_TEXTENCODING_MS_1252);
+ static sal_uInt8 aArr[] =
+ {
+ 92, 0x1
+ };
+ m_rWW8Export.pChpPlc->AppendFkpEntry(m_rWW8Export.Strm().Tell(), sizeof(aArr), aArr);
+ }
+}
+
+void WW8AttributeOutput::SetField( const SwField& rFld, ww::eField eType, const String& rCmd )
+{
+ const SwSetExpField* pSet=(const SwSetExpField*)(&rFld);
+ const String &rVar = pSet->GetPar2();
+
+ sal_uLong nFrom = m_rWW8Export.Fc2Cp(m_rWW8Export.Strm().Tell());
+
+ GetExport().OutputField(&rFld, eType, rCmd, WRITEFIELD_START |
+ WRITEFIELD_CMD_START | WRITEFIELD_CMD_END);
+
+ /*
+ Is there a bookmark at the start position of this field, if so
+ move it to the 0x14 of the result of the field. This is what word
+ does. MoveFieldMarks moves any bookmarks at this position to
+ the beginning of the field result, and marks the bookmark as a
+ fieldbookmark which is to be ended before the field end mark
+ instead of after it like a normal bookmark.
+ */
+ m_rWW8Export.MoveFieldMarks(nFrom,m_rWW8Export.Fc2Cp(m_rWW8Export.Strm().Tell()));
+
+ if (rVar.Len())
+ {
+ if (m_rWW8Export.IsUnicode())
+ SwWW8Writer::WriteString16(m_rWW8Export.Strm(), rVar, false);
+ else
+ {
+ SwWW8Writer::WriteString8(m_rWW8Export.Strm(), rVar, false,
+ RTL_TEXTENCODING_MS_1252);
+ }
+ }
+ GetExport().OutputField(&rFld, eType, rCmd, WRITEFIELD_CLOSE);
+}
+
+void WW8AttributeOutput::PostitField( const SwField* pFld )
+{
+ const SwPostItField *pPFld = (const SwPostItField*)pFld;
+ m_rWW8Export.pAtn->Append( m_rWW8Export.Fc2Cp( m_rWW8Export.Strm().Tell() ), pPFld );
+ m_rWW8Export.WritePostItBegin( m_rWW8Export.pO );
+}
+
+bool WW8AttributeOutput::DropdownField( const SwField* pFld )
+{
+ bool bExpand = true;
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ const SwDropDownField& rFld2 = *(SwDropDownField*)pFld;
+ uno::Sequence<rtl::OUString> aItems =
+ rFld2.GetItemSequence();
+ GetExport().DoComboBox(rFld2.GetName(),
+ rFld2.GetHelp(),
+ rFld2.GetToolTip(),
+ rFld2.GetSelectedItem(), aItems);
+ bExpand = false;
+ }
+ return bExpand;
+}
+
+void WW8AttributeOutput::RefField( const SwField &rFld, const String &rRef)
+{
+ String sStr( FieldString( ww::eREF ) );
+ sStr.APPEND_CONST_ASC( "\"" );
+ sStr += rRef;
+ sStr.APPEND_CONST_ASC( "\" " );
+ m_rWW8Export.OutputField( &rFld, ww::eREF, sStr, WRITEFIELD_START |
+ WRITEFIELD_CMD_START | WRITEFIELD_CMD_END );
+ String sVar = lcl_GetExpandedField( rFld );
+ if ( sVar.Len() )
+ {
+ if ( m_rWW8Export.IsUnicode() )
+ SwWW8Writer::WriteString16( m_rWW8Export.Strm(), sVar, false );
+ else
+ {
+ SwWW8Writer::WriteString8( m_rWW8Export.Strm(), sVar, false,
+ RTL_TEXTENCODING_MS_1252 );
+ }
+ }
+ m_rWW8Export.OutputField( &rFld, ww::eREF, sStr, WRITEFIELD_CLOSE );
+}
+
+void WW8AttributeOutput::WriteExpand( const SwField* pFld )
+{
+ String sExpand( lcl_GetExpandedField( *pFld ) );
+ if ( m_rWW8Export.IsUnicode() )
+ SwWW8Writer::WriteString16( m_rWW8Export.Strm(), sExpand, false );
+ else
+ {
+ SwWW8Writer::WriteString8( m_rWW8Export.Strm(), sExpand, false,
+ RTL_TEXTENCODING_MS_1252 );
+ }
+}
+
+void AttributeOutputBase::TextField( const SwFmtFld& rField )
+{
+ const SwField* pFld = rField.GetFld();
+ String sStr; // fuer optionale Parameter
+ bool bWriteExpand = false;
+ sal_uInt16 nSubType = pFld->GetSubType();
+
+ switch (pFld->GetTyp()->Which())
+ {
+ case RES_GETEXPFLD:
+ if (nSubType == nsSwGetSetExpType::GSE_STRING)
+ {
+ const SwGetExpField *pGet=(const SwGetExpField*)(pFld);
+ RefField( *pGet, pGet->GetFormula() );
+ }
+ else
+ bWriteExpand = true;
+ break;
+ case RES_SETEXPFLD:
+ if (nsSwGetSetExpType::GSE_SEQ == nSubType)
+ {
+ sStr = FieldString(ww::eSEQ);
+ sStr.APPEND_CONST_ASC("\"");
+ sStr += pFld->GetTyp()->GetName();
+ sStr.APPEND_CONST_ASC( "\" " );
+
+ GetNumberPara( sStr, *pFld );
+ GetExport().OutputField(pFld, ww::eSEQ, sStr);
+ }
+ else if (nSubType & nsSwGetSetExpType::GSE_STRING)
+ {
+ bool bShowAsWell = false;
+ ww::eField eFieldNo;
+ const SwSetExpField *pSet=(const SwSetExpField*)(pFld);
+ const String &rVar = pSet->GetPar2();
+ if (pSet->GetInputFlag())
+ {
+ sStr = FieldString(ww::eASK);
+ sStr.APPEND_CONST_ASC("\"");
+ sStr += pSet->GetPar1();
+ sStr.APPEND_CONST_ASC( "\" " );
+ sStr += pSet->GetPromptText();
+ sStr.APPEND_CONST_ASC( " \\d " );
+ sStr += rVar;
+ eFieldNo = ww::eASK;
+ }
+ else
+ {
+ sStr = FieldString(ww::eSET);
+ sStr += pSet->GetPar1();
+ sStr.APPEND_CONST_ASC(" \"");
+ sStr += rVar;
+ sStr.APPEND_CONST_ASC("\" ");
+ eFieldNo = ww::eSET;
+ bShowAsWell = (nSubType & nsSwExtendedSubType::SUB_INVISIBLE) ? false : true;
+ }
+
+ SetField( *pFld, eFieldNo, sStr );
+
+ if (bShowAsWell)
+ RefField( *pSet, pSet->GetPar1() );
+ }
+ else
+ bWriteExpand = true;
+ break;
+ case RES_PAGENUMBERFLD:
+ sStr = FieldString(ww::ePAGE);
+ GetNumberPara(sStr, *pFld);
+ GetExport().OutputField(pFld, ww::ePAGE, sStr);
+ break;
+ case RES_FILENAMEFLD:
+ sStr = FieldString(ww::eFILENAME);
+ if (pFld->GetFormat() == FF_PATHNAME)
+ sStr.APPEND_CONST_ASC("\\p ");
+ GetExport().OutputField(pFld, ww::eFILENAME, sStr);
+ break;
+ case RES_DBNAMEFLD:
+ {
+ sStr = FieldString(ww::eDATABASE);
+ SwDBData aData = GetExport().pDoc->GetDBData();
+ sStr += String(aData.sDataSource);
+ sStr += DB_DELIM;
+ sStr += String(aData.sCommand);
+ GetExport().OutputField(pFld, ww::eDATABASE, sStr);
+ }
+ break;
+ case RES_AUTHORFLD:
+ {
+ ww::eField eFld =
+ (AF_SHORTCUT & pFld->GetFormat() ? ww::eUSERINITIALS : ww::eUSERNAME);
+ GetExport().OutputField(pFld, eFld, FieldString(eFld));
+ }
+ break;
+ case RES_TEMPLNAMEFLD:
+ GetExport().OutputField(pFld, ww::eTEMPLATE, FieldString(ww::eTEMPLATE));
+ break;
+ case RES_DOCINFOFLD: // Last printed, last edited,...
+ if( DI_SUB_FIXED & nSubType )
+ bWriteExpand = true;
+ else
+ {
+ ww::eField eFld(ww::eNONE);
+ switch (0xff & nSubType)
+ {
+ case DI_TITEL:
+ eFld = ww::eTITLE;
+ break;
+ case DI_THEMA:
+ eFld = ww::eSUBJECT;
+ break;
+ case DI_KEYS:
+ eFld = ww::eKEYWORDS;
+ break;
+ case DI_COMMENT:
+ eFld = ww::eCOMMENTS;
+ break;
+ case DI_DOCNO:
+ eFld = ww::eREVNUM;
+ break;
+ case DI_CREATE:
+ if (DI_SUB_AUTHOR == (nSubType & DI_SUB_MASK))
+ eFld = ww::eAUTHOR;
+ else if (GetExport().GetNumberFmt(*pFld, sStr))
+ eFld = ww::eCREATEDATE;
+ break;
+
+ case DI_CHANGE:
+ if (DI_SUB_AUTHOR == (nSubType & DI_SUB_MASK))
+ eFld = ww::eLASTSAVEDBY;
+ else if (GetExport().GetNumberFmt(*pFld, sStr))
+ eFld = ww::eSAVEDATE;
+ break;
+
+ case DI_PRINT:
+ if (DI_SUB_AUTHOR != (nSubType & DI_SUB_MASK) &&
+ GetExport().GetNumberFmt(*pFld, sStr))
+ eFld = ww::ePRINTDATE;
+ break;
+ case DI_EDIT:
+ if( DI_SUB_AUTHOR != (nSubType & DI_SUB_MASK ) &&
+ GetExport().GetNumberFmt( *pFld, sStr ))
+ eFld = ww::eSAVEDATE;
+ break;
+ case DI_CUSTOM:
+ eFld = ww::eDOCPROPERTY;
+ {
+ static String sQuotes('\"');
+ const SwDocInfoField * pDocInfoField =
+ dynamic_cast<const SwDocInfoField *> (pFld);
+
+ if (pDocInfoField != NULL)
+ {
+ String sFieldname = pDocInfoField->GetFieldName();
+ xub_StrLen nIndex = sFieldname.Search(':');
+
+ if (nIndex != sFieldname.Len())
+ sFieldname = sFieldname.Copy(nIndex + 1);
+
+ sStr.Insert(sQuotes);
+ sStr.Insert(sFieldname);
+ sStr.Insert(sQuotes);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (eFld != ww::eNONE)
+ {
+ sStr.Insert(FieldString(eFld), 0);
+ GetExport().OutputField(pFld, eFld, sStr);
+ }
+ else
+ bWriteExpand = true;
+ }
+ break;
+ case RES_DATETIMEFLD:
+ if (FIXEDFLD & nSubType || !GetExport().GetNumberFmt(*pFld, sStr))
+ bWriteExpand = true;
+ else
+ {
+ ww::eField eFld = (DATEFLD & nSubType) ? ww::eDATE : ww::eTIME;
+ sStr.Insert(FieldString(eFld), 0);
+ GetExport().OutputField(pFld, eFld, sStr);
+ }
+ break;
+ case RES_DOCSTATFLD:
+ {
+ ww::eField eFld = ww::eNONE;
+
+ switch (nSubType)
+ {
+ case DS_PAGE:
+ eFld = ww::eNUMPAGE;
+ break;
+ case DS_WORD:
+ eFld = ww::eNUMWORDS;
+ break;
+ case DS_CHAR:
+ eFld = ww::eNUMCHARS;
+ break;
+ }
+
+ if (eFld != ww::eNONE)
+ {
+ sStr = FieldString(eFld);
+ GetNumberPara(sStr, *pFld);
+ GetExport().OutputField(pFld, eFld, sStr);
+ }
+ else
+ bWriteExpand = true;
+ }
+ break;
+ case RES_EXTUSERFLD:
+ {
+ ww::eField eFld = ww::eNONE;
+ switch (0xFF & nSubType)
+ {
+ case EU_FIRSTNAME:
+ case EU_NAME:
+ eFld = ww::eUSERNAME;
+ break;
+ case EU_SHORTCUT:
+ eFld = ww::eUSERINITIALS;
+ break;
+ case EU_STREET:
+ case EU_COUNTRY:
+ case EU_ZIP:
+ case EU_CITY:
+ eFld = ww::eUSERADDRESS;
+ break;
+ }
+
+ if (eFld != ww::eNONE)
+ {
+ sStr = FieldString(eFld);
+ GetExport().OutputField(pFld, eFld, sStr);
+ }
+ else
+ bWriteExpand = true;
+ }
+ break;
+ case RES_POSTITFLD:
+ //Sadly only possible for word in main document text
+ if (GetExport().nTxtTyp == TXT_MAINTEXT)
+ {
+ PostitField( pFld );
+ }
+ break;
+ case RES_INPUTFLD:
+ {
+ const SwInputField * pInputField =
+ dynamic_cast<const SwInputField *>(pFld);
+
+ if (pInputField->isFormField())
+ GetExport().DoFormText(pInputField);
+ else
+ {
+ sStr = FieldString(ww::eFILLIN);
+
+ sStr.APPEND_CONST_ASC("\"");
+ sStr += pFld->GetPar2();
+ sStr += '\"';
+
+ GetExport().OutputField(pFld, ww::eFILLIN, sStr);
+ }
+ }
+ break;
+ case RES_GETREFFLD:
+ {
+ ww::eField eFld = ww::eNONE;
+ const SwGetRefField& rRFld = *(SwGetRefField*)pFld;
+ switch (nSubType)
+ {
+ case REF_SETREFATTR:
+ case REF_BOOKMARK:
+ switch (pFld->GetFormat())
+ {
+ case REF_PAGE_PGDESC:
+ case REF_PAGE:
+ eFld = ww::ePAGEREF;
+ break;
+ default:
+ eFld = ww::eREF;
+ break;
+ }
+ sStr = FieldString(eFld);
+ sStr += GetExport().GetBookmarkName(nSubType,
+ &rRFld.GetSetRefName(), 0);
+ break;
+ case REF_FOOTNOTE:
+ case REF_ENDNOTE:
+ switch (pFld->GetFormat())
+ {
+ case REF_PAGE_PGDESC:
+ case REF_PAGE:
+ eFld = ww::ePAGEREF;
+ break;
+ case REF_UPDOWN:
+ eFld = ww::eREF;
+ break;
+ default:
+ eFld =
+ REF_ENDNOTE == nSubType ? ww::eNOTEREF : ww::eFOOTREF;
+ break;
+ }
+ sStr = FieldString(eFld);
+ sStr += GetExport().GetBookmarkName(nSubType, 0,
+ rRFld.GetSeqNo());
+ break;
+ }
+
+ if (eFld != ww::eNONE)
+ {
+ switch (pFld->GetFormat())
+ {
+ case REF_UPDOWN:
+ sStr.APPEND_CONST_ASC(" \\p");
+ break;
+ case REF_CHAPTER:
+ sStr.APPEND_CONST_ASC(" \\n");
+ break;
+ default:
+ break;
+ }
+ sStr.APPEND_CONST_ASC(" \\h "); // insert hyperlink
+ GetExport().OutputField(pFld, eFld, sStr);
+ }
+ else
+ bWriteExpand = true;
+ }
+ break;
+ case RES_COMBINED_CHARS:
+ {
+ /*
+ We need a font size to fill in the defaults, if these are overridden
+ (as they generally are) by character properties then those properties
+ win.
+
+ The fontsize that is used in MS for determing the defaults is always
+ the CJK fontsize even if the text is not in that language, in OOo the
+ largest fontsize used in the field is the one we should take, but
+ whatever we do, word will actually render using the fontsize set for
+ CJK text. Nevertheless we attempt to guess whether the script is in
+ asian or western text based up on the first character and use the
+ font size of that script as our default.
+ */
+ sal_uInt16 nScript;
+ if( pBreakIt->GetBreakIter().is() )
+ nScript = pBreakIt->GetBreakIter()->getScriptType( pFld->GetPar1(), 0);
+ else
+ nScript = i18n::ScriptType::ASIAN;
+
+ long nHeight = ((SvxFontHeightItem&)(GetExport().GetItem(
+ GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript)))).GetHeight();;
+
+ nHeight = (nHeight + 10) / 20; //Font Size in points;
+
+ /*
+ Divide the combined char string into its up and down part. Get the
+ font size and fill in the defaults as up == half the font size and
+ down == a fifth the font size
+ */
+ xub_StrLen nAbove = (pFld->GetPar1().Len()+1)/2;
+ sStr = FieldString(ww::eEQ);
+ sStr.APPEND_CONST_ASC("\\o (\\s\\up ");
+ sStr += String::CreateFromInt32(nHeight/2);
+
+ sStr.Append('(');
+ sStr += String(pFld->GetPar1(),0,nAbove);
+ sStr.APPEND_CONST_ASC("), \\s\\do ");
+ sStr += String::CreateFromInt32(nHeight/5);
+
+ sStr.Append('(');
+ sStr += String(pFld->GetPar1(),nAbove,pFld->GetPar1().Len()-nAbove);
+ sStr.APPEND_CONST_ASC("))");
+ GetExport().OutputField(pFld, ww::eEQ, sStr);
+ }
+ break;
+ case RES_DROPDOWN:
+ bWriteExpand = DropdownField( pFld );
+ break;
+ case RES_CHAPTERFLD:
+ bWriteExpand = true;
+ if (GetExport().bOutKF && rField.GetTxtFld())
+ {
+ const SwTxtNode *pTxtNd = GetExport().GetHdFtPageRoot();
+ if (!pTxtNd)
+ {
+ if (const SwNode *pNd = GetExport().pCurPam->GetNode())
+ pTxtNd = pNd->GetTxtNode();
+ }
+
+ if (pTxtNd)
+ {
+ SwChapterField aCopy(*(const SwChapterField*)pFld);
+ aCopy.ChangeExpansion(*pTxtNd, false);
+ WriteExpand( &aCopy );
+ bWriteExpand = false;
+ }
+ }
+ break;
+ case RES_HIDDENTXTFLD:
+ {
+ String sExpand(pFld->GetPar2());
+ if (sExpand.Len())
+ {
+ HiddenField( *pFld );
+ }
+ }
+ break;
+ default:
+ bWriteExpand = true;
+ break;
+ }
+
+ if (bWriteExpand)
+ WriteExpand( pFld );
+}
+
+void AttributeOutputBase::TextFlyContent( const SwFmtFlyCnt& rFlyContent )
+{
+ if ( GetExport().pOutFmtNode && GetExport().pOutFmtNode->ISA( SwCntntNode ) )
+ {
+ SwTxtNode* pTxtNd = (SwTxtNode*)GetExport().pOutFmtNode;
+
+ Point aLayPos;
+ aLayPos = pTxtNd->FindLayoutRect( false, &aLayPos ).Pos();
+
+ SwPosition aPos( *pTxtNd );
+ sw::Frame aFrm( *rFlyContent.GetFrmFmt(), aPos );
+
+ OutputFlyFrame_Impl( aFrm, aLayPos );
+ }
+}
+
+// TOXMarks fehlen noch
+
+// Detaillierte Einstellungen zur Trennung erlaubt WW nur dokumentenweise.
+// Man koennte folgende Mimik einbauen: Die Werte des Style "Standard" werden,
+// falls vorhanden, in die Document Properties ( DOP ) gesetzt.
+// ---
+// ACK. Dieser Vorschlag passt exakt zu unserer Implementierung des Import,
+// daher setze ich das gleich mal um. (KHZ, 07/15/2000)
+void WW8AttributeOutput::ParaHyphenZone( const SvxHyphenZoneItem& rHyphenZone )
+{
+ // sprmPFNoAutoHyph
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFNoAutoHyph );
+ else
+ m_rWW8Export.pO->Insert( 44, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.pO->Insert( rHyphenZone.IsHyphen() ? 0 : 1, m_rWW8Export.pO->Count() );
+}
+
+void WW8AttributeOutput::ParaScriptSpace( const SfxBoolItem& rScriptSpace )
+{
+ sal_uInt16 nId = 0;
+ if ( m_rWW8Export.bWrtWW8 )
+ switch ( rScriptSpace.Which() )
+ {
+ case RES_PARATR_SCRIPTSPACE: nId = NS_sprm::LN_PFAutoSpaceDE; break;
+ case RES_PARATR_HANGINGPUNCTUATION: nId = NS_sprm::LN_PFOverflowPunct; break;
+ case RES_PARATR_FORBIDDEN_RULES: nId = NS_sprm::LN_PFKinsoku; break;
+ }
+
+ if ( nId )
+ {
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( nId );
+ else
+ m_rWW8Export.pO->Insert( (sal_uInt8)nId, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.pO->Insert( rScriptSpace.GetValue() ? 1 : 0,
+ m_rWW8Export.pO->Count() );
+ }
+}
+
+void WW8AttributeOutput::ParaSnapToGrid( const SvxParaGridItem& rGrid )
+{
+ // sprmPFUsePgsuSettings
+ // 97+ only
+ if ( !m_rWW8Export.bWrtWW8 )
+ return;
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFUsePgsuSettings );
+ m_rWW8Export.pO->Insert( rGrid.GetValue(), m_rWW8Export.pO->Count() );
+}
+
+void WW8AttributeOutput::ParaVerticalAlign( const SvxParaVertAlignItem& rAlign )
+{
+ // sprmPWAlignFont
+ // 97+ only
+ if( !m_rWW8Export.bWrtWW8 )
+ return;
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PWAlignFont );
+
+ sal_Int16 nVal = rAlign.GetValue();
+ switch ( nVal )
+ {
+ case SvxParaVertAlignItem::BASELINE:
+ nVal = 2;
+ break;
+ case SvxParaVertAlignItem::TOP:
+ nVal = 0;
+ break;
+ case SvxParaVertAlignItem::CENTER:
+ nVal = 1;
+ break;
+ case SvxParaVertAlignItem::BOTTOM:
+ nVal = 3;
+ break;
+ case SvxParaVertAlignItem::AUTOMATIC:
+ nVal = 4;
+ break;
+ default:
+ nVal = 4;
+ OSL_FAIL( "Unknown vert alignment" );
+ break;
+ }
+ m_rWW8Export.InsUInt16( nVal );
+}
+
+
+// NoHyphen: ich habe keine Entsprechung in der SW-UI und WW-UI gefunden
+
+
+// RefMark, NoLineBreakHere fehlen noch
+
+void WW8Export::WriteFtnBegin( const SwFmtFtn& rFtn, WW8Bytes* pOutArr )
+{
+ WW8Bytes aAttrArr;
+ bool bAutoNum = !rFtn.GetNumStr().Len(); // Auto-Nummer
+ if( bAutoNum )
+ {
+ if( bWrtWW8 )
+ {
+ static const sal_uInt8 aSpec[] =
+ {
+ 0x03, 0x6a, 0, 0, 0, 0, // sprmCObjLocation
+ 0x55, 0x08, 1 // sprmCFSpec
+ };
+
+ aAttrArr.Insert(aSpec, sizeof(aSpec), aAttrArr.Count());
+ }
+ else
+ {
+ static sal_uInt8 const aSpec[] =
+ {
+ 117, 1, // sprmCFSpec
+ 68, 4, 0, 0, 0, 0 // sprmCObjLocation
+ };
+
+ aAttrArr.Insert(aSpec, sizeof(aSpec), aAttrArr.Count());
+ }
+ }
+
+ // sprmCIstd
+ const SwEndNoteInfo* pInfo;
+ if( rFtn.IsEndNote() )
+ pInfo = &pDoc->GetEndNoteInfo();
+ else
+ pInfo = &pDoc->GetFtnInfo();
+ const SwCharFmt* pCFmt = pOutArr
+ ? pInfo->GetAnchorCharFmt( *pDoc )
+ : pInfo->GetCharFmt( *pDoc );
+ if( bWrtWW8 )
+ SwWW8Writer::InsUInt16( aAttrArr, NS_sprm::LN_CIstd );
+ else
+ aAttrArr.Insert( 80, aAttrArr.Count() );
+ SwWW8Writer::InsUInt16( aAttrArr, GetId( *pCFmt ) );
+
+ // fSpec-Attribut true
+ // Fuer Auto-Nummer muss ein Spezial-Zeichen
+ // in den Text und darum ein fSpec-Attribut
+ pChpPlc->AppendFkpEntry( Strm().Tell() );
+ if( bAutoNum )
+ WriteChar( 0x02 ); // Auto-Nummer-Zeichen
+ else
+ // User-Nummerierung
+ OutSwString( rFtn.GetNumStr(), 0, rFtn.GetNumStr().Len(),
+ IsUnicode(), RTL_TEXTENCODING_MS_1252 );
+
+ if( pOutArr )
+ {
+ // insert at start of array, so the "hard" attribute overrule the
+ // attributes of the character template
+ pOutArr->Insert( &aAttrArr, 0 );
+ }
+ else
+ {
+ WW8Bytes aOutArr;
+
+ // insert at start of array, so the "hard" attribute overrule the
+ // attributes of the character template
+ aOutArr.Insert( &aAttrArr, 0 );
+
+ // write for the ftn number in the content, the font of the anchor
+ const SwTxtFtn* pTxtFtn = rFtn.GetTxtFtn();
+ if( pTxtFtn )
+ {
+ WW8Bytes* pOld = pO;
+ pO = &aOutArr;
+ SfxItemSet aSet( pDoc->GetAttrPool(), RES_CHRATR_FONT,
+ RES_CHRATR_FONT );
+
+ pCFmt = pInfo->GetCharFmt( *pDoc );
+ aSet.Set( pCFmt->GetAttrSet() );
+
+ pTxtFtn->GetTxtNode().GetAttr( aSet, *pTxtFtn->GetStart(),
+ (*pTxtFtn->GetStart()) + 1 );
+ m_pAttrOutput->OutputItem( aSet.Get( RES_CHRATR_FONT ) );
+ pO = pOld;
+ }
+ pChpPlc->AppendFkpEntry( Strm().Tell(), aOutArr.Count(),
+ aOutArr.GetData() );
+ }
+}
+
+static bool lcl_IsAtTxtEnd(const SwFmtFtn& rFtn)
+{
+ bool bRet = true;
+ if( rFtn.GetTxtFtn() )
+ {
+ sal_uInt16 nWh = static_cast< sal_uInt16 >(rFtn.IsEndNote() ? RES_END_AT_TXTEND
+ : RES_FTN_AT_TXTEND);
+ const SwSectionNode* pSectNd = rFtn.GetTxtFtn()->GetTxtNode().
+ FindSectionNode();
+ while( pSectNd && FTNEND_ATPGORDOCEND ==
+ ((const SwFmtFtnAtTxtEnd&)pSectNd->GetSection().GetFmt()->
+ GetFmtAttr( nWh, true)).GetValue() )
+ pSectNd = pSectNd->StartOfSectionNode()->FindSectionNode();
+
+ if (!pSectNd)
+ bRet = false; // the is ftn/end collected at Page- or Doc-End
+ }
+ return bRet;
+}
+
+
+void AttributeOutputBase::TextFootnote( const SwFmtFtn& rFtn )
+{
+ sal_uInt16 nTyp;
+ if ( rFtn.IsEndNote() )
+ {
+ nTyp = REF_ENDNOTE;
+ if ( GetExport().bEndAtTxtEnd )
+ GetExport().bEndAtTxtEnd = lcl_IsAtTxtEnd( rFtn );
+ }
+ else
+ {
+ nTyp = REF_FOOTNOTE;
+ if ( GetExport().bFtnAtTxtEnd )
+ GetExport().bFtnAtTxtEnd = lcl_IsAtTxtEnd( rFtn );
+ }
+
+ // if any reference to this footnote/endnote then insert an internal
+ // Bookmark.
+ String sBkmkNm;
+ if ( GetExport().HasRefToObject( nTyp, 0, rFtn.GetTxtFtn()->GetSeqRefNo() ))
+ {
+ sBkmkNm = GetExport().GetBookmarkName( nTyp, 0,
+ rFtn.GetTxtFtn()->GetSeqRefNo() );
+ GetExport().AppendBookmark( sBkmkNm );
+ }
+
+ TextFootnote_Impl( rFtn );
+
+ if ( sBkmkNm.Len() )
+ GetExport().AppendBookmark( sBkmkNm ); // FIXME: Why is it added twice? Shouldn't this one go to WW8AttributeOuput::TextFootnote_Impl()?
+}
+
+void WW8AttributeOutput::TextFootnote_Impl( const SwFmtFtn& rFtn )
+{
+ WW8_WrPlcFtnEdn* pFtnEnd;
+ if ( rFtn.IsEndNote() )
+ pFtnEnd = m_rWW8Export.pEdn;
+ else
+ pFtnEnd = m_rWW8Export.pFtn;
+
+ pFtnEnd->Append( m_rWW8Export.Fc2Cp( m_rWW8Export.Strm().Tell() ), rFtn );
+ m_rWW8Export.WriteFtnBegin( rFtn, m_rWW8Export.pO );
+}
+
+void WW8AttributeOutput::TextCharFormat( const SwFmtCharFmt& rCharFmt )
+{
+ if( rCharFmt.GetCharFmt() )
+ {
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CIstd );
+ else
+ m_rWW8Export.pO->Insert( 80, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( m_rWW8Export.GetId( *rCharFmt.GetCharFmt() ) );
+ }
+}
+
+/*
+ See ww8par6.cxx Read_DoubleLine for some more info
+ */
+void WW8AttributeOutput::CharTwoLines( const SvxTwoLinesItem& rTwoLines )
+{
+ // #i28331# - check that bOn is set
+ if ( rTwoLines.GetValue() )
+ {
+ //97+ only
+ if( !m_rWW8Export.bWrtWW8 )
+ return;
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_CEastAsianLayout );
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x06, m_rWW8Export.pO->Count() ); //len 6
+ m_rWW8Export.pO->Insert( (sal_uInt8)0x02, m_rWW8Export.pO->Count() );
+
+ sal_Unicode cStart = rTwoLines.GetStartBracket();
+ sal_Unicode cEnd = rTwoLines.GetEndBracket();
+
+ /*
+ As per usual we have problems. We can have seperate left and right brackets
+ in OOo, it doesn't appear that you can in word. Also in word there appear
+ to only be a limited number of possibilities, we can use pretty much
+ anything.
+
+ So if we have none, we export none, if either bracket is set to a known
+ word type we export both as that type (with the bracket winning out in
+ the case of a conflict simply being the order of test here.
+
+ Upshot being a documented created in word will be reexported with no
+ ill effects.
+ */
+
+ sal_uInt16 nType;
+ if (!cStart && !cEnd)
+ nType = 0;
+ else if ((cStart == '{') || (cEnd == '}'))
+ nType = 4;
+ else if ((cStart == '<') || (cEnd == '>'))
+ nType = 3;
+ else if ((cStart == '[') || (cEnd == ']'))
+ nType = 2;
+ else
+ nType = 1;
+ m_rWW8Export.InsUInt16( nType );
+ static const sal_uInt8 aZeroArr[ 3 ] = { 0, 0, 0 };
+ m_rWW8Export.pO->Insert( aZeroArr, 3, m_rWW8Export.pO->Count() );
+ }
+}
+
+void AttributeOutputBase::ParaNumRule( const SwNumRuleItem& rNumRule )
+{
+ const SwTxtNode* pTxtNd = 0;
+ sal_uInt16 nNumId;
+ sal_uInt8 nLvl = 0;
+ if ( rNumRule.GetValue().Len() )
+ {
+ const SwNumRule* pRule = GetExport().pDoc->FindNumRulePtr(
+ rNumRule.GetValue() );
+ if ( pRule && USHRT_MAX != ( nNumId = GetExport().GetId( *pRule ) ) )
+ {
+ ++nNumId;
+ if ( GetExport().pOutFmtNode )
+ {
+ if ( GetExport().pOutFmtNode->ISA( SwCntntNode ) )
+ {
+ pTxtNd = (SwTxtNode*)GetExport().pOutFmtNode;
+
+ if( pTxtNd->IsCountedInList())
+ {
+ nLvl = static_cast< sal_uInt8 >(pTxtNd->GetActualListLevel());
+
+ if ( pTxtNd->IsListRestart() )
+ {
+ sal_uInt16 nStartWith = static_cast< sal_uInt16 >( pTxtNd->GetActualListStartValue() );
+ nNumId = GetExport().DuplicateNumRule( pRule, nLvl, nStartWith );
+ if ( USHRT_MAX != nNumId )
+ ++nNumId;
+ }
+ }
+ else
+ {
+ // #i44815# adjust numbering for numbered paragraphs
+ // without number (NO_NUMLEVEL). These paragaphs
+ // will receive a list id 0, which WW interprets as
+ // 'no number'.
+ nNumId = 0;
+ }
+ }
+ else if ( GetExport().pOutFmtNode->ISA( SwTxtFmtColl ) )
+ {
+ const SwTxtFmtColl* pC = (SwTxtFmtColl*)GetExport().pOutFmtNode;
+ if ( pC && pC->IsAssignedToListLevelOfOutlineStyle() )
+ nLvl = static_cast< sal_uInt8 >( pC->GetAssignedOutlineStyleLevel() ); //<-end,zhaojianwei
+ }
+ }
+ }
+ else
+ nNumId = USHRT_MAX;
+ }
+ else
+ nNumId = 0;
+
+ if ( USHRT_MAX != nNumId )
+ {
+ if ( nLvl >= WW8ListManager::nMaxLevel )
+ nLvl = WW8ListManager::nMaxLevel - 1;
+
+ ParaNumRule_Impl( pTxtNd, nLvl, nNumId );
+ }
+}
+
+void WW8AttributeOutput::ParaNumRule_Impl( const SwTxtNode* pTxtNd, sal_Int32 nLvl, sal_Int32 nNumId )
+{
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ // write sprmPIlvl and sprmPIlfo
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_PIlvl );
+ m_rWW8Export.pO->Insert( ::sal::static_int_cast<sal_uInt8>(nLvl), m_rWW8Export.pO->Count() );
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, NS_sprm::LN_PIlfo );
+ SwWW8Writer::InsUInt16( *m_rWW8Export.pO, ::sal::static_int_cast<sal_uInt16>(nNumId) );
+ }
+ else if ( pTxtNd && m_rWW8Export.Out_SwNum( pTxtNd ) ) // NumRules
+ m_rWW8Export.pSepx->SetNum( pTxtNd );
+}
+
+/* File FRMATR.HXX */
+
+void WW8AttributeOutput::FormatFrameSize( const SwFmtFrmSize& rSize )
+{
+ if( m_rWW8Export.bOutFlyFrmAttrs ) // Flys
+ {
+ if( m_rWW8Export.bOutGrf )
+ return; // Fly um Grafik -> Auto-Groesse
+
+//???? was ist bei Prozentangaben ???
+ if ( rSize.GetWidth() && rSize.GetWidthSizeType() == ATT_FIX_SIZE)
+ {
+ //"sprmPDxaWidth"
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaWidth );
+ else
+ m_rWW8Export.pO->Insert( 28, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( (sal_uInt16)rSize.GetWidth() );
+ }
+
+ if ( rSize.GetHeight() )
+ {
+ // sprmPWHeightAbs
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PWHeightAbs );
+ else
+ m_rWW8Export.pO->Insert( 45, m_rWW8Export.pO->Count() );
+
+ sal_uInt16 nH = 0;
+ switch ( rSize.GetHeightSizeType() )
+ {
+ case ATT_VAR_SIZE: break;
+ case ATT_FIX_SIZE: nH = (sal_uInt16)rSize.GetHeight() & 0x7fff; break;
+ default: nH = (sal_uInt16)rSize.GetHeight() | 0x8000; break;
+ }
+ m_rWW8Export.InsUInt16( nH );
+ }
+ }
+ else if( m_rWW8Export.bOutPageDescs ) // PageDesc : Breite + Hoehe
+ {
+ if( m_rWW8Export.pAktPageDesc->GetLandscape() )
+ {
+ /*sprmSBOrientation*/
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SBOrientation );
+ else
+ m_rWW8Export.pO->Insert( 162, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( 2, m_rWW8Export.pO->Count() );
+ }
+
+ /*sprmSXaPage*/
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SXaPage );
+ else
+ m_rWW8Export.pO->Insert( 164, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16(
+ msword_cast<sal_uInt16>(SvxPaperInfo::GetSloppyPaperDimension(rSize.GetWidth())));
+
+ /*sprmSYaPage*/
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SYaPage );
+ else
+ m_rWW8Export.pO->Insert( 165, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16(
+ msword_cast<sal_uInt16>(SvxPaperInfo::GetSloppyPaperDimension(rSize.GetHeight())));
+ }
+}
+
+// FillOrder fehlt noch
+
+// ReplaceCr() wird fuer Pagebreaks und Pagedescs gebraucht. Es wird ein
+// bereits geschriebenes CR durch ein Break-Zeichen ersetzt. Replace muss
+// direkt nach Schreiben des CR gerufen werden.
+// Rueckgabe: FilePos des ersetzten CRs + 1 oder 0 fuer nicht ersetzt
+
+sal_uLong WW8Export::ReplaceCr( sal_uInt8 nChar )
+{
+ OSL_ENSURE( nChar, "gegen 0 ersetzt bringt WW97/95 zum Absturz" );
+
+ bool bReplaced = false;
+ SvStream& rStrm = Strm();
+ sal_uLong nRetPos = 0, nPos = rStrm.Tell();
+ //If there is at least two characters already output
+ if (nPos - (IsUnicode() ? 2 : 1) >= sal_uLong(pFib->fcMin))
+ {
+ sal_uInt8 nBCode=0;
+ sal_uInt16 nUCode=0;
+
+ rStrm.SeekRel(IsUnicode() ? -2 : -1);
+ if (IsUnicode())
+ rStrm >> nUCode;
+ else
+ {
+ rStrm >> nBCode;
+ nUCode = nBCode;
+ }
+ //If the last char was a cr
+ if (nUCode == 0x0d) // CR ?
+ {
+ if ((nChar == 0x0c) &&
+ (nPos - (IsUnicode() ? 4 : 2) >= sal_uLong(pFib->fcMin)))
+ {
+ rStrm.SeekRel( IsUnicode() ? -4 : -2 );
+ if (IsUnicode())
+ rStrm >> nUCode;
+ else
+ {
+ rStrm >> nUCode;
+ nUCode = nBCode;
+ }
+ }
+ else
+ {
+ rStrm.SeekRel( IsUnicode() ? -2 : -1 );
+ nUCode = 0x0;
+ }
+ //And the para is not of len 0, then replace this cr with the mark
+ if( nChar == 0x0e || nUCode == 0x0d )
+ bReplaced = false;
+ else
+ {
+ bReplaced = true;
+ WriteChar(nChar);
+ nRetPos = nPos;
+ }
+ }
+ else if ((nUCode == 0x0c) && (nChar == 0x0e))
+ {
+ // a column break after a section has no effect in writer
+ bReplaced = true;
+ }
+ rStrm.Seek( nPos );
+ }
+ else
+ bReplaced = true;
+
+ if (!bReplaced)
+ {
+ // then write as normal char
+ WriteChar(nChar);
+ pPiece->SetParaBreak();
+ pPapPlc->AppendFkpEntry(rStrm.Tell());
+ pChpPlc->AppendFkpEntry(rStrm.Tell());
+ nRetPos = rStrm.Tell();
+ }
+ return nRetPos;
+}
+
+void WW8AttributeOutput::TableRowEnd(sal_uInt32 nDepth)
+{
+ if ( nDepth == 1 )
+ m_rWW8Export.WriteChar( (sal_uInt8)0x07 );
+ else if ( nDepth > 1 )
+ m_rWW8Export.WriteChar( (sal_uInt8)0x0d );
+
+ //Technically in a word document this is a different value for a row ends
+ //that are not row ends directly after a cell with a graphic. But it
+ //doesn't seem to make a difference
+ //pMagicTable->Append(Fc2Cp(Strm().Tell()),0x1B6);
+}
+
+void AttributeOutputBase::FormatPageDescription( const SwFmtPageDesc& rPageDesc )
+{
+ if ( GetExport().bStyDef && GetExport().pOutFmtNode && GetExport().pOutFmtNode->ISA( SwTxtFmtColl ) )
+ {
+ const SwTxtFmtColl* pC = (SwTxtFmtColl*)GetExport().pOutFmtNode;
+ if ( (SFX_ITEM_SET != pC->GetItemState( RES_BREAK, false ) ) && rPageDesc.KnowsPageDesc() )
+ FormatBreak( SvxFmtBreakItem( SVX_BREAK_PAGE_BEFORE, RES_BREAK ) );
+ }
+}
+
+void WW8AttributeOutput::PageBreakBefore( bool bBreak )
+{
+ // sprmPPageBreakBefore/sprmPFPageBreakBefore
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFPageBreakBefore );
+ else
+ m_rWW8Export.pO->Insert( 9, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.pO->Insert( bBreak ? 1 : 0, m_rWW8Export.pO->Count() );
+}
+
+// Breaks schreiben nichts in das Ausgabe-Feld rWrt.pO,
+// sondern nur in den Text-Stream ( Bedingung dafuer, dass sie von Out_Break...
+// gerufen werden duerfen )
+void AttributeOutputBase::FormatBreak( const SvxFmtBreakItem& rBreak )
+{
+ if ( GetExport().bStyDef )
+ {
+ switch ( rBreak.GetBreak() )
+ {
+ case SVX_BREAK_NONE:
+ case SVX_BREAK_PAGE_BEFORE:
+ case SVX_BREAK_PAGE_BOTH:
+ PageBreakBefore( rBreak.GetValue() );
+ break;
+ default:
+ break;
+ }
+ }
+ else if ( !GetExport().mpParentFrame )
+ {
+ sal_uInt8 nC = 0;
+ bool bBefore = false;
+ // #i76300# - Note: Can only be <true>, if <bBefore> equals <false>.
+ bool bCheckForFollowPageDesc = false;
+
+ switch ( rBreak.GetBreak() )
+ {
+ case SVX_BREAK_NONE: // Ausgeschaltet
+ if ( !GetExport().bBreakBefore )
+ PageBreakBefore( false );
+ return;
+
+ case SVX_BREAK_COLUMN_BEFORE: // ColumnBreak
+ bBefore = true;
+ // no break;
+ case SVX_BREAK_COLUMN_AFTER:
+ case SVX_BREAK_COLUMN_BOTH:
+ if ( GetExport().Sections().CurrentNumberOfColumns( *GetExport().pDoc ) > 1 )
+ {
+ nC = msword::ColumnBreak;
+ }
+ break;
+
+ case SVX_BREAK_PAGE_BEFORE: // PageBreak
+ // From now on(fix for #i77900#) we prefer to save a page break as
+ // paragraph attribute, this has to be done after the export of the
+ // paragraph ( => !GetExport().bBreakBefore )
+ if ( !GetExport().bBreakBefore )
+ PageBreakBefore( true );
+ break;
+
+ case SVX_BREAK_PAGE_AFTER:
+ case SVX_BREAK_PAGE_BOTH:
+ nC = msword::PageBreak;
+ // #i76300# - check for follow page description,
+ // if current writing attributes of a paragraph.
+ if ( dynamic_cast< const SwTxtNode* >( GetExport().pOutFmtNode ) &&
+ GetExport().GetCurItemSet() )
+ {
+ bCheckForFollowPageDesc = true;
+ }
+ // <--
+ break;
+
+ default:
+ break;
+ }
+
+ if ( ( bBefore == GetExport().bBreakBefore ) && nC )
+ {
+ // #i76300#
+ bool bFollowPageDescWritten = false;
+ if ( bCheckForFollowPageDesc && !bBefore )
+ {
+ bFollowPageDescWritten =
+ GetExport().OutputFollowPageDesc( GetExport().GetCurItemSet(),
+ dynamic_cast<const SwTxtNode*>( GetExport().pOutFmtNode ) );
+ }
+ if ( !bFollowPageDescWritten )
+ {
+ SectionBreak( nC );
+ }
+ // <--
+ }
+ }
+}
+
+void WW8AttributeOutput::SectionBreak( sal_uInt8 nC, const WW8_SepInfo* /*pSectionInfo*/ )
+{
+ m_rWW8Export.ReplaceCr( nC );
+}
+
+void WW8AttributeOutput::FormatTextGrid( const SwTextGridItem& rGrid )
+{
+ if ( m_rWW8Export.bOutPageDescs && m_rWW8Export.bWrtWW8 )
+ {
+ sal_uInt16 nGridType = 0;
+ switch ( rGrid.GetGridType() )
+ {
+ default:
+ OSL_FAIL("Unknown grid type");
+ case GRID_NONE:
+ nGridType = 0;
+ break;
+ case GRID_LINES_ONLY:
+ nGridType = 2;
+ break;
+ case GRID_LINES_CHARS:
+ if ( rGrid.IsSnapToChars() )
+ nGridType = 3;
+ else
+ nGridType = 1;
+ break;
+ }
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SClm );
+ m_rWW8Export.InsUInt16( nGridType );
+
+ sal_uInt16 nHeight = rGrid.GetBaseHeight() + rGrid.GetRubyHeight();
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDyaLinePitch );
+ m_rWW8Export.InsUInt16( nHeight );
+
+ MSWordStyles * pStyles = m_rWW8Export.pStyles;
+ SwFmt * pSwFmt = pStyles->GetSwFmt();
+
+ sal_uInt32 nPageCharSize = 0;
+
+ if (pSwFmt != NULL)
+ {
+ nPageCharSize = ItemGet<SvxFontHeightItem>
+ (*pSwFmt, RES_CHRATR_FONTSIZE).GetHeight();
+ }
+ sal_uInt16 nPitch = rGrid.IsSquaredMode() ? rGrid.GetBaseHeight() :
+ rGrid.GetBaseWidth( );
+ sal_Int32 nCharSpace = ( nPitch - nPageCharSize ) * 4096 / 20;
+
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDxtCharSpace );
+ m_rWW8Export.InsUInt32( nCharSpace );
+ }
+}
+
+void WW8AttributeOutput::FormatPaperBin( const SvxPaperBinItem& rPaperBin )
+{
+ if ( m_rWW8Export.bOutPageDescs )
+ {
+ sal_uInt16 nVal;
+ switch ( rPaperBin.GetValue() )
+ {
+ case 0: nVal = 15; break; // Automatically select
+ case 1: nVal = 1; break; // Upper paper tray
+ case 2: nVal = 4; break; // Manual paper feed
+ default: nVal = 0; break;
+ }
+
+ if ( nVal )
+ {
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( m_rWW8Export.bOutFirstPage? NS_sprm::LN_SDmBinFirst: NS_sprm::LN_SDmBinOther );
+ else
+ m_rWW8Export.pO->Insert( m_rWW8Export.bOutFirstPage? 140: 141, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( nVal );
+ }
+ }
+}
+
+void WW8AttributeOutput::FormatLRSpace( const SvxLRSpaceItem& rLR )
+{
+ // Flys fehlen noch ( siehe RTF )
+
+ if ( m_rWW8Export.bOutFlyFrmAttrs ) // Flys
+ {
+ // sprmPDxaFromText10
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaFromText10 );
+ else
+ m_rWW8Export.pO->Insert( 49, m_rWW8Export.pO->Count() );
+ // Mittelwert nehmen, da WW nur 1 Wert kennt
+ m_rWW8Export.InsUInt16( (sal_uInt16) ( ( rLR.GetLeft() + rLR.GetRight() ) / 2 ) );
+ }
+ else if ( m_rWW8Export.bOutPageDescs ) // PageDescs
+ {
+ sal_uInt16 nLDist, nRDist;
+ const SfxPoolItem* pItem = m_rWW8Export.HasItem( RES_BOX );
+ if ( pItem )
+ {
+ nRDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_LEFT );
+ nLDist = ((SvxBoxItem*)pItem)->CalcLineSpace( BOX_LINE_RIGHT );
+ }
+ else
+ nLDist = nRDist = 0;
+ nLDist = nLDist + (sal_uInt16)rLR.GetLeft();
+ nRDist = nRDist + (sal_uInt16)rLR.GetRight();
+
+ // sprmSDxaLeft
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDxaLeft );
+ else
+ m_rWW8Export.pO->Insert( 166, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( nLDist );
+
+ // sprmSDxaRight
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDxaRight );
+ else
+ m_rWW8Export.pO->Insert( 167, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( nRDist );
+ }
+ else
+ { // normale Absaetze
+ // sprmPDxaLeft
+ if( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( 0x845E ); //asian version ?
+ m_rWW8Export.InsUInt16( (sal_uInt16)rLR.GetTxtLeft() );
+ }
+ else
+ {
+ m_rWW8Export.pO->Insert( 17, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( (sal_uInt16)rLR.GetTxtLeft() );
+ }
+
+ // sprmPDxaRight
+ if( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( 0x845D ); //asian version ?
+ m_rWW8Export.InsUInt16( (sal_uInt16)rLR.GetRight() );
+ }
+ else
+ {
+ m_rWW8Export.pO->Insert( 16, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( (sal_uInt16)rLR.GetRight() );
+ }
+
+ // sprmPDxaLeft1
+ if( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( 0x8460 ); //asian version ?
+ m_rWW8Export.InsUInt16( rLR.GetTxtFirstLineOfst() );
+ }
+ else
+ {
+ m_rWW8Export.pO->Insert( 19, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( rLR.GetTxtFirstLineOfst() );
+ }
+ }
+}
+
+void WW8AttributeOutput::FormatULSpace( const SvxULSpaceItem& rUL )
+{
+ // Flys fehlen noch ( siehe RTF )
+
+ if ( m_rWW8Export.bOutFlyFrmAttrs ) // Flys
+ {
+ // sprmPDyaFromText
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaFromText );
+ else
+ m_rWW8Export.pO->Insert( 48, m_rWW8Export.pO->Count() );
+ // Mittelwert nehmen, da WW nur 1 Wert kennt
+ m_rWW8Export.InsUInt16( (sal_uInt16) ( ( rUL.GetUpper() + rUL.GetLower() ) / 2 ) );
+ }
+ else if ( m_rWW8Export.bOutPageDescs ) // Page-UL
+ {
+ OSL_ENSURE( m_rWW8Export.GetCurItemSet(), "Impossible" );
+ if ( !m_rWW8Export.GetCurItemSet() )
+ return;
+
+ HdFtDistanceGlue aDistances( *m_rWW8Export.GetCurItemSet() );
+
+ if ( aDistances.HasHeader() )
+ {
+ //sprmSDyaHdrTop
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDyaHdrTop );
+ else
+ m_rWW8Export.pO->Insert( 156, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( aDistances.dyaHdrTop );
+ }
+
+ // sprmSDyaTop
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDyaTop );
+ else
+ m_rWW8Export.pO->Insert( 168, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( aDistances.dyaTop );
+
+ if ( aDistances.HasFooter() )
+ {
+ //sprmSDyaHdrBottom
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDyaHdrBottom );
+ else
+ m_rWW8Export.pO->Insert( 157, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( aDistances.dyaHdrBottom );
+ }
+
+ //sprmSDyaBottom
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDyaBottom );
+ else
+ m_rWW8Export.pO->Insert( 169, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( aDistances.dyaBottom );
+ }
+ else
+ {
+ // sprmPDyaBefore
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaBefore );
+ else
+ m_rWW8Export.pO->Insert( 21, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( rUL.GetUpper() );
+ // sprmPDyaAfter
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaAfter );
+ else
+ m_rWW8Export.pO->Insert( 22, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( rUL.GetLower() );
+ }
+}
+
+// Print, Opaque, Protect fehlen noch
+
+void WW8AttributeOutput::FormatSurround( const SwFmtSurround& rSurround )
+{
+ if ( m_rWW8Export.bOutFlyFrmAttrs )
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PWr );
+ else
+ m_rWW8Export.pO->Insert( 37, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.pO->Insert(
+ ( SURROUND_NONE != rSurround.GetSurround() ) ? 2 : 1,
+ m_rWW8Export.pO->Count() );
+ }
+}
+
+void WW8AttributeOutput::FormatVertOrientation( const SwFmtVertOrient& rFlyVert )
+{
+//!!!! Ankertyp und entsprechende Umrechnung fehlt noch
+
+ if ( m_rWW8Export.bOutFlyFrmAttrs )
+ {
+ short nPos;
+ switch( rFlyVert.GetVertOrient() )
+ {
+ case text::VertOrientation::NONE:
+ nPos = (short)rFlyVert.GetPos();
+ break;
+ case text::VertOrientation::CENTER:
+ case text::VertOrientation::LINE_CENTER:
+ nPos = -8;
+ break;
+ case text::VertOrientation::BOTTOM:
+ case text::VertOrientation::LINE_BOTTOM:
+ nPos = -12;
+ break;
+ case text::VertOrientation::TOP:
+ case text::VertOrientation::LINE_TOP:
+ default:
+ nPos = -4;
+ break;
+ }
+
+ // sprmPDyaAbs
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaAbs );
+ else
+ m_rWW8Export.pO->Insert( 27, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( nPos );
+ }
+}
+
+
+void WW8AttributeOutput::FormatHorizOrientation( const SwFmtHoriOrient& rFlyHori )
+{
+ if ( !m_rWW8Export.mpParentFrame )
+ {
+ OSL_ENSURE( m_rWW8Export.mpParentFrame, "HoriOrient without mpParentFrame !!" );
+ return;
+ }
+
+//!!!! Ankertyp und entsprechende Umrechnung fehlt noch
+ if ( m_rWW8Export.bOutFlyFrmAttrs )
+ {
+ short nPos;
+ switch( rFlyHori.GetHoriOrient() )
+ {
+ case text::HoriOrientation::NONE:
+ nPos = (short)rFlyHori.GetPos();
+ if( !nPos )
+ nPos = 1; // WW: 0 ist reserviert
+ break;
+ case text::HoriOrientation::LEFT:
+ nPos = rFlyHori.IsPosToggle() ? -12 : 0;
+ break;
+ case text::HoriOrientation::RIGHT:
+ nPos = rFlyHori.IsPosToggle() ? -16 : -8;
+ break;
+ case text::HoriOrientation::CENTER:
+ case text::HoriOrientation::FULL: // FULL nur fuer Tabellen
+ default:
+ nPos = -4;
+ break;
+ }
+
+ // sprmPDxaAbs
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDxaAbs );
+ else
+ m_rWW8Export.pO->Insert( 26, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt16( nPos );
+ }
+}
+
+void WW8AttributeOutput::FormatAnchor( const SwFmtAnchor& rAnchor )
+{
+ OSL_ENSURE( m_rWW8Export.mpParentFrame, "Anchor without mpParentFrame !!" );
+
+ if ( m_rWW8Export.bOutFlyFrmAttrs )
+ {
+ sal_uInt8 nP = 0;
+ switch ( rAnchor.GetAnchorId() )
+ {
+ case FLY_AT_PAGE:
+ // Vert: Page | Horz: Page
+ nP |= (1 << 4) | (2 << 6);
+ break;
+ // Im Fall eine Flys als Zeichen: Absatz-gebunden setzen!!!
+ case FLY_AT_FLY:
+ case FLY_AT_CHAR:
+ case FLY_AT_PARA:
+ case FLY_AS_CHAR:
+ // Vert: Page | Horz: Page
+ nP |= (2 << 4) | (0 << 6);
+ break;
+ default:
+ break;
+ }
+
+ // sprmPPc
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PPc );
+ else
+ m_rWW8Export.pO->Insert( 29, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( nP, m_rWW8Export.pO->Count() );
+ }
+}
+
+void WW8AttributeOutput::FormatBackground( const SvxBrushItem& rBrush )
+{
+ // WW cannot have background in a section
+ if ( !m_rWW8Export.bOutPageDescs )
+ {
+ WW8_SHD aSHD;
+
+ m_rWW8Export.TransBrush( rBrush.GetColor(), aSHD );
+ // sprmPShd
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PShd );
+ else
+ m_rWW8Export.pO->Insert(47, m_rWW8Export.pO->Count());
+ m_rWW8Export.InsUInt16( aSHD.GetValue() );
+
+ // Quite a few unknowns, some might be transparency or something
+ // of that nature...
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( 0xC64D );
+ m_rWW8Export.pO->Insert( 10, m_rWW8Export.pO->Count() );
+ m_rWW8Export.InsUInt32( 0xFF000000 );
+ m_rWW8Export.InsUInt32( SuitableBGColor( rBrush.GetColor().GetColor() ) );
+ m_rWW8Export.InsUInt16( 0x0000 );
+ }
+ }
+}
+
+WW8_BRC WW8Export::TranslateBorderLine(const SvxBorderLine& rLine,
+ sal_uInt16 nDist, bool bShadow)
+{
+ // M.M. This function writes out border lines to the word format similar to
+ // what SwRTFWriter::OutRTFBorder does in the RTF filter Eventually it
+ // would be nice if all this functionality was in the one place
+ WW8_BRC aBrc;
+ sal_uInt16 nWidth = rLine.GetWidth();
+ sal_uInt8 brcType = 0, nColCode = 0;
+
+ if( nWidth ) // Linie ?
+ {
+ // BRC.brcType
+ bool bThick = !rLine.isDouble() && !bWrtWW8 && nWidth > 75;
+ if( bThick )
+ brcType = 2;
+ else
+ {
+ brcType = 0;
+ if ( bWrtWW8 )
+ {
+ // All the border types values are available on
+ // http://msdn.microsoft.com/en-us/library/dd908142%28v=office.12%29.aspx
+ switch ( rLine.GetStyle( ) )
+ {
+ case ::editeng::SOLID:
+ {
+ if ( rLine.GetWidth( ) == DEF_LINE_WIDTH_0 )
+ brcType = 5;
+ else
+ brcType = 1;
+ }
+ break;
+ case ::editeng::DOTTED:
+ brcType = 6;
+ break;
+ case ::editeng::DASHED:
+ brcType = 7;
+ break;
+ case ::editeng::DOUBLE:
+ brcType = 3;
+ break;
+ case ::editeng::THINTHICK_SMALLGAP:
+ brcType = 11;
+ break;
+ case ::editeng::THINTHICK_MEDIUMGAP:
+ brcType = 14;
+ break;
+ case ::editeng::THINTHICK_LARGEGAP:
+ brcType = 17;
+ break;
+ case ::editeng::THICKTHIN_SMALLGAP:
+ brcType = 12;
+ break;
+ case ::editeng::THICKTHIN_MEDIUMGAP:
+ brcType = 15;
+ break;
+ case ::editeng::THICKTHIN_LARGEGAP:
+ brcType = 18;
+ break;
+ case ::editeng::EMBOSSED:
+ brcType = 24;
+ break;
+ case ::editeng::ENGRAVED:
+ brcType = 25;
+ break;
+ case ::editeng::OUTSET:
+ brcType = 26;
+ break;
+ case ::editeng::INSET:
+ brcType = 27;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ // BRC.dxpLineWidth
+ if( bThick )
+ nWidth /= 2;
+
+ if( bWrtWW8 )
+ {
+ // Angabe in 8tel Punkten, also durch 2.5, da 1 Punkt = 20 Twips
+ nWidth = (( nWidth * 8 ) + 10 ) / 20;
+ if( 0xff < nWidth )
+ nWidth = 0xff;
+ }
+ else
+ {
+ // Angabe in 0.75 pt
+ nWidth = ( nWidth + 7 ) / 15;
+ if( nWidth > 5 )
+ nWidth = 5;
+ if ( ::editeng::DOTTED == rLine.GetStyle( ) )
+ nWidth = 6;
+ else if ( ::editeng::DASHED == rLine.GetStyle( ) )
+ nWidth = 7;
+ }
+
+ if( 0 == nWidth ) // ganz duenne Linie
+ nWidth = 1; // nicht weglassen
+
+ // BRC.ico
+ nColCode = TransCol( rLine.GetColor() );
+ }
+
+ // BRC.dxpSpace
+ sal_uInt16 nLDist = nDist;
+ nLDist /= 20; // Masseinheit : pt
+ if( nLDist > 0x1f )
+ nLDist = 0x1f;
+
+ if( bWrtWW8 )
+ {
+ aBrc.aBits1[0] = sal_uInt8(nWidth);
+ aBrc.aBits1[1] = brcType;
+ aBrc.aBits2[0] = nColCode;
+ aBrc.aBits2[1] = sal_uInt8(nLDist);
+
+ // fShadow, keine weiteren Einstellungen im WW moeglich
+ if( bShadow )
+ aBrc.aBits2[1] |= 0x20;
+ }
+ else
+ {
+ sal_uInt16 aBits = nWidth + ( brcType << 3 );
+ aBits |= (nColCode & 0x1f) << 6;
+ aBits |= nLDist << 11;
+ // fShadow, keine weiteren Einstellungen im WW moeglich
+ if( bShadow )
+ aBits |= 0x20;
+ ShortToSVBT16( aBits, aBrc.aBits1);
+ }
+
+ return aBrc;
+}
+
+// MakeBorderLine() bekommt einen WW8Bytes* uebergeben, um die Funktion
+// auch fuer die Tabellen-Umrandungen zu benutzen.
+// Wenn nSprmNo == 0, dann wird der Opcode nicht ausgegeben.
+// bShadow darf bei Tabellenzellen *nicht* gesetzt sein !
+void WW8Export::Out_BorderLine(WW8Bytes& rO, const SvxBorderLine* pLine,
+ sal_uInt16 nDist, sal_uInt16 nSprmNo, bool bShadow)
+{
+ OSL_ENSURE( ( nSprmNo == 0 ) ||
+ ( nSprmNo >= 38 && nSprmNo <= 41 ) ||
+ ( nSprmNo >= NS_sprm::LN_PBrcTop && nSprmNo <= NS_sprm::LN_PBrcRight ) ||
+ ( nSprmNo >= NS_sprm::LN_SBrcTop && nSprmNo <= NS_sprm::LN_SBrcRight ),
+ "Sprm for border out is of range" );
+
+ WW8_BRC aBrc;
+
+ if (pLine)
+ aBrc = TranslateBorderLine( *pLine, nDist, bShadow );
+
+ if( bWrtWW8 )
+ {
+ // WW97-SprmIds
+ if ( nSprmNo != 0 )
+ SwWW8Writer::InsUInt16( rO, nSprmNo );
+
+ rO.Insert( aBrc.aBits1, 2, rO.Count() );
+ rO.Insert( aBrc.aBits2, 2, rO.Count() );
+ }
+ else
+ {
+ // WW95-SprmIds
+ if ( nSprmNo != 0 )
+ rO.Insert( (sal_uInt8)( nSprmNo ), rO.Count() );
+ rO.Insert( aBrc.aBits1, 2, rO.Count() );
+ }
+}
+
+// FormatBox1() ist fuer alle Boxen ausser in Tabellen.
+// es wird pO des WW8Writers genommen
+void WW8Export::Out_SwFmtBox(const SvxBoxItem& rBox, bool bShadow)
+{
+ if ( bOutPageDescs && !bWrtWW8 )
+ return; // no page ouline in WW6
+
+ static const sal_uInt16 aBorders[] =
+ {
+ BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
+ };
+ static const sal_uInt16 aPBrc[] =
+ {
+ NS_sprm::LN_PBrcTop, NS_sprm::LN_PBrcLeft, NS_sprm::LN_PBrcBottom, NS_sprm::LN_PBrcRight
+ };
+ static const sal_uInt16 aSBrc[] =
+ {
+ NS_sprm::LN_SBrcTop, NS_sprm::LN_SBrcLeft, NS_sprm::LN_SBrcBottom, NS_sprm::LN_SBrcRight
+ };
+ static const sal_uInt16 aWW6PBrc[] =
+ {
+ 38, 39, 40, 41
+ };
+
+ const sal_uInt16* pBrd = aBorders;
+ for( sal_uInt16 i = 0; i < 4; ++i, ++pBrd )
+ {
+ const SvxBorderLine* pLn = rBox.GetLine( *pBrd );
+
+ sal_uInt16 nSprmNo = 0;
+ if ( !bWrtWW8 )
+ nSprmNo = aWW6PBrc[i];
+ else if ( bOutPageDescs )
+ nSprmNo = aSBrc[i];
+ else
+ nSprmNo = aPBrc[i];
+
+ Out_BorderLine( *pO, pLn, rBox.GetDistance( *pBrd ), nSprmNo, bShadow );
+ }
+}
+
+// FormatBox2() ist fuer TC-Strukturen in Tabellen. Der Sprm-Opcode
+// wird nicht geschrieben, da es in der TC-Structur ohne Opcode gepackt ist.
+// dxpSpace wird immer 0, da WW das in Tabellen so verlangt
+// ( Tabellenumrandungen fransen sonst aus )
+// Ein WW8Bytes-Ptr wird als Ausgabe-Parameter uebergeben
+
+void WW8Export::Out_SwFmtTableBox( WW8Bytes& rO, const SvxBoxItem * pBox )
+{
+ // moeglich und vielleicht besser waere 0xffff
+ static const sal_uInt16 aBorders[] =
+ {
+ BOX_LINE_TOP, BOX_LINE_LEFT, BOX_LINE_BOTTOM, BOX_LINE_RIGHT
+ };
+ static const SvxBorderLine aBorderLine;
+
+ const sal_uInt16* pBrd = aBorders;
+ for( int i = 0; i < 4; ++i, ++pBrd )
+ {
+ const SvxBorderLine* pLn;
+ if (pBox != NULL)
+ pLn = pBox->GetLine( *pBrd );
+ else
+ pLn = & aBorderLine;
+
+ Out_BorderLine(rO, pLn, 0, 0, false);
+ }
+}
+
+void WW8AttributeOutput::FormatBox( const SvxBoxItem& rBox )
+{
+ // Fly um Grafik-> keine Umrandung hier, da
+ // der GrafikHeader bereits die Umrandung hat
+ if ( !m_rWW8Export.bOutGrf )
+ {
+ bool bShadow = false;
+ const SfxPoolItem* pItem = m_rWW8Export.HasItem( RES_SHADOW );
+ if ( pItem )
+ {
+ const SvxShadowItem* p = (const SvxShadowItem*)pItem;
+ bShadow = ( p->GetLocation() != SVX_SHADOW_NONE )
+ && ( p->GetWidth() != 0 );
+ }
+
+ m_rWW8Export.Out_SwFmtBox( rBox, bShadow );
+ }
+}
+
+SwTwips WW8Export::CurrentPageWidth(SwTwips &rLeft, SwTwips &rRight) const
+{
+ const SwFrmFmt* pFmt = pAktPageDesc ? &pAktPageDesc->GetMaster()
+ : &const_cast<const SwDoc *>(pDoc)->GetPageDesc(0).GetMaster();
+
+ const SvxLRSpaceItem& rLR = pFmt->GetLRSpace();
+ SwTwips nPageSize = pFmt->GetFrmSize().GetWidth();
+ rLeft = rLR.GetLeft();
+ rRight = rLR.GetRight();
+ return nPageSize;
+}
+
+void WW8AttributeOutput::FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol & rCol, bool bEven, SwTwips nPageSize )
+{
+ // CColumns
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SCcolumns );
+ else
+ m_rWW8Export.pO->Insert( 144, m_rWW8Export.pO->Count( ) );
+ m_rWW8Export.InsUInt16( nCols - 1 );
+
+ // DxaColumns
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDxaColumns );
+ else
+ m_rWW8Export.pO->Insert( 145, m_rWW8Export.pO->Count( ) );
+ m_rWW8Export.InsUInt16( rCol.GetGutterWidth( true ) );
+
+ // LBetween
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SLBetween );
+ else
+ m_rWW8Export.pO->Insert( 158, m_rWW8Export.pO->Count( ) );
+ m_rWW8Export.pO->Insert( COLADJ_NONE == rCol.GetLineAdj( )? 0 : 1,
+ m_rWW8Export.pO->Count( ) );
+
+ const SwColumns & rColumns = rCol.GetColumns( );
+
+ // FEvenlySpaced
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SFEvenlySpaced );
+ else
+ m_rWW8Export.pO->Insert( 138, m_rWW8Export.pO->Count( ) );
+ m_rWW8Export.pO->Insert( bEven ? 1 : 0, m_rWW8Export.pO->Count( ) );
+
+ if ( !bEven )
+ {
+ for ( sal_uInt16 n = 0; n < nCols; ++n )
+ {
+ //sprmSDxaColWidth
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDxaColWidth );
+ else
+ m_rWW8Export.pO->Insert( 136, m_rWW8Export.pO->Count( ) );
+ m_rWW8Export.pO->Insert( ( sal_uInt8 ) n, m_rWW8Export.pO->Count( ) );
+ m_rWW8Export.InsUInt16( rCol.
+ CalcPrtColWidth( n,
+ ( sal_uInt16 ) nPageSize ) );
+
+ if ( n + 1 != nCols )
+ {
+ //sprmSDxaColSpacing
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SDxaColSpacing );
+ else
+ m_rWW8Export.pO->Insert( 137,
+ m_rWW8Export.pO->Count( ) );
+ m_rWW8Export.pO->Insert( ( sal_uInt8 ) n,
+ m_rWW8Export.pO->Count( ) );
+ m_rWW8Export.InsUInt16( rColumns[n]->GetRight( ) +
+ rColumns[n + 1]->GetLeft( ) );
+ }
+ }
+ }
+}
+
+void AttributeOutputBase::FormatColumns( const SwFmtCol& rCol )
+{
+ const SwColumns& rColumns = rCol.GetColumns();
+
+ sal_uInt16 nCols = rColumns.Count();
+ if ( 1 < nCols && !GetExport( ).bOutFlyFrmAttrs )
+ {
+ // dann besorge mal die Seitenbreite ohne Raender !!
+
+ const SwFrmFmt* pFmt = GetExport( ).pAktPageDesc ? &GetExport( ).pAktPageDesc->GetMaster() : &const_cast<const SwDoc *>(GetExport( ).pDoc)->GetPageDesc(0).GetMaster();
+ const SvxFrameDirectionItem &frameDirection = pFmt->GetFrmDir();
+ SwTwips nPageSize;
+ if ( frameDirection.GetValue() == FRMDIR_VERT_TOP_RIGHT || frameDirection.GetValue() == FRMDIR_VERT_TOP_LEFT )
+ {
+ const SvxULSpaceItem &rUL = pFmt->GetULSpace();
+ nPageSize = pFmt->GetFrmSize().GetHeight();
+ nPageSize -= rUL.GetUpper() + rUL.GetLower();
+
+ const SwFmtHeader *header = dynamic_cast<const SwFmtHeader *>(pFmt->GetAttrSet().GetItem(RES_HEADER));
+ if ( header )
+ {
+ const SwFrmFmt *headerFmt = header->GetHeaderFmt();
+ if (headerFmt)
+ {
+ nPageSize -= headerFmt->GetFrmSize().GetHeight();
+ }
+ }
+ const SwFmtFooter *footer = dynamic_cast<const SwFmtFooter *>(pFmt->GetAttrSet().GetItem(RES_FOOTER));
+ if ( footer )
+ {
+ const SwFrmFmt *footerFmt = footer->GetFooterFmt();
+ if ( footerFmt )
+ {
+ nPageSize -= footerFmt->GetFrmSize().GetHeight();
+ }
+ }
+ }
+ else
+ {
+ const SvxLRSpaceItem &rLR = pFmt->GetLRSpace();
+ nPageSize = pFmt->GetFrmSize().GetWidth();
+ nPageSize -= rLR.GetLeft() + rLR.GetRight();
+ }
+
+ // Nachsehen, ob alle Spalten gleich sind
+ bool bEven = true;
+ sal_uInt16 n;
+ sal_uInt16 nColWidth = rCol.CalcPrtColWidth( 0, (sal_uInt16)nPageSize );
+ for ( n = 1; n < nCols; n++ )
+ {
+ short nDiff = nColWidth -
+ rCol.CalcPrtColWidth( n, (sal_uInt16)nPageSize );
+
+ if ( nDiff > 10 || nDiff < -10 ) // Toleranz: 10 tw
+ {
+ bEven = false;
+ break;
+ }
+ }
+
+ FormatColumns_Impl( nCols, rCol, bEven, nPageSize );
+ }
+}
+
+// "Paragraphs together"
+void WW8AttributeOutput::FormatKeep( const SvxFmtKeepItem& rKeep )
+{
+ // sprmFKeepFollow
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFKeepFollow );
+ else
+ m_rWW8Export.pO->Insert( 8, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.pO->Insert( rKeep.GetValue() ? 1 : 0, m_rWW8Export.pO->Count() );
+}
+
+// exclude a paragraph from Line Numbering
+void WW8AttributeOutput::FormatLineNumbering( const SwFmtLineNumber& rNumbering )
+{
+ // sprmPFNoLineNumb
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFNoLineNumb );
+ else
+ m_rWW8Export.pO->Insert( 14, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.pO->Insert( rNumbering.IsCount() ? 0 : 1, m_rWW8Export.pO->Count() );
+}
+
+
+/* File PARATR.HXX */
+
+void WW8AttributeOutput::ParaLineSpacing_Impl( short nSpace, short nMulti )
+{
+ // sprmPDyaLine
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PDyaLine );
+ else
+ m_rWW8Export.pO->Insert( 20, m_rWW8Export.pO->Count() );
+
+ m_rWW8Export.InsUInt16( nSpace );
+ m_rWW8Export.InsUInt16( nMulti );
+}
+
+void AttributeOutputBase::ParaLineSpacing( const SvxLineSpacingItem& rSpacing )
+{
+ short nSpace = 240, nMulti = 0;
+
+ switch ( rSpacing.GetLineSpaceRule() )
+ {
+ default:
+ break;
+ case SVX_LINE_SPACE_AUTO:
+ case SVX_LINE_SPACE_FIX:
+ case SVX_LINE_SPACE_MIN:
+ {
+ switch ( rSpacing.GetInterLineSpaceRule() )
+ {
+ case SVX_INTER_LINE_SPACE_FIX: // unser Durchschuss
+ {
+ // gibt es aber nicht in WW - also wie kommt man an
+ // die MaxLineHeight heran?
+ nSpace = (short)rSpacing.GetInterLineSpace();
+ sal_uInt16 nScript =
+ i18n::ScriptType::LATIN;
+ const SwAttrSet *pSet = 0;
+ if ( GetExport().pOutFmtNode && GetExport().pOutFmtNode->ISA( SwFmt ) )
+ {
+ const SwFmt *pFmt = (const SwFmt*)( GetExport().pOutFmtNode );
+ pSet = &pFmt->GetAttrSet();
+ }
+ else if ( GetExport().pOutFmtNode && GetExport().pOutFmtNode->ISA( SwTxtNode ) )
+ {
+ const SwTxtNode* pNd = (const SwTxtNode*)GetExport().pOutFmtNode;
+ pSet = &pNd->GetSwAttrSet();
+ if ( pBreakIt->GetBreakIter().is() )
+ {
+ nScript = pBreakIt->GetBreakIter()->
+ getScriptType(pNd->GetTxt(), 0);
+ }
+ }
+ OSL_ENSURE( pSet, "No attrset for lineheight :-(" );
+ if ( pSet )
+ {
+ nSpace = nSpace + (short)( AttrSetToLineHeight( *GetExport().pDoc,
+ *pSet, *Application::GetDefaultDevice(), nScript ) );
+ }
+ }
+ break;
+ case SVX_INTER_LINE_SPACE_PROP:
+ nSpace = (short)( ( 240L * rSpacing.GetPropLineSpace() ) / 100L );
+ nMulti = 1;
+ break;
+ default: // z.B. Minimum oder FIX?
+ if ( SVX_LINE_SPACE_FIX == rSpacing.GetLineSpaceRule() )
+ nSpace = -(short)rSpacing.GetLineHeight();
+ else
+ nSpace = (short)rSpacing.GetLineHeight();
+ break;
+ }
+ }
+ break;
+ }
+ // if nSpace is negative, it is a fixed size in 1/20 of a point
+ // if nSpace is positive and nMulti is 1, it is 1/240 of a single line height
+ // otherwise, I have no clue what the heck it is
+ ParaLineSpacing_Impl( nSpace, nMulti );
+}
+
+void WW8AttributeOutput::ParaAdjust( const SvxAdjustItem& rAdjust )
+{
+ // sprmPJc
+ sal_uInt8 nAdj = 255;
+ sal_uInt8 nAdjBiDi = 255;
+ switch ( rAdjust.GetAdjust() )
+ {
+ case SVX_ADJUST_LEFT:
+ nAdj = 0;
+ nAdjBiDi = 2;
+ break;
+ case SVX_ADJUST_RIGHT:
+ nAdj = 2;
+ nAdjBiDi = 0;
+ break;
+ case SVX_ADJUST_BLOCKLINE:
+ case SVX_ADJUST_BLOCK:
+ nAdj = nAdjBiDi = 3;
+ break;
+ case SVX_ADJUST_CENTER:
+ nAdj = nAdjBiDi = 1;
+ break;
+ default:
+ return; // not a supported Attribut
+ }
+
+ if ( 255 != nAdj ) // supported Attribut?
+ {
+ if ( m_rWW8Export.bWrtWW8 )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PJc );
+ m_rWW8Export.pO->Insert( nAdj, m_rWW8Export.pO->Count() );
+
+ /*
+ Sadly for left to right paragraphs both these values are the same,
+ for right to left paragraphs the bidi one is the reverse of the
+ normal one.
+ */
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PJcExtra ); //bidi version ?
+ bool bBiDiSwap = false;
+ if ( m_rWW8Export.pOutFmtNode )
+ {
+ short nDirection = FRMDIR_HORI_LEFT_TOP;
+ if ( m_rWW8Export.pOutFmtNode->ISA( SwTxtNode ) )
+ {
+ SwPosition aPos(*(const SwCntntNode*)m_rWW8Export.pOutFmtNode);
+ nDirection = m_rWW8Export.pDoc->GetTextDirection(aPos);
+ }
+ else if ( m_rWW8Export.pOutFmtNode->ISA( SwTxtFmtColl ) )
+ {
+ const SwTxtFmtColl* pC =
+ (const SwTxtFmtColl*)m_rWW8Export.pOutFmtNode;
+ const SvxFrameDirectionItem &rItem =
+ ItemGet<SvxFrameDirectionItem>(*pC, RES_FRAMEDIR);
+ nDirection = rItem.GetValue();
+ }
+ if ( ( nDirection == FRMDIR_HORI_RIGHT_TOP ) ||
+ ( nDirection == FRMDIR_ENVIRONMENT && Application::GetSettings().GetLayoutRTL() ) )
+ {
+ bBiDiSwap = true;
+ }
+ }
+
+ if ( bBiDiSwap )
+ m_rWW8Export.pO->Insert( nAdjBiDi, m_rWW8Export.pO->Count() );
+ else
+ m_rWW8Export.pO->Insert( nAdj, m_rWW8Export.pO->Count() );
+ }
+ else
+ {
+ m_rWW8Export.pO->Insert( 5, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( nAdj, m_rWW8Export.pO->Count() );
+ }
+ }
+}
+
+void WW8AttributeOutput::FormatFrameDirection( const SvxFrameDirectionItem& rDirection )
+{
+ if ( !m_rWW8Export.bWrtWW8 ) //8+ only
+ return;
+
+ sal_uInt16 nTextFlow=0;
+ bool bBiDi = false;
+ short nDir = rDirection.GetValue();
+
+ if ( nDir == FRMDIR_ENVIRONMENT )
+ {
+ if ( m_rWW8Export.bOutPageDescs )
+ nDir = m_rWW8Export.GetCurrentPageDirection();
+ else if ( m_rWW8Export.pOutFmtNode )
+ {
+ if ( m_rWW8Export.bOutFlyFrmAttrs ) //frame
+ {
+ nDir = m_rWW8Export.TrueFrameDirection(
+ *(const SwFrmFmt*)m_rWW8Export.pOutFmtNode );
+ }
+ else if ( m_rWW8Export.pOutFmtNode->ISA( SwCntntNode ) ) //pagagraph
+ {
+ const SwCntntNode* pNd =
+ (const SwCntntNode*)m_rWW8Export.pOutFmtNode;
+ SwPosition aPos( *pNd );
+ nDir = m_rWW8Export.pDoc->GetTextDirection( aPos );
+ }
+ else if ( m_rWW8Export.pOutFmtNode->ISA( SwTxtFmtColl ) )
+ nDir = FRMDIR_HORI_LEFT_TOP; //what else can we do :-(
+ }
+
+ if ( nDir == FRMDIR_ENVIRONMENT )
+ nDir = FRMDIR_HORI_LEFT_TOP; //Set something
+ }
+
+ switch ( nDir )
+ {
+ default:
+ //Can't get an unknown type here
+ OSL_FAIL("Unknown frame direction");
+ case FRMDIR_HORI_LEFT_TOP:
+ nTextFlow = 0;
+ break;
+ case FRMDIR_HORI_RIGHT_TOP:
+ nTextFlow = 0;
+ bBiDi = true;
+ break;
+ case FRMDIR_VERT_TOP_LEFT: //word doesn't have this
+ case FRMDIR_VERT_TOP_RIGHT:
+ nTextFlow = 1;
+ break;
+ }
+
+ if ( m_rWW8Export.bOutPageDescs )
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_STextFlow );
+ m_rWW8Export.InsUInt16( nTextFlow );
+ m_rWW8Export.InsUInt16( NS_sprm::LN_SFBiDi );
+ m_rWW8Export.pO->Insert( bBiDi, m_rWW8Export.pO->Count() );
+ }
+ else if ( !m_rWW8Export.bOutFlyFrmAttrs ) //paragraph/style
+ {
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFBiDi );
+ m_rWW8Export.pO->Insert( bBiDi, m_rWW8Export.pO->Count() );
+ }
+}
+
+// "Separate paragraphs"
+void WW8AttributeOutput::ParaSplit( const SvxFmtSplitItem& rSplit )
+{
+ // sprmPFKeep
+ if ( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFKeep );
+ else
+ m_rWW8Export.pO->Insert( 7, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( rSplit.GetValue() ? 0 : 1, m_rWW8Export.pO->Count() );
+}
+
+// Es wird nur das Item "SvxWidowItem" und nicht die Orphans uebersetzt,
+// da es fuer beides im WW nur ein Attribut "Absatzkontrolle" gibt und
+// im SW wahrscheinlich vom Anwender immer Beide oder keiner gesetzt werden.
+void WW8AttributeOutput::ParaWidows( const SvxWidowsItem& rWidows )
+{
+// sprmPFWidowControl
+ if( m_rWW8Export.bWrtWW8 )
+ m_rWW8Export.InsUInt16( NS_sprm::LN_PFWidowControl );
+ else
+ m_rWW8Export.pO->Insert( 51, m_rWW8Export.pO->Count() );
+ m_rWW8Export.pO->Insert( rWidows.GetValue() ? 1 : 0, m_rWW8Export.pO->Count() );
+}
+
+
+class SwWW8WrTabu
+{
+ sal_uInt8* pDel; // DelArray
+ sal_uInt8* pAddPos; // AddPos-Array
+ sal_uInt8* pAddTyp; // AddTyp-Array
+ sal_uInt16 nAdd; // so viele Tabs kommen hinzu
+ sal_uInt16 nDel; // so viele Tabs fallen weg
+public:
+ SwWW8WrTabu(sal_uInt16 nDelMax, sal_uInt16 nAddMax);
+ ~SwWW8WrTabu();
+
+ void Add(const SvxTabStop &rTS, long nAdjustment);
+ void Del(const SvxTabStop &rTS, long nAdjustment);
+ void PutAll(WW8Export& rWW8Wrt);
+};
+
+SwWW8WrTabu::SwWW8WrTabu(sal_uInt16 nDelMax, sal_uInt16 nAddMax)
+ : nAdd(0), nDel(0)
+{
+ pDel = nDelMax ? new sal_uInt8[nDelMax * 2] : 0;
+ pAddPos = new sal_uInt8[nAddMax * 2];
+ pAddTyp = new sal_uInt8[nAddMax];
+}
+
+SwWW8WrTabu::~SwWW8WrTabu()
+{
+ delete[] pAddTyp;
+ delete[] pAddPos;
+ delete[] pDel;
+}
+
+// Add( const SvxTabStop & rTS ) fuegt einen Tab in die WW-Struktur ein
+void SwWW8WrTabu::Add(const SvxTabStop & rTS, long nAdjustment)
+{
+ // Tab-Position eintragen
+ ShortToSVBT16(msword_cast<sal_Int16>(rTS.GetTabPos() + nAdjustment),
+ pAddPos + (nAdd * 2));
+
+ // Tab-Typ eintragen
+ sal_uInt8 nPara = 0;
+ switch (rTS.GetAdjustment())
+ {
+ case SVX_TAB_ADJUST_RIGHT:
+ nPara = 2;
+ break;
+ case SVX_TAB_ADJUST_CENTER:
+ nPara = 1;
+ break;
+ case SVX_TAB_ADJUST_DECIMAL:
+ /*
+ Theres nothing we can do btw the the decimal seperator has been
+ customized, but if you think different remember that different
+ locales have different seperators, i.e. german is a , while english
+ is a .
+ */
+ nPara = 3;
+ break;
+ default:
+ break;
+ }
+
+ switch( rTS.GetFill() )
+ {
+ case '.': // dotted leader
+ nPara |= 1 << 3;
+ break;
+ case '_': // Single line leader
+ nPara |= 3 << 3;
+ break;
+ case '-': // hyphenated leader
+ nPara |= 2 << 3;
+ break;
+ case '=': // heavy line leader
+ nPara |= 4 << 3;
+ break;
+ }
+
+ ByteToSVBT8(nPara, pAddTyp + nAdd);
+ ++nAdd;
+}
+
+// Del( const SvxTabStop & rTS ) fuegt einen zu loeschenden Tab
+// in die WW-Struktur ein
+void SwWW8WrTabu::Del(const SvxTabStop &rTS, long nAdjustment)
+{
+ // Tab-Position eintragen
+ ShortToSVBT16(msword_cast<sal_Int16>(rTS.GetTabPos() + nAdjustment),
+ pDel + (nDel * 2));
+ ++nDel;
+}
+
+// PutAll( WW8Export& rWW8Wrt ) schreibt das Attribut nach rWrt.pO
+void SwWW8WrTabu::PutAll(WW8Export& rWrt)
+{
+ if (!nAdd && !nDel) //It its a no-op
+ return;
+ OSL_ENSURE(nAdd <= 255, "more than 255 added tabstops ?");
+ OSL_ENSURE(nDel <= 255, "more than 244 removed tabstops ?");
+ if (nAdd > 255)
+ nAdd = 255;
+ if (nDel > 255)
+ nDel = 255;
+
+ sal_uInt16 nSiz = 2 * nDel + 3 * nAdd + 2;
+ if (nSiz > 255)
+ nSiz = 255;
+
+ if (rWrt.bWrtWW8)
+ rWrt.InsUInt16(NS_sprm::LN_PChgTabsPapx);
+ else
+ rWrt.pO->Insert(15, rWrt.pO->Count());
+ // cch eintragen
+ rWrt.pO->Insert(msword_cast<sal_uInt8>(nSiz), rWrt.pO->Count());
+ // DelArr schreiben
+ rWrt.pO->Insert(msword_cast<sal_uInt8>(nDel), rWrt.pO->Count());
+ rWrt.OutSprmBytes(pDel, nDel * 2);
+ // InsArr schreiben
+ rWrt.pO->Insert(msword_cast<sal_uInt8>(nAdd), rWrt.pO->Count());
+ rWrt.OutSprmBytes(pAddPos, 2 * nAdd); // AddPosArray
+ rWrt.OutSprmBytes(pAddTyp, nAdd); // AddTypArray
+}
+
+
+static void ParaTabStopAdd( WW8Export& rWrt, const SvxTabStopItem& rTStops,
+ long nLParaMgn )
+{
+ SwWW8WrTabu aTab( 0, rTStops.Count());
+
+ for( sal_uInt16 n = 0; n < rTStops.Count(); n++ )
+ {
+ const SvxTabStop& rTS = rTStops[n];
+ // Def-Tabs ignorieren
+ if (SVX_TAB_ADJUST_DEFAULT != rTS.GetAdjustment())
+ aTab.Add(rTS, nLParaMgn);
+ }
+ aTab.PutAll( rWrt );
+}
+
+bool lcl_IsEqual(long nOneLeft, const SvxTabStop &rOne,
+ long nTwoLeft, const SvxTabStop &rTwo)
+{
+ return(
+ nOneLeft == nTwoLeft &&
+ rOne.GetAdjustment() == rTwo.GetAdjustment() &&
+ rOne.GetDecimal() == rTwo.GetDecimal() &&
+ rOne.GetFill() == rTwo.GetFill()
+ );
+}
+
+static void ParaTabStopDelAdd( WW8Export& rWrt, const SvxTabStopItem& rTStyle,
+ long nLStypeMgn, const SvxTabStopItem& rTNew, long nLParaMgn )
+{
+ SwWW8WrTabu aTab(rTStyle.Count(), rTNew.Count());
+
+ sal_uInt16 nO = 0; // rTStyle Index
+ sal_uInt16 nN = 0; // rTNew Index
+
+ do {
+ const SvxTabStop* pTO;
+ long nOP;
+ if( nO < rTStyle.Count() ) // alt noch nicht am Ende ?
+ {
+ pTO = &rTStyle[ nO ];
+ nOP = pTO->GetTabPos() + nLStypeMgn;
+ if( SVX_TAB_ADJUST_DEFAULT == pTO->GetAdjustment() )
+ {
+ nO++; // Default-Tab ignorieren
+ continue;
+ }
+ }
+ else
+ {
+ pTO = 0;
+ nOP = LONG_MAX;
+ }
+
+ const SvxTabStop* pTN;
+ long nNP;
+ if( nN < rTNew.Count() ) // neu noch nicht am Ende
+ {
+ pTN = &rTNew[ nN ];
+ nNP = pTN->GetTabPos() + nLParaMgn;
+ if( SVX_TAB_ADJUST_DEFAULT == pTN->GetAdjustment() )
+ {
+ nN++; // Default-Tab ignorieren
+ continue;
+ }
+ }
+ else
+ {
+ pTN = 0;
+ nNP = LONG_MAX;
+ }
+
+ if( nOP == LONG_MAX && nNP == LONG_MAX )
+ break; // alles fertig
+
+ if( nOP < nNP ) // naechster Tab ist alt
+ {
+ aTab.Del(*pTO, nLStypeMgn); // muss geloescht werden
+ nO++;
+ }
+ else if( nNP < nOP ) // naechster Tab ist neu
+ {
+ aTab.Add(*pTN, nLParaMgn); // muss eigefuegt werden
+ nN++;
+ }
+ else if (lcl_IsEqual(nOP, *pTO, nNP, *pTN)) // Tabs sind gleich:
+ {
+ nO++; // nichts zu tun
+ nN++;
+ }
+ else // Tabs selbe Pos, diff Typ
+ {
+ aTab.Del(*pTO, nLStypeMgn); // alten loeschen
+ aTab.Add(*pTN, nLParaMgn); // neuen einfuegen
+ nO++;
+ nN++;
+ }
+ } while( 1 );
+
+ aTab.PutAll( rWrt );
+}
+
+void WW8AttributeOutput::ParaTabStop( const SvxTabStopItem& rTabStops )
+{
+ bool bTabsRelativeToIndex = m_rWW8Export.pCurPam->GetDoc()->get( IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT );
+ long nCurrentLeft = 0;
+
+ if ( bTabsRelativeToIndex )
+ {
+ const SfxPoolItem* pLR = m_rWW8Export.HasItem( RES_LR_SPACE );
+
+ if ( pLR != NULL )
+ nCurrentLeft = ((const SvxLRSpaceItem*)pLR)->GetTxtLeft();
+ }
+
+ // #i100264#
+ if ( m_rWW8Export.bStyDef &&
+ m_rWW8Export.pCurrentStyle != NULL &&
+ m_rWW8Export.pCurrentStyle->DerivedFrom() != NULL )
+ {
+ SvxTabStopItem aTabs( 0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
+ const SwFmt *pParentStyle = m_rWW8Export.pCurrentStyle->DerivedFrom();
+ const SvxTabStopItem* pParentTabs = HasItem<SvxTabStopItem>( pParentStyle->GetAttrSet(), RES_PARATR_TABSTOP );
+ if ( pParentTabs )
+ {
+ aTabs.Insert( pParentTabs );
+ }
+
+ ParaTabStopDelAdd( m_rWW8Export, aTabs, 0, rTabStops, 0 );
+ return;
+ }
+ // <--
+
+ // StyleDef -> "einfach" eintragen || keine Style-Attrs -> dito
+ const SvxTabStopItem* pStyleTabs = 0;
+ if ( !m_rWW8Export.bStyDef && m_rWW8Export.pStyAttr )
+ {
+ pStyleTabs =
+ HasItem<SvxTabStopItem>( *m_rWW8Export.pStyAttr, RES_PARATR_TABSTOP );
+ }
+
+ if ( !pStyleTabs )
+ ParaTabStopAdd(m_rWW8Export, rTabStops, nCurrentLeft);
+ else
+ {
+ long nStyleLeft = 0;
+
+ if (bTabsRelativeToIndex)
+ {
+ const SvxLRSpaceItem &rStyleLR =
+ ItemGet<SvxLRSpaceItem>(*m_rWW8Export.pStyAttr, RES_LR_SPACE);
+ nStyleLeft = rStyleLR.GetTxtLeft();
+ }
+
+ ParaTabStopDelAdd(m_rWW8Export, *pStyleTabs, nStyleLeft, rTabStops,
+ nCurrentLeft);
+ }
+}
+
+//-----------------------------------------------------------------------
+
+void AttributeOutputBase::OutputItem( const SfxPoolItem& rHt )
+{
+ // FIXME maybe use 'item_cast', like 'item_cast<SvxCharHiddenItem>( rHt )'?
+ switch ( rHt.Which() )
+ {
+ case RES_CHRATR_CASEMAP:
+ CharCaseMap( static_cast< const SvxCaseMapItem& >( rHt ) );
+ break;
+ case RES_CHRATR_COLOR:
+ CharColor( static_cast< const SvxColorItem& >( rHt ) );
+ break;
+ case RES_CHRATR_CONTOUR:
+ CharContour( static_cast< const SvxContourItem& >( rHt ) );
+ break;
+ case RES_CHRATR_CROSSEDOUT:
+ CharCrossedOut( static_cast< const SvxCrossedOutItem& >( rHt ) );
+ break;
+ case RES_CHRATR_ESCAPEMENT:
+ CharEscapement( static_cast< const SvxEscapementItem& >( rHt ) );
+ break;
+ case RES_CHRATR_FONT:
+ CharFont( static_cast< const SvxFontItem& >( rHt ) );
+ break;
+ case RES_CHRATR_FONTSIZE:
+ CharFontSize( static_cast< const SvxFontHeightItem& >( rHt ) );
+ break;
+ case RES_CHRATR_KERNING:
+ CharKerning( static_cast< const SvxKerningItem& >( rHt ) );
+ break;
+ case RES_CHRATR_LANGUAGE:
+ CharLanguage( static_cast< const SvxLanguageItem& >( rHt ) );
+ break;
+ case RES_CHRATR_POSTURE:
+ CharPosture( static_cast< const SvxPostureItem& >( rHt ) );
+ break;
+ case RES_CHRATR_SHADOWED:
+ CharShadow( static_cast< const SvxShadowedItem& >( rHt ) );
+ break;
+ case RES_CHRATR_UNDERLINE:
+ CharUnderline( static_cast< const SvxUnderlineItem& >( rHt ) );
+ break;
+ case RES_CHRATR_WEIGHT:
+ CharWeight( static_cast< const SvxWeightItem& >( rHt ) );
+ break;
+ case RES_CHRATR_AUTOKERN:
+ CharAutoKern( static_cast< const SvxAutoKernItem& >( rHt ) );
+ break;
+ case RES_CHRATR_BLINK:
+ CharAnimatedText( static_cast< const SvxBlinkItem& >( rHt ) );
+ break;
+ case RES_CHRATR_BACKGROUND:
+ CharBackground( static_cast< const SvxBrushItem& >( rHt ) );
+ break;
+
+ case RES_CHRATR_CJK_FONT:
+ CharFontCJK( static_cast< const SvxFontItem& >( rHt ) );
+ break;
+ case RES_CHRATR_CJK_FONTSIZE:
+ CharFontSizeCJK( static_cast< const SvxFontHeightItem& >( rHt ) );
+ break;
+ case RES_CHRATR_CJK_LANGUAGE:
+ CharLanguageCJK( static_cast< const SvxLanguageItem& >( rHt ) );
+ break;
+ case RES_CHRATR_CJK_POSTURE:
+ CharPostureCJK( static_cast< const SvxPostureItem& >( rHt ) );
+ break;
+ case RES_CHRATR_CJK_WEIGHT:
+ CharWeightCJK( static_cast< const SvxWeightItem& >( rHt ) );
+ break;
+
+ case RES_CHRATR_CTL_FONT:
+ CharFontCTL( static_cast< const SvxFontItem& >( rHt ) );
+ break;
+ case RES_CHRATR_CTL_FONTSIZE:
+ CharFontSizeCTL( static_cast< const SvxFontHeightItem& >( rHt ) );
+ break;
+ case RES_CHRATR_CTL_LANGUAGE:
+ CharLanguageCTL( static_cast< const SvxLanguageItem& >( rHt ) );
+ break;
+ case RES_CHRATR_CTL_POSTURE:
+ CharPostureCTL( static_cast< const SvxPostureItem& >( rHt ) );
+ break;
+ case RES_CHRATR_CTL_WEIGHT:
+ CharWeightCTL( static_cast< const SvxWeightItem& >( rHt ) );
+ break;
+
+ case RES_CHRATR_ROTATE:
+ CharRotate( static_cast< const SvxCharRotateItem& >( rHt ) );
+ break;
+ case RES_CHRATR_EMPHASIS_MARK:
+ CharEmphasisMark( static_cast< const SvxEmphasisMarkItem& >( rHt ) );
+ break;
+ case RES_CHRATR_TWO_LINES:
+ CharTwoLines( static_cast< const SvxTwoLinesItem& >( rHt ) );
+ break;
+ case RES_CHRATR_SCALEW:
+ CharScaleWidth( static_cast< const SvxCharScaleWidthItem& >( rHt ) );
+ break;
+ case RES_CHRATR_RELIEF:
+ CharRelief( static_cast< const SvxCharReliefItem& >( rHt ) );
+ break;
+ case RES_CHRATR_HIDDEN:
+ CharHidden( static_cast< const SvxCharHiddenItem& >( rHt ) );
+ break;
+
+ case RES_TXTATR_INETFMT:
+ TextINetFormat( static_cast< const SwFmtINetFmt& >( rHt ) );
+ break;
+ case RES_TXTATR_CHARFMT:
+ TextCharFormat( static_cast< const SwFmtCharFmt& >( rHt ) );
+ break;
+ case RES_TXTATR_FIELD:
+ TextField( static_cast< const SwFmtFld& >( rHt ) );
+ break;
+ case RES_TXTATR_FLYCNT:
+ TextFlyContent( static_cast< const SwFmtFlyCnt& >( rHt ) );
+ break;
+ case RES_TXTATR_FTN:
+ TextFootnote( static_cast< const SwFmtFtn& >( rHt ) );
+ break;
+
+ case RES_PARATR_LINESPACING:
+ ParaLineSpacing( static_cast< const SvxLineSpacingItem& >( rHt ) );
+ break;
+ case RES_PARATR_ADJUST:
+ ParaAdjust( static_cast< const SvxAdjustItem& >( rHt ) );
+ break;
+ case RES_PARATR_SPLIT:
+ ParaSplit( static_cast< const SvxFmtSplitItem& >( rHt ) );
+ break;
+ case RES_PARATR_WIDOWS:
+ ParaWidows( static_cast< const SvxWidowsItem& >( rHt ) );
+ break;
+ case RES_PARATR_TABSTOP:
+ ParaTabStop( static_cast< const SvxTabStopItem& >( rHt ) );
+ break;
+ case RES_PARATR_HYPHENZONE:
+ ParaHyphenZone( static_cast< const SvxHyphenZoneItem& >( rHt ) );
+ break;
+ case RES_PARATR_NUMRULE:
+ ParaNumRule( static_cast< const SwNumRuleItem& >( rHt ) );
+ break;
+ case RES_PARATR_SCRIPTSPACE:
+ ParaScriptSpace( static_cast< const SfxBoolItem& >( rHt ) );
+ break;
+ case RES_PARATR_HANGINGPUNCTUATION:
+ ParaHangingPunctuation( static_cast< const SfxBoolItem& >( rHt ) );
+ break;
+ case RES_PARATR_FORBIDDEN_RULES:
+ ParaForbiddenRules( static_cast< const SfxBoolItem& >( rHt ) );
+ break;
+ case RES_PARATR_VERTALIGN:
+ ParaVerticalAlign( static_cast< const SvxParaVertAlignItem& >( rHt ) );
+ break;
+ case RES_PARATR_SNAPTOGRID:
+ ParaSnapToGrid( static_cast< const SvxParaGridItem& >( rHt ) );
+ break;
+
+ case RES_FRM_SIZE:
+ FormatFrameSize( static_cast< const SwFmtFrmSize& >( rHt ) );
+ break;
+ case RES_PAPER_BIN:
+ FormatPaperBin( static_cast< const SvxPaperBinItem& >( rHt ) );
+ break;
+ case RES_LR_SPACE:
+ FormatLRSpace( static_cast< const SvxLRSpaceItem& >( rHt ) );
+ break;
+ case RES_UL_SPACE:
+ FormatULSpace( static_cast< const SvxULSpaceItem& >( rHt ) );
+ break;
+ case RES_PAGEDESC:
+ FormatPageDescription( static_cast< const SwFmtPageDesc& >( rHt ) );
+ break;
+ case RES_BREAK:
+ FormatBreak( static_cast< const SvxFmtBreakItem& >( rHt ) );
+ break;
+ case RES_SURROUND:
+ FormatSurround( static_cast< const SwFmtSurround& >( rHt ) );
+ break;
+ case RES_VERT_ORIENT:
+ FormatVertOrientation( static_cast< const SwFmtVertOrient& >( rHt ) );
+ break;
+ case RES_HORI_ORIENT:
+ FormatHorizOrientation( static_cast< const SwFmtHoriOrient& >( rHt ) );
+ break;
+ case RES_ANCHOR:
+ FormatAnchor( static_cast< const SwFmtAnchor& >( rHt ) );
+ break;
+ case RES_BACKGROUND:
+ FormatBackground( static_cast< const SvxBrushItem& >( rHt ) );
+ break;
+ case RES_BOX:
+ FormatBox( static_cast< const SvxBoxItem& >( rHt ) );
+ break;
+ case RES_COL:
+ FormatColumns( static_cast< const SwFmtCol& >( rHt ) );
+ break;
+ case RES_KEEP:
+ FormatKeep( static_cast< const SvxFmtKeepItem& >( rHt ) );
+ break;
+ case RES_TEXTGRID:
+ FormatTextGrid( static_cast< const SwTextGridItem& >( rHt ) );
+ break;
+ case RES_LINENUMBER:
+ FormatLineNumbering( static_cast< const SwFmtLineNumber& >( rHt ) );
+ break;
+ case RES_FRAMEDIR:
+ FormatFrameDirection( static_cast< const SvxFrameDirectionItem& >( rHt ) );
+ break;
+
+ default:
+ OSL_TRACE("Unhandled SfxPoolItem with id %d.\n", rHt.Which() );
+ break;
+ }
+}
+
+void AttributeOutputBase::OutputStyleItemSet( const SfxItemSet& rSet, sal_Bool bDeep, sal_Bool bTestForDefault )
+{
+ // based on OutputItemSet() from wrt_fn.cxx
+
+ const SfxItemPool& rPool = *rSet.GetPool();
+ const SfxItemSet* pSet = &rSet;
+ if ( !pSet->Count() )
+ {
+ if ( !bDeep )
+ return;
+
+ while ( 0 != ( pSet = pSet->GetParent() ) && !pSet->Count() )
+ ;
+
+ if ( !pSet )
+ return;
+ }
+
+ const SfxPoolItem* pItem;
+ if ( !bDeep || !pSet->GetParent() )
+ {
+ OSL_ENSURE( rSet.Count(), "Wurde doch schon behandelt oder?" );
+ SfxItemIter aIter( *pSet );
+ pItem = aIter.GetCurItem();
+ do {
+ OutputItem( *pItem );
+ } while ( !aIter.IsAtEnd() && 0 != ( pItem = aIter.NextItem() ) );
+ }
+ else
+ {
+ SfxWhichIter aIter( *pSet );
+ sal_uInt16 nWhich = aIter.FirstWhich();
+ while ( nWhich )
+ {
+ if ( SFX_ITEM_SET == pSet->GetItemState( nWhich, bDeep, &pItem ) &&
+ ( !bTestForDefault ||
+ *pItem != rPool.GetDefaultItem( nWhich ) ||
+ ( pSet->GetParent() && *pItem != pSet->GetParent()->Get( nWhich ) ) ) )
+ {
+ OutputItem( *pItem );
+ }
+ nWhich = aIter.NextWhich();
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8attributeoutput.hxx b/sw/source/filter/ww8/ww8attributeoutput.hxx
new file mode 100644
index 000000000000..fa9c1703e3b7
--- /dev/null
+++ b/sw/source/filter/ww8/ww8attributeoutput.hxx
@@ -0,0 +1,444 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WW8ATTRIBUTEOUTPUT_HXX_
+#define _WW8ATTRIBUTEOUTPUT_HXX_
+
+#include "attributeoutputbase.hxx"
+#include "wrtww8.hxx"
+
+class WW8AttributeOutput : public AttributeOutputBase
+{
+public:
+ /// Export the state of RTL/CJK.
+ virtual void RTLAndCJKState( bool bIsRTL, sal_uInt16 nScript );
+
+ /// Start of the paragraph.
+ virtual void StartParagraph( ww8::WW8TableNodeInfo::Pointer_t /*pTextNodeInfo*/ ) {}
+
+ /// End of the paragraph.
+ virtual void EndParagraph( ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner );
+
+ /// Called before we start outputting the attributes.
+ virtual void StartParagraphProperties( const SwTxtNode& /*rNode*/ ) {}
+
+ /// Called after we end outputting the attributes.
+ virtual void EndParagraphProperties() {}
+
+ /// Empty paragraph.
+ virtual void EmptyParagraph();
+
+ /// Start of the text run.
+ ///
+ virtual void StartRun( const SwRedlineData* pRedlineData );
+
+ /// End of the text run.
+ ///
+ /// No-op for binary filters.
+ virtual void EndRun() {}
+
+ /// Before we start outputting the attributes.
+ virtual void StartRunProperties();
+
+ /// After we end outputting the attributes.
+ virtual void EndRunProperties( const SwRedlineData* pRedlineData );
+
+ /// Output text.
+ virtual void RunText( const String& rText, rtl_TextEncoding eCharSet );
+
+ /// Output text (without markup).
+ virtual void RawText( const String& rText, bool bForceUnicode, rtl_TextEncoding eCharSet );
+
+ /// Output ruby start.
+ virtual void StartRuby( const SwTxtNode& rNode, xub_StrLen nPos, const SwFmtRuby& rRuby );
+
+ /// Output ruby end.
+ virtual void EndRuby();
+
+ /// Output URL start.
+ virtual bool StartURL( const String &rUrl, const String &rTarget );
+
+ /// Output URL end.
+ virtual bool EndURL();
+
+ virtual void FieldVanish( const String& rTxt, ww::eField eType );
+
+ /// Output redlining.
+ virtual void Redline( const SwRedlineData* pRedline );
+
+ virtual void FormatDrop( const SwTxtNode& rNode, const SwFmtDrop &rSwFmtDrop, sal_uInt16 nStyle, ww8::WW8TableNodeInfo::Pointer_t pTextNodeInfo, ww8::WW8TableNodeInfoInner::Pointer_t pTextNodeInfoInner );
+
+ /// Output FKP (Formatted disK Page) - necessary for binary formats only.
+ /// FIXME having it in AttributeOutputBase is probably a hack, it
+ /// should be in WW8AttributeOutput only...
+ virtual void OutputFKP();
+
+ /// Output style.
+ virtual void ParagraphStyle( sal_uInt16 nStyle );
+
+ virtual void TableInfoCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo );
+ virtual void TableInfoRow( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo );
+ virtual void TableDefinition( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo );
+ virtual void TableDefaultBorders( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo );
+ virtual void TableBackgrounds( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo );
+ virtual void TableHeight( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo );
+ virtual void TableCanSplit( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo );
+ virtual void TableBidi( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo );
+ virtual void TableVerticalCell( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfo );
+ virtual void TableNodeInfo( ww8::WW8TableNodeInfo::Pointer_t pNodeInfo );
+ virtual void TableNodeInfoInner( ww8::WW8TableNodeInfoInner::Pointer_t pNodeInfoInner );
+ virtual void TableOrientation( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableSpacing( ww8::WW8TableNodeInfoInner::Pointer_t pTableTextNodeInfoInner );
+ virtual void TableRowEnd( sal_uInt32 nDepth = 1 );
+
+ /// Start of the styles table.
+ virtual void StartStyles();
+
+ /// End of the styles table.
+ virtual void EndStyles( sal_uInt16 nNumberOfStyles );
+
+ /// Write default style.
+ virtual void DefaultStyle( sal_uInt16 nStyle );
+
+ /// Start of a style in the styles table.
+ virtual void StartStyle( const String& rName, bool bPapFmt,
+ sal_uInt16 nBase, sal_uInt16 nNext, sal_uInt16 nWwIdi, sal_uInt16 nId,
+ bool bAutoUpdate );
+
+ /// End of a style in the styles table.
+ virtual void EndStyle();
+
+ /// Start of (paragraph or run) properties of a style.
+ virtual void StartStyleProperties( bool bParProp, sal_uInt16 nStyle );
+
+ /// End of (paragraph or run) properties of a style.
+ virtual void EndStyleProperties( bool bParProp );
+
+ /// Numbering rule and Id.
+ virtual void OutlineNumbering( sal_uInt8 nLvl, const SwNumFmt &rNFmt, const SwFmt &rFmt );
+
+ /// Page break
+ /// As a paragraph property - the paragraph should be on the next page.
+ virtual void PageBreakBefore( bool bBreak );
+
+ /// Write a section break
+ /// msword::ColumnBreak or msword::PageBreak
+ virtual void SectionBreak( sal_uInt8 nC, const WW8_SepInfo* pSectionInfo = NULL );
+
+ /// Start of the section properties.
+ virtual void StartSection();
+
+ /// End of the section properties.
+ ///
+ /// No-op for binary filters.
+ virtual void EndSection() {}
+
+ /// Protection of forms.
+ virtual void SectionFormProtection( bool bProtected );
+
+ /// Numbering of the lines in the document.
+ virtual void SectionLineNumbering( sal_uLong nRestartNo, const SwLineNumberInfo& rLnNumInfo );
+
+ /// Has different headers/footers for the title page.
+ virtual void SectionTitlePage();
+
+ /// Description of the page borders.
+ virtual void SectionPageBorders( const SwFrmFmt* pFmt, const SwFrmFmt* pFirstPageFmt );
+
+ /// Columns populated from right/numbers on the right side?
+ virtual void SectionBiDi( bool bBiDi );
+
+ /// The style of the page numbers.
+ ///
+ /// nPageRestartNumberr being 0 means no restart.
+ virtual void SectionPageNumbering( sal_uInt16 nNumType, sal_uInt16 nPageRestartNumber );
+
+ /// The type of breaking.
+ virtual void SectionType( sal_uInt8 nBreakCode );
+
+ /// Special header/footer flags, needed for old versions only.
+ virtual void SectionWW6HeaderFooterFlags( sal_uInt8 nHeadFootFlags );
+
+ /// Definition of a numbering instance.
+ virtual void NumberingDefinition( sal_uInt16 nId, const SwNumRule &rRule );
+
+ /// All the numbering level information.
+ virtual void NumberingLevel( sal_uInt8 nLevel,
+ sal_uInt16 nStart,
+ sal_uInt16 nNumberingType,
+ SvxAdjust eAdjust,
+ const sal_uInt8 *pNumLvlPos,
+ sal_uInt8 nFollow,
+ const wwFont *pFont,
+ const SfxItemSet *pOutSet,
+ sal_Int16 nIndentAt,
+ sal_Int16 nFirstLineIndex,
+ sal_Int16 nListTabPos,
+ const String &rNumberingString );
+
+protected:
+ /// Output frames - the implementation.
+ void OutputFlyFrame_Impl( const sw::Frame& rFmt, const Point& rNdTopLeft );
+
+ /// Sfx item Sfx item RES_CHRATR_CASEMAP
+ virtual void CharCaseMap( const SvxCaseMapItem& );
+
+ /// Sfx item Sfx item RES_CHRATR_COLOR
+ virtual void CharColor( const SvxColorItem& );
+
+ /// Sfx item Sfx item RES_CHRATR_CONTOUR
+ virtual void CharContour( const SvxContourItem& );
+
+ /// Sfx item RES_CHRATR_CROSSEDOUT
+ virtual void CharCrossedOut( const SvxCrossedOutItem& rHt );
+
+ /// Sfx item RES_CHRATR_ESCAPEMENT
+ virtual void CharEscapement( const SvxEscapementItem& );
+
+ /// Sfx item RES_CHRATR_FONT
+ virtual void CharFont( const SvxFontItem& );
+
+ /// Sfx item RES_CHRATR_FONTSIZE
+ virtual void CharFontSize( const SvxFontHeightItem& );
+
+ /// Sfx item RES_CHRATR_KERNING
+ virtual void CharKerning( const SvxKerningItem& );
+
+ /// Sfx item RES_CHRATR_LANGUAGE
+ virtual void CharLanguage( const SvxLanguageItem& );
+
+ /// Sfx item RES_CHRATR_POSTURE
+ virtual void CharPosture( const SvxPostureItem& );
+
+ /// Sfx item RES_CHRATR_SHADOWED
+ virtual void CharShadow( const SvxShadowedItem& );
+
+ /// Sfx item RES_CHRATR_UNDERLINE
+ virtual void CharUnderline( const SvxUnderlineItem& );
+
+ /// Sfx item RES_CHRATR_WEIGHT
+ virtual void CharWeight( const SvxWeightItem& );
+
+ /// Sfx item RES_CHRATR_AUTOKERN
+ virtual void CharAutoKern( const SvxAutoKernItem& );
+
+ /// Sfx item RES_CHRATR_BLINK
+ virtual void CharAnimatedText( const SvxBlinkItem& );
+
+ /// Sfx item RES_CHRATR_BACKGROUND
+ virtual void CharBackground( const SvxBrushItem& );
+
+ /// Sfx item RES_CHRATR_CJK_FONT
+ virtual void CharFontCJK( const SvxFontItem& );
+
+ /// Sfx item RES_CHRATR_CJK_FONTSIZE
+ virtual void CharFontSizeCJK( const SvxFontHeightItem& rHt ) { CharFontSize( rHt ); }
+
+ /// Sfx item RES_CHRATR_CJK_LANGUAGE
+ virtual void CharLanguageCJK( const SvxLanguageItem& rHt ) { CharLanguage( rHt ); }
+
+ /// Sfx item RES_CHRATR_CJK_POSTURE
+ virtual void CharPostureCJK( const SvxPostureItem& rHt ) { CharPosture( rHt ); }
+
+ /// Sfx item RES_CHRATR_CJK_WEIGHT
+ virtual void CharWeightCJK( const SvxWeightItem& rHt ) { CharWeight( rHt ); }
+
+ /// Sfx item RES_CHRATR_CTL_FONT
+ virtual void CharFontCTL( const SvxFontItem& );
+
+ /// Sfx item RES_CHRATR_CTL_FONTSIZE
+ virtual void CharFontSizeCTL( const SvxFontHeightItem& rHt ) { CharFontSize( rHt ); }
+
+ /// Sfx item RES_CHRATR_CTL_LANGUAGE
+ virtual void CharLanguageCTL( const SvxLanguageItem& rHt ) { CharLanguage( rHt ); }
+
+ /// Sfx item RES_CHRATR_CTL_POSTURE
+ virtual void CharPostureCTL( const SvxPostureItem& );
+
+ /// Sfx item RES_CHRATR_CTL_WEIGHT
+ virtual void CharWeightCTL( const SvxWeightItem& );
+
+ /// Sfx item RES_CHRATR_ROTATE
+ virtual void CharRotate( const SvxCharRotateItem& );
+
+ /// Sfx item RES_CHRATR_EMPHASIS_MARK
+ virtual void CharEmphasisMark( const SvxEmphasisMarkItem& rHt );
+
+ /// Sfx item RES_CHRATR_TWO_LINES
+ virtual void CharTwoLines( const SvxTwoLinesItem& );
+
+ /// Sfx item RES_CHRATR_SCALEW
+ virtual void CharScaleWidth( const SvxCharScaleWidthItem& );
+
+ /// Sfx item RES_CHRATR_RELIEF
+ virtual void CharRelief( const SvxCharReliefItem& );
+
+ /// Sfx item RES_CHRATR_HIDDEN
+ virtual void CharHidden( const SvxCharHiddenItem& );
+
+ /// Sfx item RES_TXTATR_INETFMT
+ virtual void TextINetFormat( const SwFmtINetFmt& );
+
+ /// Sfx item RES_TXTATR_CHARFMT
+ virtual void TextCharFormat( const SwFmtCharFmt& );
+
+ /// Sfx item RES_TXTATR_FTN
+ virtual void TextFootnote_Impl( const SwFmtFtn& );
+
+ /// Sfx item RES_PARATR_LINESPACING
+ virtual void ParaLineSpacing_Impl( short nSpace, short nMulti );
+
+ /// Sfx item RES_PARATR_ADJUST
+ virtual void ParaAdjust( const SvxAdjustItem& rHt );
+
+ /// Sfx item RES_PARATR_SPLIT
+ virtual void ParaSplit( const SvxFmtSplitItem& );
+
+ /// Sfx item RES_PARATR_WIDOWS
+ virtual void ParaWidows( const SvxWidowsItem& rHt );
+
+ /// Sfx item RES_PARATR_TABSTOP
+ virtual void ParaTabStop( const SvxTabStopItem& rHt );
+
+ /// Sfx item RES_PARATR_HYPHENZONE
+ virtual void ParaHyphenZone( const SvxHyphenZoneItem& );
+
+ /// Sfx item RES_PARATR_NUMRULE
+ virtual void ParaNumRule_Impl( const SwTxtNode *pTxtNd, sal_Int32 nLvl, sal_Int32 nNumId );
+
+ /// Sfx item RES_PARATR_SCRIPTSPACE
+ virtual void ParaScriptSpace( const SfxBoolItem& );
+
+ /// Sfx item RES_PARATR_VERTALIGN
+ virtual void ParaVerticalAlign( const SvxParaVertAlignItem& );
+
+ /// Sfx item RES_PARATR_SNAPTOGRID
+ virtual void ParaSnapToGrid( const SvxParaGridItem& );
+
+ /// Sfx item RES_FRM_SIZE
+ virtual void FormatFrameSize( const SwFmtFrmSize& );
+
+ /// Sfx item RES_PAPER_BIN
+ virtual void FormatPaperBin( const SvxPaperBinItem& );
+
+ /// Sfx item RES_LR_SPACE
+ virtual void FormatLRSpace( const SvxLRSpaceItem& );
+
+ /// Sfx item RES_UL_SPACE
+ virtual void FormatULSpace( const SvxULSpaceItem& rHt );
+
+ /// Sfx item RES_SURROUND
+ virtual void FormatSurround( const SwFmtSurround& );
+
+ /// Sfx item RES_VERT_ORIENT
+ virtual void FormatVertOrientation( const SwFmtVertOrient& );
+
+ /// Sfx item RES_HORI_ORIENT
+ virtual void FormatHorizOrientation( const SwFmtHoriOrient& );
+
+ /// Sfx item RES_ANCHOR
+ virtual void FormatAnchor( const SwFmtAnchor& );
+
+ /// Sfx item RES_BACKGROUND
+ virtual void FormatBackground( const SvxBrushItem& );
+
+ /// Sfx item RES_BOX
+ virtual void FormatBox( const SvxBoxItem& );
+
+ /// Sfx item RES_COL
+ virtual void FormatColumns_Impl( sal_uInt16 nCols, const SwFmtCol & rCol, bool bEven, SwTwips nPageSize );
+
+ /// Sfx item RES_KEEP
+ virtual void FormatKeep( const SvxFmtKeepItem& );
+
+ /// Sfx item RES_TEXTGRID
+ virtual void FormatTextGrid( const SwTextGridItem& );
+
+ /// Sfx item RES_LINENUMBER
+ virtual void FormatLineNumbering( const SwFmtLineNumber& );
+
+ /// Sfx item RES_FRAMEDIR
+ virtual void FormatFrameDirection( const SvxFrameDirectionItem& );
+
+ /// Write the expanded field
+ virtual void WriteExpand( const SwField* pFld );
+
+ virtual void RefField ( const SwField& rFld, const String& rRef );
+ virtual void HiddenField( const SwField& rFld );
+ virtual void SetField( const SwField& rFld, ww::eField eType, const String& rCmd );
+ virtual void PostitField( const SwField* pFld );
+ virtual bool DropdownField( const SwField* pFld );
+
+ virtual bool AnalyzeURL( const String& rURL, const String& rTarget, String* pLinkURL, String* pMark );
+
+ /// Reference to the export, where to get the data from
+ WW8Export &m_rWW8Export;
+
+ /// For output of styles.
+ ///
+ /// We have to remember these positions between the StartStyle() and
+ /// EndStyle().
+ sal_uInt16 nPOPosStdLen1, nPOPosStdLen2;
+
+ /// For output of styles.
+ ///
+ /// We have to remember this position between StartStyleProperties() and
+ /// EndStyleProperties().
+ sal_uInt16 m_nStyleStartSize, m_nStyleLenPos;
+
+ /// For output of styles.
+ ///
+ /// Used between StartStyles() and EndStyles().
+ sal_uLong m_nStyAnzPos;
+
+ /// For output of run properties.
+ ///
+ /// We have to remember the number of field results, and do not export end
+ /// of the field results if we were forced to split text.
+ sal_uInt16 m_nFieldResults;
+
+public:
+ WW8AttributeOutput( WW8Export &rWW8Export ) : AttributeOutputBase(), m_rWW8Export( rWW8Export ) {}
+ virtual ~WW8AttributeOutput() {}
+
+ /// Return the right export class.
+ virtual WW8Export& GetExport() { return m_rWW8Export; }
+ const WW8Export& GetExport() const { return m_rWW8Export; }
+
+protected:
+ /// Output the bold etc. attributes
+ void OutputWW8Attribute( sal_uInt8 nId, bool bVal );
+
+ /// Output the bold etc. attributes, the Complex Text Layout version
+ void OutputWW8AttributeCTL( sal_uInt8 nId, bool bVal );
+
+};
+
+#endif // _WW8ATTRIBUTEOUTPUT_HXX_
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8glsy.cxx b/sw/source/filter/ww8/ww8glsy.cxx
new file mode 100644
index 000000000000..380b38a34411
--- /dev/null
+++ b/sw/source/filter/ww8/ww8glsy.cxx
@@ -0,0 +1,272 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/urlobj.hxx>
+#include <svl/urihelper.hxx>
+#include <rtl/tencinfo.h>
+#include <swerror.h>
+#include <ndtxt.hxx>
+#include <pam.hxx>
+#include <shellio.hxx>
+#include <docsh.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include "ww8glsy.hxx"
+#include "ww8par.hxx"
+
+
+WW8Glossary::WW8Glossary(SvStorageStreamRef &refStrm, sal_uInt8 nVersion,
+ SvStorage *pStg)
+ : pGlossary(0), rStrm(refStrm), xStg(pStg), nStrings(0)
+{
+ refStrm->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ WW8Fib aWwFib(*refStrm, nVersion);
+
+ if (aWwFib.nFibBack >= 0x6A) //Word97
+ {
+ xTableStream = pStg->OpenSotStream(String::CreateFromAscii(
+ aWwFib.fWhichTblStm ? SL::a1Table : SL::a0Table), STREAM_STD_READ);
+
+ if (xTableStream.Is() && SVSTREAM_OK == xTableStream->GetError())
+ {
+ xTableStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ pGlossary =
+ new WW8GlossaryFib(*refStrm, nVersion, *xTableStream, aWwFib);
+ }
+ }
+}
+
+bool WW8Glossary::HasBareGraphicEnd(SwDoc *pDoc,SwNodeIndex &rIdx)
+{
+ bool bRet=false;
+ for( sal_uInt16 nCnt = pDoc->GetSpzFrmFmts()->Count(); nCnt; )
+ {
+ SwFrmFmt* pFrmFmt = (*pDoc->GetSpzFrmFmts())[ --nCnt ];
+ if ( RES_FLYFRMFMT != pFrmFmt->Which() &&
+ RES_DRAWFRMFMT != pFrmFmt->Which() )
+ continue;
+ const SwFmtAnchor& rAnchor = pFrmFmt->GetAnchor();
+ SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
+ if (pAPos &&
+ ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
+ (FLY_AT_CHAR == rAnchor.GetAnchorId())) &&
+ rIdx == pAPos->nNode.GetIndex() )
+ {
+ bRet=true;
+ break;
+ }
+ }
+ return bRet;
+}
+
+bool WW8Glossary::MakeEntries(SwDoc *pD, SwTextBlocks &rBlocks,
+ bool bSaveRelFile, const std::vector<String>& rStrings,
+ const std::vector<ww::bytes>& rExtra)
+{
+ // this code will be called after reading all text into the
+ // empty sections
+ const String aOldURL( rBlocks.GetBaseURL() );
+ bool bRet=false;
+ if( bSaveRelFile )
+ {
+ rBlocks.SetBaseURL(
+ URIHelper::SmartRel2Abs(
+ INetURLObject(), rBlocks.GetFileName(),
+ URIHelper::GetMaybeFileHdl()));
+ }
+ else
+ rBlocks.SetBaseURL( aEmptyStr );
+
+ SwNodeIndex aDocEnd( pD->GetNodes().GetEndOfContent() );
+ SwNodeIndex aStart( *aDocEnd.GetNode().StartOfSectionNode(), 1 );
+
+ // search the first NormalStartNode
+ while( !( aStart.GetNode().IsStartNode() && SwNormalStartNode ==
+ aStart.GetNode().GetStartNode()->GetStartNodeType()) &&
+ aStart < aDocEnd )
+ aStart++;
+
+ if( aStart < aDocEnd )
+ {
+ SwTxtFmtColl* pColl = pD->GetTxtCollFromPool
+ (RES_POOLCOLL_STANDARD, false);
+ sal_uInt16 nGlosEntry = 0;
+ SwCntntNode* pCNd = 0;
+ do {
+ SwPaM aPam( aStart );
+ {
+ SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
+ rIdx++;
+ if( 0 == ( pCNd = rIdx.GetNode().GetTxtNode() ) )
+ {
+ pCNd = pD->GetNodes().MakeTxtNode( rIdx, pColl );
+ rIdx = *pCNd;
+ }
+ }
+ aPam.GetPoint()->nContent.Assign( pCNd, 0 );
+ aPam.SetMark();
+ {
+ SwNodeIndex& rIdx = aPam.GetPoint()->nNode;
+ rIdx = aStart.GetNode().EndOfSectionIndex() - 1;
+ if(( 0 == ( pCNd = rIdx.GetNode().GetCntntNode() ) )
+ || HasBareGraphicEnd(pD,rIdx))
+ {
+ rIdx++;
+ pCNd = pD->GetNodes().MakeTxtNode( rIdx, pColl );
+ rIdx = *pCNd;
+ }
+ }
+ aPam.GetPoint()->nContent.Assign( pCNd, pCNd->Len() );
+
+ // now we have the right selection for one entry. Copy this to
+ // the definied TextBlock, but only if it is not an autocorrection
+ // entry (== -1) otherwise the group indicates the group in the
+ // sttbfglsystyle list that this entry belongs to. Unused at the
+ // moment
+ const ww::bytes &rData = rExtra[nGlosEntry];
+ sal_uInt16 n = SVBT16ToShort( &(rData[2]) );
+ if(n != 0xFFFF)
+ {
+ rBlocks.ClearDoc();
+ const String &rLNm = rStrings[nGlosEntry];
+
+ String sShortcut = rLNm;
+
+ // Need to check make sure the shortcut is not already being used
+ xub_StrLen nStart = 0;
+ sal_uInt16 nCurPos = rBlocks.GetIndex( sShortcut );
+ xub_StrLen nLen = sShortcut.Len();
+ while( (sal_uInt16)-1 != nCurPos )
+ {
+ sShortcut.Erase( nLen ) +=
+ String::CreateFromInt32( ++nStart ); // add an Number to it
+ nCurPos = rBlocks.GetIndex( sShortcut );
+ }
+
+ if( rBlocks.BeginPutDoc( sShortcut, sShortcut )) // Make the shortcut and the name the same
+
+ {
+ SwDoc* pGlDoc = rBlocks.GetDoc();
+ SwNodeIndex aIdx( pGlDoc->GetNodes().GetEndOfContent(),
+ -1 );
+ pCNd = aIdx.GetNode().GetCntntNode();
+ SwPosition aPos( aIdx, SwIndex( pCNd, pCNd->Len() ));
+ pD->CopyRange( aPam, aPos, false );
+ rBlocks.PutDoc();
+ }
+ }
+ aStart = aStart.GetNode().EndOfSectionIndex() + 1;
+ ++nGlosEntry;
+ } while( aStart.GetNode().IsStartNode() &&
+ SwNormalStartNode == aStart.GetNode().
+ GetStartNode()->GetStartNodeType());
+ bRet=true;
+ }
+
+// this code will be called after reading all text into the empty sections
+
+ rBlocks.SetBaseURL( aOldURL );
+ return bRet;
+}
+
+
+bool WW8Glossary::Load( SwTextBlocks &rBlocks, bool bSaveRelFile )
+{
+ bool bRet=false;
+ if (pGlossary && pGlossary->IsGlossaryFib() && rBlocks.StartPutMuchBlockEntries())
+ {
+ //read the names of the autotext entries
+ std::vector<String> aStrings;
+ std::vector<ww::bytes> aData;
+
+ rtl_TextEncoding eStructCharSet =
+ WW8Fib::GetFIBCharset(pGlossary->chseTables);
+
+ WW8ReadSTTBF(true, *xTableStream, pGlossary->fcSttbfglsy,
+ pGlossary->lcbSttbfglsy, 0, eStructCharSet, aStrings, &aData );
+
+ rStrm->Seek(0);
+
+ if ( 0 != (nStrings = static_cast< sal_uInt16 >(aStrings.size())))
+ {
+ SfxObjectShellLock xDocSh(new SwDocShell(SFX_CREATE_MODE_INTERNAL));
+ if (xDocSh->DoInitNew(0))
+ {
+ SwDoc *pD = ((SwDocShell*)(&xDocSh))->GetDoc();
+ SwWW8ImplReader* pRdr = new SwWW8ImplReader(pGlossary->nVersion,
+ xStg, &rStrm, *pD, rBlocks.GetBaseURL(), true);
+
+ SwNodeIndex aIdx(
+ *pD->GetNodes().GetEndOfContent().StartOfSectionNode(), 1);
+ if( !aIdx.GetNode().IsTxtNode() )
+ {
+ OSL_ENSURE( !this, "wo ist der TextNode?" );
+ pD->GetNodes().GoNext( &aIdx );
+ }
+ SwPaM aPamo( aIdx );
+ aPamo.GetPoint()->nContent.Assign(aIdx.GetNode().GetCntntNode(),
+ 0);
+ pRdr->LoadDoc(aPamo,this);
+
+ bRet = MakeEntries(pD, rBlocks, bSaveRelFile, aStrings, aData);
+
+ delete pRdr;
+ }
+ xDocSh->DoClose();
+ rBlocks.EndPutMuchBlockEntries();
+ }
+ }
+ return bRet;
+}
+
+
+bool WW8GlossaryFib::IsGlossaryFib()
+{
+ // fGlsy will indicate whether this has AutoText or not
+ return fGlsy;
+}
+
+sal_uInt32 WW8GlossaryFib::FindGlossaryFibOffset(SvStream & /* rTableStrm */,
+ SvStream & /* rStrm */,
+ const WW8Fib &rFib)
+{
+ sal_uInt32 nGlossaryFibOffset = 0;
+ if ( rFib.fDot ) // its a template
+ {
+ if ( rFib.pnNext )
+ nGlossaryFibOffset = ( rFib.pnNext * 512 );
+ }
+ return nGlossaryFibOffset;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8glsy.hxx b/sw/source/filter/ww8/ww8glsy.hxx
new file mode 100644
index 000000000000..fe7b4a33bf63
--- /dev/null
+++ b/sw/source/filter/ww8/ww8glsy.hxx
@@ -0,0 +1,92 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WW8GLSY_HXX
+#define _WW8GLSY_HXX
+
+#include <sot/storage.hxx>
+#include "ww8scan.hxx"
+
+class SwTextBlocks;
+class SwNodeIndex;
+
+/*
+ * GlossaryFib takes the document fib and finds the glossary fib which may
+ * not exist. The glossary fib has the offsets into the autotext subdocument
+ * which is at the end of template .dot's
+ */
+class WW8GlossaryFib : public WW8Fib
+{
+public:
+ WW8GlossaryFib( SvStream& rStrm, sal_uInt8 nWantedVersion ,
+ SvStream& rTableStrm, const WW8Fib &rFib) : WW8Fib(rStrm,
+ nWantedVersion,FindGlossaryFibOffset(rTableStrm,rStrm,rFib)) {}
+ bool IsGlossaryFib();
+private:
+ sal_uInt32 FindGlossaryFibOffset(SvStream &rTableStrm,SvStream &rStrm,
+ const WW8Fib &rFib);
+};
+
+/*
+ * Imports glossaries from word, given the document it gets the usual word
+ * doc information, then the glossary fib and uses the usual reader class to
+ * wrap the autotext into a star doc. Afterwards taking each section entry and
+ * making it a single star autotext entry.
+ *
+ * ToDo currently all autotext entries become resource hungry star autotext
+ * formatted text, need to use a flag in the ww8reader class to determine if
+ * an entry is formatted or not.
+ */
+class WW8Glossary
+{
+public:
+ WW8Glossary( SvStorageStreamRef &refStrm, sal_uInt8 nVersion, SvStorage *pStg=0);
+ bool Load( SwTextBlocks &rBlocks, bool bSaveRelFile );
+ ~WW8Glossary() { delete pGlossary; }
+ WW8GlossaryFib *GetFib() { return pGlossary; }
+ sal_uInt16 GetNoStrings() const { return nStrings; }
+
+private:
+ WW8GlossaryFib *pGlossary;
+ SvStorageStreamRef xTableStream;
+ SvStorageStreamRef &rStrm;
+ SvStorageRef xStg;
+ sal_uInt16 nStrings;
+
+ bool MakeEntries(SwDoc *pD, SwTextBlocks &rBlocks, bool bSaveRelFile,
+ const ::std::vector<String>& rStrings,
+ const ::std::vector<ww::bytes>& rExtra);
+ bool HasBareGraphicEnd(SwDoc *pD,SwNodeIndex &rIdx);
+
+ //No copying
+ WW8Glossary(const WW8Glossary&);
+ WW8Glossary& operator=(const WW8Glossary&);
+};
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8graf.cxx b/sw/source/filter/ww8/ww8graf.cxx
new file mode 100644
index 000000000000..a8bb36ebc33c
--- /dev/null
+++ b/sw/source/filter/ww8/ww8graf.cxx
@@ -0,0 +1,3083 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <svl/urihelper.hxx>
+#include <hintids.hxx>
+#include <osl/endian.h>
+#include <svx/fmglob.hxx>
+#include <svx/sdtaitm.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <svx/xlineit.hxx>
+#include <svx/xfillit.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdocapt.hxx>
+#include <svx/sxctitm.hxx>
+#include <editeng/editeng.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdopath.hxx>
+#include <svx/svdocirc.hxx>
+#include <editeng/outlobj.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdoole2.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <svx/svdoattr.hxx>
+#include <editeng/brshitem.hxx>
+#include <svx/rectenum.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/outliner.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <svx/xfltrit.hxx>
+#include <filter/msfilter/msdffimp.hxx>
+#include <grfatr.hxx> // class SwCropGrf
+#include <fmtornt.hxx>
+#include <fmtcntnt.hxx>
+#include <frmfmt.hxx>
+#include <fmtanchr.hxx>
+#include <pam.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <ndgrf.hxx>
+#include <ndtxt.hxx>
+#include <dcontact.hxx>
+#include <docsh.hxx>
+#include <mdiexp.hxx> // Progress
+#include <fmtcnct.hxx>
+#include <swunodef.hxx>
+#include "ww8struc.hxx"
+#include "ww8scan.hxx"
+#include "ww8par.hxx" // class SwWWImplReader
+#include "ww8par2.hxx" // SwWW8StyInf
+#include "ww8graf.hxx"
+#include <fmtinfmt.hxx>
+#include <editeng/eeitem.hxx>
+#include <editeng/flditem.hxx>
+// #i18732#
+#include <fmtfollowtextflow.hxx>
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include <basegfx/point/b2dpoint.hxx>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <editeng/editobj.hxx>
+
+#include <math.h>
+
+using ::editeng::SvxBorderLine;
+using namespace ::com::sun::star;
+using namespace sw::types;
+using namespace sw::util;
+
+// Hilfsroutinen
+
+Color WW8TransCol(SVBT32 nWC)
+{
+#if 1 // 1 = Vordefinierte Farben benutzen, 0 = ignorieren
+
+ // Farbtabelle zum Umrechnen RGB-Werte in vordefinierte Farben
+ // ( Damit bei der Writer-UI die Farbnamen stimmen )
+ // Die Tabelle int im *3er-System* aufgeteilt. Die Grauwerte fehlen,
+ // da sie nicht ins 3er-System passen ( 4 Werte: sw, ws, 2 * grau )
+ static ColorData eColA[] = { // B G R B G R B G R
+ COL_BLACK, COL_RED, COL_LIGHTRED, // 0 0 0, 0 0 1, 0 0 2
+ COL_GREEN, COL_BROWN, COL_BLACK, // 0 1 0, 0 1 1, 0 1 2
+ COL_LIGHTGREEN, COL_BLACK, COL_YELLOW, // 0 2 0, 0 2 1, 0 2 2
+ COL_BLUE, COL_MAGENTA, COL_BLACK, // 1 0 0, 1 0 1, 1 0 2
+ COL_CYAN, COL_LIGHTGRAY, COL_BLACK, // 1 1 0, 1 1 1, 1 1 2
+ COL_BLACK, COL_BLACK, COL_BLACK, // 1 2 0, 1 2 1, 1 2 2
+ COL_LIGHTBLUE, COL_BLACK, COL_LIGHTMAGENTA, // 2 0 0, 2 0 1, 2 0 2
+ COL_BLACK, COL_BLACK, COL_BLACK, // 2 1 0, 2 1 1, 2 1 2
+ COL_LIGHTCYAN, COL_BLACK, COL_WHITE }; // 2 2 0, 2 2 1, 2 2 2
+
+ // In nWC[3] steht ein Byte, dass in der WW-Doku nicht beschrieben ist.
+ // Die Bedeutung ist anscheinend folgende: Bei 0 ist es eine normale
+ // Farbe, dessen RGB-Wert in nWC[0..2] steht. stehen in nWC[3] die
+ // Werte 0x1, 0x7d oder 0x83, dann ist es ein Grauwert, dessen
+ // Schwarzanteil in 1/2 % in nWC[0] steht.
+ // Ich vermute, dass es auf Bit0 in nWV[3] ankommt, ob es RGB oder Grau ist.
+
+ if( !( nWC[3] & 0x1 ) && // keine Spezial-Farbe (grau)
+ ( ( nWC[0] == 0 || nWC[0]== 0x80 || nWC[0] == 0xff ) // R-Anteil
+ && ( nWC[1] == 0 || nWC[1]== 0x80 || nWC[1] == 0xff ) // G-Anteil
+ && ( nWC[2] == 0 || nWC[2]== 0x80 || nWC[2] == 0xff ) ) ){// B-Anteil
+ int nIdx = 0; // und nun: Idx-Berechnung im 3er-System
+ for (int i = 2; i >= 0; i--)
+ {
+ nIdx *= 3;
+ if (nWC[i])
+ nIdx += ((nWC[i] == 0xff) ? 2 : 1);
+ }
+ if (eColA[nIdx] != COL_BLACK)
+ return Color(eColA[nIdx]); // Standard-Color
+ }
+#endif
+
+ if (nWC[3] & 0x1)
+ {
+ //Special colour gray
+ sal_uInt8 u = (sal_uInt8)( (sal_uLong)( 200 - nWC[0] ) * 256 / 200 );
+ return Color(u, u, u);
+ }
+
+ // User-Color
+ return Color(nWC[0], nWC[1], nWC[2]);
+}
+
+void wwFrameNamer::SetUniqueGraphName(SwFrmFmt *pFrmFmt, const String &rFixed)
+{
+ if (mbIsDisabled || !rFixed.Len())
+ return;
+ String aName(msSeed);
+ aName += String::CreateFromInt32(++mnImportedGraphicsCount);
+ aName.APPEND_CONST_ASC( ": " );
+ aName += rFixed;
+ pFrmFmt->SetName( aName );
+}
+
+// ReadGrafStart liest die ObjektDaten ein und erzeugt falls noetig einen Anker
+bool SwWW8ImplReader::ReadGrafStart(void* pData, short nDataSiz,
+ WW8_DPHEAD* pHd, const WW8_DO* pDo, SfxAllItemSet &rSet)
+{
+ if (SVBT16ToShort(pHd->cb) < sizeof(WW8_DPHEAD) + nDataSiz)
+ {
+ OSL_ENSURE( !this, "+Grafik-Element: Size ?" );
+ pStrm->SeekRel(SVBT16ToShort(pHd->cb) - sizeof(WW8_DPHEAD));
+ return false;
+ }
+ pStrm->Read(pData, nDataSiz);
+
+ RndStdIds eAnchor = (SVBT8ToByte(pDo->by) < 2) ? FLY_AT_PAGE : FLY_AT_PARA;
+ rSet.Put(SwFmtAnchor(eAnchor));
+
+ nDrawXOfs2 = nDrawXOfs;
+ nDrawYOfs2 = nDrawYOfs;
+
+ if (eAnchor == FLY_AT_PARA)
+ {
+ if( SVBT8ToByte( pDo->bx ) == 1 ) // Pos: echt links
+ nDrawXOfs2 = static_cast< short >(nDrawXOfs2 - maSectionManager.GetPageLeft());
+ if( nInTable ) // Obj in Table
+ nDrawXOfs2 = nDrawXOfs2 - GetTableLeft(); // -> siehe Kommentar
+ // bei GetTableLeft()
+ }
+ else
+ {
+ if( SVBT8ToByte( pDo->bx ) != 1 )
+ nDrawXOfs2 = static_cast< short >(nDrawXOfs2 + maSectionManager.GetPageLeft());
+ }
+
+ return true;
+}
+
+// SetStdAttr() setzt die Attribute, die jedes Objekt hat
+
+static void SetStdAttr( SfxItemSet& rSet, WW8_DP_LINETYPE& rL,
+ WW8_DP_SHADOW& rSh )
+{
+ if( SVBT16ToShort( rL.lnps ) == 5 ){ // unsichtbar
+ rSet.Put( XLineStyleItem( XLINE_NONE ) );
+ }else{ // sichtbar
+ Color aCol( WW8TransCol( rL.lnpc ) ); // LinienFarbe
+ rSet.Put( XLineColorItem( aEmptyStr, aCol ) );
+ rSet.Put( XLineWidthItem( SVBT16ToShort( rL.lnpw ) ) );
+ // LinienDicke
+ if( SVBT16ToShort( rL.lnps ) >= 1
+ && SVBT16ToShort(rL.lnps ) <= 4 ){ // LinienStil
+ rSet.Put( XLineStyleItem( XLINE_DASH ) );
+ sal_Int16 nLen = SVBT16ToShort( rL.lnpw );
+ XDash aD( XDASH_RECT, 1, 2 * nLen, 1, 5 * nLen, 5 * nLen );
+ switch( SVBT16ToShort( rL.lnps ) ){
+ case 1: aD.SetDots( 0 ); // Dash
+ aD.SetDashLen( 6 * nLen );
+ aD.SetDistance( 4 * nLen );
+ break;
+ case 2: aD.SetDashes( 0 ); break; // Dot
+ case 3: break; // Dash Dot
+ case 4: aD.SetDots( 2 ); break; // Dash Dot Dot
+ }
+ rSet.Put( XLineDashItem( aEmptyStr, aD ) );
+ }else{
+ rSet.Put( XLineStyleItem( XLINE_SOLID ) ); // noetig fuer TextBox
+ }
+ }
+ if( SVBT16ToShort( rSh.shdwpi ) ){ // Schatten
+ rSet.Put(SdrShadowItem(true));
+ rSet.Put( SdrShadowXDistItem( SVBT16ToShort( rSh.xaOffset ) ) );
+ rSet.Put( SdrShadowYDistItem( SVBT16ToShort( rSh.yaOffset ) ) );
+ }
+}
+
+// SetFill setzt Fuellattribute wie Vordergrund- und Hintergrund-Farbe
+// und Muster durch Reduktion auf eine Farbe.
+// SetFill() setzt z.Zt kein Muster, da Sdr das nur sehr umstaendlich kann
+// und die Sdr-Schraffur ( XDash ) noch nicht fertig ist.
+// Statt dessen wird eine Mischfarbe gewaehlt, die auf den entsprechenden
+// Farbton zwischen den Farben liegt.
+
+static void SetFill( SfxItemSet& rSet, WW8_DP_FILL& rFill )
+{
+ static sal_uInt8 nPatA[] =
+ {
+ 0, 0, 5, 10, 20, 25, 30, 40, 50, 60, 70, 75, 80,
+ 90, 50, 50, 50, 50, 50, 50, 33, 33, 33, 33, 33, 33
+ };
+ sal_uInt16 nPat = SVBT16ToShort(rFill.flpp);
+
+ if (nPat == 0) // transparent
+ rSet.Put(XFillStyleItem(XFILL_NONE));
+ else
+ {
+ rSet.Put(XFillStyleItem(XFILL_SOLID)); // necessary for textbox
+ if (nPat <= 1 || nPat > sizeof(nPatA))
+ {
+ // Solid Background or unknown
+ rSet.Put(XFillColorItem(aEmptyStr, WW8TransCol(rFill.dlpcBg)));
+ }
+ else
+ { // Brush -> Farbmischung
+ Color aB( WW8TransCol( rFill.dlpcBg ) );
+ Color aF( WW8TransCol( rFill.dlpcFg ) );
+ aB.SetRed( (sal_uInt8)( ( (sal_uLong)aF.GetRed() * nPatA[nPat]
+ + (sal_uLong)aB.GetRed() * ( 100 - nPatA[nPat] ) ) / 100 ) );
+ aB.SetGreen( (sal_uInt8)( ( (sal_uLong)aF.GetGreen() * nPatA[nPat]
+ + (sal_uLong)aB.GetGreen() * ( 100 - nPatA[nPat] ) ) / 100 ) );
+ aB.SetBlue( (sal_uInt8)( ( (sal_uLong)aF.GetBlue() * nPatA[nPat]
+ + (sal_uLong)aB.GetBlue() * ( 100 - nPatA[nPat] ) ) / 100 ) );
+ rSet.Put( XFillColorItem( aEmptyStr, aB ) );
+ }
+ }
+}
+
+static void SetLineEndAttr( SfxItemSet& rSet, WW8_DP_LINEEND& rLe,
+ WW8_DP_LINETYPE& rLt )
+{
+ sal_uInt16 aSB = SVBT16ToShort( rLe.aStartBits );
+ if( aSB & 0x3 )
+ {
+ ::basegfx::B2DPolygon aPolygon;
+ aPolygon.append(::basegfx::B2DPoint(0.0, 330.0));
+ aPolygon.append(::basegfx::B2DPoint(100.0, 0.0));
+ aPolygon.append(::basegfx::B2DPoint(200.0, 330.0));
+ aPolygon.setClosed(true);
+ rSet.Put( XLineEndItem( aEmptyStr, ::basegfx::B2DPolyPolygon(aPolygon) ) );
+ sal_uInt16 nSiz = SVBT16ToShort( rLt.lnpw )
+ * ( ( aSB >> 2 & 0x3 ) + ( aSB >> 4 & 0x3 ) );
+ if( nSiz < 220 ) nSiz = 220;
+ rSet.Put(XLineEndWidthItem(nSiz));
+ rSet.Put(XLineEndCenterItem(false));
+ }
+
+ sal_uInt16 aEB = SVBT16ToShort( rLe.aEndBits );
+ if( aEB & 0x3 ){
+ ::basegfx::B2DPolygon aPolygon;
+ aPolygon.append(::basegfx::B2DPoint(0.0, 330.0));
+ aPolygon.append(::basegfx::B2DPoint(100.0, 0.0));
+ aPolygon.append(::basegfx::B2DPoint(200.0, 330.0));
+ aPolygon.setClosed(true);
+ rSet.Put( XLineStartItem( aEmptyStr, ::basegfx::B2DPolyPolygon(aPolygon) ) );
+ sal_uInt16 nSiz = SVBT16ToShort( rLt.lnpw )
+ * ( ( aEB >> 2 & 0x3 ) + ( aEB >> 4 & 0x3 ) );
+ if( nSiz < 220 ) nSiz = 220;
+ rSet.Put(XLineStartWidthItem(nSiz));
+ rSet.Put(XLineStartCenterItem(false));
+ }
+}
+
+// Ab hier folgen die Routinen fuer die einzelnen Objekte
+SdrObject* SwWW8ImplReader::ReadLine( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ WW8_DP_LINE aLine;
+
+ if( !ReadGrafStart( (void*)&aLine, sizeof( aLine ), pHd, pDo, rSet ) )
+ return 0;
+
+ Point aP[2];
+ {
+ Point& rP0 = aP[0];
+ Point& rP1 = aP[1];
+
+ rP0.X() = (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2;
+ rP0.Y() = (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2;
+ rP1 = rP0;
+ rP0.X() += (sal_Int16)SVBT16ToShort( aLine.xaStart );
+ rP0.Y() += (sal_Int16)SVBT16ToShort( aLine.yaStart );
+ rP1.X() += (sal_Int16)SVBT16ToShort( aLine.xaEnd );
+ rP1.Y() += (sal_Int16)SVBT16ToShort( aLine.yaEnd );
+ }
+
+ ::basegfx::B2DPolygon aPolygon;
+ aPolygon.append(::basegfx::B2DPoint(aP[0].X(), aP[0].Y()));
+ aPolygon.append(::basegfx::B2DPoint(aP[1].X(), aP[1].Y()));
+ SdrObject* pObj = new SdrPathObj(OBJ_LINE, ::basegfx::B2DPolyPolygon(aPolygon));
+
+ SetStdAttr( rSet, aLine.aLnt, aLine.aShd );
+ SetLineEndAttr( rSet, aLine.aEpp, aLine.aLnt );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadRect( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ WW8_DP_RECT aRect;
+
+ if( !ReadGrafStart( (void*)&aRect, sizeof( aRect ), pHd, pDo, rSet ) )
+ return 0;
+
+ Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
+ (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
+ Point aP1( aP0 );
+ aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
+ aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
+
+ SdrObject* pObj = new SdrRectObj( Rectangle( aP0, aP1 ) );
+
+ SetStdAttr( rSet, aRect.aLnt, aRect.aShd );
+ SetFill( rSet, aRect.aFill );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadElipse( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ WW8_DP_ELIPSE aElipse;
+
+ if( !ReadGrafStart( (void*)&aElipse, sizeof( aElipse ), pHd, pDo, rSet ) )
+ return 0;
+
+ Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
+ (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
+ Point aP1( aP0 );
+ aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
+ aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
+
+ SdrObject* pObj = new SdrCircObj( OBJ_CIRC, Rectangle( aP0, aP1 ) );
+
+ SetStdAttr( rSet, aElipse.aLnt, aElipse.aShd );
+ SetFill( rSet, aElipse.aFill );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadArc( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ WW8_DP_ARC aArc;
+
+ if( !ReadGrafStart( (void*)&aArc, sizeof( aArc ), pHd, pDo, rSet ) )
+ return 0;
+
+ Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
+ (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
+ Point aP1( aP0 );
+ aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa ) * 2;
+ aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya ) * 2;
+
+ short nA[] = { 2, 3, 1, 0 };
+ short nW = nA[ ( ( SVBT8ToByte( aArc.fLeft ) & 1 ) << 1 )
+ + ( SVBT8ToByte( aArc.fUp ) & 1 ) ];
+ if( !SVBT8ToByte( aArc.fLeft ) ){
+ aP0.Y() -= (sal_Int16)SVBT16ToShort( pHd->dya );
+ aP1.Y() -= (sal_Int16)SVBT16ToShort( pHd->dya );
+ }
+ if( SVBT8ToByte( aArc.fUp ) ){
+ aP0.X() -= (sal_Int16)SVBT16ToShort( pHd->dxa );
+ aP1.X() -= (sal_Int16)SVBT16ToShort( pHd->dxa );
+ }
+
+ SdrObject* pObj = new SdrCircObj( OBJ_SECT, Rectangle( aP0, aP1 ),
+ nW * 9000, ( ( nW + 1 ) & 3 ) * 9000 );
+
+ SetStdAttr( rSet, aArc.aLnt, aArc.aShd );
+ SetFill( rSet, aArc.aFill );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadPolyLine( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ WW8_DP_POLYLINE aPoly;
+
+ if( !ReadGrafStart( (void*)&aPoly, sizeof( aPoly ), pHd, pDo, rSet ) )
+ return 0;
+
+ sal_uInt16 nCount = SVBT16ToShort( aPoly.aBits1 ) >> 1 & 0x7fff;
+ SVBT16 *pP = new SVBT16[nCount * 2];
+ pStrm->Read( pP, nCount * 4 ); // Punkte einlesen
+ Polygon aP( nCount );
+ Point aPt;
+ sal_uInt16 i;
+
+ for( i=0; i<nCount; i++ ){
+ aPt.X() = SVBT16ToShort( pP[i << 1] ) + nDrawXOfs2
+ + (sal_Int16)SVBT16ToShort( pHd->xa );
+ aPt.Y() = SVBT16ToShort( pP[( i << 1 ) + 1] ) + nDrawYOfs2
+ + (sal_Int16)SVBT16ToShort( pHd->ya );
+ aP[i] = aPt;
+ }
+ delete[] pP;
+
+ SdrObject* pObj = new SdrPathObj(( SVBT16ToShort( aPoly.aBits1 ) & 0x1 ) ? OBJ_POLY : OBJ_PLIN, ::basegfx::B2DPolyPolygon(aP.getB2DPolygon()));
+ SetStdAttr( rSet, aPoly.aLnt, aPoly.aShd );
+ SetFill( rSet, aPoly.aFill );
+
+ return pObj;
+}
+
+ESelection SwWW8ImplReader::GetESelection( long nCpStart, long nCpEnd )
+{
+ sal_uInt16 nPCnt = mpDrawEditEngine->GetParagraphCount();
+ sal_uInt16 nSP = 0;
+ sal_uInt16 nEP = 0;
+ while( (nSP < nPCnt)
+ && (nCpStart >= mpDrawEditEngine->GetTextLen( nSP ) + 1) )
+ {
+ nCpStart -= mpDrawEditEngine->GetTextLen( nSP ) + 1;
+ nSP++;
+ }
+ // Beim Ende erst 1 Zeichen spaeter auf naechste Zeile umschalten,
+ // da sonst Zeilenattribute immer eine Zeile zu weit reichen.
+ while( (nEP < nPCnt)
+ && (nCpEnd > mpDrawEditEngine->GetTextLen( nEP ) + 1) )
+ {
+ nCpEnd -= mpDrawEditEngine->GetTextLen( nEP ) + 1;
+ nEP++;
+ }
+ return ESelection( nSP, (sal_uInt16)nCpStart, nEP, (sal_uInt16)nCpEnd );
+}
+
+// InsertTxbxStyAttrs() setzt die Style-Attribute in den uebergebenen ItemSet.
+// Es werden die SW-Styles genommen, die Import-WW-Styles sind zu diesem
+// Zeitpunkt schon destruiert.
+// Die SW-Styles werden per Tiefensuche, d.h. mit Parent-Styles nach den
+// in aSrcTab angegebenen Attributen untersucht. Diese werden per Clone
+// dupliziert, bei den Duplikaten werden die Which-IDs
+// gemaess der Tabelle aDstTab umgesetzt, damit die EditEngine sie nicht
+// ignoriert.
+// Es werden hierbei sowohl Para- wie auch Zeichen-Attribute in den
+// ItemSet gestopft.
+void SwWW8ImplReader::InsertTxbxStyAttrs( SfxItemSet& rS, sal_uInt16 nColl )
+{
+ SwWW8StyInf * pStyInf = GetStyle(nColl);
+ if( pStyInf != NULL && pStyInf->pFmt && pStyInf->bColl )
+ {
+ const SfxPoolItem* pItem;
+ for( sal_uInt16 i = POOLATTR_BEGIN; i < POOLATTR_END; i++ )
+ {
+ //If we are set in the source and not set in the destination
+ //then add it in.
+ if ( SFX_ITEM_SET == pStyInf->pFmt->GetItemState(
+ i, true, &pItem ) )
+ {
+ SfxItemPool *pEditPool = rS.GetPool();
+ sal_uInt16 nWhich = i;
+ sal_uInt16 nSlotId = rDoc.GetAttrPool().GetSlotId(nWhich);
+ if (
+ nSlotId && nWhich != nSlotId &&
+ 0 != (nWhich = pEditPool->GetWhich(nSlotId)) &&
+ nWhich != nSlotId &&
+ ( SFX_ITEM_SET != rS.GetItemState(nWhich, false) )
+ )
+ {
+ SfxPoolItem* pCopy = pItem->Clone();
+ pCopy->SetWhich( nWhich );
+ rS.Put( *pCopy );
+ delete pCopy;
+ }
+ }
+ }
+ }
+
+}
+
+static void lcl_StripFields(String &rString, long &rNewStartCp)
+{
+ for(sal_uInt16 i=0; i < rString.Len(); i++)
+ {
+ if( 0x13 == rString.GetChar( i ) )
+ {
+ do
+ {
+ rString.Erase( i, 1 );
+ rNewStartCp++;
+ }
+ while( rString.Len()
+ && ( i < rString.Len())
+ && (0x14 != rString.GetChar( i ) )
+ && (0x15 != rString.GetChar( i ) ) );
+ if( rString.Len() )
+ {
+ if( 0x14 == rString.GetChar( i ) )
+ {
+ rString.Erase( i, 1 );
+ rNewStartCp++;
+ do
+ {
+ i++;
+ }
+ while( rString.Len()
+ && ( i < rString.Len())
+ && (0x15 != rString.GetChar( i ) ) );
+ if( i < rString.Len() )
+ rString.Erase( i, 1 );
+ }
+ else if( 0x15 == rString.GetChar( i ) )
+ rString.Erase( i, 1 );
+ }
+ }
+ }
+}
+
+class Chunk
+{
+private:
+ String msURL;
+ long mnStartPos; //0x13
+ long mnEndPos; //0x15
+public:
+ explicit Chunk(long nStart, const String &rURL)
+ : msURL(rURL), mnStartPos(nStart), mnEndPos(0) {}
+ Chunk(const Chunk &rChunk)
+ : msURL(rChunk.msURL), mnStartPos(rChunk.mnStartPos),
+ mnEndPos(rChunk.mnEndPos) {}
+ Chunk& operator=(const Chunk &rChunk)
+ {
+ msURL = rChunk.msURL;
+ mnStartPos = rChunk.mnStartPos;
+ mnEndPos = rChunk.mnEndPos;
+ return *this;
+ }
+ void SetEndPos(long nEnd) { mnEndPos = nEnd; }
+ long GetStartPos() const {return mnStartPos;}
+ long GetEndPos() const {return mnEndPos;}
+ const String &GetURL() const {return msURL;}
+ void Adjust(xub_StrLen nAdjust)
+ {
+ mnStartPos-=nAdjust;
+ mnEndPos-=nAdjust;
+ }
+};
+
+// InsertAttrsAsDrawingAttrs() setzt zwischen StartCp und EndCp die Attribute.
+// Dabei werden Style-Attribute als harte Attribute, Absatz- und Zeichen-
+// attribute gesetzt.
+void SwWW8ImplReader::InsertAttrsAsDrawingAttrs(long nStartCp, long nEndCp,
+ ManTypes eType, bool bONLYnPicLocFc)
+{
+ /*
+ Save and create new plcxman for this drawing object, of the type that
+ will include the para end mark inside a paragraph property range, as
+ drawing boxes have real paragraph marks as part of their text, while
+ normal writer has seperate nodes for each paragraph and so has no actual
+ paragraph mark as part of the paragraph text.
+ */
+ WW8ReaderSave aSave(this);
+ pPlcxMan = new WW8PLCFMan(pSBase, eType, nStartCp, true);
+
+ WW8_CP nStart = pPlcxMan->Where();
+ WW8_CP nNext, nEnd, nStartReplace=0;
+
+ bool bDoingSymbol = false;
+ sal_Unicode cReplaceSymbol = cSymbol;
+
+ SfxItemSet *pS = new SfxItemSet(mpDrawEditEngine->GetEmptyItemSet());
+ WW8PLCFManResult aRes;
+
+ std::deque<Chunk> aChunks;
+
+ //Here store stack location
+ sal_uInt16 nCurrentCount = static_cast< sal_uInt16 >(pCtrlStck->Count());
+ while (nStart < nEndCp)
+ {
+ //nStart is the beginning of the attributes for this range, and
+ //may be before the text itself. So watch out for that
+ WW8_CP nTxtStart = nStart;
+ if (nTxtStart < nStartCp)
+ nTxtStart = nStartCp;
+ // get position of next SPRM
+ bool bStartAttr = pPlcxMan->Get(&aRes);
+ nAktColl = pPlcxMan->GetColl();
+ if (aRes.nSprmId)
+ {
+ if( bONLYnPicLocFc )
+ {
+ if ( (68 == aRes.nSprmId) || (0x6A03 == aRes.nSprmId) )
+ {
+ Read_PicLoc(aRes.nSprmId, aRes.pMemPos +
+ mpSprmParser->DistanceToData(aRes.nSprmId), 4);
+ // Ok, that's what we were looking for. Now let's get
+ // out of here!
+ break;
+ }
+ }
+ else if ( aRes.nSprmId && (
+ (eFTN > aRes.nSprmId) || (0x0800 <= aRes.nSprmId) ) )
+ {
+ //Here place them onto our usual stack and we will pop them
+ //off and convert them later
+ if (bStartAttr)
+ {
+ ImportSprm(aRes.pMemPos, aRes.nSprmId);
+ if (!bDoingSymbol && bSymbol == true)
+ {
+ bDoingSymbol = true;
+ nStartReplace = nTxtStart;
+ cReplaceSymbol = cSymbol;
+ }
+ }
+ else
+ {
+ EndSprm( aRes.nSprmId );
+ if (bSymbol == false && bDoingSymbol)
+ {
+ bDoingSymbol = false;
+ String sTemp;
+ sTemp.Fill(writer_cast<xub_StrLen>(
+ nTxtStart - nStartReplace), cReplaceSymbol);
+ mpDrawEditEngine->QuickInsertText(sTemp,
+ GetESelection(nStartReplace - nStartCp,
+ nTxtStart - nStartCp ) );
+ }
+ }
+ }
+ else if (aRes.nSprmId == eFLD)
+ {
+ if (bStartAttr)
+ {
+ sal_uInt16 nCount = static_cast< sal_uInt16 >(pCtrlStck->Count());
+ if (maFieldStack.empty() && Read_Field(&aRes))
+ {
+ String sURL;
+ for (sal_uInt16 nI = static_cast< sal_uInt16 >(pCtrlStck->Count()); nI > nCount; --nI)
+ {
+ const SfxPoolItem *pItem = ((*pCtrlStck)[nI-1])->pAttr;
+ sal_uInt16 nWhich = pItem->Which();
+ if (nWhich == RES_TXTATR_INETFMT)
+ {
+ const SwFmtINetFmt *pURL =
+ (const SwFmtINetFmt *)pItem;
+ sURL = pURL->GetValue();
+ }
+ pCtrlStck->DeleteAndDestroy(nI-1);
+ }
+ aChunks.push_back(Chunk(nStart, sURL));
+ }
+ }
+ else
+ {
+ if (!maFieldStack.empty() && End_Field())
+ aChunks.back().SetEndPos(nStart+1);
+ }
+ }
+ }
+
+ (*pPlcxMan)++;
+ nNext = pPlcxMan->Where();
+
+ if( (nNext != nStart) && !bONLYnPicLocFc )
+ {
+ nEnd = ( nNext < nEndCp ) ? nNext : nEndCp;
+ SfxItemPool *pEditPool = pS->GetPool();
+
+ //Here read current properties and convert them into pS
+ //and put those attrs into the draw box if they can be converted
+ //to draw attributes
+ if (pCtrlStck->Count() - nCurrentCount)
+ {
+ for (sal_uInt16 i = nCurrentCount; i < pCtrlStck->Count(); i++)
+ {
+ const SfxPoolItem *pItem = ((*pCtrlStck)[i])->pAttr;
+ sal_uInt16 nWhich = pItem->Which();
+ if( nWhich < RES_FLTRATTR_BEGIN ||
+ nWhich >= RES_FLTRATTR_END )
+ {
+ sal_uInt16 nSlotId = rDoc.GetAttrPool().GetSlotId(nWhich);
+ if (
+ nSlotId && nWhich != nSlotId &&
+ 0 != (nWhich = pEditPool->GetWhich(nSlotId)) &&
+ nWhich != nSlotId
+ )
+ {
+ SfxPoolItem* pCopy = pItem->Clone();
+ pCopy->SetWhich( nWhich );
+ pS->Put( *pCopy );
+ delete pCopy;
+ }
+ }
+ }
+ }
+ //Fill in the remainder from the style
+ InsertTxbxStyAttrs(*pS, nAktColl);
+
+ if( pS->Count() )
+ {
+ mpDrawEditEngine->QuickSetAttribs( *pS,
+ GetESelection( nTxtStart - nStartCp, nEnd - nStartCp ) );
+ delete pS;
+ pS = new SfxItemSet(mpDrawEditEngine->GetEmptyItemSet());
+ }
+ }
+ nStart = nNext;
+ }
+ delete pS;
+
+ //pop off as far as recorded location just in case there were some left
+ //unclosed
+ for (sal_uInt16 nI = static_cast< sal_uInt16 >(pCtrlStck->Count()); nI > nCurrentCount; --nI)
+ pCtrlStck->DeleteAndDestroy(nI-1);
+
+ typedef std::deque<Chunk>::iterator myIter;
+ myIter aEnd = aChunks.end();
+ for (myIter aIter = aChunks.begin(); aIter != aEnd; ++aIter)
+ {
+ ESelection aSel(GetESelection(aIter->GetStartPos()-nStartCp,
+ aIter->GetEndPos()-nStartCp));
+ String aString(mpDrawEditEngine->GetText(aSel));
+ xub_StrLen nOrigLen = aString.Len();
+ long nDummy(0);
+ lcl_StripFields(aString, nDummy);
+
+ xub_StrLen nChanged;
+ if (aIter->GetURL().Len())
+ {
+ SvxURLField aURL(aIter->GetURL(), aString,
+ SVXURLFORMAT_APPDEFAULT);
+ mpDrawEditEngine->QuickInsertField(SvxFieldItem(aURL, EE_FEATURE_FIELD), aSel);
+ nChanged = nOrigLen - 1;
+ }
+ else
+ {
+ mpDrawEditEngine->QuickInsertText(aString, aSel);
+ nChanged = nOrigLen - aString.Len();
+ }
+ for (myIter aIter2 = aIter+1; aIter2 != aEnd; ++aIter2)
+ aIter2->Adjust(nChanged);
+ }
+
+ /*
+ Don't worry about the new pPlcxMan, the restorer removes it when
+ replacing the current one with the old one.
+ */
+ aSave.Restore(this);
+}
+
+bool SwWW8ImplReader::GetTxbxTextSttEndCp(WW8_CP& rStartCp, WW8_CP& rEndCp,
+ sal_uInt16 nTxBxS, sal_uInt16 nSequence)
+{
+ // rasch den TextBox-PLCF greifen
+ WW8PLCFspecial* pT = pPlcxMan ? pPlcxMan->GetTxbx() : 0;
+ if( !pT )
+ {
+ OSL_ENSURE( !this, "+Wo ist der Grafik-Text (1) ?" );
+ return false;
+ }
+
+ // ggfs. zuerst die richtige TextBox-Story finden
+ bool bCheckTextBoxStory = ( nTxBxS && pT->GetIMax() >= nTxBxS );
+ if( bCheckTextBoxStory )
+ pT->SetIdx( nTxBxS-1 );
+
+ // dann Start und Ende ermitteln
+ void* pT0;
+ if( !pT->Get( rStartCp, pT0 ) )
+ {
+ OSL_ENSURE( !this, "+Wo ist der Grafik-Text (2) ?" );
+ return false;
+ }
+
+ if( bCheckTextBoxStory )
+ {
+ bool bReusable = (0 != SVBT16ToShort( ((WW8_TXBXS*)pT0)->fReusable ));
+ while( bReusable )
+ {
+ (*pT)++;
+ if( !pT->Get( rStartCp, pT0 ) )
+ {
+ OSL_ENSURE( !this, "+Wo ist der Grafik-Text (2-a) ?" );
+ return false;
+ }
+ bReusable = (0 != SVBT16ToShort( ((WW8_TXBXS*)pT0)->fReusable ));
+ }
+ }
+ (*pT)++;
+ if( !pT->Get( rEndCp, pT0 ) )
+ {
+ OSL_ENSURE( !this, "+Wo ist der Grafik-Text (3) ?" );
+ return false;
+ }
+
+ // jetzt ggfs. die passende Page in der Break-Table finden
+ if( bCheckTextBoxStory )
+ {
+ // Sonderfall: gesamte(!) Kette soll ermittelt werden,
+ // dann sind wir hier schon fertig!
+ if( USHRT_MAX > nSequence )
+ {
+ long nMinStartCp = rStartCp;
+ long nMaxEndCp = rEndCp;
+ // rasch den TextBox-Break-Deskriptor-PLCF greifen
+ pT = pPlcxMan->GetTxbxBkd();
+ if (!pT) //It can occur on occasion, Caolan
+ return false;
+
+ // den ersten Eintrag fuer diese TextBox-Story finden
+ if( !pT->SeekPos( rStartCp ) )
+ {
+ OSL_ENSURE( !this, "+Wo ist der Grafik-Text (4) ?" );
+ return false;
+ }
+ // ggfs. entsprechende Anzahl Eintraege weitergehen
+ for(sal_uInt16 iSequence = 0; iSequence < nSequence; iSequence++) (*pT)++;
+ // dann die tatsaechlichen Start und Ende ermitteln
+ if( (!pT->Get( rStartCp, pT0 ))
+ || ( nMinStartCp > rStartCp ) )
+ {
+ OSL_ENSURE( !this, "+Wo ist der Grafik-Text (5) ?" );
+ return false;
+ }
+ if( rStartCp >= nMaxEndCp )
+ rEndCp = rStartCp; // kein Error: leerer String!
+ else
+ {
+ (*pT)++;
+ if( (!pT->Get( rEndCp, pT0 ))
+ || ( nMaxEndCp < rEndCp-1 ) )
+ {
+ OSL_ENSURE( !this, "+Wo ist der Grafik-Text (6) ?" );
+ return false;
+ }
+ rEndCp -= 1;
+ }
+ }
+ else
+ rEndCp -= 1;
+ }
+ else
+ rEndCp -= 1;
+ return true;
+}
+
+// TxbxText() holt aus WW-File den Text und gibt diesen und den Anfangs- und
+// den um -2 (bzw. -1 bei Ver8) korrigierten End-Cp zurueck
+bool SwWW8ImplReader::GetRangeAsDrawingString(String& rString, long nStartCp, long nEndCp, ManTypes eType)
+{
+ WW8_CP nOffset = pWwFib->GetBaseCp(eType);
+
+ bool bOk = false;
+ OSL_ENSURE(nStartCp <= nEndCp, "+Wo ist der Grafik-Text (7) ?");
+ if (nStartCp == nEndCp)
+ rString.Erase(); // leerer String: durchaus denkbar!
+ else if (nStartCp < nEndCp)
+ {
+ // den Text einlesen: kann sich ueber mehrere Pieces erstrecken!!!
+ sal_uInt16 nLen = pSBase->WW8ReadString(*pStrm, rString,
+ nStartCp + nOffset, nEndCp - nStartCp, GetCurrentCharSet());
+ OSL_ENSURE(nLen, "+Wo ist der Grafik-Text (8) ?");
+ if (nLen)
+ {
+ bOk = true;
+ if( 0x0d == rString.GetChar(nLen - 1) )
+ rString.Erase(nLen - 1);
+
+ rString.SearchAndReplaceAll( 0xb, 0xa );
+ }
+ }
+ return bOk;
+}
+
+OutlinerParaObject* SwWW8ImplReader::ImportAsOutliner(String &rString, WW8_CP nStartCp, WW8_CP nEndCp, ManTypes eType)
+{
+ OutlinerParaObject* pRet = 0;
+
+ if (GetRangeAsDrawingString( rString, nStartCp, nEndCp, eType ))
+ {
+ if (!mpDrawEditEngine)
+ mpDrawEditEngine = new EditEngine(0);
+
+ mpDrawEditEngine->SetText(rString);
+ InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType);
+
+ //Annotations typically begin with a (useless) 0x5
+ if ((eType == MAN_AND) && mpDrawEditEngine->GetTextLen())
+ {
+ ESelection aFirstChar(0, 0, 0, 1);
+ if (mpDrawEditEngine->GetText( aFirstChar ) == String(sal_Unicode(0x5)))
+ mpDrawEditEngine->QuickDelete(aFirstChar);
+ }
+
+ EditTextObject* pTemporaryText = mpDrawEditEngine->CreateTextObject();
+ pRet = new OutlinerParaObject(*pTemporaryText);
+ pRet->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT );
+ delete pTemporaryText;
+
+ mpDrawEditEngine->SetText( aEmptyStr );
+ mpDrawEditEngine->SetParaAttribs(0, mpDrawEditEngine->GetEmptyItemSet());
+
+ //Strip out fields, leaving the result
+ long nDummy(0);
+ lcl_StripFields(rString, nDummy);
+ //Strip out word's special characters for the simple string
+ rString.EraseAllChars(0x1);
+ rString.EraseAllChars(0x5);
+ rString.EraseAllChars(0x8);
+ rString.SearchAndReplaceAllAscii("\007\007", String::CreateFromAscii("\007\012"));
+ rString.SearchAndReplaceAll(0x7, ' ');
+
+ }
+
+ return pRet;
+}
+
+// InsertTxbxText() fuegt fuer TextBoxen und CaptionBoxen den Text
+// und die Attribute ein
+SwFrmFmt* SwWW8ImplReader::InsertTxbxText(SdrTextObj* pTextObj,
+ Size* pObjSiz, sal_uInt16 nTxBxS, sal_uInt16 nSequence, long nPosCp,
+ SwFrmFmt* pOldFlyFmt, bool bMakeSdrGrafObj, bool& rbEraseTextObj,
+ bool* pbTestTxbxContainsText, long* pnStartCp, long* pnEndCp,
+ bool* pbContainsGraphics, SvxMSDffImportRec* pRecord)
+{
+ SwFrmFmt* pFlyFmt = 0;
+ sal_uLong nOld = pStrm->Tell();
+
+ ManTypes eType = pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX;
+
+ rbEraseTextObj = false;
+
+ String aString;
+ WW8_CP nStartCp, nEndCp;
+ bool bContainsGraphics = false;
+ bool bTextWasRead = GetTxbxTextSttEndCp( nStartCp, nEndCp, nTxBxS,
+ nSequence ) && GetRangeAsDrawingString( aString, nStartCp, nEndCp, eType );
+
+ if (!mpDrawEditEngine)
+ mpDrawEditEngine = new EditEngine(0);
+ if( pObjSiz )
+ mpDrawEditEngine->SetPaperSize( *pObjSiz );
+
+ String aOrigString(aString);
+ if( bTextWasRead )
+ {
+ long nNewStartCp = nStartCp;
+ lcl_StripFields(aString, nNewStartCp);
+
+ if (1 != aString.Len())
+ {
+ if ( (STRING_NOTFOUND != aString.Search(0x1)) ||
+ (STRING_NOTFOUND != aString.Search(0x8)) )
+ {
+ bContainsGraphics = true;
+ }
+ }
+ else // May be a single graphic or object
+ {
+ bool bDone = true;
+ switch( aString.GetChar(0) )
+ {
+ case 0x1:
+ if (!pbTestTxbxContainsText)
+ {
+ WW8ReaderSave aSave(this, nNewStartCp -1);
+ bool bOldEmbeddObj = bEmbeddObj;
+ //bEmbedd Ordinarily would have been set by field
+ //parse, but this is impossible here so...
+ bEmbeddObj = true;
+
+ // 1st look for OLE- or Graph-Indicator Sprms
+ WW8PLCFx_Cp_FKP* pChp = pPlcxMan->GetChpPLCF();
+ WW8PLCFxDesc aDesc;
+ pChp->GetSprms( &aDesc );
+ WW8SprmIter aSprmIter(aDesc.pMemPos, aDesc.nSprmsLen,
+ *mpSprmParser);
+
+ const sal_uInt8* pParams = aSprmIter.GetAktParams();
+ for( int nLoop = 0; nLoop < 2; ++nLoop )
+ {
+ while( aSprmIter.GetSprms()
+ && (0 != (pParams = aSprmIter.GetAktParams())) )
+ {
+ sal_uInt16 nAktId = aSprmIter.GetAktId();
+ switch( nAktId )
+ {
+ case 75:
+ case 118:
+ case 0x080A:
+ case 0x0856:
+ Read_Obj(nAktId, pParams, 1);
+ break;
+ case 68: // Read_Pic()
+ case 0x6A03:
+ case 0x680E:
+ Read_PicLoc(nAktId, pParams, 1);
+ break;
+ }
+ aSprmIter.advance();
+ }
+
+ if( !nLoop )
+ {
+ pChp->GetPCDSprms( aDesc );
+ aSprmIter.SetSprms( aDesc.pMemPos,
+ aDesc.nSprmsLen );
+ }
+ }
+ aSave.Restore(this);
+ bEmbeddObj=bOldEmbeddObj;
+
+ // then import either an OLE of a Graphic
+ if( bObj )
+ {
+ if( bMakeSdrGrafObj && pTextObj &&
+ pTextObj->GetUpGroup() )
+ {
+ // SdrOleObj/SdrGrafObj anstatt des
+ // SdrTextObj in dessen Gruppe einsetzen
+
+ Graphic aGraph;
+ SdrObject* pNew = ImportOleBase(aGraph);
+
+ if( !pNew )
+ {
+ pNew = new SdrGrafObj;
+ ((SdrGrafObj*)pNew)->SetGraphic(aGraph);
+ }
+
+ GrafikCtor();
+
+ pNew->SetModel( pDrawModel );
+ pNew->SetLogicRect( pTextObj->GetCurrentBoundRect() );
+ pNew->SetLayer( pTextObj->GetLayer() );
+
+ pTextObj->GetUpGroup()->GetSubList()->
+ ReplaceObject(pNew, pTextObj->GetOrdNum());
+ }
+ else
+ pFlyFmt = ImportOle();
+ bObj = false;
+ }
+ else
+ {
+ InsertAttrsAsDrawingAttrs(nNewStartCp, nNewStartCp+1,
+ eType, true);
+ pFlyFmt = ImportGraf(bMakeSdrGrafObj ? pTextObj : 0,
+ pOldFlyFmt);
+ }
+ }
+ break;
+ case 0x8:
+ if ( (!pbTestTxbxContainsText) && (!bObj) )
+ pFlyFmt = Read_GrafLayer( nPosCp );
+ break;
+ default:
+ bDone = false;
+ break;
+ }
+
+ if( bDone )
+ {
+ if( pFlyFmt )
+ {
+ if( pRecord )
+ {
+ SfxItemSet aFlySet( rDoc.GetAttrPool(),
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1 );
+
+ Rectangle aInnerDist( pRecord->nDxTextLeft,
+ pRecord->nDyTextTop,
+ pRecord->nDxTextRight,
+ pRecord->nDyTextBottom );
+ MatchSdrItemsIntoFlySet( pTextObj,
+ aFlySet,
+ pRecord->eLineStyle,
+ pRecord->eLineDashing,
+ pRecord->eShapeType,
+ aInnerDist );
+
+ pFlyFmt->SetFmtAttr( aFlySet );
+
+ MapWrapIntoFlyFmt(pRecord, pFlyFmt);
+ }
+ }
+ aString.Erase();
+ rbEraseTextObj = (0 != pFlyFmt);
+ }
+ }
+ }
+
+ if( pnStartCp )
+ *pnStartCp = nStartCp;
+ if( pnEndCp )
+ *pnEndCp = nEndCp;
+
+ if( pbTestTxbxContainsText )
+ *pbTestTxbxContainsText = bTextWasRead && ! rbEraseTextObj;
+ else if( !rbEraseTextObj )
+ {
+ if( bTextWasRead )
+ {
+ mpDrawEditEngine->SetText(aOrigString);
+ InsertAttrsAsDrawingAttrs(nStartCp, nEndCp, eType);
+ }
+
+ bool bVertical = pTextObj->IsVerticalWriting() ? true : false;
+ EditTextObject* pTemporaryText = mpDrawEditEngine->CreateTextObject();
+ OutlinerParaObject* pOp = new OutlinerParaObject(*pTemporaryText);
+ pOp->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT );
+ pOp->SetVertical( bVertical );
+ delete pTemporaryText;
+ pTextObj->NbcSetOutlinerParaObject( pOp );
+ pTextObj->SetVerticalWriting(bVertical);
+
+ // Fuer die naechste Textbox noch die alten Absatz-Attribute
+ // und Styles entfernen, sonst startet die naechste Box
+ // mit falschen Attributen.
+ // Vorgehen: Text loeschen = auf 1 Absatz reduzieren
+ // und an diesem Absatz die Absatzattribute und Styles loeschen
+ // (Empfehlung JOE)
+ mpDrawEditEngine->SetText( aEmptyStr );
+ mpDrawEditEngine->SetParaAttribs(0, mpDrawEditEngine->GetEmptyItemSet());
+ }
+
+ pStrm->Seek( nOld );
+ if (pbContainsGraphics)
+ *pbContainsGraphics = bContainsGraphics;
+ return pFlyFmt;
+}
+
+
+bool SwWW8ImplReader::TxbxChainContainsRealText(sal_uInt16 nTxBxS, long& rStartCp,
+ long& rEndCp)
+{
+ bool bErase, bContainsText;
+ InsertTxbxText( 0,0,nTxBxS,USHRT_MAX,0,0,0, bErase, &bContainsText,
+ &rStartCp, &rEndCp );
+ return bContainsText;
+}
+
+
+// TextBoxes only for Ver67 !!
+SdrObject* SwWW8ImplReader::ReadTxtBox( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ bool bDummy;
+ WW8_DP_TXTBOX aTxtB;
+
+ if( !ReadGrafStart( (void*)&aTxtB, sizeof( aTxtB ), pHd, pDo, rSet ) )
+ return 0;
+
+ Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) + nDrawXOfs2,
+ (sal_Int16)SVBT16ToShort( pHd->ya ) + nDrawYOfs2 );
+ Point aP1( aP0 );
+ aP1.X() += (sal_Int16)SVBT16ToShort( pHd->dxa );
+ aP1.Y() += (sal_Int16)SVBT16ToShort( pHd->dya );
+
+ SdrObject* pObj = new SdrRectObj( OBJ_TEXT, Rectangle( aP0, aP1 ) );
+ pObj->SetModel( pDrawModel );
+ pObj->NbcSetSnapRect(Rectangle(aP0, aP1));
+ Size aSize( (sal_Int16)SVBT16ToShort( pHd->dxa ) ,
+ (sal_Int16)SVBT16ToShort( pHd->dya ) );
+
+ long nStartCpFly,nEndCpFly;
+ bool bContainsGraphics;
+ InsertTxbxText(PTR_CAST(SdrTextObj,pObj), &aSize, 0, 0, 0, 0, false,
+ bDummy,0,&nStartCpFly,&nEndCpFly,&bContainsGraphics);
+
+ SetStdAttr( rSet, aTxtB.aLnt, aTxtB.aShd );
+ SetFill( rSet, aTxtB.aFill );
+
+ rSet.Put( SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE ) );
+ rSet.Put( SdrTextAutoGrowWidthItem(false));
+ rSet.Put( SdrTextAutoGrowHeightItem(false));
+ rSet.Put( SdrTextLeftDistItem( MIN_BORDER_DIST*2 ) );
+ rSet.Put( SdrTextRightDistItem( MIN_BORDER_DIST*2 ) );
+ rSet.Put( SdrTextUpperDistItem( MIN_BORDER_DIST ) );
+ rSet.Put( SdrTextLowerDistItem( MIN_BORDER_DIST ) );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadCaptionBox( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ static SdrCaptionType aCaptA[] = { SDRCAPT_TYPE1, SDRCAPT_TYPE2,
+ SDRCAPT_TYPE3, SDRCAPT_TYPE4 };
+
+ WW8_DP_CALLOUT_TXTBOX aCallB;
+
+ if( !ReadGrafStart( (void*)&aCallB, sizeof( aCallB ), pHd, pDo, rSet ) )
+ return 0;
+
+ sal_uInt16 nCount = SVBT16ToShort( aCallB.dpPolyLine.aBits1 ) >> 1 & 0x7fff;
+ SVBT16 *pP = new SVBT16[nCount * 2];
+ pStrm->Read( pP, nCount * 4 ); // Punkte einlesen
+ sal_uInt8 nTyp = (sal_uInt8)nCount - 1;
+ if( nTyp == 1 && SVBT16ToShort( pP[0] ) == SVBT16ToShort( pP[2] ) )
+ nTyp = 0;
+
+ Point aP0( (sal_Int16)SVBT16ToShort( pHd->xa ) +
+ (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.xa ) + nDrawXOfs2,
+ (sal_Int16)SVBT16ToShort( pHd->ya )
+ + (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.ya ) + nDrawYOfs2 );
+ Point aP1( aP0 );
+ aP1.X() += (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dxa );
+ aP1.Y() += (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dya );
+ Point aP2( (sal_Int16)SVBT16ToShort( pHd->xa )
+ + (sal_Int16)SVBT16ToShort( aCallB.dpheadPolyLine.xa )
+ + nDrawXOfs2 + (sal_Int16)SVBT16ToShort( pP[0] ),
+ (sal_Int16)SVBT16ToShort( pHd->ya )
+ + (sal_Int16)SVBT16ToShort( aCallB.dpheadPolyLine.ya )
+ + nDrawYOfs2 + (sal_Int16)SVBT16ToShort( pP[1] ) );
+ delete[] pP;
+
+ SdrCaptionObj* pObj = new SdrCaptionObj( Rectangle( aP0, aP1 ), aP2 );
+ pObj->SetModel( pDrawModel );
+ pObj->NbcSetSnapRect(Rectangle(aP0, aP1));
+ Size aSize( (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dxa ),
+ (sal_Int16)SVBT16ToShort( aCallB.dpheadTxbx.dya ) );
+ bool bEraseThisObject;
+
+ InsertTxbxText(pObj, &aSize, 0, 0, 0, 0, false, bEraseThisObject );
+
+ if( SVBT16ToShort( aCallB.dptxbx.aLnt.lnps ) != 5 ) // Umrandung sichtbar ?
+ SetStdAttr( rSet, aCallB.dptxbx.aLnt, aCallB.dptxbx.aShd );
+ else // nein -> Nimm Linie
+ SetStdAttr( rSet, aCallB.dpPolyLine.aLnt, aCallB.dptxbx.aShd );
+ SetFill( rSet, aCallB.dptxbx.aFill );
+ rSet.Put( SdrCaptionTypeItem( aCaptA[nTyp] ) );
+
+ return pObj;
+}
+
+
+SdrObject *SwWW8ImplReader::ReadGroup( WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ sal_Int16 nGrouped;
+
+ if( !ReadGrafStart( (void*)&nGrouped, sizeof( nGrouped ), pHd, pDo, rSet ) )
+ return 0;
+
+#ifdef OSL_BIGENDIAN
+ nGrouped = (sal_Int16)SWAPSHORT( nGrouped );
+#endif
+
+ nDrawXOfs = nDrawXOfs + (sal_Int16)SVBT16ToShort( pHd->xa );
+ nDrawYOfs = nDrawYOfs + (sal_Int16)SVBT16ToShort( pHd->ya );
+
+ SdrObject* pObj = new SdrObjGroup;
+
+ short nLeft = (sal_Int16)SVBT16ToShort( pHd->cb ) - sizeof( WW8_DPHEAD );
+ for (int i = 0; i < nGrouped; i++)
+ {
+ SfxAllItemSet aSet(pDrawModel->GetItemPool());
+ if (SdrObject *pObject = ReadGrafPrimitive(nLeft, pDo, aSet))
+ {
+ // first add and then set ItemSet
+ SdrObjList *pSubGroup = pObj->GetSubList();
+ OSL_ENSURE(pSubGroup, "Why no sublist available?");
+ if (pSubGroup)
+ pSubGroup->InsertObject(pObject, 0);
+ pObject->SetMergedItemSetAndBroadcast(aSet);
+ }
+ }
+
+ nDrawXOfs = nDrawXOfs - (sal_Int16)SVBT16ToShort( pHd->xa );
+ nDrawYOfs = nDrawYOfs - (sal_Int16)SVBT16ToShort( pHd->ya );
+
+ return pObj;
+}
+
+SdrObject* SwWW8ImplReader::ReadGrafPrimitive( short& rLeft, const WW8_DO* pDo,
+ SfxAllItemSet &rSet)
+{
+ //cmc: This whole archaic word 6 graphic import can probably be refactored
+ //into an object hierarachy with a little effort.
+ SdrObject *pRet=0;
+ WW8_DPHEAD aHd; // Lese Draw-Primitive-Header
+ pStrm->Read(&aHd, sizeof(WW8_DPHEAD));
+
+ if( rLeft >= SVBT16ToShort(aHd.cb) ) // Vorsichtsmassmahme
+ {
+ rSet.Put(SwFmtSurround(SURROUND_THROUGHT));
+ switch (SVBT16ToShort(aHd.dpk) & 0xff )
+ {
+ case 0:
+ pRet = ReadGroup( &aHd, pDo, rSet );
+ break;
+ case 1:
+ pRet = ReadLine( &aHd, pDo, rSet );
+ break;
+ case 2:
+ pRet = ReadTxtBox( &aHd, pDo, rSet );
+ break;
+ case 3:
+ pRet = ReadRect( &aHd, pDo, rSet );
+ break;
+ case 4:
+ pRet = ReadElipse( &aHd, pDo, rSet );
+ break;
+ case 5:
+ pRet = ReadArc( &aHd, pDo, rSet );
+ break;
+ case 6:
+ pRet = ReadPolyLine( &aHd, pDo, rSet );
+ break;
+ case 7:
+ pRet = ReadCaptionBox( &aHd, pDo, rSet );
+ break;
+ default: // unbekannt
+ pStrm->SeekRel(SVBT16ToShort(aHd.cb) - sizeof(WW8_DPHEAD));
+ break;
+ }
+ }
+ else
+ {
+ OSL_ENSURE( !this, "+Grafik-Overlap" );
+ }
+ rLeft = rLeft - SVBT16ToShort( aHd.cb );
+ return pRet;
+}
+
+void SwWW8ImplReader::ReadGrafLayer1( WW8PLCFspecial* pPF, long nGrafAnchorCp )
+{
+ pPF->SeekPos( nGrafAnchorCp );
+ WW8_FC nStartFc;
+ void* pF0;
+ if( !pPF->Get( nStartFc, pF0 ) )
+ {
+ OSL_ENSURE( !this, "+Wo ist die Grafik (2) ?" );
+ return;
+ }
+ WW8_FDOA* pF = (WW8_FDOA*)pF0;
+ if( !SVBT32ToUInt32( pF->fc ) )
+ {
+ OSL_ENSURE( !this, "+Wo ist die Grafik (3) ?" );
+ return;
+ }
+ WW8_DO aDo;
+ pStrm->Seek( SVBT32ToUInt32( pF->fc ) ); // Lese Draw-Header
+ pStrm->Read( &aDo, sizeof( WW8_DO ) );
+
+ short nLeft = SVBT16ToShort( aDo.cb ) - sizeof( WW8_DO );
+ while (nLeft > static_cast<short>(sizeof(WW8_DPHEAD)))
+ {
+ SfxAllItemSet aSet( pDrawModel->GetItemPool() );
+ if (SdrObject *pObject = ReadGrafPrimitive( nLeft, &aDo, aSet ))
+ {
+ pWWZOrder->InsertDrawingObject(pObject, SVBT16ToShort(aDo.dhgt));
+ SwFrmFmt *pFrm = rDoc.Insert( *pPaM, *pObject, &aSet, NULL);
+ pObject->SetMergedItemSet(aSet);
+ pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFrm);
+ }
+ }
+}
+
+sal_Int32 SwMSDffManager::GetEscherLineMatch(MSO_LineStyle eStyle,
+ MSO_SPT eShapeType, sal_Int32 &rThick)
+{
+ sal_Int32 nOutsideThick = 0;
+ /*
+ Beachte: im Gegensatz zu den Winword-ueblichen Tabellen- und
+ Rahmen-Randbreiten-Angaben, bei denen jeweils aus der Staerke *einer*
+ Linie die Gesamt-Randbreite zu errechnen ist, liegen die aus dem ESCHER
+ stammenden Daten bereits als Gesamt-Breite [twips] vor!
+
+ Der Winword default ist 15 tw. Wir nehmen hierfuer unsere 20 tw Linie. (
+ 0.75 pt uns 1.0 pt sehen sich auf dem Ausdruck naemlich aehnlicher als
+ etwas 0.75 pt und unsere 0.05 pt Haarlinie. ) Die Haarlinie setzen wir nur
+ bei Winword-Staerken bis zu maximal 0.5 pt ein.
+ */
+ switch( eStyle )
+ {
+ case mso_lineTriple:
+ case mso_lineSimple:
+ nOutsideThick = eShapeType != mso_sptTextBox ? rThick : rThick/2;
+ break;
+ case mso_lineDouble:
+ if (eShapeType == mso_sptTextBox)
+ {
+ nOutsideThick = rThick/6;
+ rThick = rThick*2/3;
+ }
+ else
+ nOutsideThick = rThick*2/3;
+ break;
+ case mso_lineThickThin:
+ if (eShapeType == mso_sptTextBox)
+ {
+ nOutsideThick = rThick*3/10;
+ rThick = rThick*4/5;
+ }
+ else
+ nOutsideThick = rThick*4/5;
+ break;
+ case mso_lineThinThick:
+ {
+ if (eShapeType == mso_sptTextBox)
+ {
+ nOutsideThick = rThick/10;
+ rThick = rThick*3/5;
+ }
+ else
+ nOutsideThick = rThick*3/5;
+ }
+ break;
+ default:
+ break;
+ }
+ return nOutsideThick;
+}
+
+//Returns the thickness of the line outside the frame, the logic of
+//words positioning of borders around floating objects is that of a
+//disturbed mind.
+sal_Int32 SwWW8ImplReader::MatchSdrBoxIntoFlyBoxItem(const Color& rLineColor,
+ MSO_LineStyle eLineStyle, MSO_LineDashing eDashing, MSO_SPT eShapeType, sal_Int32 &rLineThick,
+ SvxBoxItem& rBox )
+{
+ sal_Int32 nOutsideThick = 0;
+ if( !rLineThick )
+ return nOutsideThick;
+
+ ::editeng::SvxBorderStyle nIdx = ::editeng::SOLID;
+
+ sal_Int32 nLineThick=rLineThick;
+ nOutsideThick = SwMSDffManager::GetEscherLineMatch(eLineStyle,
+ eShapeType, rLineThick);
+
+ /*
+ Beachte: im Gegensatz zu den Winword-ueblichen Tabellen- und
+ Rahmen-Randbreiten-Angaben, bei denen jeweils aus der Staerke *einer*
+ Linie die Gesamt-Randbreite zu errechnen ist, liegen die aus dem ESCHER
+ stammenden Daten bereits als Gesamt-Breite [twips] vor!
+
+ Der Winword default ist 15 tw. Wir nehmen hierfuer unsere 20 tw Linie. (
+ 0.75 pt uns 1.0 pt sehen sich auf dem Ausdruck naemlich aehnlicher als
+ etwas 0.75 pt und unsere 0.05 pt Haarlinie. ) Die Haarlinie setzen wir nur
+ bei Winword-Staerken bis zu maximal 0.5 pt ein.
+ */
+ switch( +eLineStyle )
+ {
+ // zuerst die Einzel-Linien
+ case mso_lineSimple:
+ nIdx = ::editeng::SOLID;
+ break;
+ // dann die Doppel-Linien, fuer die wir feine Entsprechungen haben :-)))
+ case mso_lineDouble:
+ nIdx = ::editeng::DOUBLE;
+ break;
+ case mso_lineThickThin:
+ nIdx = ::editeng::THICKTHIN_SMALLGAP;
+ break;
+ case mso_lineThinThick:
+ nIdx = ::editeng::THINTHICK_SMALLGAP;
+ break;
+ // We have no triple border, use double instead.
+ case mso_lineTriple:
+ nIdx = ::editeng::DOUBLE;
+ break;
+ // no line style is set
+ case (MSO_LineStyle)USHRT_MAX:
+ break;
+ // erroneously not implemented line style is set
+ default:
+ OSL_ENSURE(!this, "eLineStyle is not (yet) implemented!");
+ break;
+ }
+
+ switch( eDashing )
+ {
+ case mso_lineDashGEL:
+ nIdx = ::editeng::DASHED;
+ break;
+ case mso_lineDotGEL:
+ nIdx = ::editeng::DOTTED;
+ break;
+ default:
+ break;
+ }
+
+ if (::editeng::NO_STYLE != nIdx)
+ {
+ SvxBorderLine aLine;
+ aLine.SetColor( rLineColor );
+
+ aLine.SetWidth( long ( nLineThick / 65 ) ); // Convert EMUs to Twips
+ aLine.SetStyle( nIdx );
+
+ for(sal_uInt16 nLine = 0; nLine < 4; ++nLine)
+ rBox.SetLine(new SvxBorderLine( aLine ), nLine);
+ }
+
+ return nOutsideThick;
+}
+
+#define WW8ITEMVALUE(ItemSet,Id,Cast) ((const Cast&)(ItemSet).Get(Id)).GetValue()
+
+void SwWW8ImplReader::MatchSdrItemsIntoFlySet( SdrObject* pSdrObj,
+ SfxItemSet& rFlySet, MSO_LineStyle eLineStyle, MSO_LineDashing eDashing, MSO_SPT eShapeType,
+ Rectangle& rInnerDist )
+{
+/*
+ am Rahmen zu setzende Frame-Attribute
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ SwFmtFrmSize falls noch nicht gesetzt, hier setzen
+ SvxLRSpaceItem hier setzen
+ SvxULSpaceItem hier setzen
+ SvxOpaqueItem (Derzeit bei Rahmen nicht moeglich! khz 10.2.1999)
+ SwFmtSurround bereits gesetzt
+ SwFmtVertOrient bereits gesetzt
+ SwFmtHoriOrient bereits gesetzt
+ SwFmtAnchor bereits gesetzt
+ SvxBoxItem hier setzen
+ SvxBrushItem hier setzen
+ SvxShadowItem hier setzen
+*/
+
+ // 1. GrafikObjekt des Docs?
+ GrafikCtor();
+
+ const SfxItemSet& rOldSet = pSdrObj->GetMergedItemSet();
+
+ // einige Items koennen direkt so uebernommen werden
+ const sal_uInt16 nDirectMatch = 2;
+ static RES_FRMATR const aDirectMatch[ nDirectMatch ] =
+ {
+ RES_LR_SPACE, // Aussenabstand links/rechts: SvxLRSpaceItem
+ RES_UL_SPACE // Aussenabstand Oben/unten: SvxULSpaceItem
+ };
+ const SfxPoolItem* pPoolItem;
+ for(sal_uInt16 nItem = 0; nItem < nDirectMatch; ++nItem)
+ if( SFX_ITEM_SET == rOldSet.GetItemState(
+ static_cast< sal_uInt16 >(aDirectMatch[ nItem ]), false, &pPoolItem) )
+ {
+ rFlySet.Put( *pPoolItem );
+ }
+
+
+ // jetzt die Umrandung berechnen und die Box bauen: Das Mass wird fuer die
+ // Rahmen-GROESSE benoetigt!
+ SvxBoxItem aBox(sw::util::ItemGet<SvxBoxItem>(rFlySet, RES_BOX));
+ // dashed oder solid wird zu solid
+ sal_Int32 nLineThick = 0, nOutside=0;
+
+ // check if LineStyle is *really* set!
+ const SfxPoolItem* pItem;
+
+ SfxItemState eState = rOldSet.GetItemState(XATTR_LINESTYLE,true,&pItem);
+ if( eState == SFX_ITEM_SET )
+ {
+ // Now, that we know there is a line style we will make use the
+ // parameter given to us when calling the method... :-)
+ const Color aLineColor = static_cast< XLineColorItem const & >(
+ rOldSet.Get(XATTR_LINECOLOR)).GetColorValue();
+ nLineThick = WW8ITEMVALUE(rOldSet, XATTR_LINEWIDTH, XLineWidthItem);
+
+ if( !nLineThick )
+ nLineThick = 15; // WW-default: 0.75 pt
+
+ nOutside = MatchSdrBoxIntoFlyBoxItem(aLineColor, eLineStyle,
+ eDashing, eShapeType, nLineThick, aBox);
+ }
+
+ rInnerDist.Left()+=nLineThick;
+ rInnerDist.Top()+=nLineThick;
+ rInnerDist.Right()+=nLineThick;
+ rInnerDist.Bottom()+=nLineThick;
+
+ const SvxBorderLine *pLine;
+ if (0 != (pLine = aBox.GetLine(BOX_LINE_LEFT)))
+ {
+ rInnerDist.Left() -= (pLine->GetScaledWidth());
+ }
+
+ if (0 != (pLine = aBox.GetLine(BOX_LINE_TOP)))
+ {
+ rInnerDist.Top() -= (pLine->GetScaledWidth());
+ }
+
+ if (0 != (pLine = aBox.GetLine(BOX_LINE_RIGHT)))
+ {
+ rInnerDist.Right() -= (pLine->GetScaledWidth());
+ }
+
+ if (0 != (pLine = aBox.GetLine(BOX_LINE_BOTTOM)))
+ {
+ rInnerDist.Bottom() -= (pLine->GetScaledWidth());
+ }
+
+ // set distances from box's border to text contained within the box
+ if( 0 < rInnerDist.Left() )
+ aBox.SetDistance( (sal_uInt16)rInnerDist.Left(), BOX_LINE_LEFT );
+ if( 0 < rInnerDist.Top() )
+ aBox.SetDistance( (sal_uInt16)rInnerDist.Top(), BOX_LINE_TOP );
+ if( 0 < rInnerDist.Right() )
+ aBox.SetDistance( (sal_uInt16)rInnerDist.Right(), BOX_LINE_RIGHT );
+ if( 0 < rInnerDist.Bottom() )
+ aBox.SetDistance( (sal_uInt16)rInnerDist.Bottom(), BOX_LINE_BOTTOM );
+
+ bool bFixSize = !(WW8ITEMVALUE(rOldSet, SDRATTR_TEXT_AUTOGROWHEIGHT,
+ SdrTextAutoGrowHeightItem));
+
+ // Size: SwFmtFrmSize
+ if( SFX_ITEM_SET != rFlySet.GetItemState(RES_FRM_SIZE, false) )
+ {
+ const Rectangle& rSnapRect = pSdrObj->GetSnapRect();
+ // if necessary adapt width and position of the framework: The
+ // recorded interior is to remain equally large despite thick edges.
+ rFlySet.Put( SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE,
+ rSnapRect.GetWidth() + 2*nOutside,
+ rSnapRect.GetHeight() + 2*nOutside) );
+ }
+ else //If a size is set, adjust it to consider border thickness
+ {
+ SwFmtFrmSize aSize = (const SwFmtFrmSize &)(rFlySet.Get(RES_FRM_SIZE));
+
+ SwFmtFrmSize aNewSize = SwFmtFrmSize(bFixSize ? ATT_FIX_SIZE : ATT_VAR_SIZE,
+ aSize.GetWidth() + 2*nOutside,
+ aSize.GetHeight() + 2*nOutside);
+ aNewSize.SetWidthSizeType(aSize.GetWidthSizeType());
+ rFlySet.Put( aNewSize );
+ }
+
+ //Sadly word puts escher borders outside the graphic, but orients the
+ //graphic in relation to the top left inside the border. We don't
+ if (nOutside)
+ {
+ SwFmtHoriOrient aHori = (const SwFmtHoriOrient &)(rFlySet.Get(
+ RES_HORI_ORIENT));
+ aHori.SetPos(MakeSafePositioningValue(aHori.GetPos()-nOutside));
+ rFlySet.Put(aHori);
+
+ SwFmtVertOrient aVert = (const SwFmtVertOrient &)(rFlySet.Get(
+ RES_VERT_ORIENT));
+ aVert.SetPos(aVert.GetPos()-nOutside);
+ rFlySet.Put(aVert);
+ }
+
+ // jetzt die Umrandung setzen
+ rFlySet.Put( aBox );
+
+ // Schattenwurf der Box: SvxShadowItem
+ if( WW8ITEMVALUE(rOldSet, SDRATTR_SHADOW, SdrShadowItem) )
+ {
+ SvxShadowItem aShadow( RES_SHADOW );
+
+ const Color aShdColor = static_cast< SdrShadowColorItem const & >(
+ rOldSet.Get(SDRATTR_SHADOWCOLOR)).GetColorValue();
+ const sal_Int32 nShdDistX = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWXDIST,
+ SdrShadowXDistItem);
+ const sal_Int32 nShdDistY = WW8ITEMVALUE(rOldSet, SDRATTR_SHADOWYDIST,
+ SdrShadowYDistItem);
+
+ aShadow.SetColor( Color( aShdColor ) );
+
+ aShadow.SetWidth(writer_cast<sal_uInt16>((Abs( nShdDistX) +
+ Abs( nShdDistY )) / 2 ));
+
+ SvxShadowLocation eShdPosi;
+ if( 0 <= nShdDistX )
+ {
+ if( 0 <= nShdDistY )
+ eShdPosi = SVX_SHADOW_BOTTOMRIGHT;
+ else
+ eShdPosi = SVX_SHADOW_TOPRIGHT;
+ }
+ else
+ {
+ if( 0 <= nShdDistY )
+ eShdPosi = SVX_SHADOW_BOTTOMLEFT;
+ else
+ eShdPosi = SVX_SHADOW_TOPLEFT;
+ }
+ aShadow.SetLocation( eShdPosi );
+
+ rFlySet.Put( aShadow );
+ }
+ Color Temp(COL_WHITE);
+ SvxBrushItem aBrushItem(Temp, RES_BACKGROUND);
+ bool bBrushItemOk = false;
+ sal_uInt8 nTrans = 0;
+
+ //Seperate transparency
+ eState = rOldSet.GetItemState(XATTR_FILLTRANSPARENCE, true, &pItem);
+ if (eState == SFX_ITEM_SET)
+ {
+ sal_uInt16 nRes = WW8ITEMVALUE(rOldSet, XATTR_FILLTRANSPARENCE,
+ XFillTransparenceItem);
+ nTrans = sal_uInt8((nRes * 0xFE) / 100);
+ aBrushItem.GetColor().SetTransparency(nTrans);
+ bBrushItemOk = true;
+ }
+
+ // Hintergrund: SvxBrushItem
+ eState = rOldSet.GetItemState(XATTR_FILLSTYLE, true, &pItem);
+ if (eState == SFX_ITEM_SET)
+ {
+ const XFillStyle eFill = ((const XFillStyleItem*)pItem)->GetValue();
+
+ switch (eFill)
+ {
+ case XFILL_NONE:
+ //Writer graphics don't have it yet
+ if (eShapeType != mso_sptPictureFrame)
+ {
+ aBrushItem.GetColor().SetTransparency(0xFE);
+ bBrushItemOk = true;
+ }
+ break;
+ case XFILL_SOLID:
+ case XFILL_GRADIENT:
+ {
+ const Color aColor = static_cast< XFillColorItem const & >(
+ rOldSet.Get(XATTR_FILLCOLOR)).GetColorValue();
+ aBrushItem.SetColor(aColor);
+
+ if (bBrushItemOk) //has trans
+ aBrushItem.GetColor().SetTransparency(nTrans);
+
+ bBrushItemOk = true;
+ }
+ break;
+ //case XFILL_GRADIENT:
+ //break;
+ case XFILL_HATCH:
+ break;
+ case XFILL_BITMAP:
+ {
+ const Graphic aGraphic(
+ static_cast< XFillBitmapItem const & >(
+ rOldSet.Get(XATTR_FILLBITMAP)).
+ GetBitmapValue().GetBitmap());
+ bool bTile = WW8ITEMVALUE(rOldSet, XATTR_FILLBMP_TILE,
+ SfxBoolItem) ? true: false;
+ GraphicObject aGrfObj(aGraphic);
+
+ aBrushItem.SetGraphicObject(aGrfObj);
+
+ if (bBrushItemOk) //has trans
+ {
+ GraphicObject *pGraphicObject =
+ const_cast<GraphicObject *>
+ (aBrushItem.GetGraphicObject());
+ GraphicAttr aAttr(pGraphicObject->GetAttr());
+ aAttr.SetTransparency(nTrans);
+ pGraphicObject->SetAttr(aAttr);
+ }
+
+ aBrushItem.SetGraphicPos(bTile ? GPOS_TILED : GPOS_AREA);
+
+ bBrushItemOk = true;
+ }
+ break;
+ }
+ }
+
+ if (bBrushItemOk)
+ rFlySet.Put(aBrushItem, RES_BACKGROUND);
+}
+
+void SwWW8ImplReader::AdjustLRWrapForWordMargins(
+ const SvxMSDffImportRec &rRecord, SvxLRSpaceItem &rLR)
+{
+ sal_uInt32 nXRelTo = SvxMSDffImportRec::RELTO_DEFAULT;
+ if ( rRecord.pXRelTo )
+ {
+ nXRelTo = *(rRecord.pXRelTo);
+ }
+
+ // Left adjustments - if horizontally aligned to left of
+ // margin or column then remove the left wrapping
+ if (rRecord.nXAlign == 1)
+ {
+ if ((nXRelTo == 0) || (nXRelTo == 2))
+ rLR.SetLeft((sal_uInt16)0);
+ }
+
+ // Right adjustments - if horizontally aligned to right of
+ // margin or column then remove the right wrapping
+ if (rRecord.nXAlign == 3)
+ {
+ if ((nXRelTo == 0) || (nXRelTo == 2))
+ rLR.SetRight((sal_uInt16)0);
+ }
+
+ //Inside margin, remove left wrapping
+ if ((rRecord.nXAlign == 4) && (nXRelTo == 0))
+ {
+ rLR.SetLeft((sal_uInt16)0);
+ }
+
+ //Outside margin, remove left wrapping
+ if ((rRecord.nXAlign == 5) && (nXRelTo == 0))
+ {
+ rLR.SetRight((sal_uInt16)0);
+ }
+}
+
+
+void SwWW8ImplReader::AdjustULWrapForWordMargins(
+ const SvxMSDffImportRec &rRecord, SvxULSpaceItem &rUL)
+{
+ sal_uInt32 nYRelTo = SvxMSDffImportRec::RELTO_DEFAULT;
+ if ( rRecord.pYRelTo )
+ {
+ nYRelTo = *(rRecord.pYRelTo);
+ }
+
+ // Top adjustment - remove upper wrapping if aligned to page
+ // printable area or to page
+ if (rRecord.nYAlign == 1)
+ {
+ if ((nYRelTo == 0) || (nYRelTo == 1))
+ rUL.SetUpper((sal_uInt16)0);
+ }
+
+ // Bottom adjustment - remove bottom wrapping if aligned to page or
+ // printable area or to page
+ if (rRecord.nYAlign == 3)
+ {
+ if ((nYRelTo == 0) || (nYRelTo == 1))
+ rUL.SetLower((sal_uInt16)0);
+ }
+
+ //Remove top margin if aligned vertically inside margin
+ if ((rRecord.nYAlign == 4) && (nYRelTo == 0))
+ rUL.SetUpper((sal_uInt16)0);
+}
+
+void SwWW8ImplReader::MapWrapIntoFlyFmt(SvxMSDffImportRec* pRecord,
+ SwFrmFmt* pFlyFmt)
+{
+ if (!pRecord || !pFlyFmt)
+ return;
+
+ if (pRecord->nDxWrapDistLeft || pRecord->nDxWrapDistRight)
+ {
+ SvxLRSpaceItem aLR(writer_cast<sal_uInt16>(pRecord->nDxWrapDistLeft),
+ writer_cast<sal_uInt16>(pRecord->nDxWrapDistRight), 0, 0, RES_LR_SPACE);
+ AdjustLRWrapForWordMargins(*pRecord, aLR);
+ pFlyFmt->SetFmtAttr(aLR);
+ }
+ if (pRecord->nDyWrapDistTop || pRecord->nDyWrapDistBottom)
+ {
+ SvxULSpaceItem aUL(writer_cast<sal_uInt16>(pRecord->nDyWrapDistTop),
+ writer_cast<sal_uInt16>(pRecord->nDyWrapDistBottom), RES_UL_SPACE);
+ AdjustULWrapForWordMargins(*pRecord, aUL);
+ pFlyFmt->SetFmtAttr(aUL);
+ }
+
+ //If we are contoured and have a custom polygon...
+ if (pRecord->pWrapPolygon && pFlyFmt->GetSurround().IsContour())
+ {
+ if (SwNoTxtNode *pNd = GetNoTxtNodeFromSwFrmFmt(*pFlyFmt))
+ {
+
+ /*
+ Gather round children and hear of a tale that will raise the
+ hairs on the back of your neck this dark halloween night.
+
+ There is a polygon in word that describes the wraping around
+ the graphic.
+
+ Here are some sample values for the simplest case of a square
+ around some solid coloured graphics
+
+ X Y Pixel size of graphic
+ TopLeft -54 21600 400x400
+ Bottom Right 0 21546
+
+ TopLeft -108 21600 200x200
+ Bottom Right 0 21492
+
+ TopLeft -216 21600 100x100
+ Bottom Right 0 21384
+
+ TopLeft -432 21600 50x50
+ Bottom Right 0 21168
+
+ TopLeft -76 21600 283x212
+ Bottom Right 0 21498
+
+ So given that the size of the values remains pretty much the
+ same despite the size of the graphic, we can tell that the
+ polygon is measured in units that are independant of the
+ graphic. But why does the left corner move a different value
+ to the left each time, and why does the bottom move upwards
+ each time, when the right and top remain at the same value ?
+
+ I have no idea, but clearly once we calculate the values out
+ we see that the left margin is always a fixed realworld
+ distance from the true left and the polygon bottom is the same
+ fixed value from the bottom. i.e. 15twips.
+
+ So here we take our word provided polygon, shift it to the
+ right by 15twips and rescale it widthwise to shrink the width
+ a little to fit the now moved right margin back to where it
+ was, and stretch the height a little to make the bottom move
+ down the missing 15twips then we get a polygon that matches
+ what I actually see in word
+ */
+
+ PolyPolygon aPoly(*pRecord->pWrapPolygon);
+ const Size &rSize = pNd->GetTwipSize();
+ /*
+ Move to the left by 15twips, and rescale to
+ a) shrink right bound back to orig position
+ b) stretch bottom bound to where I think it should have been
+ in the first place
+ */
+ Fraction aMoveHack(ww::nWrap100Percent, rSize.Width());
+ aMoveHack *= Fraction(15, 1);
+ long nMove(aMoveHack);
+ aPoly.Move(nMove, 0);
+
+ Fraction aHackX(ww::nWrap100Percent, ww::nWrap100Percent + nMove);
+ Fraction aHackY(ww::nWrap100Percent, ww::nWrap100Percent - nMove);
+ aPoly.Scale(aHackX, aHackY);
+
+ //Turn polygon back into units that match the graphic's
+ const Size &rOrigSize = pNd->GetGraphic().GetPrefSize();
+ Fraction aMapPolyX(rOrigSize.Width(), ww::nWrap100Percent);
+ Fraction aMapPolyY(rOrigSize.Height(), ww::nWrap100Percent);
+ aPoly.Scale(aMapPolyX, aMapPolyY);
+
+ // #i47277# - contour is already in unit of the
+ // graphic prefered unit. Thus, call method <SetContour(..)>
+ pNd->SetContour(&aPoly);
+ // <--
+ }
+ }
+}
+
+void SwWW8ImplReader::SetAttributesAtGrfNode( SvxMSDffImportRec* pRecord,
+ SwFrmFmt *pFlyFmt, WW8_FSPA *pF )
+{
+ const SwNodeIndex* pIdx = pFlyFmt->GetCntnt(false).GetCntntIdx();
+ SwGrfNode* pGrfNd;
+ if( pIdx && 0 != (pGrfNd = rDoc.GetNodes()[pIdx->GetIndex() + 1]->GetGrfNode() ))
+ {
+ Size aSz(pGrfNd->GetTwipSize());
+ // use type <sal_uInt64> instead of sal_uLong to get correct results
+ // in the following calculations.
+ sal_uInt64 rHeight = aSz.Height();
+ sal_uInt64 rWidth = aSz.Width();
+ if( !rWidth && pF)
+ rWidth = pF->nXaRight - pF->nXaLeft;
+ else if( !rHeight && pF)
+ rHeight = pF->nYaBottom - pF->nYaTop;
+
+ if( pRecord->nCropFromTop || pRecord->nCropFromBottom ||
+ pRecord->nCropFromLeft || pRecord->nCropFromRight )
+ {
+ SwCropGrf aCrop; // Cropping is stored in 'fixed floats'
+ // 16.16 (it est fraction times total
+ if( pRecord->nCropFromTop ) // image width or height resp.)
+ aCrop.SetTop( static_cast< sal_Int32 >(
+ ( ( (pRecord->nCropFromTop >> 16 ) * rHeight )
+ + (((pRecord->nCropFromTop & 0xffff) * rHeight ) >> 16) )));
+ if( pRecord->nCropFromBottom )
+ aCrop.SetBottom( static_cast< sal_Int32 >(
+ ( ( (pRecord->nCropFromBottom >> 16 ) * rHeight )
+ + (((pRecord->nCropFromBottom & 0xffff) * rHeight ) >> 16) )));
+ if( pRecord->nCropFromLeft )
+ aCrop.SetLeft( static_cast< sal_Int32 >(
+ ( ( (pRecord->nCropFromLeft >> 16 ) * rWidth )
+ + (((pRecord->nCropFromLeft & 0xffff) * rWidth ) >> 16) )));
+ if( pRecord->nCropFromRight )
+ aCrop.SetRight( static_cast< sal_Int32 >(
+ ( ( (pRecord->nCropFromRight >> 16 ) * rWidth )
+ + (((pRecord->nCropFromRight & 0xffff) * rWidth ) >> 16) )));
+
+ pGrfNd->SetAttr( aCrop );
+ }
+
+ if (pRecord && pRecord->pObj)
+ {
+ const SfxItemSet& rOldSet = pRecord->pObj->GetMergedItemSet();
+ //contrast
+ if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFCONTRAST,
+ SdrGrafContrastItem))
+ {
+ SwContrastGrf aContrast(
+ WW8ITEMVALUE(rOldSet,
+ SDRATTR_GRAFCONTRAST, SdrGrafContrastItem));
+ pGrfNd->SetAttr( aContrast );
+ }
+
+ //luminance
+ if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFLUMINANCE,
+ SdrGrafLuminanceItem))
+ {
+ SwLuminanceGrf aLuminance(WW8ITEMVALUE(rOldSet,
+ SDRATTR_GRAFLUMINANCE, SdrGrafLuminanceItem));
+ pGrfNd->SetAttr( aLuminance );
+ }
+ //gamma
+ if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA, SdrGrafGamma100Item))
+ {
+ double fVal = WW8ITEMVALUE(rOldSet, SDRATTR_GRAFGAMMA,
+ SdrGrafGamma100Item);
+ pGrfNd->SetAttr(SwGammaGrf(fVal/100.));
+ }
+
+ //drawmode
+ if (WW8ITEMVALUE(rOldSet, SDRATTR_GRAFMODE, SdrGrafModeItem))
+ {
+ SwDrawModeGrf aDrawMode( static_cast< sal_uInt16 >(WW8ITEMVALUE(rOldSet,
+ SDRATTR_GRAFMODE, SdrGrafModeItem)) );
+ pGrfNd->SetAttr( aDrawMode );
+ }
+ }
+ }
+}
+
+SdrObject* SwWW8ImplReader::CreateContactObject(SwFrmFmt* pFlyFmt)
+{
+ if (pFlyFmt)
+ {
+ SdrObject* pNewObject = mbNewDoc ? 0 : pFlyFmt->FindRealSdrObject();
+ if (!pNewObject)
+ pNewObject = pFlyFmt->FindSdrObject();
+ if (!pNewObject && pFlyFmt->ISA(SwFlyFrmFmt))
+ {
+ SwFlyDrawContact* pContactObject
+ = new SwFlyDrawContact(static_cast<SwFlyFrmFmt*>(pFlyFmt),
+ pDrawModel);
+ pNewObject = pContactObject->GetMaster();
+ }
+ return pNewObject;
+ }
+ return 0;
+}
+
+// Miserable miserable hack to fudge word's graphic layout in RTL mode to ours.
+bool SwWW8ImplReader::MiserableRTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
+ sal_Int16 eHoriOri, sal_Int16 eHoriRel)
+{
+ if (!IsRightToLeft())
+ return false;
+ return RTLGraphicsHack(rLeft, nWidth, eHoriOri, eHoriRel,
+ maSectionManager.GetPageLeft(),
+ maSectionManager.GetPageRight(),
+ maSectionManager.GetPageWidth());
+}
+
+RndStdIds SwWW8ImplReader::ProcessEscherAlign(SvxMSDffImportRec* pRecord,
+ WW8_FSPA *pFSPA, SfxItemSet &rFlySet, bool /*bOrgObjectWasReplace*/)
+{
+ OSL_ENSURE(pRecord || pFSPA, "give me something! to work with for anchoring");
+ if (!pRecord && !pFSPA)
+ return FLY_AT_PAGE;
+
+ SvxMSDffImportRec aRecordFromFSPA;
+ if (!pRecord)
+ pRecord = &aRecordFromFSPA;
+ if (!(pRecord->pXRelTo) && pFSPA)
+ {
+ pRecord->pXRelTo = new sal_uInt32;
+ *(pRecord->pXRelTo) = pFSPA->nbx;
+ }
+ if (!(pRecord->pYRelTo) && pFSPA)
+ {
+ pRecord->pYRelTo = new sal_uInt32;
+ *(pRecord->pYRelTo) = pFSPA->nby;
+ }
+
+ // nXAlign - abs. Position, Left, Centered, Right, Inside, Outside
+ // nYAlign - abs. Position, Top, Centered, Bottom, Inside, Outside
+
+ // nXRelTo - Page printable area, Page, Column, Character
+ // nYRelTo - Page printable area, Page, Paragraph, Line
+
+ const sal_uInt32 nCntXAlign = 6;
+ const sal_uInt32 nCntYAlign = 6;
+
+ const sal_uInt32 nCntRelTo = 4;
+
+ sal_uInt32 nXAlign = nCntXAlign > pRecord->nXAlign ? pRecord->nXAlign : 1;
+ sal_uInt32 nYAlign = nCntYAlign > pRecord->nYAlign ? pRecord->nYAlign : 1;
+
+ if (pFSPA)
+ {
+ /*
+ #i15718# #i19008#
+ Strangely in this case the FSPA value seems to be considered before
+ the newer escher nXRelTo record.
+ */
+ // #i52565# - correct condition checking:
+ // first check, if <nXRelTo> and <nYRelTo> have default values. This
+ // is a hint that these values aren't set by the escher import - see
+ // method <SwMSDffManager::ProcessObj(..)>. Then, check if for each
+ // values, if it differs from the one in the FSPA.
+ if ( *(pRecord->pXRelTo) == 2 && *(pRecord->pYRelTo) == 2 )
+ {
+ // if <nYRelTo> differs from <FSPA.nby> overwrite <nYRelTo>
+ if ( pFSPA->nby != *(pRecord->pYRelTo) )
+ {
+ *(pRecord->pYRelTo) = pFSPA->nby;
+ }
+ }
+ }
+
+ sal_uInt32 nXRelTo = nCntRelTo > *(pRecord->pXRelTo) ? *(pRecord->pXRelTo) : 1;
+ sal_uInt32 nYRelTo = nCntRelTo > *(pRecord->pYRelTo) ? *(pRecord->pYRelTo) : 1;
+
+ RndStdIds eAnchor = IsInlineEscherHack() ? FLY_AS_CHAR : FLY_AT_CHAR; // #i43718#
+
+ SwFmtAnchor aAnchor( eAnchor );
+ aAnchor.SetAnchor( pPaM->GetPoint() );
+ rFlySet.Put( aAnchor );
+
+ if (pFSPA)
+ {
+ // #i18732#
+ //Given new layout where everything is changed to be anchored to
+ //character the following 4 tables may need to be changed.
+
+ // horizontal Adjustment
+ static const sal_Int16 aHoriOriTab[ nCntXAlign ] =
+ {
+ text::HoriOrientation::NONE, // From left position
+ text::HoriOrientation::LEFT, // left
+ text::HoriOrientation::CENTER, // centered
+ text::HoriOrientation::RIGHT, // right
+ // #i36649#
+ // - inside -> text::HoriOrientation::LEFT and outside -> text::HoriOrientation::RIGHT
+ text::HoriOrientation::LEFT, // inside
+ text::HoriOrientation::RIGHT // outside
+ // <--
+ };
+
+
+ // generic vertical Adjustment
+ static const sal_Int16 aVertOriTab[ nCntYAlign ] =
+ {
+ text::VertOrientation::NONE, // From Top position
+ text::VertOrientation::TOP, // top
+ text::VertOrientation::CENTER, // centered
+ text::VertOrientation::BOTTOM, // bottom
+ text::VertOrientation::LINE_TOP, // inside (obscure)
+ text::VertOrientation::LINE_BOTTOM // outside (obscure)
+ };
+
+ // #i22673# - to-line vertical alignment
+ static const sal_Int16 aToLineVertOriTab[ nCntYAlign ] =
+ {
+ text::VertOrientation::NONE, // below
+ text::VertOrientation::LINE_BOTTOM, // top
+ text::VertOrientation::LINE_CENTER, // centered
+ text::VertOrientation::LINE_TOP, // bottom
+ text::VertOrientation::LINE_BOTTOM, // inside (obscure)
+ text::VertOrientation::LINE_TOP // outside (obscure)
+ };
+
+ // Adjustment is horizontally relative to...
+ static const sal_Int16 aHoriRelOriTab[nCntRelTo] =
+ {
+ text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
+ text::RelOrientation::PAGE_FRAME, // 1 is page margin
+ text::RelOrientation::FRAME, // 2 is relative to column
+ text::RelOrientation::CHAR // 3 is relative to character
+ };
+
+ // Adjustment is vertically relative to...
+ // #i22673# - adjustment for new vertical alignment at top of line.
+ static const sal_Int16 aVertRelOriTab[nCntRelTo] =
+ {
+ text::RelOrientation::PAGE_PRINT_AREA, // 0 is page textarea margin
+ text::RelOrientation::PAGE_FRAME, // 1 is page margin
+ text::RelOrientation::FRAME, // 2 is relative to paragraph
+ text::RelOrientation::TEXT_LINE // 3 is relative to line
+ };
+
+ sal_Int16 eHoriOri = aHoriOriTab[ nXAlign ];
+ sal_Int16 eHoriRel = aHoriRelOriTab[ nXRelTo ];
+
+ // #i36649# - adjustments for certain alignments
+ if ( eHoriOri == text::HoriOrientation::LEFT && eHoriRel == text::RelOrientation::PAGE_FRAME )
+ {
+ // convert 'left to page' to 'from left -<width> to page text area'
+ eHoriOri = text::HoriOrientation::NONE;
+ eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
+ const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
+ pFSPA->nXaLeft = -nWidth;
+ pFSPA->nXaRight = 0;
+ }
+ else if ( eHoriOri == text::HoriOrientation::RIGHT && eHoriRel == text::RelOrientation::PAGE_FRAME )
+ {
+ // convert 'right to page' to 'from left 0 to right page border'
+ eHoriOri = text::HoriOrientation::NONE;
+ eHoriRel = text::RelOrientation::PAGE_RIGHT;
+ const long nWidth = pFSPA->nXaRight - pFSPA->nXaLeft;
+ pFSPA->nXaLeft = 0;
+ pFSPA->nXaRight = nWidth;
+ }
+ // <--
+
+ // #i24255# - position of floating screen objects in
+ // R2L layout are given in L2R layout, thus convert them of all
+ // floating screen objects, which are imported.
+ {
+ // Miserable miserable hack.
+ SwTwips nWidth = (pFSPA->nXaRight - pFSPA->nXaLeft);
+ SwTwips nLeft = pFSPA->nXaLeft;
+ if (MiserableRTLGraphicsHack(nLeft, nWidth, eHoriOri,
+ eHoriRel))
+ {
+ pFSPA->nXaLeft = nLeft;
+ pFSPA->nXaRight = pFSPA->nXaLeft + nWidth;
+ }
+ }
+ // <--
+
+ // if the object is anchored inside a table cell, is horizontal aligned
+ // at frame|character and has wrap through, but its attribute
+ // 'layout in table cell' isn't set, convert its horizontal alignment to page text area.
+ // #i84783# - use new method <IsObjectLayoutInTableCell()>
+ if ( nInTable &&
+ ( eHoriRel == text::RelOrientation::FRAME || eHoriRel == text::RelOrientation::CHAR ) &&
+ pFSPA->nwr == 3 &&
+ !IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell ) )
+ {
+ eHoriRel = text::RelOrientation::PAGE_PRINT_AREA;
+ }
+ // <--
+
+ SwFmtHoriOrient aHoriOri(MakeSafePositioningValue(pFSPA->nXaLeft),
+ eHoriOri, eHoriRel);
+ if( 4 <= nXAlign )
+ aHoriOri.SetPosToggle(true);
+ rFlySet.Put( aHoriOri );
+
+ //Writer honours this wrap distance when aligned as "left" or "right",
+ //Word doesn't. Writer doesn't honour it when its "from left".
+ if (eHoriOri == text::HoriOrientation::LEFT)
+ pRecord->nDxWrapDistLeft=0;
+ else if (eHoriOri == text::HoriOrientation::RIGHT)
+ pRecord->nDxWrapDistRight=0;
+
+ sal_Int16 eVertRel;
+ eVertRel = aVertRelOriTab[ nYRelTo ]; // #i18732#
+ // #i22673# - fill <eVertOri> in dependence of <eVertRel>
+ sal_Int16 eVertOri;
+ if ( eVertRel == text::RelOrientation::TEXT_LINE )
+ {
+ eVertOri = aToLineVertOriTab[ nYAlign ];
+ }
+ else
+ {
+ eVertOri = aVertOriTab[ nYAlign ];
+ }
+
+ //Below line in word is a positive value, while in writer its
+ //negative
+ long nYPos = pFSPA->nYaTop;
+ // #i22673#
+ if ((eVertRel == text::RelOrientation::TEXT_LINE) && (eVertOri == text::VertOrientation::NONE))
+ nYPos = -nYPos;
+
+ rFlySet.Put(SwFmtVertOrient(MakeSafePositioningValue(nYPos),
+ eVertOri, eVertRel));
+
+ if (
+ (pFSPA->nYaTop < 0) && (eVertOri == text::VertOrientation::NONE) &&
+ ((eAnchor == FLY_AT_PARA) || (eAnchor == FLY_AT_CHAR))
+ )
+ {
+ maTracer.Log(sw::log::eNegativeVertPlacement);
+ }
+ }
+
+ return eAnchor;
+}
+
+// #i84783#
+bool SwWW8ImplReader::IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTableCell ) const
+{
+ bool bIsObjectLayoutInTableCell = false;
+
+ if ( bVer8 )
+ {
+ const sal_uInt16 nWWVersion = pWwFib->nProduct & 0xE000;
+ switch ( nWWVersion )
+ {
+ case 0x0000: // version 8 aka Microsoft Word 97
+ {
+ bIsObjectLayoutInTableCell = false;
+ OSL_ENSURE( nLayoutInTableCell == 0xFFFFFFFF,
+ "no explicit object attribute layout in table cell excepted." );
+ }
+ break;
+ case 0x2000: // version 9 aka Microsoft Word 2000
+ case 0x4000: // version 10 aka Microsoft Word 2002
+ case 0x6000: // version 11 aka Microsoft Word 2003
+ case 0x8000: // version 12 aka Microsoft Word 2007
+ {
+ // #i98037#
+ // adjustment of conditions needed after deeper analysis of
+ // certain test cases.
+ if ( nLayoutInTableCell == 0xFFFFFFFF || // no explicit attribute value given
+ nLayoutInTableCell & 0x80008000 ||
+ ( nLayoutInTableCell & 0x02000000 &&
+ !(nLayoutInTableCell & 0x80000000 ) ) )
+ // <--
+ {
+ bIsObjectLayoutInTableCell = true;
+ }
+ else
+ {
+ bIsObjectLayoutInTableCell = false;
+ }
+ }
+ break;
+ default:
+ {
+ OSL_FAIL( "unknown version." );
+ }
+ }
+ }
+
+ return bIsObjectLayoutInTableCell;
+}
+// <--
+
+SwFrmFmt* SwWW8ImplReader::Read_GrafLayer( long nGrafAnchorCp )
+{
+ if( nIniFlags & WW8FL_NO_GRAFLAYER )
+ return 0;
+
+ ::SetProgressState(nProgress, mpDocShell); // Update
+
+ nDrawCpO = pWwFib->GetBaseCp(pPlcxMan->GetManType() == MAN_HDFT ? MAN_TXBX_HDFT : MAN_TXBX);
+
+ GrafikCtor();
+
+ WW8PLCFspecial* pPF = pPlcxMan->GetFdoa();
+ if( !pPF )
+ {
+ OSL_ENSURE( !this, "Where is the grapic (1) ?" );
+ return 0;
+ }
+
+ if( bVer67 )
+ {
+ long nOldPos = pStrm->Tell();
+
+ nDrawXOfs = nDrawYOfs = 0;
+ ReadGrafLayer1( pPF, nGrafAnchorCp );
+
+ pStrm->Seek( nOldPos );
+ return 0;
+ }
+
+ //Normal case of Word 8+ version stuff
+ pPF->SeekPos( nGrafAnchorCp );
+
+ WW8_FC nStartFc;
+ void* pF0;
+ if( !pPF->Get( nStartFc, pF0 ) ){
+ OSL_ENSURE( !this, "+Wo ist die Grafik (2) ?" );
+ return 0;
+ }
+
+ WW8_FSPA_SHADOW* pFS = (WW8_FSPA_SHADOW*)pF0;
+ WW8_FSPA* pF;
+#ifdef __WW8_NEEDS_COPY
+ WW8_FSPA aFSFA;
+ pF = &aFSFA;
+ WW8FSPAShadowToReal( pFS, pF );
+#else
+ pF = (WW8_FSPA*)pFS;
+#endif // defined __WW8_NEEDS_COPY
+ if( !pF->nSpId )
+ {
+ OSL_ENSURE( !this, "+Wo ist die Grafik (3) ?" );
+ return 0;
+ }
+
+ if (!pMSDffManager->GetModel())
+ pMSDffManager->SetModel(pDrawModel, 1440);
+
+
+ Rectangle aRect(pF->nXaLeft, pF->nYaTop, pF->nXaRight, pF->nYaBottom);
+ SvxMSDffImportData aData( aRect );
+
+ /*
+ #i20540#
+ The SdrOle2Obj will try and manage any ole objects it finds, causing all
+ sorts of trouble later on
+ */
+ SwDocShell* pPersist = rDoc.GetDocShell();
+ rDoc.SetDocShell(0); //#i20540# Persist guard
+
+ SdrObject* pObject = 0;
+ bool bOk = (pMSDffManager->GetShape(pF->nSpId, pObject, aData) && pObject);
+
+ rDoc.SetDocShell(pPersist); //#i20540# Persist guard
+
+ if (!bOk)
+ {
+ OSL_ENSURE( !this, "Where is the Shape ?" );
+ return 0;
+ }
+
+ bool bDone = false;
+ SdrObject* pOurNewObject = 0;
+ bool bReplaceable = false;
+
+ switch (SdrObjKind(pObject->GetObjIdentifier()))
+ {
+ case OBJ_GRAF:
+ bReplaceable = true;
+ bDone = true;
+ break;
+ case OBJ_OLE2:
+ bReplaceable = true;
+ break;
+ default:
+ break;
+
+ }
+
+ // when in a header or footer word appears to treat all elements as wrap through
+
+ // Umfluss-Modus ermitteln
+ SfxItemSet aFlySet(rDoc.GetAttrPool(), RES_FRMATR_BEGIN, RES_FRMATR_END-1);
+ SwSurround eSurround = SURROUND_PARALLEL;
+ bool bContour = false;
+ switch (pF->nwr)
+ {
+ case 0: //0 like 2, but doesn't require absolute object
+ case 2: //2 wrap around absolute object
+ eSurround = SURROUND_PARALLEL;
+ break;
+ case 1: //1 no text next to shape
+ eSurround = SURROUND_NONE;
+ break;
+ case 3: //3 wrap as if no object present
+ eSurround = SURROUND_THROUGHT;
+ break;
+ case 4: //4 wrap tightly around object
+ case 5: //5 wrap tightly, but allow holes
+ eSurround = SURROUND_PARALLEL;
+ bContour = true;
+ break;
+ }
+
+ // bei Modus 2 oder 4 auch den Zusatzparameter beruecksichtigen
+ if ( (2 == pF->nwr) || (4 == pF->nwr) )
+ {
+ switch( pF->nwrk )
+ {
+ //0 wrap both sides
+ case 0:
+ eSurround = SURROUND_PARALLEL;
+ break;
+ //1 wrap only on left
+ case 1:
+ eSurround = SURROUND_LEFT;
+ break;
+ //2 wrap only on right
+ case 2:
+ eSurround = SURROUND_RIGHT;
+ break;
+ //3 wrap only on largest side
+ case 3:
+ eSurround = SURROUND_IDEAL;
+ break;
+ }
+ }
+
+ SwFmtSurround aSur( eSurround );
+ aSur.SetContour( bContour );
+ aSur.SetOutside(true); // Winword kann nur Aussen-Konturen
+ aFlySet.Put( aSur );
+
+ // eingelesenes Objekt (kann eine ganze Gruppe sein) jetzt korrekt
+ // positionieren usw.
+
+ OSL_ENSURE(!((aData.GetRecCount() != 1) && bReplaceable),
+ "Replaceable drawing with > 1 entries ?");
+
+ if (aData.GetRecCount() != 1)
+ bReplaceable = false;
+
+ SvxMSDffImportRec* pRecord = 0;
+ /*
+ Get the record for top level object, so we can get the word anchoring
+ and wrapping information for it.
+ */
+ sal_uInt16 nRecCount = aData.GetRecCount();
+ for (sal_uInt16 nTxbx=0; nTxbx < nRecCount; ++nTxbx )
+ {
+ pRecord = aData.GetRecord( nTxbx );
+ if (pRecord && pRecord->pObj == pObject)
+ break;
+ else
+ pRecord = 0;
+ }
+
+ OSL_ENSURE(pRecord, "how did that happen?");
+ if (!pRecord)
+ return 0;
+
+ const bool bLayoutInTableCell =
+ nInTable && IsObjectLayoutInTableCell( pRecord->nLayoutInTableCell );
+ // <--
+
+ // #i18732# - Switch on 'follow text flow', if object is laid out
+ // inside table cell and its wrapping isn't 'SURROUND_THROUGH'
+ if (bLayoutInTableCell && eSurround != SURROUND_THROUGHT)
+ {
+ SwFmtFollowTextFlow aFollowTextFlow( sal_True );
+ aFlySet.Put( aFollowTextFlow );
+ }
+
+
+ //#i21847#
+ //Some shapes are set to *hidden*, don't import those ones.
+ if (pRecord->bHidden)
+ return 0;
+
+ // If we are to be "below text" then we are not to be opaque
+ // #i14045# MM If we are in a header or footer then make the object transparent
+ // Not exactly like word but close enough for now
+
+ // both flags <bBelowText> and <bDrawHell> have to be set to move object into the background.
+ // #i46794# - it reveals that value of flag <bBelowText> can be neglected.
+ const bool bMoveToBackgrd = pRecord->bDrawHell ||
+ ( ( bIsHeader || bIsFooter ) && pF->nwr == 3 );
+ if ( bMoveToBackgrd )
+ aFlySet.Put(SvxOpaqueItem(RES_OPAQUE,false));
+
+ String aObjName = pObject->GetName();
+
+ SwFrmFmt* pRetFrmFmt = 0;
+ if (bReplaceable)
+ {
+ //Single graphics or ole objects
+ pRetFrmFmt = ImportReplaceableDrawables(pObject, pOurNewObject, pRecord,
+ pF, aFlySet);
+ }
+ else
+ {
+ //Drawing objects, (e.g. ovals or drawing groups)
+ if (pF->bRcaSimple)
+ {
+ pF->nbx = WW8_FSPA::RelPageBorder;
+ pF->nby = WW8_FSPA::RelPageBorder;
+ }
+
+ RndStdIds eAnchor = ProcessEscherAlign(pRecord, pF, aFlySet,
+ bReplaceable);
+
+ // Should we, and is it possible to make this into a writer textbox
+ if ((!(nIniFlags1 & WW8FL_NO_FLY_FOR_TXBX)) && pRecord->bReplaceByFly)
+ {
+ pRetFrmFmt = ConvertDrawTextToFly(pObject, pOurNewObject, pRecord,
+ eAnchor, pF, aFlySet);
+ if (pRetFrmFmt)
+ bDone = true;
+ }
+
+ if (!bDone)
+ {
+ sw::util::SetLayer aSetLayer(rDoc);
+ if ( bMoveToBackgrd )
+ aSetLayer.SendObjectToHell(*pObject);
+ else
+ aSetLayer.SendObjectToHeaven(*pObject);
+
+ if (!IsInlineEscherHack())
+ {
+ /* Need to make sure that the correct layer ordering is applied. */
+ // pass information, if object is in page header|footer to method.
+ pWWZOrder->InsertEscherObject( pObject, pF->nSpId,
+ bIsHeader || bIsFooter );
+ // <--
+ }
+ else
+ {
+ pWWZOrder->InsertTextLayerObject(pObject);
+ }
+
+ pRetFrmFmt = rDoc.Insert(*pPaM, *pObject, &aFlySet, NULL);
+
+ OSL_ENSURE(pRetFrmFmt->GetAnchor().GetAnchorId() ==
+ eAnchor, "Not the anchor type requested!");
+
+ /*
+ Insert text if necessary into textboxes contained in groups.
+ */
+ if (aData.HasRecords())
+ {
+ sal_uInt16 nCount = aData.GetRecCount();
+ for (sal_uInt16 nTxbx=0; nTxbx < nCount; ++nTxbx)
+ {
+ pRecord = aData.GetRecord(nTxbx);
+ if (pRecord && pRecord->pObj && pRecord->aTextId.nTxBxS)
+ { // #i52825# pRetFrmFmt can be NULL
+ pRetFrmFmt = MungeTextIntoDrawBox(pRecord->pObj,
+ pRecord, nGrafAnchorCp, pRetFrmFmt);
+ }
+ }
+ }
+ }
+ }
+
+ // #i44344#, #i44681# - positioning attributes already set
+ if ( pRetFrmFmt /*#i52825# */ && pRetFrmFmt->ISA(SwDrawFrmFmt) )
+ {
+ static_cast<SwDrawFrmFmt*>(pRetFrmFmt)->PosAttrSet();
+ }
+ // <--
+ if (!IsInlineEscherHack())
+ MapWrapIntoFlyFmt(pRecord, pRetFrmFmt);
+
+ // Set frame name with object name
+ if( pRetFrmFmt /*#i52825# */ && aObjName.Len() )
+ pRetFrmFmt->SetName( aObjName );
+ return AddAutoAnchor(pRetFrmFmt);
+}
+
+SwFrmFmt *SwWW8ImplReader::AddAutoAnchor(SwFrmFmt *pFmt)
+{
+ if (pFmt && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR))
+ {
+ sal_uInt16 nTextAreaWidth = static_cast< sal_uInt16 >( maSectionManager.GetPageWidth() -
+ maSectionManager.GetPageRight() - maSectionManager.GetPageLeft());
+
+ if (pFmt->GetFrmSize().GetSize().Width() > nTextAreaWidth)
+ maTracer.Log(sw::log::eTooWideAsChar);
+ }
+
+ /*
+ * anchored to character at the current position will move along the
+ * paragraph as text is added because we are at the insertion point.
+ *
+ * Leave to later and set the correct location then.
+ */
+ if ((pFmt) && (pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR))
+ {
+ pAnchorStck->AddAnchor(*pPaM->GetPoint(), pFmt);
+ }
+ return pFmt;
+}
+
+SwFrmFmt* SwWW8ImplReader::MungeTextIntoDrawBox(SdrObject* pTrueObject,
+ SvxMSDffImportRec *pRecord, long nGrafAnchorCp, SwFrmFmt* pRetFrmFmt)
+{
+ SdrTextObj* pSdrTextObj;
+
+ // Pruefen, ob Gruppenobjekt (z.B. zwei Klammern) vorliegt
+ if (SdrObjGroup* pThisGroup = PTR_CAST(SdrObjGroup, pRecord->pObj))
+ {
+ // Gruppenobjekte haben keinen Text. Fuege ein Textobjekt in die
+ // Gruppe ein, um den Text zu halten.
+ pSdrTextObj = new SdrRectObj( OBJ_TEXT, pThisGroup->GetCurrentBoundRect());
+
+ SfxItemSet aSet(pDrawModel->GetItemPool());
+ aSet.Put(XFillStyleItem(XFILL_NONE));
+ aSet.Put(XLineStyleItem(XLINE_NONE));
+ aSet.Put(SdrTextFitToSizeTypeItem( SDRTEXTFIT_NONE ));
+ aSet.Put(SdrTextAutoGrowHeightItem(false));
+ aSet.Put(SdrTextAutoGrowWidthItem(false));
+ pSdrTextObj->SetMergedItemSet(aSet);
+
+ long nAngle = pRecord->nTextRotationAngle;
+ if ( nAngle )
+ {
+ double a = nAngle*nPi180;
+ pSdrTextObj->NbcRotate(pSdrTextObj->GetCurrentBoundRect().Center(), nAngle,
+ sin(a), cos(a) );
+ }
+
+ pSdrTextObj->NbcSetLayer( pThisGroup->GetLayer() );
+ pThisGroup->GetSubList()->NbcInsertObject(pSdrTextObj);
+ }
+ else
+ pSdrTextObj = PTR_CAST(SdrTextObj, pRecord->pObj);
+
+ if( pSdrTextObj )
+ {
+ Size aObjSize(pSdrTextObj->GetSnapRect().GetWidth(),
+ pSdrTextObj->GetSnapRect().GetHeight());
+
+ // Objekt ist Bestandteil einer Gruppe?
+ SdrObject* pGroupObject = pSdrTextObj->GetUpGroup();
+
+ sal_uInt32 nOrdNum = pSdrTextObj->GetOrdNum();
+ bool bEraseThisObject;
+ InsertTxbxText( pSdrTextObj, &aObjSize, pRecord->aTextId.nTxBxS,
+ pRecord->aTextId.nSequence, nGrafAnchorCp, pRetFrmFmt,
+ (pSdrTextObj != pTrueObject) || (0 != pGroupObject),
+ bEraseThisObject, 0, 0, 0, 0, pRecord);
+
+ // wurde dieses Objekt ersetzt ??
+ if (bEraseThisObject)
+ {
+ if( pGroupObject || (pSdrTextObj != pTrueObject) )
+ {
+ // Objekt wurde bereits (in der Gruppe und) der Drawing-Page
+ // durch ein neues SdrGrafObj ersetzt.
+
+ SdrObject* pNewObj = pGroupObject ?
+ pGroupObject->GetSubList()->GetObj(nOrdNum) : pTrueObject;
+ if (pSdrTextObj != pNewObj)
+ {
+ // Objekt in der Z-Order-Liste ersetzen
+ pMSDffManager->ExchangeInShapeOrder(pSdrTextObj, 0,0, pNewObj);
+ // Objekt jetzt noch loeschen
+ SdrObject::Free( pRecord->pObj );
+ // und das neue Objekt merken.
+ pRecord->pObj = pNewObj;
+ }
+ }
+ else
+ {
+ // Objekt aus der Z-Order-Liste loeschen
+ pMSDffManager->RemoveFromShapeOrder( pSdrTextObj );
+ // Objekt aus der Drawing-Page rausnehmen
+ if( pSdrTextObj->GetPage() )
+ pDrawPg->RemoveObject( pSdrTextObj->GetOrdNum() );
+ // und FrameFormat entfernen, da durch Grafik ersetzt (dies
+ // loescht auch das Objekt)
+ rDoc.DelFrmFmt( pRetFrmFmt );
+ pRetFrmFmt = 0;
+ // auch den Objektmerker loeschen
+ pRecord->pObj = 0;
+ }
+ }
+ else
+ {
+ // ww8-default Randabstand einsetzen
+ SfxItemSet aItemSet(pDrawModel->GetItemPool(),
+ SDRATTR_TEXT_LEFTDIST, SDRATTR_TEXT_LOWERDIST);
+ aItemSet.Put( SdrTextLeftDistItem( pRecord->nDxTextLeft ) );
+ aItemSet.Put( SdrTextRightDistItem( pRecord->nDxTextRight ) );
+ aItemSet.Put( SdrTextUpperDistItem( pRecord->nDyTextTop ) );
+ aItemSet.Put( SdrTextLowerDistItem( pRecord->nDyTextBottom ) );
+ pSdrTextObj->SetMergedItemSetAndBroadcast(aItemSet);
+ }
+ }
+ return pRetFrmFmt;
+}
+
+SwFlyFrmFmt* SwWW8ImplReader::ConvertDrawTextToFly(SdrObject* &rpObject,
+ SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, RndStdIds eAnchor,
+ WW8_FSPA *pF, SfxItemSet &rFlySet)
+{
+ SwFlyFrmFmt* pRetFrmFmt = 0;
+ long nStartCp;
+ long nEndCp;
+
+ // Check if this textbox chain contains text as conversion of an empty
+ // chain would not make sense.
+ if ( TxbxChainContainsRealText(pRecord->aTextId.nTxBxS,nStartCp,nEndCp) )
+ {
+ // The Text is not read into SdrTextObj! Rather insert a frame and
+ // insert the text from nStartCp to nEndCp.
+ //
+ // More attributes can be used in a frame compared to the
+ // Edit-Enging, and it can contain field, OLEs or graphics...
+ Rectangle aInnerDist(pRecord->nDxTextLeft, pRecord->nDyTextTop,
+ pRecord->nDxTextRight, pRecord->nDyTextBottom);
+
+ SwFmtFrmSize aFrmSize(ATT_FIX_SIZE, pF->nXaRight - pF->nXaLeft, pF->nYaBottom - pF->nYaTop);
+ aFrmSize.SetWidthSizeType(pRecord->bAutoWidth ? ATT_VAR_SIZE : ATT_FIX_SIZE);
+ rFlySet.Put(aFrmSize);
+
+ MatchSdrItemsIntoFlySet( rpObject, rFlySet, pRecord->eLineStyle,
+ pRecord->eLineDashing, pRecord->eShapeType, aInnerDist );
+
+
+ SdrTextObj *pSdrTextObj = PTR_CAST(SdrTextObj, rpObject);
+ if (pSdrTextObj && pSdrTextObj->IsVerticalWriting())
+ rFlySet.Put(SvxFrameDirectionItem(FRMDIR_VERT_TOP_RIGHT, RES_FRAMEDIR));
+
+ pRetFrmFmt = rDoc.MakeFlySection(eAnchor, pPaM->GetPoint(), &rFlySet);
+ OSL_ENSURE(pRetFrmFmt->GetAnchor().GetAnchorId() == eAnchor,
+ "Not the anchor type requested!");
+
+ // if everything is OK, find pointer on new object and correct
+ // Z-order list (oder delete entry)
+ rpOurNewObject = CreateContactObject(pRetFrmFmt);
+
+ // remove old object from the Z-Order list
+ pMSDffManager->RemoveFromShapeOrder( rpObject );
+
+ // and delete the object
+ SdrObject::Free( rpObject );
+ /*
+ NB: only query pOrgShapeObject starting here!
+ */
+
+ if (rpOurNewObject)
+ {
+ /*
+ We do not store our rpOutNewObject in the ShapeOrder because we
+ have a FrmFmt from which we can regenerate the contact object when
+ we need it. Because, we can have frames anchored to paragraphs in
+ header/footers and we can copy header/footers, if we do copy a
+ header/footer with a nonpage anchored frame in it then the contact
+ objects are invalidated. Under this condition the FrmFmt will be
+ updated to reflect this change and can be used to get a new
+ contact object, while a raw rpOutNewObject stored here becomes
+ deleted and useless.
+ */
+ pMSDffManager->StoreShapeOrder(pF->nSpId,
+ (((sal_uLong)pRecord->aTextId.nTxBxS) << 16) +
+ pRecord->aTextId.nSequence, 0, pRetFrmFmt);
+
+ // The Kontakt object has to be inserted into the draw page, so
+ // SwWW8ImplReader::LoadDoc1() can determine the z-order.
+ if (!rpOurNewObject->IsInserted())
+ {
+ // pass information, if object is in page header|footer to method.
+ pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
+ bIsHeader || bIsFooter );
+ }
+ }
+
+ // Box-0 receives the text for the whole chain!
+ if( !pRecord->aTextId.nSequence )
+ {
+ // save flags etc and reset them
+ WW8ReaderSave aSave( this );
+
+ MoveInsideFly(pRetFrmFmt);
+
+ SwNodeIndex aStart(pPaM->GetPoint()->nNode);
+
+ pWWZOrder->InsideEscher(pF->nSpId);
+
+ // read in the text
+ bTxbxFlySection = true;
+ bool bJoined = ReadText(nStartCp, (nEndCp-nStartCp),
+ MAN_MAINTEXT == pPlcxMan->GetManType() ?
+ MAN_TXBX : MAN_TXBX_HDFT);
+
+ pWWZOrder->OutsideEscher();
+
+ MoveOutsideFly(pRetFrmFmt, aSave.GetStartPos(),!bJoined);
+
+ aSave.Restore( this );
+ }
+ }
+ return pRetFrmFmt;
+}
+
+void MatchEscherMirrorIntoFlySet(const SvxMSDffImportRec &rRecord,
+ SfxItemSet &rFlySet)
+{
+ if (rRecord.bVFlip || rRecord.bHFlip)
+ {
+ MirrorGraph eType(RES_MIRROR_GRAPH_DONT);
+ if (rRecord.bVFlip && rRecord.bHFlip)
+ eType = RES_MIRROR_GRAPH_BOTH;
+ else if (rRecord.bVFlip)
+ eType = RES_MIRROR_GRAPH_HOR;
+ else
+ eType = RES_MIRROR_GRAPH_VERT;
+ rFlySet.Put( SwMirrorGrf(eType) );
+ }
+}
+
+SwFlyFrmFmt* SwWW8ImplReader::ImportReplaceableDrawables( SdrObject* &rpObject,
+ SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, WW8_FSPA *pF,
+ SfxItemSet &rFlySet )
+{
+ SwFlyFrmFmt* pRetFrmFmt = 0;
+ long nWidthTw = pF->nXaRight - pF->nXaLeft;
+ if (0 > nWidthTw)
+ nWidthTw = 0;
+ long nHeightTw = pF->nYaBottom - pF->nYaTop;
+ if (0 > nHeightTw)
+ nHeightTw = 0;
+
+ ProcessEscherAlign(pRecord, pF, rFlySet, true);
+
+ rFlySet.Put(SwFmtFrmSize(ATT_FIX_SIZE, nWidthTw, nHeightTw));
+
+ SfxItemSet aGrSet(rDoc.GetAttrPool(), RES_GRFATR_BEGIN, RES_GRFATR_END-1);
+
+ if (pRecord)
+ {
+ //Note that the escher inner distance only seems to be honoured in
+ //word for textboxes, not for graphics and ole objects.
+ Rectangle aInnerDist(0, 0, 0, 0);
+
+ MatchSdrItemsIntoFlySet(rpObject, rFlySet, pRecord->eLineStyle,
+ pRecord->eLineDashing, pRecord->eShapeType, aInnerDist);
+
+ MatchEscherMirrorIntoFlySet(*pRecord, aGrSet);
+ }
+
+ String aObjectName(rpObject->GetName());
+ if (OBJ_OLE2 == SdrObjKind(rpObject->GetObjIdentifier()))
+ pRetFrmFmt = InsertOle(*((SdrOle2Obj*)rpObject), rFlySet, aGrSet);
+ else
+ {
+ const SdrGrafObj *pGrf= (const SdrGrafObj*)rpObject;
+ bool bDone = false;
+ if (pGrf->IsLinkedGraphic() && pGrf->GetFileName().Len())
+ {
+ GraphicType eType = pGrf->GetGraphicType();
+ String aGrfName(
+ URIHelper::SmartRel2Abs(
+ INetURLObject(sBaseURL), pGrf->GetFileName(),
+ URIHelper::GetMaybeFileHdl()));
+ // correction of fix for issue #i10939#:
+ // One of the two conditions have to be true to insert the graphic
+ // as a linked graphic -
+ if (GRAPHIC_NONE == eType || CanUseRemoteLink(aGrfName))
+ // <--
+ {
+ pRetFrmFmt = rDoc.Insert(*pPaM, aGrfName, aEmptyStr, 0,
+ &rFlySet, &aGrSet, NULL);
+ bDone = true;
+ }
+ }
+ if (!bDone)
+ {
+ const Graphic& rGraph = pGrf->GetGraphic();
+ pRetFrmFmt = rDoc.Insert(*pPaM, aEmptyStr, aEmptyStr, &rGraph,
+ &rFlySet, &aGrSet, NULL);
+ }
+ }
+
+ if (pRetFrmFmt)
+ {
+ if( pRecord )
+ {
+ if( OBJ_OLE2 != SdrObjKind(rpObject->GetObjIdentifier()) )
+ SetAttributesAtGrfNode( pRecord, pRetFrmFmt, pF );
+ }
+ // mehrfaches Auftreten gleicher Grafik-Namen vermeiden
+ maGrfNameGenerator.SetUniqueGraphName(pRetFrmFmt, aObjectName);
+ }
+ //falls alles Ok, Zeiger auf neues Objekt ermitteln und Z-Order-Liste
+ //entsprechend korrigieren (oder Eintrag loeschen)
+ rpOurNewObject = CreateContactObject(pRetFrmFmt);
+
+ // altes Objekt aus der Z-Order-Liste entfernen
+ pMSDffManager->RemoveFromShapeOrder( rpObject );
+ // aus der Drawing-Page rausnehmen
+ if( rpObject->GetPage() )
+ pDrawPg->RemoveObject( rpObject->GetOrdNum() );
+
+ // und das Objekt loeschen
+ SdrObject::Free( rpObject );
+ /*
+ Achtung: ab jetzt nur noch pOrgShapeObject abfragen!
+ */
+
+ // Kontakt-Objekt in die Z-Order-Liste und die Page aufnehmen
+ if (rpOurNewObject)
+ {
+ if (!bHdFtFtnEdn)
+ pMSDffManager->StoreShapeOrder(pF->nSpId, 0, rpOurNewObject, 0 );
+
+ // Das Kontakt-Objekt MUSS in die Draw-Page gesetzt werden, damit in
+ // SwWW8ImplReader::LoadDoc1() die Z-Order festgelegt werden kann !!!
+ if (!rpOurNewObject->IsInserted())
+ {
+ // pass information, if object is in page header|footer to method.
+ pWWZOrder->InsertEscherObject( rpOurNewObject, pF->nSpId,
+ bIsHeader || bIsFooter );
+ // <--
+ }
+ }
+ return pRetFrmFmt;
+}
+
+void SwWW8ImplReader::GrafikCtor() // Fuer SVDraw und VCControls und Escher
+{
+ if (!pDrawModel)
+ {
+ rDoc.GetOrCreateDrawModel(); // #i52858# - method name changed
+ pDrawModel = rDoc.GetDrawModel();
+ OSL_ENSURE(pDrawModel, "Kann DrawModel nicht anlegen");
+ pDrawPg = pDrawModel->GetPage(0);
+
+ pMSDffManager = new SwMSDffManager(*this);
+ pMSDffManager->SetModel(pDrawModel, 1440);
+ /*
+ Now the dff manager always needs a controls //converter as well, but a
+ control converter may still exist //without a dffmanager. cmc
+ */
+ pFormImpl = new SwMSConvertControls(mpDocShell, pPaM);
+
+ pWWZOrder = new wwZOrderer(sw::util::SetLayer(rDoc), pDrawPg,
+ pMSDffManager ? pMSDffManager->GetShapeOrders() : 0);
+ }
+}
+
+void SwWW8ImplReader::GrafikDtor()
+{
+ DELETEZ(mpDrawEditEngine); // evtl. von Grafik angelegt
+ DELETEZ(pWWZOrder); // dito
+}
+
+void SwWW8FltAnchorStack::AddAnchor(const SwPosition& rPos, SwFrmFmt *pFmt)
+{
+ OSL_ENSURE(pFmt->GetAnchor().GetAnchorId() != FLY_AS_CHAR,
+ "Don't use fltanchors with inline frames, slap!");
+ NewAttr(rPos, SwFltAnchor(pFmt));
+}
+
+void SwWW8FltAnchorStack::Flush()
+{
+ sal_uInt16 nCnt = static_cast< sal_uInt16 >(Count());
+ for (sal_uInt16 i=0; i < nCnt; ++i)
+ {
+ SwFltStackEntry *pEntry = (*this)[i];
+ SwPosition aDummy(pEntry->nMkNode);
+ SetAttrInDoc(aDummy,pEntry);
+ DeleteAndDestroy(i--);
+ --nCnt;
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8graf.hxx b/sw/source/filter/ww8/ww8graf.hxx
new file mode 100644
index 000000000000..516660a5defa
--- /dev/null
+++ b/sw/source/filter/ww8/ww8graf.hxx
@@ -0,0 +1,106 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WW8GRAF_HXX
+#define _WW8GRAF_HXX
+
+#include <vector>
+#include <stack>
+#include "writerhelper.hxx"
+
+struct EscherShape
+{
+ sal_uLong mnEscherShapeOrder;
+ sal_uLong mnNoInlines;
+ // new member <mbInHeaderFooter>
+ bool mbInHeaderFooter;
+ EscherShape( sal_uLong nEscherShapeOrder,
+ bool _bInHeaderFooter )
+ : mnEscherShapeOrder(nEscherShapeOrder),
+ mnNoInlines(0),
+ mbInHeaderFooter( _bInHeaderFooter )
+ {}
+ // <--
+};
+
+class wwZOrderer
+{
+private:
+ // consider that objects in page header/footer
+ // are always behind objects in page body. Thus, assure, that in vector
+ // <maEscherLayer> objects in page header|footer are inserted before
+ // objects in page body - see method <GetEscherObjectPos(..)>.
+ //No of objects in doc before starting (always 0 unless using file->insert
+ //and probably 0 then as well
+ std::vector<EscherShape> maEscherLayer;
+ // <--
+ typedef std::vector<EscherShape>::iterator myeiter;
+
+ std::vector<short> maDrawHeight;
+ typedef std::vector<short>::iterator myditer;
+
+ std::stack<sal_uInt16> maIndexes;
+
+ sw::util::SetLayer maSetLayer;
+
+ sal_uLong mnNoInitialObjects;
+ sal_uLong mnInlines;
+ SdrPage* mpDrawPg;
+ const SvxMSDffShapeOrders *mpShapeOrders;
+
+ sal_uInt16 GetEscherObjectIdx(sal_uLong nSpId);
+ myeiter MapEscherIdxToIter(sal_uLong nIdx);
+ // new parameter <_bInHeaderFooter>, indicating
+ // that object is in header or footer
+ sal_uLong GetEscherObjectPos( sal_uLong nSpId,
+ const bool _bInHeaderFooter );
+ // <--
+ sal_uLong GetDrawingObjectPos(short nWwHeight);
+ bool InsertObject(SdrObject *pObject, sal_uLong nPos);
+public:
+ wwZOrderer(const sw::util::SetLayer &rSetLayer, SdrPage* pDrawPg,
+ const SvxMSDffShapeOrders *pShapeOrders);
+ void InsertTextLayerObject(SdrObject* pObject);
+ /*
+ cmc: We should have have seperate ZOrder classes for 95- and 97+ and
+ instantiate the appropiate one at run time.
+ */
+ void InsertDrawingObject(SdrObject* pObj, short nWwHeight);
+ // new parameter <_bInHeaderFooter>, indicating that object is in header or footer
+ void InsertEscherObject( SdrObject* pObject,
+ sal_uLong nSpId,
+ const bool _bInHeaderFooter );
+ // <--
+ void InsideEscher(sal_uLong nIndex);
+ void OutsideEscher();
+};
+
+void WW8FSPAShadowToReal( WW8_FSPA_SHADOW* pFSPAS, WW8_FSPA* pPic );
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8graf2.cxx b/sw/source/filter/ww8/ww8graf2.cxx
new file mode 100644
index 000000000000..0a8a99510fe0
--- /dev/null
+++ b/sw/source/filter/ww8/ww8graf2.cxx
@@ -0,0 +1,785 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <iterator>
+#include <hintids.hxx>
+#include <svl/urihelper.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdograf.hxx>
+#include <svx/svdoole2.hxx>
+#include <editeng/opaqitem.hxx>
+#include <filter/msfilter/msdffimp.hxx>
+#include <sfx2/app.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/fcontnr.hxx>
+#include <grfatr.hxx> // class SwCropGrf
+#include <fmtflcnt.hxx>
+#include <fmtanchr.hxx>
+#include <frmfmt.hxx>
+#include <fltshell.hxx>
+#include <pam.hxx>
+#include <doc.hxx>
+#include <ndtxt.hxx> // class SwTxtNode
+#include <mdiexp.hxx> // Progress
+#include "writerwordglue.hxx"
+#include "ww8struc.hxx"
+#include "ww8scan.hxx"
+#include "ww8par.hxx" // class SwWWImplReader
+#include "ww8par2.hxx" // struct WWFlyPara
+#include "ww8graf.hxx"
+#include <svtools/filter.hxx>
+
+using namespace ::com::sun::star;
+using namespace sw::types;
+
+wwZOrderer::wwZOrderer(const sw::util::SetLayer &rSetLayer, SdrPage* pDrawPg,
+ const SvxMSDffShapeOrders *pShapeOrders)
+ : maSetLayer(rSetLayer), mnInlines(0), mpDrawPg(pDrawPg),
+ mpShapeOrders(pShapeOrders)
+{
+ mnNoInitialObjects = mpDrawPg->GetObjCount();
+ OSL_ENSURE(mpDrawPg,"Missing draw page impossible!");
+}
+
+void wwZOrderer::InsideEscher(sal_uLong nSpId)
+{
+ maIndexes.push(GetEscherObjectIdx(nSpId));
+}
+
+void wwZOrderer::OutsideEscher()
+{
+ maIndexes.pop();
+}
+
+// consider new parameter <_bInHeaderFooter>
+void wwZOrderer::InsertEscherObject( SdrObject* pObject,
+ sal_uLong nSpId,
+ const bool _bInHeaderFooter )
+{
+ sal_uLong nInsertPos = GetEscherObjectPos( nSpId, _bInHeaderFooter );
+// <--
+ InsertObject(pObject, nInsertPos + mnNoInitialObjects + mnInlines);
+}
+
+wwZOrderer::myeiter wwZOrderer::MapEscherIdxToIter(sal_uLong nIdx)
+{
+ myeiter aIter = maEscherLayer.begin();
+ myeiter aEnd = maEscherLayer.end();
+ while (aIter != aEnd)
+ {
+ if (aIter->mnEscherShapeOrder == nIdx)
+ break;
+ ++aIter;
+ }
+ return aIter;
+}
+
+sal_uInt16 wwZOrderer::GetEscherObjectIdx(sal_uLong nSpId)
+{
+ sal_uInt16 nFound=0;
+ sal_uInt16 nShapeCount = mpShapeOrders ? mpShapeOrders->Count() : 0;
+ // First, find out what position this shape is in in the Escher order.
+ for (sal_uInt16 nShapePos=0; nShapePos < nShapeCount; nShapePos++)
+ {
+ const SvxMSDffShapeOrder *pOrder = mpShapeOrders->GetObject(nShapePos);
+ if (pOrder->nShapeId == nSpId)
+ {
+ nFound = nShapePos;
+ break;
+ }
+ }
+ return nFound;
+}
+
+// consider new parameter <_bInHeaderFooter>
+sal_uLong wwZOrderer::GetEscherObjectPos( sal_uLong nSpId,
+ const bool _bInHeaderFooter )
+{
+ /*
+ EscherObjects have their own ordering which needs to be matched to
+ the actual ordering that should be used when inserting them into the
+ document.
+ */
+ sal_uInt16 nFound = GetEscherObjectIdx(nSpId);
+ // Match the ordering position from the ShapeOrders to the ordering of all
+ // objects in the document, there is a complexity when escherobjects
+ // contain inlines objects, we need to consider thsose as part of the
+ // escher count
+ sal_uLong nRet=0;
+ myeiter aIter = maEscherLayer.begin();
+ myeiter aEnd = maEscherLayer.end();
+ // skip objects in page header|footer,
+ // if current object isn't in page header|footer
+ if ( !_bInHeaderFooter )
+ {
+ while ( aIter != aEnd )
+ {
+ if ( !aIter->mbInHeaderFooter )
+ {
+ break;
+ }
+ nRet += aIter->mnNoInlines + 1;
+ ++aIter;
+ }
+ }
+ // <--
+ while (aIter != aEnd)
+ {
+ // insert object in page header|footer
+ // before objects in page body
+ if ( _bInHeaderFooter && !aIter->mbInHeaderFooter )
+ {
+ break;
+ }
+ // <--
+ if ( aIter->mnEscherShapeOrder > nFound )
+ break;
+ nRet += aIter->mnNoInlines+1;
+ ++aIter;
+ }
+ maEscherLayer.insert(aIter, EscherShape( nFound, _bInHeaderFooter ) );
+ return nRet;
+}
+// <--
+
+// InsertObj() fuegt das Objekt in die Sw-Page ein und merkt sich die Z-Pos in
+// einem VarArr
+void wwZOrderer::InsertDrawingObject(SdrObject* pObj, short nWwHeight)
+{
+ sal_uLong nPos = GetDrawingObjectPos(nWwHeight);
+ if (nWwHeight & 0x2000) // Heaven ?
+ maSetLayer.SendObjectToHeaven(*pObj);
+ else
+ maSetLayer.SendObjectToHell(*pObj);
+
+ InsertObject(pObj, nPos + mnNoInitialObjects + mnInlines);
+}
+
+void wwZOrderer::InsertTextLayerObject(SdrObject* pObject)
+{
+ maSetLayer.SendObjectToHeaven(*pObject);
+ if (maIndexes.empty())
+ {
+ InsertObject(pObject, mnNoInitialObjects + mnInlines);
+ ++mnInlines;
+ }
+ else
+ {
+ //If we are inside an escher objects, place us just after that
+ //escher obj, and increment its inline count
+ sal_uInt16 nIdx = maIndexes.top();
+ myeiter aEnd = MapEscherIdxToIter(nIdx);
+
+ sal_uLong nInsertPos=0;
+ myeiter aIter = maEscherLayer.begin();
+ while (aIter != aEnd)
+ {
+ nInsertPos += aIter->mnNoInlines+1;
+ ++aIter;
+ }
+
+ OSL_ENSURE(aEnd != maEscherLayer.end(), "Something very wrong here");
+ if (aEnd != maEscherLayer.end())
+ {
+ aEnd->mnNoInlines++;
+ nInsertPos += aEnd->mnNoInlines;
+ }
+
+ InsertObject(pObject, mnNoInitialObjects + mnInlines + nInsertPos);
+ }
+}
+
+// Parallel zu dem Obj-Array im Dokument baue ich ein Array auf,
+// dass die Ww-Height ( -> Wer ueberdeckt wen ) beinhaltet.
+// Anhand dieses VARARR wird die Einfuegeposition ermittelt.
+// Der Offset bei Datei in bestehendes Dokument mit Grafiklayer einfuegen
+// muss der Aufrufer den Index um mnNoInitialObjects erhoeht werden, damit die
+// neuen Objekte am Ende landen ( Einfuegen ist dann schneller )
+sal_uLong wwZOrderer::GetDrawingObjectPos(short nWwHeight)
+{
+ myditer aIter = maDrawHeight.begin();
+ myditer aEnd = maDrawHeight.end();
+
+ while (aIter != aEnd)
+ {
+ if ((*aIter & 0x1fff) > (nWwHeight & 0x1fff))
+ break;
+ ++aIter;
+ }
+
+ aIter = maDrawHeight.insert(aIter, nWwHeight);
+ return std::distance(maDrawHeight.begin(), aIter);
+}
+
+bool wwZOrderer::InsertObject(SdrObject* pObject, sal_uLong nPos)
+{
+ if (!pObject->IsInserted())
+ {
+ mpDrawPg->InsertObject(pObject, nPos);
+ return true;
+ }
+ return false;
+}
+
+#ifdef __WW8_NEEDS_COPY
+extern void WW8PicShadowToReal( WW8_PIC_SHADOW* pPicS, WW8_PIC* pPic );
+#endif // defined __WW8_NEEDS_COPY
+
+bool SwWW8ImplReader::GetPictGrafFromStream(Graphic& rGraphic, SvStream& rSrc)
+{
+ return 0 == GraphicFilter::GetGraphicFilter()->ImportGraphic(rGraphic, aEmptyStr, rSrc,
+ GRFILTER_FORMAT_DONTKNOW);
+}
+
+bool SwWW8ImplReader::ReadGrafFile(String& rFileName, Graphic*& rpGraphic,
+ const WW8_PIC& rPic, SvStream* pSt, sal_uLong nFilePos, bool* pbInDoc)
+{ // Grafik in File schreiben
+ *pbInDoc = true; // default
+
+ sal_uLong nPosFc = nFilePos + rPic.cbHeader;
+
+ switch (rPic.MFP.mm)
+ {
+ case 94: // BMP-File ( nicht embeddet ) oder GIF
+ case 99: // TIFF-File ( nicht embeddet )
+ pSt->Seek(nPosFc);
+ // Name als P-String einlesen
+ rFileName = WW8ReadPString(*pSt, eStructCharSet, 0);
+ if (rFileName.Len())
+ rFileName = URIHelper::SmartRel2Abs(
+ INetURLObject(sBaseURL), rFileName,
+ URIHelper::GetMaybeFileHdl());
+ *pbInDoc = false; // Datei anschliessend nicht loeschen
+ return rFileName.Len() != 0; // Einlesen OK
+ }
+
+ GDIMetaFile aWMF;
+ pSt->Seek( nPosFc );
+ bool bOk = ReadWindowMetafile( *pSt, aWMF, NULL ) ? true : false;
+
+ if (!bOk || pSt->GetError() || !aWMF.GetActionCount())
+ return false;
+
+ if (pWwFib->envr != 1) // !MAC als Creator
+ {
+ rpGraphic = new Graphic( aWMF );
+ return true;
+ }
+
+ // MAC - Word als Creator
+ // im WMF steht nur "Benutzen sie Word 6.0c" Mac-Pict steht dahinter
+ // allerdings ohne die ersten 512 Bytes, bei einem MAC-PICT egal sind (
+ // werden nicht ausgewertet )
+ bOk = false;
+ long nData = rPic.lcb - ( pSt->Tell() - nPosFc );
+ if (nData > 0)
+ {
+ rpGraphic = new Graphic();
+ if (0 == (bOk = SwWW8ImplReader::GetPictGrafFromStream(*rpGraphic, *pSt)))
+ DELETEZ(rpGraphic);
+ }
+ return bOk; // Grafik drin
+}
+
+struct WW8PicDesc
+{
+ sal_Int16 nCL, nCR, nCT, nCB;
+ long nWidth, nHeight;
+
+ WW8PicDesc( const WW8_PIC& rPic );
+};
+
+WW8PicDesc::WW8PicDesc( const WW8_PIC& rPic )
+{
+ //See #i21190# before fiddling with this method
+ long nOriWidth = rPic.dxaGoal; //Size in 1/100 mm before crop
+ long nOriHeight = rPic.dyaGoal;
+
+ nCL = rPic.dxaCropLeft;
+ nCR = rPic.dxaCropRight;
+ nCT = rPic.dyaCropTop;
+ nCB = rPic.dyaCropBottom;
+
+ long nAktWidth = nOriWidth - (nCL + nCR); // Size after crop
+ long nAktHeight = nOriHeight - (nCT + nCB);
+ if (!nAktWidth)
+ nAktWidth = 1;
+ if (!nAktHeight)
+ nAktHeight = 1;
+ nWidth = nAktWidth * rPic.mx / 1000; // Writer Size
+ nHeight = nAktHeight * rPic.my / 1000;
+}
+
+void SwWW8ImplReader::ReplaceObj(const SdrObject &rReplaceObj,
+ SdrObject &rSubObj)
+{
+ // SdrGrafObj anstatt des SdrTextObj in dessen Gruppe einsetzen
+ if (SdrObject* pGroupObject = rReplaceObj.GetUpGroup())
+ {
+ SdrObjList* pObjectList = pGroupObject->GetSubList();
+
+ rSubObj.SetLogicRect(rReplaceObj.GetCurrentBoundRect());
+ rSubObj.SetLayer(rReplaceObj.GetLayer());
+
+ // altes Objekt raus aus Gruppen-Liste und neues rein
+ // (dies tauscht es ebenfalls in der Drawing-Page aus)
+ pObjectList->ReplaceObject(&rSubObj, rReplaceObj.GetOrdNum());
+ }
+ else
+ {
+ OSL_ENSURE( !this, "Impossible!");
+ }
+}
+
+// MakeGrafNotInCntnt setzt eine nicht-Zeichengebundene Grafik
+// ( bGrafApo == true)
+SwFlyFrmFmt* SwWW8ImplReader::MakeGrafNotInCntnt(const WW8PicDesc& rPD,
+ const Graphic* pGraph, const String& rFileName, const SfxItemSet& rGrfSet)
+{
+
+ sal_uInt32 nWidth = rPD.nWidth;
+ sal_uInt32 nHeight = rPD.nHeight;
+
+ // Vertikale Verschiebung durch Zeilenabstand
+ sal_Int32 nNetHeight = nHeight + rPD.nCT + rPD.nCB;
+ if( pSFlyPara->nLineSpace && pSFlyPara->nLineSpace > nNetHeight )
+ pSFlyPara->nYPos =
+ (sal_uInt16)( pSFlyPara->nYPos + pSFlyPara->nLineSpace - nNetHeight );
+
+ WW8FlySet aFlySet(*this, pWFlyPara, pSFlyPara, true);
+
+ SwFmtAnchor aAnchor(pSFlyPara->eAnchor);
+ aAnchor.SetAnchor(pPaM->GetPoint());
+ aFlySet.Put(aAnchor);
+
+ aFlySet.Put( SwFmtFrmSize( ATT_FIX_SIZE, nWidth, nHeight ) );
+
+ SwFlyFrmFmt* pFlyFmt = rDoc.Insert(*pPaM, rFileName, aEmptyStr, pGraph,
+ &aFlySet, &rGrfSet, NULL);
+
+ // Damit die Frames bei Einfuegen in existierendes Doc erzeugt werden:
+ if (rDoc.GetCurrentViewShell() && //swmod 071108//swmod 071225
+ (FLY_AT_PARA == pFlyFmt->GetAnchor().GetAnchorId()))
+ {
+ pFlyFmt->MakeFrms();
+ }
+ return pFlyFmt;
+}
+
+
+// MakeGrafInCntnt fuegt zeichengebundene Grafiken ein
+SwFrmFmt* SwWW8ImplReader::MakeGrafInCntnt(const WW8_PIC& rPic,
+ const WW8PicDesc& rPD, const Graphic* pGraph, const String& rFileName,
+ const SfxItemSet& rGrfSet)
+{
+ WW8FlySet aFlySet(*this, pPaM, rPic, rPD.nWidth, rPD.nHeight);
+
+ SwFrmFmt* pFlyFmt = 0;
+
+ if (!rFileName.Len() && nObjLocFc) // dann sollte ists ein OLE-Object
+ pFlyFmt = ImportOle(pGraph, &aFlySet, &rGrfSet);
+
+ if( !pFlyFmt ) // dann eben als Graphic
+ {
+
+ pFlyFmt = rDoc.Insert( *pPaM, rFileName, aEmptyStr, pGraph, &aFlySet,
+ &rGrfSet, NULL);
+ }
+
+ // Grafik im Rahmen ? ok, Rahmen auf Bildgroesse vergroessern
+ // ( nur wenn Auto-Breite )
+ if( pSFlyPara )
+ pSFlyPara->BoxUpWidth( rPD.nWidth );
+ return pFlyFmt;
+}
+
+SwFrmFmt* SwWW8ImplReader::ImportGraf1(WW8_PIC& rPic, SvStream* pSt,
+ sal_uLong nFilePos )
+{
+ SwFrmFmt* pRet = 0;
+ if( pSt->IsEof() || rPic.fError || rPic.MFP.mm == 99 )
+ return 0;
+
+ String aFileName;
+ bool bInDoc;
+ Graphic* pGraph = 0;
+ bool bOk = ReadGrafFile(aFileName, pGraph, rPic, pSt, nFilePos, &bInDoc);
+
+ if (!bOk)
+ {
+ delete pGraph;
+ return 0; // Grafik nicht korrekt eingelesen
+ }
+
+ WW8PicDesc aPD( rPic );
+
+ SwAttrSet aGrfSet( rDoc.GetAttrPool(), RES_GRFATR_BEGIN, RES_GRFATR_END-1);
+ if( aPD.nCL || aPD.nCR || aPD.nCT || aPD.nCB )
+ {
+ SwCropGrf aCrop( aPD.nCL, aPD.nCR, aPD.nCT, aPD.nCB) ;
+ aGrfSet.Put( aCrop );
+ }
+
+ if( pWFlyPara && pWFlyPara->bGrafApo )
+ pRet = MakeGrafNotInCntnt(aPD,pGraph,aFileName,aGrfSet);
+ else
+ pRet = MakeGrafInCntnt(rPic,aPD,pGraph,aFileName,aGrfSet);
+ delete pGraph;
+ return pRet;
+}
+
+void SwWW8ImplReader::PicRead(SvStream *pDataStream, WW8_PIC *pPic,
+ bool bVer67)
+{
+ //Only the first 0x2e bytes are the same between version 6/7 and 8+
+#ifdef __WW8_NEEDS_COPY
+ WW8_PIC_SHADOW aPicS;
+ pDataStream->Read( &aPicS, sizeof( aPicS ) );
+ WW8PicShadowToReal( &aPicS, pPic );
+#else
+ pDataStream->Read( pPic, 0x2E);
+#endif // defined __WW8_NEEDS_COPY
+ for (int i=0;i<4;i++)
+ pDataStream->Read( &pPic->rgbrc[i], bVer67 ? 2 : 4);
+ *pDataStream >> pPic->dxaOrigin;
+ *pDataStream >> pPic->dyaOrigin;
+ if (!bVer67)
+ pDataStream->SeekRel(2); //cProps
+}
+
+SwFrmFmt* SwWW8ImplReader::ImportGraf(SdrTextObj* pTextObj,
+ SwFrmFmt* pOldFlyFmt)
+{
+ SwFrmFmt* pRet = 0;
+ if (
+ ((pStrm == pDataStream ) && !nPicLocFc) ||
+ (nIniFlags & WW8FL_NO_GRAF)
+ )
+ {
+ return 0;
+ }
+
+ ::SetProgressState(nProgress, mpDocShell); // Update
+
+ GrafikCtor();
+
+ /*
+ kleiner Spass von Microsoft: manchmal existiert ein Stream Namens DATA
+ Dieser enthaelt dann den PICF und die entsprechende Grafik !!!
+ Wir mappen ansonsten die Variable pDataStream auf pStream.
+ */
+
+ sal_uLong nOldPos = pDataStream->Tell();
+ WW8_PIC aPic;
+ pDataStream->Seek( nPicLocFc );
+ PicRead( pDataStream, &aPic, bVer67);
+
+ // Plausibilitaetstest ist noetig, da z.B. bei CheckBoxen im
+ // Feld-Result ein WMF-aehnliches Struct vorkommt.
+ if ((aPic.lcb >= 58) && !pDataStream->GetError())
+ {
+ if( pFlyFmtOfJustInsertedGraphic )
+ {
+ // Soeben haben wir einen Grafik-Link ins Doc inserted.
+ // Wir muessen ihn jetzt noch Positioniern und Skalieren.
+ //
+ WW8PicDesc aPD( aPic );
+
+ WW8FlySet aFlySet( *this, pPaM, aPic, aPD.nWidth, aPD.nHeight );
+
+ // the correct anchor is set in Read_F_IncludePicture and the current PaM point's
+ // behind the position if it is anchored in content; because this anchor add
+ // a character into the textnode. IussueZilla task 2806
+ if (FLY_AS_CHAR ==
+ pFlyFmtOfJustInsertedGraphic->GetAnchor().GetAnchorId() )
+ {
+ aFlySet.ClearItem( RES_ANCHOR );
+ }
+
+ pFlyFmtOfJustInsertedGraphic->SetFmtAttr( aFlySet );
+
+ pFlyFmtOfJustInsertedGraphic = 0;
+ }
+ else if((0x64 == aPic.MFP.mm) || (0x66 == aPic.MFP.mm))
+ {
+ // verlinkte Grafik im Escher-Objekt
+ SdrObject* pObject = 0;
+
+ //#i17200#, a bit of guesswork I'm afraid
+ if (aPic.dxaGoal == 1000 && aPic.mx == 1) //100% hack ?
+ {
+ aPic.mx = msword_cast<sal_uInt16>(
+ maSectionManager.GetPageWidth() -
+ maSectionManager.GetPageRight() -
+ maSectionManager.GetPageLeft());
+ }
+
+ WW8PicDesc aPD( aPic );
+ String aGrName;
+ if (!pMSDffManager)
+ pMSDffManager = new SwMSDffManager(*this);
+ /*
+ ##835##
+ Disable use of main stream as fallback stream for inline direct
+ blips as it is known that they are directly after the record
+ header, testing for existance in main stream may lead to an
+ incorrect fallback graphic being found if other escher graphics
+ have been inserted in the document
+ */
+ pMSDffManager->DisableFallbackStream();
+ if( !pMSDffManager->GetModel() )
+ pMSDffManager->SetModel(pDrawModel, 1440);
+
+ if (0x66 == aPic.MFP.mm)
+ {
+ //These ones have names prepended
+ sal_uInt8 nNameLen=0;
+ *pDataStream >> nNameLen;
+ pDataStream->SeekRel( nNameLen );
+ }
+
+ Rectangle aChildRect;
+ Rectangle aClientRect( 0,0, aPD.nWidth, aPD.nHeight);
+ SvxMSDffImportData aData( aClientRect );
+ pObject = pMSDffManager->ImportObj(*pDataStream, &aData, aClientRect, aChildRect );
+ if (pObject)
+ {
+ // fuer den Rahmen
+ SfxItemSet aAttrSet( rDoc.GetAttrPool(), RES_FRMATR_BEGIN,
+ RES_FRMATR_END-1 );
+
+ SvxMSDffImportRec *pRecord =
+ (aData.HasRecords() && (1 == aData.GetRecCount() ) ) ?
+ aData.GetRecord( 0 ) : 0;
+
+ if( pRecord )
+ {
+ //A graphic of this type in this location is always
+ //inline, and uses the pic in the same mould as ww6
+ //graphics.
+ if (pWFlyPara && pWFlyPara->bGrafApo)
+ {
+ WW8FlySet aFlySet(*this, pWFlyPara, pSFlyPara, true);
+
+ SwFmtAnchor aAnchor(pSFlyPara->eAnchor);
+ aAnchor.SetAnchor(pPaM->GetPoint());
+ aFlySet.Put(aAnchor);
+
+ aAttrSet.Put(aFlySet);
+ }
+ else
+ {
+ WW8FlySet aFlySet( *this, pPaM, aPic, aPD.nWidth,
+ aPD.nHeight );
+
+ aAttrSet.Put(aFlySet);
+ }
+
+ Rectangle aInnerDist( pRecord->nDxTextLeft,
+ pRecord->nDyTextTop, pRecord->nDxTextRight,
+ pRecord->nDyTextBottom );
+
+ MatchSdrItemsIntoFlySet( pObject, aAttrSet,
+ pRecord->eLineStyle, pRecord->eLineDashing,
+ pRecord->eShapeType, aInnerDist );
+
+ //Groesse aus der WinWord PIC-Struktur als
+ //Grafik-Groesse nehmen
+ aAttrSet.Put( SwFmtFrmSize( ATT_FIX_SIZE, aPD.nWidth,
+ aPD.nHeight ) );
+ }
+
+ // for the Grafik
+ SfxItemSet aGrSet( rDoc.GetAttrPool(), RES_GRFATR_BEGIN,
+ RES_GRFATR_END-1 );
+
+ if( aPD.nCL || aPD.nCR || aPD.nCT || aPD.nCB )
+ {
+ SwCropGrf aCrop( aPD.nCL, aPD.nCR, aPD.nCT, aPD.nCB );
+ aGrSet.Put( aCrop );
+ }
+
+ if (pRecord)
+ MatchEscherMirrorIntoFlySet(*pRecord, aGrSet);
+
+ // ggfs. altes AttrSet uebernehmen und
+ // horiz. Positionierungs-Relation korrigieren
+ if( pOldFlyFmt )
+ {
+ aAttrSet.Put( pOldFlyFmt->GetAttrSet() );
+ const SwFmtHoriOrient &rHori = pOldFlyFmt->GetHoriOrient();
+ if( text::RelOrientation::FRAME == rHori.GetRelationOrient() )
+ {
+ aAttrSet.Put( SwFmtHoriOrient( rHori.GetPos(),
+ text::HoriOrientation::NONE, text::RelOrientation::PAGE_PRINT_AREA ) );
+ }
+ }
+
+ bool bTextObjWasGrouped = false;
+ if (pOldFlyFmt && pTextObj && pTextObj->GetUpGroup())
+ bTextObjWasGrouped = true;
+
+ if (bTextObjWasGrouped)
+ ReplaceObj(*pTextObj, *pObject);
+ else
+ {
+ if (sal_uInt16(OBJ_OLE2) == pObject->GetObjIdentifier())
+ {
+ // the size from BLIP, if there is any, should be already set
+ pRet = InsertOle(*((SdrOle2Obj*)pObject), aAttrSet, aGrSet);
+ }
+ else
+ {
+ if (SdrGrafObj* pGraphObject = PTR_CAST(SdrGrafObj, pObject))
+ {
+ // Nun den Link bzw. die Grafik ins Doc stopfen
+ const Graphic& rGraph = pGraphObject->GetGraphic();
+
+ if (nObjLocFc) // is it a OLE-Object?
+ pRet = ImportOle(&rGraph, &aAttrSet, &aGrSet, pObject->GetBLIPSizeRectangle());
+
+ if (!pRet)
+ {
+ pRet = rDoc.Insert(*pPaM, aEmptyStr, aEmptyStr,
+ &rGraph, &aAttrSet, &aGrSet, NULL );
+ }
+ }
+ else
+ pRet = rDoc.Insert(*pPaM, *pObject, &aAttrSet, NULL);
+ }
+ }
+
+ // also nur, wenn wir ein *Insert* gemacht haben
+ if (pRet)
+ {
+ if (pRecord)
+ SetAttributesAtGrfNode(pRecord, pRet, 0);
+
+ // #i68101#
+ // removed pObject->HasSetName() usage since always returned true,
+ // also removed else-part and wrote an informing mail to Henning Brinkmann
+ // about this to clarify.
+ pRet->SetName(pObject->GetName());
+
+ // Zeiger auf neues Objekt ermitteln und Z-Order-Liste
+ // entsprechend korrigieren (oder Eintrag loeschen)
+ if (SdrObject* pOurNewObject = CreateContactObject(pRet))
+ {
+ if (pOurNewObject != pObject)
+ {
+ pMSDffManager->ExchangeInShapeOrder( pObject, 0, 0,
+ pOurNewObject );
+
+ // altes SdrGrafObj aus der Page loeschen und
+ // zerstoeren
+ if (pObject->GetPage())
+ pDrawPg->RemoveObject(pObject->GetOrdNum());
+ SdrObject::Free( pObject );
+ }
+ }
+ else
+ pMSDffManager->RemoveFromShapeOrder( pObject );
+ }
+ else
+ pMSDffManager->RemoveFromShapeOrder( pObject );
+
+ // auch das ggfs. Page loeschen, falls nicht gruppiert,
+ if (pTextObj && !bTextObjWasGrouped && pTextObj->GetPage())
+ pDrawPg->RemoveObject( pTextObj->GetOrdNum() );
+ }
+ pMSDffManager->EnableFallbackStream();
+ }
+ else if (aPic.lcb >= 58)
+ pRet = ImportGraf1(aPic, pDataStream, nPicLocFc);
+ }
+ pDataStream->Seek( nOldPos );
+
+ if (pRet)
+ {
+ SdrObject* pOurNewObject = CreateContactObject(pRet);
+ pWWZOrder->InsertTextLayerObject(pOurNewObject);
+ }
+
+ return AddAutoAnchor(pRet);
+}
+
+#ifdef __WW8_NEEDS_COPY
+
+void WW8PicShadowToReal( WW8_PIC_SHADOW * pPicS, WW8_PIC * pPic )
+{
+ pPic->lcb = SVBT32ToUInt32( pPicS->lcb );
+ pPic->cbHeader = SVBT16ToShort( pPicS->cbHeader );
+ pPic->MFP.mm = SVBT16ToShort( pPicS->MFP.mm );
+ pPic->MFP.xExt = SVBT16ToShort( pPicS->MFP.xExt );
+ pPic->MFP.yExt = SVBT16ToShort( pPicS->MFP.yExt );
+ pPic->MFP.hMF = SVBT16ToShort( pPicS->MFP.hMF );
+ for( sal_uInt16 i = 0; i < 14 ; i++ )
+ pPic->rcWinMF[i] = SVBT8ToByte( pPicS->rcWinMF[i] );
+ pPic->dxaGoal = SVBT16ToShort( pPicS->dxaGoal );
+ pPic->dyaGoal = SVBT16ToShort( pPicS->dyaGoal );
+ pPic->mx = SVBT16ToShort( pPicS->mx );
+ pPic->my = SVBT16ToShort( pPicS->my );
+ pPic->dxaCropLeft = SVBT16ToShort( pPicS->dxaCropLeft );
+ pPic->dyaCropTop = SVBT16ToShort( pPicS->dyaCropTop );
+ pPic->dxaCropRight = SVBT16ToShort( pPicS->dxaCropRight );
+ pPic->dyaCropBottom = SVBT16ToShort( pPicS->dyaCropBottom );
+ pPic->brcl = pPicS->aBits1[0] & 0x0f;
+ pPic->fFrameEmpty = (pPicS->aBits1[0] & 0x10) >> 4;
+ pPic->fBitmap = (pPicS->aBits1[0] & 0x20) >> 5;
+ pPic->fDrawHatch = (pPicS->aBits1[0] & 0x40) >> 6;
+ pPic->fError = (pPicS->aBits1[0] & 0x80) >> 7;
+ pPic->bpp = pPicS->aBits2[0];
+}
+
+void WW8FSPAShadowToReal( WW8_FSPA_SHADOW * pFSPAS, WW8_FSPA * pFSPA )
+{
+ pFSPA->nSpId = SVBT32ToUInt32( pFSPAS->nSpId );
+ pFSPA->nXaLeft = SVBT32ToUInt32( pFSPAS->nXaLeft );
+ pFSPA->nYaTop = SVBT32ToUInt32( pFSPAS->nYaTop );
+ pFSPA->nXaRight = SVBT32ToUInt32( pFSPAS->nXaRight );
+ pFSPA->nYaBottom = SVBT32ToUInt32( pFSPAS->nYaBottom );
+
+ sal_uInt16 nBits = SVBT16ToShort( pFSPAS->aBits1 );
+
+ pFSPA->bHdr = 0 != ( nBits & 0x0001 );
+ pFSPA->nbx = ( nBits & 0x0006 ) >> 1;
+ pFSPA->nby = ( nBits & 0x0018 ) >> 3;
+ pFSPA->nwr = ( nBits & 0x01E0 ) >> 5;
+ pFSPA->nwrk = ( nBits & 0x1E00 ) >> 9;
+ pFSPA->bRcaSimple = 0 != ( nBits & 0x2000 );
+ pFSPA->bBelowText = 0 != ( nBits & 0x4000 );
+ pFSPA->bAnchorLock = 0 != ( nBits & 0x8000 );
+ pFSPA->nTxbx = SVBT32ToUInt32( pFSPAS->nTxbx );
+}
+#endif // defined __WW8_NEEDS_COPY
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
new file mode 100644
index 000000000000..fd05e95c58b6
--- /dev/null
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -0,0 +1,5675 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <boost/unordered_set.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XStorage.hpp>
+
+#include <unotools/ucbstreamhelper.hxx>
+#include <tools/solar.h>
+#include <rtl/tencinfo.h>
+#include <rtl/random.h>
+
+#include <sot/storage.hxx>
+#include <sfx2/docinf.hxx>
+#include <sfx2/docfile.hxx>
+#include <sfx2/request.hxx>
+#include <sfx2/frame.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/tempfile.hxx>
+#include <svtools/sfxecode.hxx>
+
+#include <comphelper/docpasswordrequest.hxx>
+#include <hintids.hxx>
+
+#include <editeng/tstpitem.hxx>
+#include <editeng/cscoitem.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdpage.hxx>
+#include <editeng/paperinf.hxx>
+#include <editeng/lrspitem.hxx> // SvxLRSpaceItem
+#include <editeng/ulspitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/opaqitem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <filter/msfilter/svxmsbas.hxx>
+#include <svx/unoapi.hxx>
+#include <svx/svdoole2.hxx>
+#include <filter/msfilter/msdffimp.hxx>
+#include <svx/svdoashp.hxx>
+#include <svx/svxerr.hxx>
+#include <filter/msfilter/mscodec.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/xflclit.hxx>
+
+#include <unotools/fltrcfg.hxx>
+#include <fmtfld.hxx>
+#include <fmturl.hxx>
+#include <fmtinfmt.hxx>
+#include <IMark.hxx>
+#include <reffld.hxx>
+#include <fmthdft.hxx>
+#include <fmtcntnt.hxx>
+#include <fmtcnct.hxx>
+#include <fmtpdsc.hxx>
+#include <ftninfo.hxx>
+#include <fmtftn.hxx>
+#include <txtftn.hxx>
+#include <pam.hxx> // fuer SwPam
+#include <doc.hxx>
+#include <ndtxt.hxx> // class SwTxtNode
+#include <pagedesc.hxx> // class SwPageDesc
+#include <paratr.hxx>
+#include <fmtclds.hxx>
+#include <fmtclbl.hxx>
+#include <section.hxx>
+#include <docsh.hxx>
+#include <docufld.hxx>
+#include <swfltopt.hxx>
+#include <viewsh.hxx>
+#include <shellres.hxx>
+#include <mdiexp.hxx> // Progress
+#include <statstr.hrc> // ResId fuer Statusleiste
+#include <swerror.h> // ERR_WW8_...
+#include <swunodef.hxx>
+#include <unodraw.hxx>
+#include <swtable.hxx> // class SwTableLines, ...
+// #i18732#
+#include <fmtfollowtextflow.hxx>
+#include <fchrfmt.hxx>
+#include <charfmt.hxx>
+
+
+#include <com/sun/star/i18n/ForbiddenCharacters.hpp>
+#include <comphelper/extract.hxx>
+#include <comphelper/sequenceashashmap.hxx>
+#include <fltini.hxx>
+
+#include <algorithm>
+#include <functional>
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+
+
+#include "ww8par2.hxx" // class WW8RStyle, class WW8AnchorPara
+
+#include <frmatr.hxx>
+
+#include <math.h>
+#include <com/sun/star/beans/XPropertyContainer.hpp>
+
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
+#include <com/sun/star/document/XDocumentProperties.hpp>
+#include <svl/itemiter.hxx> //SfxItemIter
+
+#include <stdio.h>
+#include <comphelper/processfactory.hxx>
+#include <basic/basmgr.hxx>
+
+#include "ww8toolbar.hxx"
+#include <osl/file.hxx>
+#include <com/sun/star/document/XDocumentInfoSupplier.hpp>
+
+#include <breakit.hxx>
+
+#ifdef DEBUG
+#include <iostream>
+#include <dbgoutsw.hxx>
+#endif
+#include <unotools/localfilehelper.hxx>
+#include <comphelper/configurationhelper.hxx>
+
+#include "WW8Sttbf.hxx"
+#include "WW8FibData.hxx"
+#define MM_250 1417 // WW-Default fuer Hor. Seitenraender: 2.5 cm
+#define MM_200 1134 // WW-Default fuer u.Seitenrand: 2.0 cm
+
+using namespace ::com::sun::star;
+using namespace sw::util;
+using namespace sw::types;
+using namespace nsHdFtFlags;
+
+#include <com/sun/star/document/XEventsSupplier.hpp>
+#include <com/sun/star/container/XNameReplace.hpp>
+#include <com/sun/star/i18n/XBreakIterator.hpp>
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <com/sun/star/frame/XModel.hpp>
+#include <filter/msfilter/msvbahelper.hxx>
+#include <unotools/pathoptions.hxx>
+#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
+
+#include <comphelper/processfactory.hxx>
+#include <com/sun/star/document/XFilter.hpp>
+#include <com/sun/star/script/vba/XVBACompatibility.hpp>
+#include <com/sun/star/document/XImporter.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <comphelper/mediadescriptor.hxx>
+
+using ::comphelper::MediaDescriptor;
+using ::comphelper::getProcessServiceFactory;
+
+class BasicProjImportHelper
+{
+ SwDocShell& mrDocShell;
+public:
+ BasicProjImportHelper( SwDocShell& rShell ) : mrDocShell( rShell ) {}
+ bool import();
+ bool import( const com::sun::star::uno::Sequence< com::sun::star::beans::NamedValue >& aArgSeq );
+ rtl::OUString getProjectName();
+};
+
+bool BasicProjImportHelper::import()
+{
+ uno::Sequence< beans::NamedValue > aArgSeq;
+ return import( aArgSeq );
+}
+
+bool BasicProjImportHelper::import( const uno::Sequence< beans::NamedValue >& aArgSeq )
+{
+ bool bRet = false;
+ try
+ {
+ uno::Reference< lang::XComponent > xComponent( mrDocShell.GetModel(), uno::UNO_QUERY_THROW );
+ // #TODO #FIXME, get rid of the uno access, better ( and less lines I suspect ) to
+ // access this directly ( just need to figure out what stream manipulation I need to
+ // do )
+ uno::Reference< lang::XMultiServiceFactory > xFac( getProcessServiceFactory(), uno::UNO_QUERY_THROW );
+ uno::Reference< document::XImporter > xImporter;
+ if ( aArgSeq.getLength() )
+ {
+ uno::Sequence< uno::Any > aArgs( 2 );
+ aArgs[ 0 ] <<= getProcessServiceFactory();
+ aArgs[ 1 ] <<= aArgSeq;
+ xImporter.set( xFac->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.oox.WordVbaProjectFilter" ) ), aArgs ), uno::UNO_QUERY_THROW );
+ }
+ else
+ xImporter.set( xFac->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.oox.WordVbaProjectFilter" ) )), uno::UNO_QUERY_THROW );
+ xImporter->setTargetDocument( xComponent );
+
+ MediaDescriptor aMediaDesc;
+ SfxMedium& rMedium = *mrDocShell.GetMedium();
+ SfxItemSet* pItemSet = rMedium.GetItemSet();
+ if( pItemSet )
+ {
+ if( const SfxStringItem* pItem = static_cast< const SfxStringItem* >( pItemSet->GetItem( SID_FILE_NAME ) ) )
+ aMediaDesc[ MediaDescriptor::PROP_URL() ] <<= ::rtl::OUString( pItem->GetValue() );
+ if( const SfxStringItem* pItem = static_cast< const SfxStringItem* >( pItemSet->GetItem( SID_PASSWORD ) ) )
+ aMediaDesc[ MediaDescriptor::PROP_PASSWORD() ] <<= ::rtl::OUString( pItem->GetValue() );
+ }
+ aMediaDesc[ MediaDescriptor::PROP_INPUTSTREAM() ] <<= rMedium.GetInputStream();
+ aMediaDesc[ MediaDescriptor::PROP_INTERACTIONHANDLER() ] <<= rMedium.GetInteractionHandler();
+
+ // call the filter
+ uno::Reference< document::XFilter > xFilter( xImporter, uno::UNO_QUERY_THROW );
+ bRet = xFilter->filter( aMediaDesc.getAsConstPropertyValueList() );
+ }
+ catch( uno::Exception& )
+ {
+ bRet = false;
+ }
+ return bRet;
+}
+
+rtl::OUString BasicProjImportHelper::getProjectName()
+{
+ rtl::OUString sProjName( RTL_CONSTASCII_USTRINGPARAM("Standard") );
+ uno::Reference< beans::XPropertySet > xProps( mrDocShell.GetModel(), uno::UNO_QUERY );
+ if ( xProps.is() )
+ {
+ try
+ {
+ uno::Reference< script::vba::XVBACompatibility > xVBA( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "BasicLibraries" ) ) ), uno::UNO_QUERY_THROW );
+ sProjName = xVBA->getProjectName();
+
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+ return sProjName;
+}
+
+
+class Sttb : TBBase
+{
+struct SBBItem
+{
+ sal_uInt16 cchData;
+ rtl::OUString data;
+ SBBItem() : cchData(0){}
+};
+ sal_uInt16 fExtend;
+ sal_uInt16 cData;
+ sal_uInt16 cbExtra;
+
+ std::vector< SBBItem > dataItems;
+
+ Sttb(const Sttb&);
+ Sttb& operator = ( const Sttb&);
+public:
+ Sttb();
+ ~Sttb();
+ bool Read(SvStream *pS);
+ void Print( FILE* fp );
+ rtl::OUString getStringAtIndex( sal_uInt32 );
+};
+
+Sttb::Sttb() : fExtend( 0 )
+,cData( 0 )
+,cbExtra( 0 )
+{
+}
+
+Sttb::~Sttb()
+{
+}
+
+bool Sttb::Read( SvStream* pS )
+{
+ OSL_TRACE("Sttb::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ *pS >> fExtend >> cData >> cbExtra;
+ if ( cData )
+ {
+ for ( sal_Int32 index = 0; index < cData; ++index )
+ {
+ SBBItem aItem;
+ *pS >> aItem.cchData;
+ aItem.data = readUnicodeString( pS, aItem.cchData );
+ dataItems.push_back( aItem );
+ }
+ }
+ return true;
+}
+
+void Sttb::Print( FILE* fp )
+{
+ fprintf( fp, "[ 0x%" SAL_PRIxUINT32 " ] Sttb - dump\n", nOffSet);
+ fprintf( fp, " fExtend 0x%x [expected 0xFFFF ]\n", fExtend );
+ fprintf( fp, " cData no. or string data items %d (0x%x)\n", cData, cData );
+
+ if ( cData )
+ {
+ for ( sal_Int32 index = 0; index < cData; ++index )
+ fprintf(fp," string dataItem[ %d(0x%x) ] has name %s\n", static_cast< int >( index ), static_cast< unsigned int >( index ), rtl::OUStringToOString( dataItems[ index ].data, RTL_TEXTENCODING_UTF8 ).getStr() );
+ }
+
+}
+
+rtl::OUString
+Sttb::getStringAtIndex( sal_uInt32 index )
+{
+ rtl::OUString aRet;
+ if ( index < dataItems.size() )
+ aRet = dataItems[ index ].data;
+ return aRet;
+}
+
+SwMSDffManager::SwMSDffManager( SwWW8ImplReader& rRdr )
+ : SvxMSDffManager(*rRdr.pTableStream, rRdr.GetBaseURL(), rRdr.pWwFib->fcDggInfo,
+ rRdr.pDataStream, 0, 0, COL_WHITE, 12, rRdr.pStrm,
+ rRdr.maTracer.GetTrace()),
+ rReader(rRdr), pFallbackStream(0), pOldEscherBlipCache(0)
+{
+ SetSvxMSDffSettings( GetSvxMSDffSettings() );
+ nSvxMSDffOLEConvFlags = SwMSDffManager::GetFilterFlags();
+}
+
+sal_uInt32 SwMSDffManager::GetFilterFlags()
+{
+ sal_uInt32 nFlags(0);
+ if (const SvtFilterOptions* pOpt = SvtFilterOptions::Get())
+ {
+ if (pOpt->IsMathType2Math())
+ nFlags |= OLE_MATHTYPE_2_STARMATH;
+ if (pOpt->IsExcel2Calc())
+ nFlags |= OLE_EXCEL_2_STARCALC;
+ if (pOpt->IsPowerPoint2Impress())
+ nFlags |= OLE_POWERPOINT_2_STARIMPRESS;
+ if (pOpt->IsWinWord2Writer())
+ nFlags |= OLE_WINWORD_2_STARWRITER;
+ }
+ return nFlags;
+}
+
+/*
+ * I would like to override the default OLE importing to add a test
+ * and conversion of OCX controls from their native OLE type into our
+ * native nonOLE Form Control Objects.
+ *
+ * cmc
+ */
+// #i32596# - consider new parameter <_nCalledByGroup>
+SdrObject* SwMSDffManager::ImportOLE( long nOLEId,
+ const Graphic& rGrf,
+ const Rectangle& rBoundRect,
+ const Rectangle& rVisArea,
+ const int _nCalledByGroup,
+ sal_Int64 nAspect ) const
+{
+ // #i32596# - no import of OLE object, if it's inside a group.
+ // NOTE: This can be undone, if grouping of Writer fly frames is possible or
+ // if drawing OLE objects are allowed in Writer.
+ if ( _nCalledByGroup > 0 )
+ {
+ return 0L;
+ }
+ // <--
+
+ SdrObject* pRet = 0;
+ String sStorageName;
+ SotStorageRef xSrcStg;
+ uno::Reference < embed::XStorage > xDstStg;
+ if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg ))
+ {
+ SvStorageRef xSrc = xSrcStg->OpenSotStorage( sStorageName,
+ STREAM_READWRITE| STREAM_SHARE_DENYALL );
+ OSL_ENSURE(rReader.pFormImpl, "No Form Implementation!");
+ STAR_REFERENCE( drawing::XShape ) xShape;
+ if ( (!(rReader.bIsHeader || rReader.bIsFooter)) &&
+ rReader.pFormImpl->ReadOCXStream(xSrc,&xShape,true))
+ {
+ pRet = GetSdrObjectFromXShape(xShape);
+ }
+ else
+ {
+ ErrCode nError = ERRCODE_NONE;
+ pRet = CreateSdrOLEFromStorage( sStorageName, xSrcStg, xDstStg,
+ rGrf, rBoundRect, rVisArea, pStData, nError, nSvxMSDffOLEConvFlags, nAspect );
+ }
+ }
+ return pRet;
+}
+
+void SwMSDffManager::DisableFallbackStream()
+{
+ OSL_ENSURE(!pFallbackStream || !pOldEscherBlipCache,
+ "if you're recursive, you're broken");
+ pFallbackStream = pStData2;
+ pOldEscherBlipCache = pEscherBlipCache;
+ pEscherBlipCache = 0;
+ pStData2 = 0;
+}
+
+void SwMSDffManager::EnableFallbackStream()
+{
+ pStData2 = pFallbackStream;
+ pEscherBlipCache = pOldEscherBlipCache;
+ pOldEscherBlipCache = 0;
+ pFallbackStream = 0;
+}
+
+sal_uInt16 SwWW8ImplReader::GetToggleAttrFlags() const
+{
+ return pCtrlStck ? pCtrlStck->GetToggleAttrFlags() : 0;
+}
+
+sal_uInt16 SwWW8ImplReader::GetToggleBiDiAttrFlags() const
+{
+ return pCtrlStck ? pCtrlStck->GetToggleBiDiAttrFlags() : 0;
+}
+
+void SwWW8ImplReader::SetToggleAttrFlags(sal_uInt16 nFlags)
+{
+ if (pCtrlStck)
+ pCtrlStck->SetToggleAttrFlags(nFlags);
+}
+
+void SwWW8ImplReader::SetToggleBiDiAttrFlags(sal_uInt16 nFlags)
+{
+ if (pCtrlStck)
+ pCtrlStck->SetToggleBiDiAttrFlags(nFlags);
+}
+
+
+SdrObject* SwMSDffManager::ProcessObj(SvStream& rSt,
+ DffObjData& rObjData,
+ void* pData,
+ Rectangle& rTextRect,
+ SdrObject* pObj
+ )
+{
+ if( !rTextRect.IsEmpty() )
+ {
+ SvxMSDffImportData& rImportData = *(SvxMSDffImportData*)pData;
+ SvxMSDffImportRec* pImpRec = new SvxMSDffImportRec;
+
+ // fill Import Record with data
+ pImpRec->nShapeId = rObjData.nShapeId;
+ pImpRec->eShapeType = rObjData.eShapeType;
+
+ rObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt,
+ DFF_msofbtClientAnchor,
+ SEEK_FROM_CURRENT_AND_RESTART );
+ if( rObjData.bClientAnchor )
+ ProcessClientAnchor( rSt,
+ maShapeRecords.Current()->nRecLen,
+ pImpRec->pClientAnchorBuffer, pImpRec->nClientAnchorLen );
+
+ rObjData.bClientData = maShapeRecords.SeekToContent( rSt,
+ DFF_msofbtClientData,
+ SEEK_FROM_CURRENT_AND_RESTART );
+ if( rObjData.bClientData )
+ ProcessClientData( rSt,
+ maShapeRecords.Current()->nRecLen,
+ pImpRec->pClientDataBuffer, pImpRec->nClientDataLen );
+
+
+ // process user (== Winword) defined parameters in 0xF122 record
+ // #i84783# - set special value to determine, if property is provided or not.
+ pImpRec->nLayoutInTableCell = 0xFFFFFFFF;
+
+ if( maShapeRecords.SeekToContent( rSt,
+ DFF_msofbtUDefProp,
+ SEEK_FROM_CURRENT_AND_RESTART )
+ && maShapeRecords.Current()->nRecLen )
+ {
+ sal_uInt32 nBytesLeft = maShapeRecords.Current()->nRecLen;
+ sal_uInt32 nUDData;
+ sal_uInt16 nPID;
+ while( 5 < nBytesLeft )
+ {
+ rSt >> nPID;
+ if ( rSt.GetError() != 0 )
+ break;
+ rSt >> nUDData;
+ switch( nPID )
+ {
+ case 0x038F: pImpRec->nXAlign = nUDData; break;
+ case 0x0390:
+ if (pImpRec->pXRelTo)
+ delete pImpRec->pXRelTo;
+ pImpRec->pXRelTo = new sal_uInt32;
+ *(pImpRec->pXRelTo) = nUDData;
+ break;
+ case 0x0391: pImpRec->nYAlign = nUDData; break;
+ case 0x0392:
+ if (pImpRec->pYRelTo)
+ delete pImpRec->pYRelTo;
+ pImpRec->pYRelTo = new sal_uInt32;
+ *(pImpRec->pYRelTo) = nUDData;
+ break;
+ case 0x03BF: pImpRec->nLayoutInTableCell = nUDData; break;
+ }
+ if ( rSt.GetError() != 0 )
+ break;
+ pImpRec->bHasUDefProp = sal_True;
+ nBytesLeft -= 6;
+ }
+ }
+
+ // Textrahmen, auch Title oder Outline
+ sal_uInt32 nTextId = GetPropertyValue( DFF_Prop_lTxid, 0 );
+ if( nTextId )
+ {
+ SfxItemSet aSet( pSdrModel->GetItemPool() );
+
+ //Originally anything that as a mso_sptTextBox was created as a
+ //textbox, this was changed for #88277# to be created as a simple
+ //rect to keep impress happy. For the rest of us we'd like to turn
+ //it back into a textbox again.
+ sal_Bool bIsSimpleDrawingTextBox = (pImpRec->eShapeType == mso_sptTextBox);
+ if (!bIsSimpleDrawingTextBox)
+ {
+ //Either
+ //a) its a simple text object or
+ //b) its a rectangle with text and square wrapping.
+ bIsSimpleDrawingTextBox =
+ (
+ (pImpRec->eShapeType == mso_sptTextSimple) ||
+ (
+ (pImpRec->eShapeType == mso_sptRectangle)
+ && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() )
+ )
+ );
+ }
+
+ // Distance of Textbox to it's surrounding Autoshape
+ sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 91440L);
+ sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 91440L );
+ sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 45720L );
+ sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 45720L );
+
+ ScaleEmu( nTextLeft );
+ ScaleEmu( nTextRight );
+ ScaleEmu( nTextTop );
+ ScaleEmu( nTextBottom );
+
+ sal_Int32 nTextRotationAngle=0;
+ bool bVerticalText = false;
+ if ( IsProperty( DFF_Prop_txflTextFlow ) )
+ {
+ MSO_TextFlow eTextFlow = (MSO_TextFlow)(GetPropertyValue(
+ DFF_Prop_txflTextFlow) & 0xFFFF);
+ switch( eTextFlow )
+ {
+ case mso_txflBtoT:
+ nTextRotationAngle = 9000;
+ break;
+ case mso_txflVertN:
+ case mso_txflTtoBN:
+ nTextRotationAngle = 27000;
+ break;
+ case mso_txflTtoBA:
+ bVerticalText = true;
+ break;
+ case mso_txflHorzA:
+ bVerticalText = true;
+ nTextRotationAngle = 9000;
+ case mso_txflHorzN:
+ default :
+ break;
+ }
+ }
+
+ if (nTextRotationAngle)
+ {
+ while (nTextRotationAngle > 360000)
+ nTextRotationAngle-=9000;
+ switch (nTextRotationAngle)
+ {
+ case 9000:
+ {
+ long nWidth = rTextRect.GetWidth();
+ rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight();
+ rTextRect.Bottom() = rTextRect.Top() + nWidth;
+
+ sal_Int32 nOldTextLeft = nTextLeft;
+ sal_Int32 nOldTextRight = nTextRight;
+ sal_Int32 nOldTextTop = nTextTop;
+ sal_Int32 nOldTextBottom = nTextBottom;
+
+ nTextLeft = nOldTextBottom;
+ nTextRight = nOldTextTop;
+ nTextTop = nOldTextLeft;
+ nTextBottom = nOldTextRight;
+ }
+ break;
+ case 27000:
+ {
+ long nWidth = rTextRect.GetWidth();
+ rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight();
+ rTextRect.Bottom() = rTextRect.Top() + nWidth;
+
+ sal_Int32 nOldTextLeft = nTextLeft;
+ sal_Int32 nOldTextRight = nTextRight;
+ sal_Int32 nOldTextTop = nTextTop;
+ sal_Int32 nOldTextBottom = nTextBottom;
+
+ nTextLeft = nOldTextTop;
+ nTextRight = nOldTextBottom;
+ nTextTop = nOldTextRight;
+ nTextBottom = nOldTextLeft;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (bIsSimpleDrawingTextBox)
+ {
+ SdrObject::Free( pObj );
+ pObj = new SdrRectObj(OBJ_TEXT, rTextRect);
+ }
+
+ // Die vertikalen Absatzeinrueckungen sind im BoundRect mit drin,
+ // hier rausrechnen
+ Rectangle aNewRect(rTextRect);
+ aNewRect.Bottom() -= nTextTop + nTextBottom;
+ aNewRect.Right() -= nTextLeft + nTextRight;
+
+ // Nur falls es eine einfache Textbox ist, darf der Writer
+ // das Objekt durch einen Rahmen ersetzen, ansonsten
+ if( bIsSimpleDrawingTextBox )
+ {
+ SvxMSDffShapeInfo aTmpRec( 0, pImpRec->nShapeId );
+ aTmpRec.bSortByShapeId = sal_True;
+
+ sal_uInt16 nFound;
+ if( GetShapeInfos()->Seek_Entry( &aTmpRec, &nFound ) )
+ {
+ SvxMSDffShapeInfo& rInfo = *GetShapeInfos()->GetObject(nFound);
+ pImpRec->bReplaceByFly = rInfo.bReplaceByFly;
+ pImpRec->bLastBoxInChain = rInfo.bLastBoxInChain;
+ }
+ }
+
+ if( bIsSimpleDrawingTextBox )
+ ApplyAttributes( rSt, aSet, rObjData );
+
+ if (GetPropertyValue(DFF_Prop_FitTextToShape) & 2)
+ {
+ aSet.Put( SdrTextAutoGrowHeightItem( sal_True ) );
+ aSet.Put( SdrTextMinFrameHeightItem(
+ aNewRect.Bottom() - aNewRect.Top() ) );
+ aSet.Put( SdrTextMinFrameWidthItem(
+ aNewRect.Right() - aNewRect.Left() ) );
+ }
+ else
+ {
+ aSet.Put( SdrTextAutoGrowHeightItem( sal_False ) );
+ aSet.Put( SdrTextAutoGrowWidthItem( sal_False ) );
+ }
+
+ switch ( (MSO_WrapMode)
+ GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) )
+ {
+ case mso_wrapNone :
+ aSet.Put( SdrTextAutoGrowWidthItem( sal_True ) );
+ pImpRec->bAutoWidth = true;
+ break;
+ case mso_wrapByPoints :
+ aSet.Put( SdrTextContourFrameItem( sal_True ) );
+ break;
+ default:
+ ;
+ }
+
+ // Abstaende an den Raendern der Textbox setzen
+ aSet.Put( SdrTextLeftDistItem( nTextLeft ) );
+ aSet.Put( SdrTextRightDistItem( nTextRight ) );
+ aSet.Put( SdrTextUpperDistItem( nTextTop ) );
+ aSet.Put( SdrTextLowerDistItem( nTextBottom ) );
+ pImpRec->nDxTextLeft = nTextLeft;
+ pImpRec->nDyTextTop = nTextTop;
+ pImpRec->nDxTextRight = nTextRight;
+ pImpRec->nDyTextBottom = nTextBottom;
+
+ // taking the correct default (which is mso_anchorTop)
+ MSO_Anchor eTextAnchor =
+ (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop );
+
+ SdrTextVertAdjust eTVA = bVerticalText
+ ? SDRTEXTVERTADJUST_BLOCK
+ : SDRTEXTVERTADJUST_CENTER;
+ SdrTextHorzAdjust eTHA = bVerticalText
+ ? SDRTEXTHORZADJUST_CENTER
+ : SDRTEXTHORZADJUST_BLOCK;
+
+ switch( eTextAnchor )
+ {
+ case mso_anchorTop:
+ {
+ if ( bVerticalText )
+ eTHA = SDRTEXTHORZADJUST_RIGHT;
+ else
+ eTVA = SDRTEXTVERTADJUST_TOP;
+ }
+ break;
+ case mso_anchorTopCentered:
+ {
+ if ( bVerticalText )
+ eTHA = SDRTEXTHORZADJUST_RIGHT;
+ else
+ eTVA = SDRTEXTVERTADJUST_TOP;
+ }
+ break;
+ case mso_anchorMiddle:
+ break;
+ case mso_anchorMiddleCentered:
+ break;
+ case mso_anchorBottom:
+ {
+ if ( bVerticalText )
+ eTHA = SDRTEXTHORZADJUST_LEFT;
+ else
+ eTVA = SDRTEXTVERTADJUST_BOTTOM;
+ }
+ break;
+ case mso_anchorBottomCentered:
+ {
+ if ( bVerticalText )
+ eTHA = SDRTEXTHORZADJUST_LEFT;
+ else
+ eTVA = SDRTEXTVERTADJUST_BOTTOM;
+ }
+ break;
+ default:
+ ;
+ }
+
+ aSet.Put( SdrTextVertAdjustItem( eTVA ) );
+ aSet.Put( SdrTextHorzAdjustItem( eTHA ) );
+
+ if (pObj != NULL)
+ {
+ pObj->SetMergedItemSet(aSet);
+ pObj->SetModel(pSdrModel);
+
+ if (bVerticalText && dynamic_cast< SdrTextObj* >( pObj ) )
+ dynamic_cast< SdrTextObj* >( pObj )->SetVerticalWriting(sal_True);
+
+ if ( bIsSimpleDrawingTextBox )
+ {
+ if ( nTextRotationAngle )
+ {
+ long nMinWH = rTextRect.GetWidth() < rTextRect.GetHeight() ?
+ rTextRect.GetWidth() : rTextRect.GetHeight();
+ nMinWH /= 2;
+ Point aPivot(rTextRect.TopLeft());
+ aPivot.X() += nMinWH;
+ aPivot.Y() += nMinWH;
+ double a = nTextRotationAngle * nPi180;
+ pObj->NbcRotate(aPivot, nTextRotationAngle, sin(a), cos(a));
+ }
+ }
+
+ if ( ( ( rObjData.nSpFlags & SP_FFLIPV ) || mnFix16Angle || nTextRotationAngle ) && dynamic_cast< SdrObjCustomShape* >( pObj ) )
+ {
+ SdrObjCustomShape* pCustomShape = dynamic_cast< SdrObjCustomShape* >( pObj );
+
+ double fExtraTextRotation = 0.0;
+ if ( mnFix16Angle && !( GetPropertyValue( DFF_Prop_FitTextToShape ) & 4 ) )
+ { // text is already rotated, we have to take back the object rotation if DFF_Prop_RotateText is false
+ fExtraTextRotation = -mnFix16Angle;
+ }
+ if ( rObjData.nSpFlags & SP_FFLIPV ) // sj: in ppt the text is flipped, whereas in word the text
+ { // remains unchanged, so we have to take back the flipping here
+ fExtraTextRotation += 18000.0; // because our core will flip text if the shape is flipped.
+ }
+ fExtraTextRotation += nTextRotationAngle;
+ if ( !::basegfx::fTools::equalZero( fExtraTextRotation ) )
+ {
+ fExtraTextRotation /= 100.0;
+ SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
+ const rtl::OUString sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) );
+ com::sun::star::beans::PropertyValue aPropVal;
+ aPropVal.Name = sTextRotateAngle;
+ aPropVal.Value <<= fExtraTextRotation;
+ aGeometryItem.SetPropertyValue( aPropVal );
+ pCustomShape->SetMergedItem( aGeometryItem );
+ }
+ }
+ else if ( mnFix16Angle )
+ {
+ // rotate text with shape ?
+ double a = mnFix16Angle * nPi180;
+ pObj->NbcRotate( rObjData.aBoundRect.Center(), mnFix16Angle,
+ sin( a ), cos( a ) );
+ }
+ }
+ }
+ else if( !pObj )
+ {
+ // simple rectangular objects are ignored by ImportObj() :-(
+ // this is OK for Draw but not for Calc and Writer
+ // cause here these objects have a default border
+ pObj = new SdrRectObj(rTextRect);
+ pObj->SetModel( pSdrModel );
+ SfxItemSet aSet( pSdrModel->GetItemPool() );
+ ApplyAttributes( rSt, aSet, rObjData );
+
+ const SfxPoolItem* pPoolItem=NULL;
+ SfxItemState eState = aSet.GetItemState( XATTR_FILLCOLOR,
+ sal_False, &pPoolItem );
+ if( SFX_ITEM_DEFAULT == eState )
+ aSet.Put( XFillColorItem( String(),
+ Color( mnDefaultColor ) ) );
+ pObj->SetMergedItemSet(aSet);
+ }
+
+ //Means that fBehindDocument is set
+ if (GetPropertyValue(DFF_Prop_fPrint) & 0x20)
+ pImpRec->bDrawHell = sal_True;
+ else
+ pImpRec->bDrawHell = sal_False;
+ if (GetPropertyValue(DFF_Prop_fPrint) & 0x02)
+ pImpRec->bHidden = sal_True;
+ pImpRec->nNextShapeId = GetPropertyValue( DFF_Prop_hspNext, 0 );
+
+ if ( nTextId )
+ {
+ pImpRec->aTextId.nTxBxS = (sal_uInt16)( nTextId >> 16 );
+ pImpRec->aTextId.nSequence = (sal_uInt16)nTextId;
+ }
+
+ pImpRec->nDxWrapDistLeft = GetPropertyValue(
+ DFF_Prop_dxWrapDistLeft, 114935L ) / 635L;
+ pImpRec->nDyWrapDistTop = GetPropertyValue(
+ DFF_Prop_dyWrapDistTop, 0 ) / 635L;
+ pImpRec->nDxWrapDistRight = GetPropertyValue(
+ DFF_Prop_dxWrapDistRight, 114935L ) / 635L;
+ pImpRec->nDyWrapDistBottom = GetPropertyValue(
+ DFF_Prop_dyWrapDistBottom, 0 ) / 635L;
+ // 16.16 fraction times total image width or height, as appropriate.
+
+ if (SeekToContent(DFF_Prop_pWrapPolygonVertices, rSt))
+ {
+ delete pImpRec->pWrapPolygon;
+ sal_uInt16 nNumElemVert, nNumElemMemVert, nElemSizeVert;
+ rSt >> nNumElemVert >> nNumElemMemVert >> nElemSizeVert;
+ if (nNumElemVert && ((nElemSizeVert == 8) || (nElemSizeVert == 4)))
+ {
+ pImpRec->pWrapPolygon = new Polygon(nNumElemVert);
+ for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
+ {
+ sal_Int32 nX, nY;
+ if (nElemSizeVert == 8)
+ rSt >> nX >> nY;
+ else
+ {
+ sal_Int16 nSmallX, nSmallY;
+ rSt >> nSmallX >> nSmallY;
+ nX = nSmallX;
+ nY = nSmallY;
+ }
+ (*(pImpRec->pWrapPolygon))[i].X() = nX;
+ (*(pImpRec->pWrapPolygon))[i].Y() = nY;
+ }
+ }
+ }
+
+ pImpRec->nCropFromTop = GetPropertyValue(
+ DFF_Prop_cropFromTop, 0 );
+ pImpRec->nCropFromBottom = GetPropertyValue(
+ DFF_Prop_cropFromBottom, 0 );
+ pImpRec->nCropFromLeft = GetPropertyValue(
+ DFF_Prop_cropFromLeft, 0 );
+ pImpRec->nCropFromRight = GetPropertyValue(
+ DFF_Prop_cropFromRight, 0 );
+
+ sal_uInt32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash );
+
+ if ( !IsHardAttribute( DFF_Prop_fLine ) &&
+ pImpRec->eShapeType == mso_sptPictureFrame )
+ {
+ nLineFlags &= ~0x08;
+ }
+
+ pImpRec->eLineStyle = (nLineFlags & 8)
+ ? (MSO_LineStyle)GetPropertyValue(
+ DFF_Prop_lineStyle,
+ mso_lineSimple )
+ : (MSO_LineStyle)USHRT_MAX;
+ pImpRec->eLineDashing = (MSO_LineDashing)GetPropertyValue(
+ DFF_Prop_lineDashing, mso_lineSolid );
+
+ pImpRec->nFlags = rObjData.nSpFlags;
+
+ if( pImpRec->nShapeId )
+ {
+ // Import-Record-Liste ergaenzen
+ pImpRec->pObj = pObj;
+ rImportData.aRecords.Insert( pImpRec );
+
+ // Eintrag in Z-Order-Liste um Zeiger auf dieses Objekt ergaenzen
+ /*Only store objects which are not deep inside the tree*/
+ if( ( rObjData.nCalledByGroup == 0 )
+ ||
+ ( (rObjData.nSpFlags & SP_FGROUP)
+ && (rObjData.nCalledByGroup < 2) )
+ )
+ StoreShapeOrder( pImpRec->nShapeId,
+ ( ( (sal_uLong)pImpRec->aTextId.nTxBxS ) << 16 )
+ + pImpRec->aTextId.nSequence, pObj );
+ }
+ else
+ delete pImpRec;
+ }
+
+ return pObj;
+}
+
+/***************************************************************************
+# Spezial FastSave - Attribute
+#**************************************************************************/
+
+void SwWW8ImplReader::Read_StyleCode( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if (nLen < 0)
+ {
+ bCpxStyle = false;
+ return;
+ }
+ sal_uInt16 nColl = 0;
+ if (pWwFib->GetFIBVersion() <= ww::eWW2)
+ nColl = *pData;
+ else
+ nColl = SVBT16ToShort(pData);
+ if (nColl < nColls)
+ {
+ SetTxtFmtCollAndListLevel( *pPaM, pCollA[nColl] );
+ bCpxStyle = true;
+ }
+}
+
+// Read_Majority ist fuer Majority ( 103 ) und Majority50 ( 108 )
+void SwWW8ImplReader::Read_Majority( sal_uInt16, const sal_uInt8* , short )
+{
+}
+
+//-----------------------------------------
+// Stack
+//-----------------------------------------
+void SwWW8FltControlStack::NewAttr(const SwPosition& rPos,
+ const SfxPoolItem& rAttr)
+{
+ OSL_ENSURE(RES_TXTATR_FIELD != rAttr.Which(), "probably don't want to put"
+ "fields into the control stack");
+ OSL_ENSURE(RES_FLTR_REDLINE != rAttr.Which(), "probably don't want to put"
+ "redlines into the control stack");
+ SwFltControlStack::NewAttr(rPos, rAttr);
+}
+
+void SwWW8FltControlStack::SetAttr(const SwPosition& rPos, sal_uInt16 nAttrId,
+ sal_Bool bTstEnde, long nHand, sal_Bool )
+{
+ //Doing a textbox, and using the control stack only as a temporary
+ //collection point for properties which will are not to be set into
+ //the real document
+ if (rReader.pPlcxMan && rReader.pPlcxMan->GetDoingDrawTextBox())
+ {
+ sal_uInt16 nCnt = static_cast< sal_uInt16 >(Count());
+ for (sal_uInt16 i=0; i < nCnt; ++i)
+ {
+ SwFltStackEntry* pEntry = (*this)[i];
+ if (nAttrId == pEntry->pAttr->Which())
+ {
+ DeleteAndDestroy(i--);
+ --nCnt;
+ }
+ }
+ }
+ else //Normal case, set the attribute into the document
+ SwFltControlStack::SetAttr(rPos, nAttrId, bTstEnde, nHand);
+}
+
+long GetListFirstLineIndent(const SwNumFmt &rFmt)
+{
+ OSL_ENSURE( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
+ "<GetListFirstLineIndent> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
+
+ SvxAdjust eAdj = rFmt.GetNumAdjust();
+ long nReverseListIndented;
+ if (eAdj == SVX_ADJUST_RIGHT)
+ nReverseListIndented = -rFmt.GetCharTextDistance();
+ else if (eAdj == SVX_ADJUST_CENTER)
+ nReverseListIndented = rFmt.GetFirstLineOffset()/2;
+ else
+ nReverseListIndented = rFmt.GetFirstLineOffset();
+ return nReverseListIndented;
+}
+
+long lcl_GetTrueMargin(const SvxLRSpaceItem &rLR, const SwNumFmt &rFmt,
+ long &rFirstLinePos)
+{
+ OSL_ENSURE( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
+ "<lcl_GetTrueMargin> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
+
+ const long nBodyIndent = rLR.GetTxtLeft();
+ const long nFirstLineDiff = rLR.GetTxtFirstLineOfst();
+ rFirstLinePos = nBodyIndent + nFirstLineDiff;
+
+ const long nPseudoListBodyIndent = rFmt.GetAbsLSpace();
+ const long nReverseListIndented = GetListFirstLineIndent(rFmt);
+ long nExtraListIndent = nPseudoListBodyIndent + nReverseListIndented;
+
+ return nExtraListIndent > 0 ? nExtraListIndent : 0;
+}
+
+// #i103711#
+// #i105414#
+void SyncIndentWithList( SvxLRSpaceItem &rLR,
+ const SwNumFmt &rFmt,
+ const bool bFirstLineOfstSet,
+ const bool bLeftIndentSet )
+{
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ long nWantedFirstLinePos;
+ long nExtraListIndent = lcl_GetTrueMargin(rLR, rFmt, nWantedFirstLinePos);
+ rLR.SetTxtLeft(nWantedFirstLinePos - nExtraListIndent);
+ rLR.SetTxtFirstLineOfst(0);
+ }
+ else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ if ( !bFirstLineOfstSet && bLeftIndentSet &&
+ rFmt.GetFirstLineIndent() != 0 )
+ {
+ rLR.SetTxtFirstLineOfst( rFmt.GetFirstLineIndent() );
+ }
+ else if ( bFirstLineOfstSet && !bLeftIndentSet &&
+ rFmt.GetIndentAt() != 0 )
+ {
+ rLR.SetTxtLeft( rFmt.GetIndentAt() );
+ }
+ }
+}
+// <--
+
+const SwNumFmt* SwWW8FltControlStack::GetNumFmtFromStack(const SwPosition &rPos,
+ const SwTxtNode &rTxtNode)
+{
+ const SwNumFmt *pRet = 0;
+ const SfxPoolItem *pItem = GetStackAttr(rPos, RES_FLTR_NUMRULE);
+ if (pItem && rTxtNode.GetNumRule())
+ {
+ String sName(((SfxStringItem*)pItem)->GetValue());
+ if (rTxtNode.IsCountedInList())
+ {
+ const SwNumRule *pRule = pDoc->FindNumRulePtr(sName);
+ sal_uInt8 nLvl = static_cast< sal_uInt8 >(rTxtNode.GetActualListLevel());
+ pRet = &(pRule->Get(nLvl));
+ }
+ }
+ return pRet;
+}
+
+void SwWW8FltControlStack::SetAttrInDoc(const SwPosition& rTmpPos,
+ SwFltStackEntry* pEntry)
+{
+ switch( pEntry->pAttr->Which() )
+ {
+ case RES_LR_SPACE:
+ {
+ /*
+ Loop over the affect nodes and
+ a) convert the word style absolute indent to indent relative
+ to any numbering indent active on the nodes
+ b) adjust the writer style tabstops relative to the old
+ paragraph indent to be relative to the new paragraph indent
+ */
+ using namespace sw::util;
+ SwPaM aRegion(rTmpPos);
+ if (pEntry->MakeRegion(pDoc, aRegion, false))
+ {
+ SvxLRSpaceItem aNewLR( *(SvxLRSpaceItem*)pEntry->pAttr );
+ sal_uLong nStart = aRegion.Start()->nNode.GetIndex();
+ sal_uLong nEnd = aRegion.End()->nNode.GetIndex();
+ for(; nStart <= nEnd; ++nStart)
+ {
+ SwNode* pNode = pDoc->GetNodes()[ nStart ];
+ if (!pNode || !pNode->IsTxtNode())
+ continue;
+
+ SwCntntNode* pNd = (SwCntntNode*)pNode;
+ SvxLRSpaceItem aOldLR = (const SvxLRSpaceItem&)
+ pNd->GetAttr(RES_LR_SPACE);
+
+ SwTxtNode *pTxtNode = (SwTxtNode*)pNode;
+
+ const SwNumFmt *pNum = 0;
+ pNum = GetNumFmtFromStack(*aRegion.GetPoint(),
+ *pTxtNode);
+ if (!pNum)
+ {
+ pNum = GetNumFmtFromTxtNode(*pTxtNode);
+ }
+
+ if ( pNum )
+ {
+ // #i103711#
+ const bool bFirstLineIndentSet =
+ ( rReader.maTxtNodesHavingFirstLineOfstSet.end() !=
+ rReader.maTxtNodesHavingFirstLineOfstSet.find( pNode ) );
+ // #i105414#
+ const bool bLeftIndentSet =
+ ( rReader.maTxtNodesHavingLeftIndentSet.end() !=
+ rReader.maTxtNodesHavingLeftIndentSet.find( pNode ) );
+ SyncIndentWithList( aNewLR, *pNum,
+ bFirstLineIndentSet,
+ bLeftIndentSet );
+ // <--
+ }
+
+ if (aNewLR == aOldLR)
+ continue;
+
+ pNd->SetAttr(aNewLR);
+
+ }
+ }
+ }
+ break;
+ case RES_TXTATR_FIELD:
+ OSL_ENSURE(!this, "What is a field doing in the control stack,"
+ "probably should have been in the endstack");
+ break;
+ case RES_TXTATR_INETFMT:
+ {
+ SwPaM aRegion(rTmpPos);
+ if (pEntry->MakeRegion(pDoc, aRegion, false))
+ {
+ SwFrmFmt *pFrm;
+ //If we have just one single inline graphic then
+ //don't insert a field for the single frame, set
+ //the frames hyperlink field attribute directly.
+ if (0 != (pFrm = rReader.ContainsSingleInlineGraphic(aRegion)))
+ {
+ const SwFmtINetFmt *pAttr = (const SwFmtINetFmt *)
+ pEntry->pAttr;
+ SwFmtURL aURL;
+ aURL.SetURL(pAttr->GetValue(), false);
+ aURL.SetTargetFrameName(pAttr->GetTargetFrame());
+ pFrm->SetFmtAttr(aURL);
+ }
+ else
+ {
+ pDoc->InsertPoolItem(aRegion, *pEntry->pAttr, 0);
+ }
+ }
+ }
+ break;
+ default:
+ SwFltControlStack::SetAttrInDoc(rTmpPos, pEntry);
+ break;
+ }
+}
+
+const SfxPoolItem* SwWW8FltControlStack::GetFmtAttr(const SwPosition& rPos,
+ sal_uInt16 nWhich)
+{
+ const SfxPoolItem *pItem = GetStackAttr(rPos, nWhich);
+ if (!pItem)
+ {
+ SwCntntNode const*const pNd = rPos.nNode.GetNode().GetCntntNode();
+ if (!pNd)
+ pItem = &pDoc->GetAttrPool().GetDefaultItem(nWhich);
+ else
+ {
+ /*
+ If we're hunting for the indent on a paragraph and need to use the
+ parent style indent, then return the indent in msword format, and
+ not writer format, because that's the style that the filter works
+ in (naturally)
+ */
+ if (nWhich == RES_LR_SPACE)
+ {
+ SfxItemState eState = SFX_ITEM_DEFAULT;
+ if (const SfxItemSet *pSet = pNd->GetpSwAttrSet())
+ eState = pSet->GetItemState(RES_LR_SPACE, false);
+ if (eState != SFX_ITEM_SET && rReader.pCollA != NULL)
+ pItem = &(rReader.pCollA[rReader.nAktColl].maWordLR);
+ }
+
+ /*
+ If we're hunting for a character property, try and exact position
+ within the text node for lookup
+ */
+ if (pNd->IsTxtNode())
+ {
+ xub_StrLen nPos = rPos.nContent.GetIndex();
+ SfxItemSet aSet(pDoc->GetAttrPool(), nWhich, nWhich);
+ if (static_cast<const SwTxtNode*>(pNd)->GetAttr(aSet, nPos, nPos))
+ pItem = aSet.GetItem(nWhich);
+ }
+
+ if (!pItem)
+ pItem = &pNd->GetAttr(nWhich);
+ }
+ }
+ return pItem;
+}
+
+const SfxPoolItem* SwWW8FltControlStack::GetStackAttr(const SwPosition& rPos,
+ sal_uInt16 nWhich)
+{
+ SwNodeIndex aNode( rPos.nNode, -1 );
+ sal_uInt16 nIdx = rPos.nContent.GetIndex();
+
+ sal_uInt16 nSize = static_cast< sal_uInt16 >(Count());
+ while (nSize)
+ {
+ const SwFltStackEntry* pEntry = (*this)[ --nSize ];
+ if (pEntry->pAttr->Which() == nWhich)
+ {
+ if ( (pEntry->bLocked) || (
+ (pEntry->nMkNode <= aNode) && (pEntry->nPtNode >= aNode) &&
+ (pEntry->nMkCntnt <= nIdx) && (pEntry->nPtCntnt > nIdx) ) )
+ /*
+ * e.g. half-open range [0-3) so asking for properties at 3
+ * means props that end at 3 are not included
+ */
+ {
+ return (const SfxPoolItem*)pEntry->pAttr;
+ }
+ }
+ }
+ return 0;
+}
+
+bool SwWW8FltRefStack::IsFtnEdnBkmField(const SwFmtFld& rFmtFld, sal_uInt16& rBkmNo)
+{
+ const SwField* pFld = rFmtFld.GetFld();
+ sal_uInt16 nSubType;
+ if(pFld && (RES_GETREFFLD == pFld->Which())
+ && ((REF_FOOTNOTE == (nSubType = pFld->GetSubType())) || (REF_ENDNOTE == nSubType))
+ && ((SwGetRefField*)pFld)->GetSetRefName().Len())
+ {
+ const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
+ IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark(
+ ((SwGetRefField*)pFld)->GetSetRefName());
+ if(ppBkmk != pMarkAccess->getMarksEnd())
+ {
+ // find Sequence No of corresponding Foot-/Endnote
+ rBkmNo = ppBkmk - pMarkAccess->getMarksBegin();
+ return true;
+ }
+ }
+ return false;
+}
+
+void SwWW8FltRefStack::SetAttrInDoc(const SwPosition& rTmpPos,
+ SwFltStackEntry* pEntry)
+{
+ switch( pEntry->pAttr->Which() )
+ {
+ /*
+ Look up these in our lists of bookmarks that were changed to
+ variables, and replace the ref field with a var field, otherwise
+ do normal (?) strange stuff
+ */
+ case RES_TXTATR_FIELD:
+ {
+ SwNodeIndex aIdx(pEntry->nMkNode, 1);
+ SwPaM aPaM(aIdx, pEntry->nMkCntnt);
+
+ SwFmtFld& rFmtFld = *(SwFmtFld*)pEntry->pAttr;
+ SwField* pFld = rFmtFld.GetFld();
+
+ // <NOT> got lost from revision 1.128 to 1.129
+ if (!RefToVar(pFld,pEntry))
+ {
+ sal_uInt16 nBkmNo;
+ if( IsFtnEdnBkmField(rFmtFld, nBkmNo) )
+ {
+ ::sw::mark::IMark const * const pMark = (pDoc->getIDocumentMarkAccess()->getMarksBegin() + nBkmNo)->get();
+
+ const SwPosition& rBkMrkPos = pMark->GetMarkPos();
+
+ SwTxtNode* pTxt = rBkMrkPos.nNode.GetNode().GetTxtNode();
+ if( pTxt && rBkMrkPos.nContent.GetIndex() )
+ {
+ SwTxtAttr* const pFtn = pTxt->GetTxtAttrForCharAt(
+ rBkMrkPos.nContent.GetIndex()-1, RES_TXTATR_FTN );
+ if( pFtn )
+ {
+ sal_uInt16 nRefNo = ((SwTxtFtn*)pFtn)->GetSeqRefNo();
+
+ ((SwGetRefField*)pFld)->SetSeqNo( nRefNo );
+
+ if( pFtn->GetFtn().IsEndNote() )
+ ((SwGetRefField*)pFld)->SetSubType(REF_ENDNOTE);
+ }
+ }
+ }
+ }
+
+ pDoc->InsertPoolItem(aPaM, *pEntry->pAttr, 0);
+ MoveAttrs(*aPaM.GetPoint());
+ }
+ break;
+ case RES_FLTR_TOX:
+ SwFltEndStack::SetAttrInDoc(rTmpPos, pEntry);
+ break;
+ default:
+ case RES_FLTR_BOOKMARK:
+ OSL_ENSURE(!this, "EndStck used with non field, not what we want");
+ SwFltEndStack::SetAttrInDoc(rTmpPos, pEntry);
+ break;
+ }
+}
+
+/*
+ For styles we will do our tabstop arithmetic in word style and adjust them to
+ writer style after all the styles have been finished and the dust settles as
+ to what affects what.
+
+ For explicit attributes we turn the adjusted writer tabstops back into 0 based
+ word indexes and we'll turn them back into writer indexes when setting them
+ into the document. If explicit left indent exist which affects them, then this
+ is handled when the explict left indent is set into the document
+*/
+void SwWW8ImplReader::Read_Tab(sal_uInt16 , const sal_uInt8* pData, short nLen)
+{
+ if (nLen < 0)
+ {
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_TABSTOP);
+ return;
+ }
+
+ short i;
+ const sal_uInt8* pDel = pData + 1; // Del - Array
+ sal_uInt8 nDel = pData[0];
+ const sal_uInt8* pIns = pData + 2*nDel + 2; // Ins - Array
+ sal_uInt8 nIns = pData[nDel*2+1];
+ WW8_TBD* pTyp = (WW8_TBD*)(pData + 2*nDel + 2*nIns + 2);// Typ - Array
+
+ SvxTabStopItem aAttr(0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP);
+
+ const SwTxtFmtColl* pSty = 0;
+ sal_uInt16 nTabBase;
+ if (pAktColl) // StyleDef
+ {
+ nTabBase = pCollA[nAktColl].nBase;
+ if (nTabBase < nColls) // Based On
+ pSty = (const SwTxtFmtColl*)pCollA[nTabBase].pFmt;
+ }
+ else
+ { // Text
+ nTabBase = nAktColl;
+ pSty = (const SwTxtFmtColl*)pCollA[nAktColl].pFmt;
+ }
+
+ bool bFound = false;
+ ::boost::unordered_set<size_t> aLoopWatch;
+ while (pSty && !bFound)
+ {
+ const SfxPoolItem* pTabs;
+ bFound = pSty->GetAttrSet().GetItemState(RES_PARATR_TABSTOP, false,
+ &pTabs) == SFX_ITEM_SET;
+ if( bFound )
+ aAttr = *((const SvxTabStopItem*)pTabs);
+ else
+ {
+
+ sal_uInt16 nOldTabBase = nTabBase;
+ // If based on another
+ if (nTabBase < nColls)
+ nTabBase = pCollA[nTabBase].nBase;
+
+ if (
+ nTabBase < nColls &&
+ nOldTabBase != nTabBase &&
+ nTabBase != ww::stiNil
+ )
+ {
+ // #i61789: Stop searching when next style is the same as the
+ // current one (prevent loop)
+ aLoopWatch.insert(reinterpret_cast<size_t>(pSty));
+ pSty = (const SwTxtFmtColl*)pCollA[nTabBase].pFmt;
+
+ if (aLoopWatch.find(reinterpret_cast<size_t>(pSty)) !=
+ aLoopWatch.end())
+ pSty = 0;
+ }
+ else
+ pSty = 0; // gib die Suche auf
+ }
+ }
+
+ SvxTabStop aTabStop;
+ for (i=0; i < nDel; ++i)
+ {
+ sal_uInt16 nPos = aAttr.GetPos(SVBT16ToShort(pDel + i*2));
+ if( nPos != SVX_TAB_NOTFOUND )
+ aAttr.Remove( nPos, 1 );
+ }
+
+ for (i=0; i < nIns; ++i)
+ {
+ short nPos = SVBT16ToShort(pIns + i*2);
+ aTabStop.GetTabPos() = nPos;
+ switch( SVBT8ToByte( pTyp[i].aBits1 ) & 0x7 ) // pTyp[i].jc
+ {
+ case 0:
+ aTabStop.GetAdjustment() = SVX_TAB_ADJUST_LEFT;
+ break;
+ case 1:
+ aTabStop.GetAdjustment() = SVX_TAB_ADJUST_CENTER;
+ break;
+ case 2:
+ aTabStop.GetAdjustment() = SVX_TAB_ADJUST_RIGHT;
+ break;
+ case 3:
+ aTabStop.GetAdjustment() = SVX_TAB_ADJUST_DECIMAL;
+ break;
+ case 4:
+ continue; // ignoriere Bar
+ }
+
+ switch( SVBT8ToByte( pTyp[i].aBits1 ) >> 3 & 0x7 )
+ {
+ case 0:
+ aTabStop.GetFill() = ' ';
+ break;
+ case 1:
+ aTabStop.GetFill() = '.';
+ break;
+ case 2:
+ aTabStop.GetFill() = '-';
+ break;
+ case 3:
+ case 4:
+ aTabStop.GetFill() = '_';
+ break;
+ }
+
+ sal_uInt16 nPos2 = aAttr.GetPos( nPos );
+ if (nPos2 != SVX_TAB_NOTFOUND)
+ aAttr.Remove(nPos2, 1); // sonst weigert sich das Insert()
+ aAttr.Insert(aTabStop);
+ }
+
+ if (nIns || nDel)
+ NewAttr(aAttr);
+ else
+ {
+ //Here we have a tab definition which inserts no extra tabs, or deletes
+ //no existing tabs. An older version of writer is probably the creater
+ //of the document :-( . So if we are importing a style we can just
+ //ignore it. But if we are importing into text we cannot as during
+ //text SwWW8ImplReader::Read_Tab is called at the begin and end of
+ //the range the attrib affects, and ignoring it would upset the
+ //balance
+ if (!pAktColl) //not importing into a style
+ {
+ using namespace sw::util;
+ SvxTabStopItem aOrig = pSty ?
+ ItemGet<SvxTabStopItem>(*pSty, RES_PARATR_TABSTOP) :
+ DefaultItemGet<SvxTabStopItem>(rDoc, RES_PARATR_TABSTOP);
+ NewAttr(aOrig);
+ }
+ }
+}
+
+//-----------------------------------------
+// DOP
+//-----------------------------------------
+
+void SwWW8ImplReader::ImportDop()
+{
+ maTracer.EnterEnvironment(sw::log::eDocumentProperties);
+ // correct the LastPrinted date in DocumentInfo
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocuProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocuProps.is(), "DocumentProperties is null");
+ if (xDocuProps.is())
+ {
+ DateTime aLastPrinted(
+ sw::ms::DTTM2DateTime(pWDop->dttmLastPrint));
+ ::util::DateTime uDT(aLastPrinted.Get100Sec(),
+ aLastPrinted.GetSec(), aLastPrinted.GetMin(),
+ aLastPrinted.GetHour(), aLastPrinted.GetDay(),
+ aLastPrinted.GetMonth(), aLastPrinted.GetYear());
+ xDocuProps->setPrintDate(uDT);
+ }
+
+ //
+ // COMPATIBILITY FLAGS START
+ //
+
+ // i#78951, remember the unknown compatability options
+ // so as to export them out
+ rDoc.Setn32DummyCompatabilityOptions1( pWDop->GetCompatabilityOptions());
+ rDoc.Setn32DummyCompatabilityOptions2( pWDop->GetCompatabilityOptions2());
+
+ // Abstand zwischen zwei Absaetzen ist die SUMME von unterem
+ // Abst. des ersten und oberem Abst. des zweiten
+ rDoc.set(IDocumentSettingAccess::PARA_SPACE_MAX, pWDop->fDontUseHTMLAutoSpacing);
+ rDoc.set(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES, true );
+ maTracer.Log(sw::log::eDontUseHTMLAutoSpacing);
+ // move tabs on alignment
+ rDoc.set(IDocumentSettingAccess::TAB_COMPAT, true);
+ // #i24363# tab stops relative to indent
+ rDoc.set(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT, false);
+ maTracer.Log(sw::log::eTabStopDistance);
+ // #i18732# - adjust default of option 'FollowTextFlow'
+ rDoc.SetDefault( SwFmtFollowTextFlow( sal_False ) );
+
+ // Import Default-Tabs
+ long nDefTabSiz = pWDop->dxaTab;
+ if( nDefTabSiz < 56 )
+ nDefTabSiz = 709;
+
+ // wir wollen genau einen DefaultTab
+ SvxTabStopItem aNewTab( 1, sal_uInt16(nDefTabSiz), SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
+ ((SvxTabStop&)aNewTab[0]).GetAdjustment() = SVX_TAB_ADJUST_DEFAULT;
+
+ rDoc.GetAttrPool().SetPoolDefaultItem( aNewTab );
+
+ if (!pWDop->fUsePrinterMetrics)
+ maTracer.Log(sw::log::ePrinterMetrics);
+
+ if (!pWDop->fNoLeading)
+ maTracer.Log(sw::log::eExtraLeading);
+
+ rDoc.set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, !pWDop->fUsePrinterMetrics);
+ rDoc.set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, true);
+ rDoc.set(IDocumentSettingAccess::ADD_FLY_OFFSETS, true );
+ rDoc.set(IDocumentSettingAccess::ADD_EXT_LEADING, !pWDop->fNoLeading);
+ rDoc.set(IDocumentSettingAccess::OLD_NUMBERING, false);
+ rDoc.set(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, false); // #i47448#
+ rDoc.set(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, !pWDop->fExpShRtn); // #i49277#, #i56856#
+ rDoc.set(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, false); // #i53199#
+ rDoc.set(IDocumentSettingAccess::OLD_LINE_SPACING, false);
+
+ // #i25901# - set new compatibility option
+ // 'Add paragraph and table spacing at bottom of table cells'
+ rDoc.set(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS, true);
+
+ // #i11860# - set new compatibility option
+ // 'Use former object positioning' to <sal_False>
+ rDoc.set(IDocumentSettingAccess::USE_FORMER_OBJECT_POS, false);
+
+ // #i27767# - set new compatibility option
+ // 'Conder Wrapping mode when positioning object' to <sal_True>
+ rDoc.set(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION, true);
+
+ rDoc.set(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING, false); // #i13832#, #i24135#
+
+ rDoc.set(IDocumentSettingAccess::TABLE_ROW_KEEP, true); //SetTableRowKeep( true );
+
+ rDoc.set(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, true); // #i3952#
+
+ rDoc.set(IDocumentSettingAccess::INVERT_BORDER_SPACING, true);
+ rDoc.set(IDocumentSettingAccess::COLLAPSE_EMPTY_CELL_PARA, true);
+
+ //
+ // COMPATIBILITY FLAGS END
+ //
+
+ if (!pWDop->fNoLeading)
+ maTracer.Log(sw::log::eExtraLeading);
+
+ //import magic doptypography information, if its there
+ if (pWwFib->nFib > 105)
+ ImportDopTypography(pWDop->doptypography);
+
+ // disable form design mode to be able to use imported controls directly
+ // #i31239# always disable form design mode, not only in protected docs
+ {
+ using namespace com::sun::star;
+
+ uno::Reference<lang::XComponent> xModelComp(mpDocShell->GetModel(),
+ uno::UNO_QUERY);
+ uno::Reference<beans::XPropertySet> xDocProps(xModelComp,
+ uno::UNO_QUERY);
+ if (xDocProps.is())
+ {
+ uno::Reference<beans::XPropertySetInfo> xInfo =
+ xDocProps->getPropertySetInfo();
+ sal_Bool bValue = false;
+ if (xInfo.is())
+ {
+ if (xInfo->hasPropertyByName(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ApplyFormDesignMode"))))
+ {
+ xDocProps->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ApplyFormDesignMode")),
+ cppu::bool2any(bValue));
+ }
+ }
+ }
+ }
+
+ mpDocShell->SetModifyPasswordHash(pWDop->lKeyProtDoc);
+
+ const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
+ sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
+ if (bUseEnhFields) {
+ rDoc.set(IDocumentSettingAccess::PROTECT_FORM, pWDop->fProtEnabled );
+ }
+
+ maTracer.LeaveEnvironment(sw::log::eDocumentProperties);
+}
+
+void SwWW8ImplReader::ImportDopTypography(const WW8DopTypography &rTypo)
+{
+ using namespace com::sun::star;
+ switch (rTypo.iLevelOfKinsoku)
+ {
+ case 2: //custom
+ {
+ i18n::ForbiddenCharacters aForbidden(rTypo.rgxchFPunct,
+ rTypo.rgxchLPunct);
+ rDoc.setForbiddenCharacters(rTypo.GetConvertedLang(),
+ aForbidden);
+ //Obviously cannot set the standard level 1 for japanese, so
+ //bail out now while we can.
+ if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESE)
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*
+ This MS hack means that level 2 of japanese is not in operation, so we put
+ in what we know are the MS defaults, there is a complementary reverse
+ hack in the writer. Its our default as well, but we can set it anyway
+ as a flag for later.
+ */
+ if (!rTypo.reserved2)
+ {
+ i18n::ForbiddenCharacters aForbidden(rTypo.GetJapanNotBeginLevel1(),
+ rTypo.GetJapanNotEndLevel1());
+ rDoc.setForbiddenCharacters(LANGUAGE_JAPANESE,aForbidden);
+ }
+
+ rDoc.set(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION, rTypo.fKerningPunct);
+ rDoc.setCharacterCompressionType(static_cast<SwCharCompressType>(rTypo.iJustification));
+}
+
+//-----------------------------------------
+// Fuss- und Endnoten
+
+//-----------------------------------------
+
+WW8ReaderSave::WW8ReaderSave(SwWW8ImplReader* pRdr ,WW8_CP nStartCp) :
+ maTmpPos(*pRdr->pPaM->GetPoint()),
+ mpOldStck(pRdr->pCtrlStck),
+ mpOldAnchorStck(pRdr->pAnchorStck),
+ mpOldRedlines(pRdr->mpRedlineStack),
+ mpOldPlcxMan(pRdr->pPlcxMan),
+ mpWFlyPara(pRdr->pWFlyPara),
+ mpSFlyPara(pRdr->pSFlyPara),
+ mpPreviousNumPaM(pRdr->pPreviousNumPaM),
+ mpPrevNumRule(pRdr->pPrevNumRule),
+ mpTableDesc(pRdr->pTableDesc),
+ mnInTable(pRdr->nInTable),
+ mnAktColl(pRdr->nAktColl),
+ mcSymbol(pRdr->cSymbol),
+ mbIgnoreText(pRdr->bIgnoreText),
+ mbSymbol(pRdr->bSymbol),
+ mbHdFtFtnEdn(pRdr->bHdFtFtnEdn),
+ mbTxbxFlySection(pRdr->bTxbxFlySection),
+ mbAnl(pRdr->bAnl),
+ mbInHyperlink(pRdr->bInHyperlink),
+ mbPgSecBreak(pRdr->bPgSecBreak),
+ mbWasParaEnd(pRdr->bWasParaEnd),
+ mbHasBorder(pRdr->bHasBorder),
+ mbFirstPara(pRdr->bFirstPara)
+{
+ pRdr->bSymbol = false;
+ pRdr->bHdFtFtnEdn = true;
+ pRdr->bTxbxFlySection = pRdr->bAnl = pRdr->bPgSecBreak = pRdr->bWasParaEnd
+ = pRdr->bHasBorder = false;
+ pRdr->bFirstPara = true;
+ pRdr->nInTable = 0;
+ pRdr->pWFlyPara = 0;
+ pRdr->pSFlyPara = 0;
+ pRdr->pPreviousNumPaM = 0;
+ pRdr->pPrevNumRule = 0;
+ pRdr->pTableDesc = 0;
+ pRdr->nAktColl = 0;
+
+
+ pRdr->pCtrlStck = new SwWW8FltControlStack(&pRdr->rDoc, pRdr->nFieldFlags,
+ *pRdr);
+
+ pRdr->mpRedlineStack = new sw::util::RedlineStack(pRdr->rDoc);
+
+ pRdr->pAnchorStck = new SwWW8FltAnchorStack(&pRdr->rDoc, pRdr->nFieldFlags);
+
+ // rette die Attributverwaltung: dies ist noetig, da der neu anzulegende
+ // PLCFx Manager natuerlich auf die gleichen FKPs zugreift, wie der alte
+ // und deren Start-End-Positionen veraendert...
+ if (pRdr->pPlcxMan)
+ pRdr->pPlcxMan->SaveAllPLCFx(maPLCFxSave);
+
+ if (nStartCp != -1)
+ {
+ pRdr->pPlcxMan = new WW8PLCFMan(pRdr->pSBase,
+ mpOldPlcxMan->GetManType(), nStartCp);
+ }
+
+ maOldApos.push_back(false);
+ maOldApos.swap(pRdr->maApos);
+ maOldFieldStack.swap(pRdr->maFieldStack);
+}
+
+void WW8ReaderSave::Restore( SwWW8ImplReader* pRdr )
+{
+ pRdr->pWFlyPara = mpWFlyPara;
+ pRdr->pSFlyPara = mpSFlyPara;
+ pRdr->pPreviousNumPaM = mpPreviousNumPaM;
+ pRdr->pPrevNumRule = mpPrevNumRule;
+ pRdr->pTableDesc = mpTableDesc;
+ pRdr->cSymbol = mcSymbol;
+ pRdr->bSymbol = mbSymbol;
+ pRdr->bIgnoreText = mbIgnoreText;
+ pRdr->bHdFtFtnEdn = mbHdFtFtnEdn;
+ pRdr->bTxbxFlySection = mbTxbxFlySection;
+ pRdr->nInTable = mnInTable;
+ pRdr->bAnl = mbAnl;
+ pRdr->bInHyperlink = mbInHyperlink;
+ pRdr->bWasParaEnd = mbWasParaEnd;
+ pRdr->bPgSecBreak = mbPgSecBreak;
+ pRdr->nAktColl = mnAktColl;
+ pRdr->bHasBorder = mbHasBorder;
+ pRdr->bFirstPara = mbFirstPara;
+
+ // schliesse alle Attribute, da sonst Attribute
+ // entstehen koennen, die aus dem Fly rausragen
+ pRdr->DeleteCtrlStk();
+ pRdr->pCtrlStck = mpOldStck;
+
+ pRdr->mpRedlineStack->closeall(*pRdr->pPaM->GetPoint());
+ delete pRdr->mpRedlineStack;
+ pRdr->mpRedlineStack = mpOldRedlines;
+
+ pRdr->DeleteAnchorStk();
+ pRdr->pAnchorStck = mpOldAnchorStck;
+
+ *pRdr->pPaM->GetPoint() = maTmpPos;
+
+ if (mpOldPlcxMan != pRdr->pPlcxMan)
+ {
+ delete pRdr->pPlcxMan;
+ pRdr->pPlcxMan = mpOldPlcxMan;
+ }
+ if (pRdr->pPlcxMan)
+ pRdr->pPlcxMan->RestoreAllPLCFx(maPLCFxSave);
+ pRdr->maApos.swap(maOldApos);
+ pRdr->maFieldStack.swap(maOldFieldStack);
+}
+
+void SwWW8ImplReader::Read_HdFtFtnText( const SwNodeIndex* pSttIdx,
+ long nStartCp, long nLen, ManTypes nType )
+{
+ // rettet Flags u.ae. u. setzt sie zurueck
+ WW8ReaderSave aSave( this );
+
+ pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1; //
+ pPaM->GetPoint()->nContent.Assign( pPaM->GetCntntNode(), 0 );
+
+ // dann Text fuer Header, Footer o. Footnote einlesen
+
+ ReadText( nStartCp, nLen, nType ); // Sepx dabei ignorieren
+ aSave.Restore( this );
+}
+
+//Use authornames, if not available fall back to initials.
+long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes)
+{
+ WW8PLCFx_SubDoc* pSD = pPlcxMan->GetAtn();
+ if( !pSD )
+ return 0;
+
+ String sAuthor;
+ if( bVer67 )
+ {
+ const WW67_ATRD* pDescri = (const WW67_ATRD*)pSD->GetData();
+ const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst));
+ if (pA)
+ sAuthor = *pA;
+ else
+ sAuthor = String(pDescri->xstUsrInitl + 1, pDescri->xstUsrInitl[0],
+ RTL_TEXTENCODING_MS_1252);
+ }
+ else
+ {
+ const WW8_ATRD* pDescri = (const WW8_ATRD*)pSD->GetData();
+
+ if (const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst)))
+ sAuthor = *pA;
+ else
+ {
+ sal_uInt16 nLen = SVBT16ToShort(pDescri->xstUsrInitl[0]);
+ for(sal_uInt16 nIdx = 1; nIdx <= nLen; ++nIdx)
+ sAuthor += SVBT16ToShort(pDescri->xstUsrInitl[nIdx]);
+ }
+ }
+
+ sal_uInt32 nDateTime = 0;
+
+ if (sal_uInt8 * pExtended = pPlcxMan->GetExtendedAtrds()) // Word < 2002 has no date data for comments
+ {
+ sal_uLong nIndex = pSD->GetIdx() & 0xFFFF; //Index is (stupidly) multiplexed for WW8PLCFx_SubDocs
+ if (pWwFib->lcbAtrdExtra/18 > nIndex)
+ nDateTime = SVBT32ToUInt32(*(SVBT32*)(pExtended+(nIndex*18)));
+ }
+
+ DateTime aDate = sw::ms::DTTM2DateTime(nDateTime);
+
+ String sTxt;
+ OutlinerParaObject *pOutliner = ImportAsOutliner( sTxt, pRes->nCp2OrIdx,
+ pRes->nCp2OrIdx + pRes->nMemLen, MAN_AND );
+
+ this->pFmtOfJustInsertedApo = 0;
+ SwPostItField aPostIt(
+ (SwPostItFieldType*)rDoc.GetSysFldType(RES_POSTITFLD), sAuthor,
+ sTxt, aDate );
+ aPostIt.SetTextObject(pOutliner);
+
+ pCtrlStck->NewAttr(*pPaM->GetPoint(), SvxCharHiddenItem(false, RES_CHRATR_HIDDEN));
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aPostIt), 0);
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_HIDDEN);
+
+ return 0;
+}
+
+void SwWW8ImplReader::Read_HdFtTextAsHackedFrame(long nStart, long nLen,
+ SwFrmFmt &rHdFtFmt, sal_uInt16 nPageWidth)
+{
+ const SwNodeIndex* pSttIdx = rHdFtFmt.GetCntnt().GetCntntIdx();
+ OSL_ENSURE(pSttIdx, "impossible");
+ if (!pSttIdx)
+ return;
+
+ SwPosition aTmpPos(*pPaM->GetPoint());
+
+ pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1;
+ pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(), 0);
+
+ SwFlyFrmFmt *pFrame = rDoc.MakeFlySection(FLY_AT_PARA, pPaM->GetPoint());
+
+ pFrame->SetFmtAttr(SwFmtFrmSize(ATT_MIN_SIZE, nPageWidth, MINLAY));
+ pFrame->SetFmtAttr(SwFmtSurround(SURROUND_THROUGHT));
+ pFrame->SetFmtAttr(SwFmtHoriOrient(0, text::HoriOrientation::RIGHT)); //iFOO
+ // #i43427# - send frame for header/footer into background.
+ pFrame->SetFmtAttr( SvxOpaqueItem( RES_OPAQUE, false ) );
+ SdrObject* pFrmObj = CreateContactObject( pFrame );
+ OSL_ENSURE( pFrmObj,
+ "<SwWW8ImplReader::Read_HdFtTextAsHackedFrame(..)> - missing SdrObject instance" );
+ if ( pFrmObj )
+ {
+ pFrmObj->SetOrdNum( 0L );
+ }
+ // <--
+ MoveInsideFly(pFrame);
+
+ const SwNodeIndex* pHackIdx = pFrame->GetCntnt().GetCntntIdx();
+
+ Read_HdFtFtnText(pHackIdx, nStart, nLen - 1, MAN_HDFT);
+
+ MoveOutsideFly(pFrame, aTmpPos);
+}
+
+void SwWW8ImplReader::Read_HdFtText(long nStart, long nLen, SwFrmFmt* pHdFtFmt)
+{
+ const SwNodeIndex* pSttIdx = pHdFtFmt->GetCntnt().GetCntntIdx();
+ if (!pSttIdx)
+ return;
+
+ SwPosition aTmpPos( *pPaM->GetPoint() ); // merke alte Cursorposition
+
+ Read_HdFtFtnText(pSttIdx, nStart, nLen - 1, MAN_HDFT);
+
+ *pPaM->GetPoint() = aTmpPos;
+}
+
+
+bool SwWW8ImplReader::isValid_HdFt_CP(WW8_CP nHeaderCP) const
+{
+ //each CP of Plcfhdd MUST be less than FibRgLw97.ccpHdd
+ return (nHeaderCP < pWwFib->ccpHdr) ? true : false;
+}
+
+bool SwWW8ImplReader::HasOwnHeaderFooter(sal_uInt8 nWhichItems, sal_uInt8 grpfIhdt,
+ int nSect)
+{
+ if (pHdFt)
+ {
+ WW8_CP start;
+ long nLen;
+ sal_uInt8 nNumber = 5;
+
+ for( sal_uInt8 nI = 0x20; nI; nI >>= 1, nNumber-- )
+ {
+ if (nI & nWhichItems)
+ {
+ bool bOk = true;
+ if( bVer67 )
+ bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 );
+ else
+ {
+ pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen);
+ bOk = ( 2 <= nLen ) && isValid_HdFt_CP(start);
+ }
+
+ if (bOk)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect,
+ const SwPageDesc *pPrev, const wwSection &rSection)
+{
+ sal_uInt8 nWhichItems = 0;
+ SwPageDesc *pPD = 0;
+ if (!bIsTitle)
+ {
+ nWhichItems =
+ rSection.maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST);
+ pPD = rSection.mpPage;
+ }
+ else
+ {
+ // Always read title page header/footer data - it could be used by following sections
+ nWhichItems = ( WW8_HEADER_FIRST | WW8_FOOTER_FIRST );
+
+ pPD = rSection.mpTitlePage;
+ }
+
+ sal_uInt8 grpfIhdt = rSection.maSep.grpfIhdt;
+
+
+ if( pHdFt )
+ {
+ WW8_CP start;
+ long nLen;
+ sal_uInt8 nNumber = 5;
+
+ for( sal_uInt8 nI = 0x20; nI; nI >>= 1, nNumber-- )
+ {
+ if (nI & nWhichItems)
+ {
+ bool bOk = true;
+ if( bVer67 )
+ bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 );
+ else
+ {
+ pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen);
+ bOk = ( 2 <= nLen ) && isValid_HdFt_CP(start);
+ }
+
+ bool bUseLeft
+ = (nI & ( WW8_HEADER_EVEN | WW8_FOOTER_EVEN )) ? true: false;
+ bool bFooter
+ = (nI & ( WW8_FOOTER_EVEN | WW8_FOOTER_ODD | WW8_FOOTER_FIRST )) ? true: false;
+
+ SwFrmFmt& rFmt = bUseLeft ? pPD->GetLeft() : pPD->GetMaster();
+
+ SwFrmFmt* pHdFtFmt;
+ if (bFooter)
+ {
+ bIsFooter = true;
+ //#i17196# Cannot have left without right
+ if (!pPD->GetMaster().GetFooter().GetFooterFmt())
+ pPD->GetMaster().SetFmtAttr(SwFmtFooter(true));
+ if (bUseLeft)
+ pPD->GetLeft().SetFmtAttr(SwFmtFooter(true));
+ pHdFtFmt = const_cast<SwFrmFmt*>(rFmt.GetFooter().GetFooterFmt());
+ }
+ else
+ {
+ bIsHeader = true;
+ //#i17196# Cannot have left without right
+ if (!pPD->GetMaster().GetHeader().GetHeaderFmt())
+ pPD->GetMaster().SetFmtAttr(SwFmtHeader(true));
+ if (bUseLeft)
+ pPD->GetLeft().SetFmtAttr(SwFmtHeader(true));
+ pHdFtFmt = const_cast<SwFrmFmt*>(rFmt.GetHeader().GetHeaderFmt());
+ }
+
+ if (bOk)
+ {
+ bool bHackRequired = false;
+ if (bIsHeader && rSection.IsFixedHeightHeader())
+ bHackRequired = true;
+ else if (bIsFooter && rSection.IsFixedHeightFooter())
+ bHackRequired = true;
+
+ if (bHackRequired)
+ {
+ Read_HdFtTextAsHackedFrame(start, nLen, *pHdFtFmt,
+ static_cast< sal_uInt16 >(rSection.GetTextAreaWidth()) );
+ }
+ else
+ Read_HdFtText(start, nLen, pHdFtFmt);
+ }
+ else if (!bOk && pPrev)
+ CopyPageDescHdFt(pPrev, pPD, nI);
+
+ bIsHeader = bIsFooter = false;
+ }
+ }
+ }
+ maTracer.LeaveEnvironment(sw::log::eDocumentProperties);
+}
+
+bool wwSectionManager::SectionIsProtected(const wwSection &rSection) const
+{
+ return (mrReader.pWwFib->fReadOnlyRecommended && !rSection.IsNotProtected());
+}
+
+void wwSectionManager::SetHdFt(wwSection &rSection, int nSect,
+ const wwSection *pPrevious)
+{
+ // Header / Footer nicht da
+ if (!rSection.maSep.grpfIhdt)
+ return;
+
+ OSL_ENSURE(rSection.mpPage, "makes no sense to call with a main page");
+ if (rSection.mpPage)
+ {
+ mrReader.Read_HdFt(false, nSect, pPrevious ? pPrevious->mpPage : 0,
+ rSection);
+ }
+
+ if (rSection.mpTitlePage)
+ {
+ // 2 Pagedescs noetig: 1.Seite und folgende
+ // 1. Seite einlesen
+ mrReader.Read_HdFt(true, nSect, pPrevious ? pPrevious->mpTitlePage : 0,
+ rSection);
+ }
+
+ // Kopf / Fuss - Index Updaten
+ // Damit der Index auch spaeter noch stimmt
+ if (mrReader.pHdFt)
+ mrReader.pHdFt->UpdateIndex(rSection.maSep.grpfIhdt);
+
+}
+
+class AttribHere : public std::unary_function<const xub_StrLen*, bool>
+{
+private:
+ xub_StrLen nPosition;
+public:
+ AttribHere(xub_StrLen nPos) : nPosition(nPos) {}
+ bool operator()(const xub_StrLen *pPosition) const
+ {
+ return (*pPosition >= nPosition);
+ }
+};
+
+void SwWW8ImplReader::AppendTxtNode(SwPosition& rPos)
+{
+ SwTxtNode* pTxt = pPaM->GetNode()->GetTxtNode();
+
+ const SwNumRule* pRule = NULL;
+
+ if (pTxt != NULL)
+ pRule = sw::util::GetNumRuleFromTxtNode(*pTxt);
+
+ if (
+ pRule && !pWDop->fDontUseHTMLAutoSpacing &&
+ (bParaAutoBefore || bParaAutoAfter)
+ )
+ {
+ // If after spacing is set to auto, set the after space to 0
+ if (bParaAutoAfter)
+ SetLowerSpacing(*pPaM, 0);
+
+ // If the previous textnode had numbering and
+ // and before spacing is set to auto, set before space to 0
+ if(pPrevNumRule && bParaAutoBefore)
+ SetUpperSpacing(*pPaM, 0);
+
+ // If the previous numbering rule was different we need
+ // to insert a space after the previous paragraph
+ if((pRule != pPrevNumRule) && pPreviousNumPaM)
+ SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
+
+ // cache current paragraph
+ if(pPreviousNumPaM)
+ delete pPreviousNumPaM, pPreviousNumPaM = 0;
+
+ pPreviousNumPaM = new SwPaM(*pPaM);
+ pPrevNumRule = pRule;
+ }
+ else if(!pRule && pPreviousNumPaM)
+ {
+ // If the previous paragraph has numbering but the current one does not
+ // we need to add a space after the previous paragraph
+ SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
+ delete pPreviousNumPaM, pPreviousNumPaM = 0;
+ pPrevNumRule = 0;
+ }
+ else
+ {
+ // clear paragraph cache
+ if(pPreviousNumPaM)
+ delete pPreviousNumPaM, pPreviousNumPaM = 0;
+ pPrevNumRule = pRule;
+ }
+
+ // If this is the first paragraph in the document and
+ // Auto-spacing before paragraph is set,
+ // set the upper spacing value to 0
+ if(bParaAutoBefore && bFirstPara && !pWDop->fDontUseHTMLAutoSpacing)
+ SetUpperSpacing(*pPaM, 0);
+
+ bFirstPara = false;
+
+ rDoc.AppendTxtNode(rPos);
+
+ //We can flush all anchored graphics at the end of a paragraph.
+ pAnchorStck->Flush();
+}
+
+bool SwWW8ImplReader::SetSpacing(SwPaM &rMyPam, int nSpace, bool bIsUpper )
+{
+ bool bRet = false;
+ const SwPosition* pSpacingPos = rMyPam.GetPoint();
+
+ const SvxULSpaceItem* pULSpaceItem = (const SvxULSpaceItem*)pCtrlStck->GetFmtAttr(*pSpacingPos, RES_UL_SPACE);
+
+ if(pULSpaceItem != 0)
+ {
+ SvxULSpaceItem aUL(*pULSpaceItem);
+
+ if(bIsUpper)
+ aUL.SetUpper( static_cast< sal_uInt16 >(nSpace) );
+ else
+ aUL.SetLower( static_cast< sal_uInt16 >(nSpace) );
+
+ xub_StrLen nEnd = pSpacingPos->nContent.GetIndex();
+ rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), 0);
+ pCtrlStck->NewAttr(*pSpacingPos, aUL);
+ rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), nEnd);
+ pCtrlStck->SetAttr(*pSpacingPos, RES_UL_SPACE);
+ bRet = true;
+ }
+ return bRet;
+}
+
+bool SwWW8ImplReader::SetLowerSpacing(SwPaM &rMyPam, int nSpace)
+{
+ return SetSpacing(rMyPam, nSpace, false);
+}
+
+bool SwWW8ImplReader::SetUpperSpacing(SwPaM &rMyPam, int nSpace)
+{
+ return SetSpacing(rMyPam, nSpace, true);
+}
+
+sal_uInt16 SwWW8ImplReader::TabRowSprm(int nLevel) const
+{
+ if (bVer67)
+ return 25;
+ return nLevel ? 0x244C : 0x2417;
+}
+
+void SwWW8ImplReader::EndSpecial()
+{
+ // Frame / Table / Anl
+ if (bAnl)
+ StopAllAnl(); // -> bAnl = false
+
+ while(maApos.size() > 1)
+ {
+ StopTable();
+ maApos.pop_back();
+ --nInTable;
+ if (maApos[nInTable] == true)
+ StopApo();
+ }
+
+ if (maApos[0] == true)
+ StopApo();
+
+ OSL_ENSURE(!nInTable, "unclosed table!");
+}
+
+bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync, WW8_CP nStartCp)
+{
+ // Frame / Table / Anl
+ if (bInHyperlink)
+ return false;
+
+ rbReSync = false;
+
+ OSL_ENSURE(nInTable >= 0,"nInTable < 0!");
+
+ // TabRowEnd
+ bool bTableRowEnd = (pPlcxMan->HasParaSprm(bVer67 ? 25 : 0x2417) != 0 );
+
+// es muss leider fuer jeden Absatz zuerst nachgesehen werden,
+// ob sich unter den sprms
+// das sprm 29 (bzw. 0x261B) befindet, das ein APO einleitet.
+// Alle weiteren sprms beziehen sich dann naemlich auf das APO und nicht
+// auf den normalen Text drumrum.
+// Dasselbe gilt fuer eine Tabelle ( sprm 24 (bzw. 0x2416) )
+// und Anls ( sprm 13 ).
+// WW: Tabelle in APO geht ( Beide Anfaende treten gleichzeitig auf )
+// WW: APO in Tabelle geht nicht
+// d.h. Wenn eine Tabelle Inhalt eines Apo ist, dann muss der
+// Apo-Anfang zuerst bearbeitet werden, damit die Tabelle im Apo steht
+// und nicht umgekehrt. Am Ende muss dagegen zuerst das Tabellenende
+// bearbeitet werden, da die Apo erst nach der Tabelle abgeschlossen
+// werden darf ( sonst wird das Apo-Ende nie gefunden ).
+// Dasselbe gilt fuer Fly / Anl, Tab / Anl, Fly / Tab / Anl.
+//
+// Wenn die Tabelle in einem Apo steht, fehlen im TabRowEnd-Bereich
+// die Apo-Angaben. Damit hier die Apo nicht beendet wird, wird
+// ProcessApo dann nicht aufgerufen.
+
+// KHZ: When there is a table inside the Apo the Apo-flags are also
+// missing for the 2nd, 3rd... paragraphs of each cell.
+
+
+// 1st look for in-table flag, for 2000+ there is a subtable flag to
+// be considered, the sprm 6649 gives the level of the table
+ sal_uInt8 nCellLevel = 0;
+
+ if (bVer67)
+ nCellLevel = 0 != pPlcxMan->HasParaSprm(24);
+ else
+ {
+ nCellLevel = 0 != pPlcxMan->HasParaSprm(0x2416);
+ if (!nCellLevel)
+ nCellLevel = 0 != pPlcxMan->HasParaSprm(0x244B);
+ }
+
+ WW8_TablePos *pTabPos=0;
+ WW8_TablePos aTabPos;
+ if (nCellLevel && !bVer67)
+ {
+ WW8PLCFxSave1 aSave;
+ pPlcxMan->GetPap()->Save( aSave );
+ rbReSync = true;
+ WW8PLCFx_Cp_FKP* pPap = pPlcxMan->GetPapPLCF();
+ WW8_CP nMyStartCp=nStartCp;
+
+ if (const sal_uInt8 *pLevel = pPlcxMan->HasParaSprm(0x6649))
+ nCellLevel = *pLevel;
+
+ bool bHasRowEnd = SearchRowEnd(pPap, nMyStartCp, nCellLevel-1);
+
+ //Bad Table, remain unchanged in level, e.g. #i19667#
+ if (!bHasRowEnd)
+ nCellLevel = static_cast< sal_uInt8 >(nInTable);
+
+ if (bHasRowEnd && ParseTabPos(&aTabPos,pPap))
+ pTabPos = &aTabPos;
+
+ pPlcxMan->GetPap()->Restore( aSave );
+ }
+
+// then look if we are in an Apo
+
+ ApoTestResults aApo = TestApo(nCellLevel, bTableRowEnd, pTabPos);
+
+ //look to see if we are in a Table, but Table in foot/end note not allowed
+ bool bStartTab = (nInTable < nCellLevel) && !bFtnEdn;
+
+ bool bStopTab = bWasTabRowEnd && (nInTable > nCellLevel) && !bFtnEdn;
+
+ bWasTabRowEnd = false; // must be deactivated right here to prevent next
+ // WW8TabDesc::TableCellEnd() from making nonsense
+
+ if (nInTable && !bTableRowEnd && !bStopTab && (nInTable == nCellLevel && aApo.HasStartStop()))
+ bStopTab = bStartTab = true; // Required to stop and start table
+
+// Dann auf Anl (Nummerierung) testen
+// und dann alle Ereignisse in der richtigen Reihenfolge bearbeiten
+
+ if( bAnl && !bTableRowEnd )
+ {
+ const sal_uInt8* pSprm13 = pPlcxMan->HasParaSprm( 13 );
+ if( pSprm13 )
+ { // Noch Anl ?
+ sal_uInt8 nT = static_cast< sal_uInt8 >(GetNumType( *pSprm13 ));
+ if( ( nT != WW8_Pause && nT != nWwNumType ) // Anl-Wechsel
+ || aApo.HasStartStop() // erzwungenes Anl-Ende
+ || bStopTab || bStartTab )
+ {
+ StopAnlToRestart(nT); // Anl-Restart ( = Wechsel ) ueber sprms
+ }
+ else
+ {
+ NextAnlLine( pSprm13 ); // naechste Anl-Zeile
+ }
+ }
+ else
+ { // Anl normal zuende
+ StopAllAnl(); // Wirkliches Ende
+ }
+ }
+ if (bStopTab)
+ {
+ StopTable();
+ maApos.pop_back();
+ --nInTable;
+ }
+ if (aApo.mbStopApo)
+ {
+ StopApo();
+ maApos[nInTable] = false;
+ }
+
+ if (aApo.mbStartApo)
+ {
+ maApos[nInTable] = StartApo(aApo, pTabPos);
+ // nach StartApo ist ein ReSync noetig ( eigentlich nur, falls die Apo
+ // ueber eine FKP-Grenze geht
+ rbReSync = true;
+ }
+ if (bStartTab)
+ {
+ WW8PLCFxSave1 aSave;
+ pPlcxMan->GetPap()->Save( aSave );
+
+ if (bAnl) // Nummerierung ueber Zellengrenzen
+ StopAllAnl(); // fuehrt zu Absturz -> keine Anls
+ // in Tabellen
+ while (nInTable < nCellLevel)
+ {
+ if (StartTable(nStartCp))
+ ++nInTable;
+ else
+ break;
+
+ maApos.push_back(false);
+ }
+ // nach StartTable ist ein ReSync noetig ( eigentlich nur, falls die
+ // Tabelle ueber eine FKP-Grenze geht
+ rbReSync = true;
+ pPlcxMan->GetPap()->Restore( aSave );
+ }
+ return bTableRowEnd;
+}
+
+CharSet SwWW8ImplReader::GetCurrentCharSet()
+{
+ /*
+ #i2015
+ If the hard charset is set use it, if not see if there is an open
+ character run that has set the charset, if not then fallback to the
+ current underlying paragraph style.
+ */
+ CharSet eSrcCharSet = eHardCharSet;
+ if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
+ {
+ if (!maFontSrcCharSets.empty())
+ eSrcCharSet = maFontSrcCharSets.top();
+ if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && (nCharFmt != -1))
+ eSrcCharSet = pCollA[nCharFmt].GetCharSet();
+ if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && StyleExists(nAktColl))
+ eSrcCharSet = pCollA[nAktColl].GetCharSet();
+ if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
+ { // patch from cmc for #i52786#
+ /*
+ #i22206#/#i52786#
+ The (default) character set used for a run of text is the default
+ character set for the version of Word that last saved the document.
+
+ This is a bit tentative, more might be required if the concept is correct.
+ When later version of word write older 6/95 documents the charset is
+ correctly set in the character runs involved, so its hard to reproduce
+ documents that require this to be sure of the process involved.
+ */
+ const SvxLanguageItem *pLang =
+ (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
+ if (pLang)
+ {
+ switch (pLang->GetLanguage())
+ {
+ case LANGUAGE_CZECH:
+ case LANGUAGE_HUNGARIAN:
+ case LANGUAGE_POLISH:
+ eSrcCharSet = RTL_TEXTENCODING_MS_1250;
+ break;
+ case LANGUAGE_RUSSIAN:
+ eSrcCharSet = RTL_TEXTENCODING_MS_1251;
+ break;
+ case LANGUAGE_GREEK:
+ eSrcCharSet = RTL_TEXTENCODING_MS_1253;
+ break;
+ case LANGUAGE_TURKISH:
+ eSrcCharSet = RTL_TEXTENCODING_MS_1254;
+ break;
+ default:
+ eSrcCharSet = RTL_TEXTENCODING_MS_1252;
+ break;
+ }
+ }
+ }
+ }
+ return eSrcCharSet;
+}
+
+//Takashi Ono for CJK
+CharSet SwWW8ImplReader::GetCurrentCJKCharSet()
+{
+ /*
+ #i2015
+ If the hard charset is set use it, if not see if there is an open
+ character run that has set the charset, if not then fallback to the
+ current underlying paragraph style.
+ */
+ CharSet eSrcCharSet = eHardCharSet;
+ if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
+ {
+ if (!maFontSrcCJKCharSets.empty())
+ eSrcCharSet = maFontSrcCJKCharSets.top();
+ if (pCollA != NULL)
+ {
+ if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && (nCharFmt != -1))
+ eSrcCharSet = pCollA[nCharFmt].GetCJKCharSet();
+ if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
+ eSrcCharSet = pCollA[nAktColl].GetCJKCharSet();
+ }
+ if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
+ { // patch from cmc for #i52786#
+ /*
+ #i22206#/#i52786#
+ The (default) character set used for a run of text is the default
+ character set for the version of Word that last saved the document.
+
+ This is a bit tentative, more might be required if the concept is correct.
+ When later version of word write older 6/95 documents the charset is
+ correctly set in the character runs involved, so its hard to reproduce
+ documents that require this to be sure of the process involved.
+ */
+ const SvxLanguageItem *pLang =
+ (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
+ if (pLang)
+ {
+ switch (pLang->GetLanguage())
+ {
+ case LANGUAGE_CZECH:
+ eSrcCharSet = RTL_TEXTENCODING_MS_1250;
+ break;
+ default:
+ eSrcCharSet = RTL_TEXTENCODING_MS_1252;
+ break;
+ }
+ }
+ }
+ }
+ return eSrcCharSet;
+}
+
+void SwWW8ImplReader::PostProcessAttrs()
+{
+ if (mpPostProcessAttrsInfo != NULL)
+ {
+ SfxItemIter aIter(mpPostProcessAttrsInfo->mItemSet);
+
+ const SfxPoolItem * pItem = aIter.GetCurItem();
+ if (pItem != NULL)
+ {
+ do
+ {
+ pCtrlStck->NewAttr(*mpPostProcessAttrsInfo->mPaM.GetPoint(),
+ *pItem);
+ pCtrlStck->SetAttr(*mpPostProcessAttrsInfo->mPaM.GetMark(),
+ pItem->Which(), true);
+ }
+ while (!aIter.IsAtEnd() && 0 != (pItem = aIter.NextItem()));
+ }
+
+ delete mpPostProcessAttrsInfo;
+ mpPostProcessAttrsInfo = NULL;
+ }
+}
+
+/*
+ #i9241#
+ It appears that some documents that are in a baltic 8 bit encoding which has
+ some undefined characters can have use made of those characters, in which
+ case they default to CP1252. If not then its perhaps that the font encoding
+ is only in use for 6/7 and for 8+ if we are in 8bit mode then the encoding
+ is always 1252.
+
+ So a encoding converter that on an undefined character attempts to
+ convert from 1252 on the undefined character
+*/
+sal_Size Custom8BitToUnicode(rtl_TextToUnicodeConverter hConverter,
+ sal_Char *pIn, sal_Size nInLen, sal_Unicode *pOut, sal_Size nOutLen)
+{
+ const sal_uInt32 nFlags =
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE |
+ RTL_TEXTTOUNICODE_FLAGS_FLUSH;
+
+ const sal_uInt32 nFlags2 =
+ RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE |
+ RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_IGNORE |
+ RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE |
+ RTL_TEXTTOUNICODE_FLAGS_FLUSH;
+
+ sal_Size nDestChars=0;
+ sal_Size nConverted=0;
+
+ do
+ {
+ sal_uInt32 nInfo = 0;
+ sal_Size nThisConverted=0;
+
+ nDestChars += rtl_convertTextToUnicode(hConverter, 0,
+ pIn+nConverted, nInLen-nConverted,
+ pOut+nDestChars, nOutLen-nDestChars,
+ nFlags, &nInfo, &nThisConverted);
+
+ OSL_ENSURE(nInfo == 0, "A character conversion failed!");
+
+ nConverted += nThisConverted;
+
+ if (
+ nInfo & RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR ||
+ nInfo & RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
+ )
+ {
+ sal_Size nOtherConverted;
+ rtl_TextToUnicodeConverter hCP1252Converter =
+ rtl_createTextToUnicodeConverter(RTL_TEXTENCODING_MS_1252);
+ nDestChars += rtl_convertTextToUnicode(hCP1252Converter, 0,
+ pIn+nConverted, 1,
+ pOut+nDestChars, nOutLen-nDestChars,
+ nFlags2, &nInfo, &nOtherConverted);
+ rtl_destroyTextToUnicodeConverter(hCP1252Converter);
+ nConverted+=1;
+ }
+ } while (nConverted < nInLen);
+
+ return nDestChars;
+}
+
+bool SwWW8ImplReader::LangUsesHindiNumbers(sal_uInt16 nLang)
+{
+ bool bResult = false;
+
+ switch (nLang)
+ {
+ case 0x1401: // Arabic(Algeria)
+ case 0x3c01: // Arabic(Bahrain)
+ case 0xc01: // Arabic(Egypt)
+ case 0x801: // Arabic(Iraq)
+ case 0x2c01: // Arabic (Jordan)
+ case 0x3401: // Arabic(Kuwait)
+ case 0x3001: // Arabic(Lebanon)
+ case 0x1001: // Arabic(Libya)
+ case 0x1801: // Arabic(Morocco)
+ case 0x2001: // Arabic(Oman)
+ case 0x4001: // Arabic(Qatar)
+ case 0x401: // Arabic(Saudi Arabia)
+ case 0x2801: // Arabic(Syria)
+ case 0x1c01: // Arabic(Tunisia)
+ case 0x3801: // Arabic(U.A.E)
+ case 0x2401: // Arabic(Yemen)
+ bResult = true;
+ break;
+ default:
+ break;
+ }
+
+ return bResult;
+}
+
+sal_Unicode SwWW8ImplReader::TranslateToHindiNumbers(sal_Unicode nChar)
+{
+ if (nChar >= 0x0030 && nChar <= 0x0039)
+ return nChar + 0x0630;
+
+ return nChar;
+}
+
+// Returnwert: true for no Sonderzeichen
+bool SwWW8ImplReader::ReadPlainChars(WW8_CP& rPos, long nEnd, long nCpOfs)
+{
+ // Unicode-Flag neu setzen und notfalls File-Pos korrigieren
+ // merke: Seek kostet nicht viel, da inline geprueft wird,
+ // ob die korrekte FilePos nicht schon erreicht ist.
+ WW8_FC nStreamPos = pSBase->WW8Cp2Fc(nCpOfs+rPos, &bIsUnicode);
+ pStrm->Seek( nStreamPos );
+
+ xub_StrLen nLen;
+ if (nEnd - rPos <= (STRING_MAXLEN-1))
+ nLen = writer_cast<xub_StrLen>(nEnd - rPos);
+ else
+ nLen = STRING_MAXLEN-1;
+ OSL_ENSURE(nLen, "String is 0");
+ if (!nLen)
+ return true;
+
+ const CharSet eSrcCharSet = bVer67 ? GetCurrentCharSet() :
+ RTL_TEXTENCODING_MS_1252;
+ const CharSet eSrcCJKCharSet = bVer67 ? GetCurrentCJKCharSet() :
+ RTL_TEXTENCODING_MS_1252;
+
+ // (re)alloc UniString data
+ String sPlainCharsBuf;
+
+ sal_Unicode* pBuffer = sPlainCharsBuf.AllocBuffer( nLen );
+ sal_Unicode* pWork = pBuffer;
+
+ sal_Char* p8Bits = NULL;
+
+ rtl_TextToUnicodeConverter hConverter = 0;
+ if (!bIsUnicode || bVer67)
+ hConverter = rtl_createTextToUnicodeConverter(eSrcCharSet);
+
+ if (!bIsUnicode)
+ p8Bits = new sal_Char[nLen];
+
+ // read the stream data
+ sal_uInt8 nBCode = 0;
+ sal_uInt16 nUCode;
+ xub_StrLen nL2;
+
+ sal_uInt16 nCTLLang = 0;
+ const SfxPoolItem * pItem = GetFmtAttr(RES_CHRATR_CTL_LANGUAGE);
+ if (pItem != NULL)
+ nCTLLang = dynamic_cast<const SvxLanguageItem *>(pItem)->GetLanguage();
+
+ for( nL2 = 0; nL2 < nLen; ++nL2, ++pWork )
+ {
+ if (bIsUnicode)
+ *pStrm >> nUCode; // unicode --> read 2 bytes
+ else
+ {
+ *pStrm >> nBCode; // old code --> read 1 byte
+ nUCode = nBCode;
+ }
+
+ if (pStrm->GetError())
+ {
+ rPos = WW8_CP_MAX-10; // -> eof or other error
+ sPlainCharsBuf.ReleaseBufferAccess( 0 );
+ delete [] p8Bits;
+ return true;
+ }
+
+ if ((32 > nUCode) || (0xa0 == nUCode))
+ {
+ pStrm->SeekRel( bIsUnicode ? -2 : -1 );
+ break; // Sonderzeichen < 32, == 0xa0 gefunden
+ }
+
+ if (bIsUnicode)
+ {
+ if (!bVer67)
+ *pWork = nUCode;
+ else
+ {
+ if (nUCode >= 0x3000) //0x8000 ?
+ {
+ sal_Char aTest[2];
+ aTest[0] = static_cast< sal_Char >((nUCode & 0xFF00) >> 8);
+ aTest[1] = static_cast< sal_Char >(nUCode & 0x00FF);
+ String aTemp(aTest, 2, eSrcCJKCharSet);
+ OSL_ENSURE(aTemp.Len() == 1, "so much for that theory");
+ *pWork = aTemp.GetChar(0);
+ }
+ else
+ {
+ sal_Char cTest = static_cast< sal_Char >(nUCode & 0x00FF);
+ Custom8BitToUnicode(hConverter, &cTest, 1, pWork, 1);
+ }
+ }
+ }
+ else
+ p8Bits[nL2] = nBCode;
+ }
+
+ if (nL2)
+ {
+ xub_StrLen nEndUsed = nL2;
+
+ if (!bIsUnicode)
+ nEndUsed = Custom8BitToUnicode(hConverter, p8Bits, nL2, pBuffer, nLen);
+
+ for( xub_StrLen nI = 0; nI < nLen; ++nI, ++pBuffer )
+ if (m_bRegardHindiDigits && bBidi && LangUsesHindiNumbers(nCTLLang))
+ *pBuffer = TranslateToHindiNumbers(*pBuffer);
+
+ sPlainCharsBuf.ReleaseBufferAccess( nEndUsed );
+
+ emulateMSWordAddTextToParagraph(sPlainCharsBuf);
+ rPos += nL2;
+ if (!maApos.back()) //a para end in apo doesn't count
+ bWasParaEnd = false; //kein CR
+ }
+
+ if (hConverter)
+ rtl_destroyTextToUnicodeConverter(hConverter);
+ delete [] p8Bits;
+ return nL2 >= nLen;
+}
+
+#define MSASCII SAL_MAX_INT16
+
+namespace
+{
+ //We want to force weak chars inside 0x0020 to 0x007F to LATIN
+ sal_Int16 lcl_getScriptType(
+ const uno::Reference<i18n::XBreakIterator>& rBI,
+ const rtl::OUString &rString, sal_Int32 nPos)
+ {
+ sal_Int16 nScript = rBI->getScriptType(rString, nPos);
+ if (nScript == i18n::ScriptType::WEAK && rString[nPos] >= 0x0020 && rString[nPos] <= 0x007F)
+ nScript = MSASCII;
+ return nScript;
+ }
+
+ //We want to know about WEAK segments, so endOfScript isn't
+ //useful, and see lcl_getScriptType anyway
+ sal_Int32 lcl_endOfScript(
+ const uno::Reference<i18n::XBreakIterator>& rBI,
+ const rtl::OUString &rString, sal_Int32 nPos, sal_Int16 nScript)
+ {
+ while (nPos < rString.getLength())
+ {
+ sal_Int16 nNewScript = lcl_getScriptType(rBI, rString, nPos);
+ if (nScript != nNewScript)
+ break;
+ ++nPos;
+ }
+ return nPos;
+ }
+}
+
+//In writer we categorize text into CJK, CTL and "Western" for everything else.
+//Microsoft Word basically categorizes text into East Asian, Complex, ASCII,
+//NonEastAsian/HighAnsi, with some shared characters and some properties to to
+//hint as to which way to bias those shared characters.
+//
+//That's four categories, we however have three categories. Given that problem
+//here we would ideally find out "what would word do" to see what font/language
+//word would assign to characters based on the unicode range they fall into and
+//hack the word one onto the range we use. However it's unclear what word's
+//categorization is. So we don't do that here yet.
+//
+//Additional to the categorization, when word encounters weak text for ambigious
+//chars it uses idcthint to indicate which way to bias. We don't have a idcthint
+//feature in writer.
+//
+//So what we currently do here then is to split our text into non-weak/weak
+//sections and uses word's idcthint to determine what font it would use and
+//force that on for the segment. Following what we *do* know about word's
+//categorization, we know that the range 0x0020 and 0x007F is sprmCRgFtc0 in
+//word, something we map to LATIN, so we consider all weaks chars in that range
+//to auto-bias to LATIN.
+//
+//See https://bugs.freedesktop.org/show_bug.cgi?id=34319 for an example
+void SwWW8ImplReader::emulateMSWordAddTextToParagraph(const rtl::OUString& rAddString)
+{
+ if (!rAddString.getLength())
+ return;
+
+ uno::Reference<i18n::XBreakIterator> xBI(pBreakIt->GetBreakIter());
+ if (!xBI.is())
+ {
+ simpleAddTextToParagraph(rAddString);
+ return;
+ }
+
+ sal_Int16 nScript = lcl_getScriptType(xBI, rAddString, 0);
+ sal_Int32 nLen = rAddString.getLength();
+
+ sal_Int32 nPos = 0;
+ while (nPos < nLen)
+ {
+ sal_Int32 nEnd = lcl_endOfScript(xBI, rAddString, nPos, nScript);
+ if (nEnd < 0)
+ break;
+
+ rtl::OUString sChunk(rAddString.copy(nPos, nEnd-nPos));
+ const sal_uInt16 aIds[] = {RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_FONT};
+ bool aForced[] = {false, false, false};
+
+ int nLclIdctHint = 0xFF;
+ if (nScript == i18n::ScriptType::WEAK)
+ nLclIdctHint = nIdctHint;
+ else if (nScript == MSASCII) //Force weak chars in ascii range to use LATIN font
+ nLclIdctHint = 0;
+
+ if (nLclIdctHint != 0xFF)
+ {
+ sal_uInt16 nForceFromFontId = 0;
+ switch (nLclIdctHint)
+ {
+ case 0:
+ nForceFromFontId = RES_CHRATR_FONT;
+ break;
+ case 1:
+ nForceFromFontId = RES_CHRATR_CJK_FONT;
+ break;
+ case 2:
+ nForceFromFontId = RES_CHRATR_CTL_FONT;
+ break;
+ default:
+ break;
+ }
+
+ const SvxFontItem *pSourceFont = (const SvxFontItem*)GetFmtAttr(nForceFromFontId);
+
+ for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i)
+ {
+ const SvxFontItem *pDestFont = (const SvxFontItem*)GetFmtAttr(aIds[i]);
+ aForced[i] = aIds[i] != nForceFromFontId && *pSourceFont != *pDestFont;
+ if (aForced[i])
+ {
+ SvxFontItem aForceFont(*pSourceFont);
+ aForceFont.SetWhich(aIds[i]);
+ pCtrlStck->NewAttr(*pPaM->GetPoint(), aForceFont);
+ }
+ }
+ }
+
+ simpleAddTextToParagraph(sChunk);
+
+ for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i)
+ {
+ if (aForced[i])
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), aIds[i]);
+ }
+
+ nPos = nEnd;
+ if (nPos < nLen)
+ nScript = lcl_getScriptType(xBI, rAddString, nPos);
+ }
+
+}
+
+void SwWW8ImplReader::simpleAddTextToParagraph(const String& rAddString)
+{
+ if (!rAddString.Len())
+ return;
+
+#ifdef DEBUG
+ {
+ rtl::OString sText(rtl::OUStringToOString(rAddString, RTL_TEXTENCODING_UTF8));
+ ::std::clog <<
+ "<addTextToParagraph>" << sText.getStr() << "</addTextToParagraph>"
+ << ::std::endl;
+ }
+#endif
+ const SwTxtNode* pNd = pPaM->GetCntntNode()->GetTxtNode();
+
+ if ((pNd->GetTxt().Len() + rAddString.Len()) < STRING_MAXLEN-1)
+ {
+ rDoc.InsertString(*pPaM, rAddString);
+ }
+ else
+ {
+
+ if (pNd->GetTxt().Len()< STRING_MAXLEN -1)
+ {
+ String sTempStr (rAddString,0,
+ STRING_MAXLEN - pNd->GetTxt().Len() -1);
+ rDoc.InsertString(*pPaM, sTempStr);
+ sTempStr = rAddString.Copy(sTempStr.Len(),
+ rAddString.Len() - sTempStr.Len());
+ AppendTxtNode(*pPaM->GetPoint());
+ rDoc.InsertString(*pPaM, sTempStr);
+ }
+ else
+ {
+ AppendTxtNode(*pPaM->GetPoint());
+ rDoc.InsertString(*pPaM, rAddString);
+ }
+ }
+
+ bReadTable = false;
+}
+
+// Returnwert: true for para end
+bool SwWW8ImplReader::ReadChars(WW8_CP& rPos, WW8_CP nNextAttr, long nTextEnd,
+ long nCpOfs)
+{
+ long nEnd = ( nNextAttr < nTextEnd ) ? nNextAttr : nTextEnd;
+
+ if (bSymbol || bIgnoreText)
+ {
+ if( bSymbol ) // Spezialzeichen einfuegen
+ {
+ for(sal_uInt16 nCh = 0; nCh < nEnd - rPos; ++nCh)
+ {
+ rDoc.InsertString( *pPaM, cSymbol );
+ }
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_FONT );
+ }
+ pStrm->SeekRel( nEnd- rPos );
+ rPos = nEnd; // ignoriere bis Attributende
+ return false;
+ }
+
+ while (true)
+ {
+ if (ReadPlainChars(rPos, nEnd, nCpOfs))
+ return false; // Fertig
+
+ bool bStartLine = ReadChar(rPos, nCpOfs);
+ rPos++;
+ if (bPgSecBreak || bStartLine || rPos == nEnd) // CR oder Fertig
+ {
+ return bStartLine;
+ }
+ }
+}
+
+bool SwWW8ImplReader::HandlePageBreakChar()
+{
+ bool bParaEndAdded = false;
+ //#i1909# section/page breaks should not occur in tables, word
+ //itself ignores them in this case.
+ if (!nInTable)
+ {
+ //xushanchuan add for issue106569
+ sal_Bool IsTemp=sal_True;
+ SwTxtNode* pTemp = pPaM->GetNode()->GetTxtNode();
+ if ( pTemp && !( pTemp->GetTxt().Len() ) && ( bFirstPara || bFirstParaOfPage ) )
+ {
+ IsTemp = sal_False;
+ AppendTxtNode(*pPaM->GetPoint());
+ pTemp->SetAttr(*GetDfltAttr(RES_PARATR_NUMRULE));
+ }
+ //xushanchuan end
+ bPgSecBreak = true;
+ pCtrlStck->KillUnlockedAttrs(*pPaM->GetPoint());
+ /*
+ If its a 0x0c without a paragraph end before it, act like a
+ paragraph end, but nevertheless, numbering (and perhaps other
+ similiar constructs) do not exist on the para.
+ */
+ //xushanchuan add for issue106569
+ if (!bWasParaEnd && IsTemp)
+ //xushanchuan end
+ {
+ bParaEndAdded = true;
+ if (0 >= pPaM->GetPoint()->nContent.GetIndex())
+ {
+ if (SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode())
+ {
+ pTxtNode->SetAttr(
+ *GetDfltAttr(RES_PARATR_NUMRULE));
+ }
+ }
+ }
+ }
+ return bParaEndAdded;
+}
+
+bool SwWW8ImplReader::ReadChar(long nPosCp, long nCpOfs)
+{
+ bool bNewParaEnd = false;
+ // Unicode-Flag neu setzen und notfalls File-Pos korrigieren
+ // merke: Seek kostet nicht viel, da inline geprueft wird,
+ // ob die korrekte FilePos nicht schon erreicht ist.
+ pStrm->Seek( pSBase->WW8Cp2Fc(nCpOfs+nPosCp, &bIsUnicode) );
+
+ sal_uInt8 nBCode;
+ sal_uInt16 nWCharVal;
+ if( bIsUnicode )
+ *pStrm >> nWCharVal; // unicode --> read 2 bytes
+ else
+ {
+ *pStrm >> nBCode; // old code --> read 1 byte
+ nWCharVal = nBCode;
+ }
+
+ sal_Char cInsert = '\x0';
+ bool bRet = false;
+ //xushanchuan add for issue106569
+ if ( 0xc != nWCharVal )
+ bFirstParaOfPage = false;
+ //xushanchuan end
+ switch (nWCharVal)
+ {
+ case 0:
+ {
+ // Seitennummer
+ SwPageNumberField aFld(
+ (SwPageNumberFieldType*)rDoc.GetSysFldType(
+ RES_PAGENUMBERFLD ), PG_RANDOM, SVX_NUM_ARABIC);
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
+ }
+ break;
+ case 0xe:
+ // if there is only one column word treats a column break like a pagebreak.
+ if (maSectionManager.CurrentSectionColCount() < 2)
+ bRet = HandlePageBreakChar();
+ else if (!nInTable)
+ {
+ // Always insert a txtnode for a column break, e.g. ##
+ SwCntntNode *pCntNd=pPaM->GetCntntNode();
+ if (pCntNd!=NULL && pCntNd->Len()>0) // if par is empty not break is needed
+ AppendTxtNode(*pPaM->GetPoint());
+ rDoc.InsertPoolItem(*pPaM, SvxFmtBreakItem(SVX_BREAK_COLUMN_BEFORE, RES_BREAK), 0);
+ }
+ break;
+ case 0x7:
+ bNewParaEnd = true;
+ TabCellEnd(); // table cell end (Flags abfragen!)
+ break;
+ case 0xf:
+ if( !bSpec ) // "Satellit"
+ cInsert = '\xa4';
+ break;
+ case 0x14:
+ if( !bSpec ) // "Para-Ende"-Zeichen
+ cInsert = '\xb5';
+ break;
+ case 0x15:
+ if( !bSpec ) // Juristenparagraph
+ cInsert = '\xa7';
+ break;
+ case 0x9:
+ cInsert = '\x9'; // Tab
+ break;
+ case 0xb:
+ cInsert = '\xa'; // Hard NewLine
+ break;
+ case 0xc:
+ bRet = HandlePageBreakChar();
+ break;
+ case 0x1e: // Non-breaking hyphen
+ rDoc.InsertString( *pPaM, CHAR_HARDHYPHEN );
+ break;
+ case 0x1f: // Non-required hyphens
+ rDoc.InsertString( *pPaM, CHAR_SOFTHYPHEN );
+ break;
+ case 0xa0: // Non-breaking spaces
+ rDoc.InsertString( *pPaM, CHAR_HARDBLANK );
+ break;
+ case 0x1:
+ /*
+ Current thinking is that if bObj is set then we have a
+ straightforward "traditional" ole object, otherwise we have a
+ graphic preview of an associated ole2 object (or a simple
+ graphic of course)
+ */
+ if (!IsInlineEscherHack())
+ {
+ SwFrmFmt *pResult = 0;
+ if (bObj)
+ pResult = ImportOle();
+ else if (bSpec)
+ pResult = ImportGraf();
+
+ // If we have a bad 0x1 insert a space instead.
+ if (!pResult)
+ {
+ cInsert = ' ';
+ OSL_ENSURE(!bObj && !bEmbeddObj && !nObjLocFc,
+ "WW8: Please report this document, it may have a "
+ "missing graphic");
+ }
+ else
+ {
+ // reset the flags.
+ bObj = bEmbeddObj = false;
+ nObjLocFc = 0;
+ }
+ }
+ break;
+ case 0x8:
+ if( !bObj )
+ Read_GrafLayer( nPosCp );
+ break;
+ case 0xd:
+ bNewParaEnd = bRet = true;
+ if (nInTable > 1)
+ {
+ /*
+ #i9666#/#i23161#
+ Yes complex, if there is an entry in the undocumented PLCF
+ which I believe to be a record of cell and row boundaries
+ see if the magic bit which I believe to mean cell end is
+ set. I also think btw that the third byte of the 4 byte
+ value is the level of the cell
+ */
+ WW8PLCFspecial* pTest = pPlcxMan->GetMagicTables();
+ if (pTest && pTest->SeekPosExact(nPosCp+1+nCpOfs) &&
+ pTest->Where() == nPosCp+1+nCpOfs)
+ {
+ WW8_FC nPos;
+ void *pData;
+ pTest->Get(nPos, pData);
+ sal_uInt32 nData = SVBT32ToUInt32(*(SVBT32*)pData);
+ if (nData & 0x2) //Might be how it works
+ {
+ TabCellEnd();
+ bRet = false;
+ }
+ }
+ else if (bWasTabCellEnd)
+ {
+ TabCellEnd();
+ bRet = false;
+ }
+ }
+
+ bWasTabCellEnd = false;
+
+ break; // line end
+ case 0x5: // Annotation reference
+ case 0x13:
+ break;
+ case 0x2:
+ if (!maFtnStack.empty())
+ cInsert = 0x2;
+ break; // Auto-Fussnoten-Nummer
+#if OSL_DEBUG_LEVEL > 1
+ default:
+ ::std::clog << "<unknownValue val=\"" << nWCharVal << "\">" << ::std::endl;
+ break;
+#endif
+ }
+
+ if( '\x0' != cInsert )
+ {
+ String sInsert = ByteString::ConvertToUnicode(cInsert,
+ RTL_TEXTENCODING_MS_1252 );
+ emulateMSWordAddTextToParagraph(sInsert);
+ }
+ if (!maApos.back()) //a para end in apo doesn't count
+ bWasParaEnd = bNewParaEnd;
+ return bRet;
+}
+
+void SwWW8ImplReader::ProcessAktCollChange(WW8PLCFManResult& rRes,
+ bool* pStartAttr, bool bCallProcessSpecial)
+{
+ sal_uInt16 nOldColl = nAktColl;
+ nAktColl = pPlcxMan->GetColl();
+
+ // Invalid Style-Id
+ if (nAktColl >= nColls || !pCollA[nAktColl].pFmt || !pCollA[nAktColl].bColl)
+ {
+ nAktColl = 0;
+ bParaAutoBefore = false;
+ bParaAutoAfter = false;
+ }
+ else
+ {
+ bParaAutoBefore = pCollA[nAktColl].bParaAutoBefore;
+ bParaAutoAfter = pCollA[nAktColl].bParaAutoAfter;
+ }
+
+ bool bTabRowEnd = false;
+ if( pStartAttr && bCallProcessSpecial && !bInHyperlink )
+ {
+ bool bReSync;
+ // Frame / Table / Autonumbering List Level
+ bTabRowEnd = ProcessSpecial(bReSync, rRes.nAktCp+pPlcxMan->GetCpOfs());
+ if( bReSync )
+ *pStartAttr = pPlcxMan->Get( &rRes ); // hole Attribut-Pos neu
+ }
+
+ if (!bTabRowEnd && StyleExists(nAktColl))
+ {
+ SetTxtFmtCollAndListLevel( *pPaM, pCollA[ nAktColl ]);
+ ChkToggleAttr(pCollA[ nOldColl ].n81Flags, pCollA[ nAktColl ].n81Flags);
+ ChkToggleBiDiAttr(pCollA[nOldColl].n81BiDiFlags,
+ pCollA[nAktColl].n81BiDiFlags);
+ }
+}
+
+long SwWW8ImplReader::ReadTextAttr(WW8_CP& rTxtPos, bool& rbStartLine)
+{
+ long nSkipChars = 0;
+ WW8PLCFManResult aRes;
+
+ OSL_ENSURE(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
+ bool bStartAttr = pPlcxMan->Get(&aRes); // hole Attribut-Pos
+ aRes.nAktCp = rTxtPos; // Akt. Cp-Pos
+
+ bool bNewSection = (aRes.nFlags & MAN_MASK_NEW_SEP) && !bIgnoreText;
+ if ( bNewSection ) // neue Section
+ {
+ OSL_ENSURE(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
+ // PageDesc erzeugen und fuellen
+ maSectionManager.CreateSep(rTxtPos, bPgSecBreak);
+ // -> 0xc war ein Sectionbreak, aber
+ // kein Pagebreak;
+ bPgSecBreak = false; // PageDesc erzeugen und fuellen
+ OSL_ENSURE(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
+ }
+
+ // neuer Absatz ueber Plcx.Fkp.papx
+ if ( (aRes.nFlags & MAN_MASK_NEW_PAP)|| rbStartLine )
+ {
+ ProcessAktCollChange( aRes, &bStartAttr,
+ MAN_MASK_NEW_PAP == (aRes.nFlags & MAN_MASK_NEW_PAP) &&
+ !bIgnoreText );
+ rbStartLine = false;
+ }
+
+ // position of last CP that's to be ignored
+ long nSkipPos = -1;
+
+ if( 0 < aRes.nSprmId ) // leere Attrs ignorieren
+ {
+ if( ( eFTN > aRes.nSprmId ) || ( 0x0800 <= aRes.nSprmId ) )
+ {
+ if( bStartAttr ) // WW-Attribute
+ {
+ if( aRes.nMemLen >= 0 )
+ ImportSprm(aRes.pMemPos, aRes.nSprmId);
+ }
+ else
+ EndSprm( aRes.nSprmId ); // Attr ausschalten
+ }
+ else if( aRes.nSprmId < 0x800 ) // eigene Hilfs-Attribute
+ {
+ if (bStartAttr)
+ {
+ nSkipChars = ImportExtSprm(&aRes);
+ if (
+ (aRes.nSprmId == eFTN) || (aRes.nSprmId == eEDN) ||
+ (aRes.nSprmId == eFLD) || (aRes.nSprmId == eAND)
+ )
+ {
+ // Felder/Ftn-/End-Note hier ueberlesen
+ rTxtPos += nSkipChars;
+ nSkipPos = rTxtPos-1;
+ }
+ }
+ else
+ EndExtSprm( aRes.nSprmId );
+ }
+ }
+
+ pStrm->Seek(pSBase->WW8Cp2Fc( pPlcxMan->GetCpOfs() + rTxtPos, &bIsUnicode));
+
+ // Find next Attr position (and Skip attributes of field contents if needed)
+ if (nSkipChars && !bIgnoreText)
+ pCtrlStck->MarkAllAttrsOld();
+ bool bOldIgnoreText = bIgnoreText;
+ bIgnoreText = true;
+ sal_uInt16 nOldColl = nAktColl;
+ bool bDoPlcxManPlusPLus = true;
+ long nNext;
+ do
+ {
+ if( bDoPlcxManPlusPLus )
+ (*pPlcxMan)++;
+ nNext = pPlcxMan->Where();
+
+ if (mpPostProcessAttrsInfo &&
+ mpPostProcessAttrsInfo->mnCpStart == nNext)
+ {
+ mpPostProcessAttrsInfo->mbCopy = true;
+ }
+
+ if( (0 <= nNext) && (nSkipPos >= nNext) )
+ {
+ nNext = ReadTextAttr( rTxtPos, rbStartLine );
+ bDoPlcxManPlusPLus = false;
+ bIgnoreText = true;
+ }
+
+ if (mpPostProcessAttrsInfo &&
+ nNext > mpPostProcessAttrsInfo->mnCpEnd)
+ {
+ mpPostProcessAttrsInfo->mbCopy = false;
+ }
+ }
+ while( nSkipPos >= nNext );
+ bIgnoreText = bOldIgnoreText;
+ if( nSkipChars )
+ {
+ pCtrlStck->KillUnlockedAttrs( *pPaM->GetPoint() );
+ if( nOldColl != pPlcxMan->GetColl() )
+ ProcessAktCollChange(aRes, 0, false);
+ }
+
+ return nNext;
+}
+
+void SwWW8ImplReader::ReadAttrs(WW8_CP& rNext, WW8_CP& rTxtPos, bool& rbStartLine)
+{
+ if( rTxtPos >= rNext )
+ { // Stehen Attribute an ?
+
+ do
+ {
+ rNext = ReadTextAttr( rTxtPos, rbStartLine );
+ }
+ while( rTxtPos >= rNext );
+
+ }
+ else if ( rbStartLine )
+ {
+// keine Attribute, aber trotzdem neue Zeile
+// wenn eine Zeile mit einem Seitenumbruch aufhoert und sich keine
+// Absatzattribute / Absatzvorlagen aendern, ist das Zeilenende
+// nicht im Plcx.Fkp.papx eingetragen, d.h. ( nFlags & MAN_MASK_NEW_PAP )
+// ist false. Deshalb muss als Sonderbehandlung hier die Vorlage gesetzt
+// werden.
+ if (!bCpxStyle && nAktColl < nColls)
+ SetTxtFmtCollAndListLevel(*pPaM, pCollA[nAktColl]);
+ rbStartLine = false;
+ }
+}
+
+// CloseAttrEnds zum Lesen nur der Attributenden am Ende eines Textes oder
+// Textbereiches ( Kopfzeile, Fussnote, ...). Attributanfaenge, Felder
+// werden ignoriert.
+void SwWW8ImplReader::CloseAttrEnds()
+{
+ //If there are any unclosed sprms then copy them to
+ //another stack and close the ones that must be closed
+ std::stack<sal_uInt16> aStack;
+ pPlcxMan->TransferOpenSprms(aStack);
+
+ while (!aStack.empty())
+ {
+ sal_uInt16 nSprmId = aStack.top();
+ if ((0 < nSprmId) && (( eFTN > nSprmId) || (0x0800 <= nSprmId)))
+ EndSprm(nSprmId);
+ aStack.pop();
+ }
+
+ EndSpecial();
+}
+
+bool SwWW8ImplReader::ReadText(long nStartCp, long nTextLen, ManTypes nType)
+{
+ sw::log::Environment eContext = sw::log::eMainText;
+ if (nType == MAN_MAINTEXT)
+ eContext = sw::log::eMainText;
+ else
+ eContext = sw::log::eSubDoc;
+ maTracer.EnterEnvironment(eContext);
+
+ bool bJoined=false;
+
+ bool bStartLine = true;
+ short nCrCount = 0;
+ short nDistance = 0;
+
+ bWasParaEnd = false;
+ nAktColl = 0;
+ pAktItemSet = 0;
+ nCharFmt = -1;
+ bSpec = false;
+ bPgSecBreak = false;
+
+ pPlcxMan = new WW8PLCFMan( pSBase, nType, nStartCp );
+ long nCpOfs = pPlcxMan->GetCpOfs(); // Offset fuer Header/Footer, Footnote
+
+ WW8_CP nNext = pPlcxMan->Where();
+ SwTxtNode* pPreviousNode = 0;
+ sal_uInt8 nDropLines = 0;
+ SwCharFmt* pNewSwCharFmt = 0;
+ const SwCharFmt* pFmt = 0;
+ pStrm->Seek( pSBase->WW8Cp2Fc( nStartCp + nCpOfs, &bIsUnicode ) );
+
+ WW8_CP l = nStartCp;
+ while ( l<nStartCp+nTextLen )
+ {
+ ReadAttrs( nNext, l, bStartLine );// behandelt auch Section-Breaks
+ OSL_ENSURE(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
+
+ if (mpPostProcessAttrsInfo != NULL)
+ PostProcessAttrs();
+
+ if( l>= nStartCp + nTextLen )
+ break;
+
+ bStartLine = ReadChars(l, nNext, nStartCp+nTextLen, nCpOfs);
+
+ // If the previous paragraph was a dropcap then do not
+ // create a new txtnode and join the two paragraphs together
+
+ if (bStartLine && !pPreviousNode) // Zeilenende
+ AppendTxtNode(*pPaM->GetPoint());
+
+ if (pPreviousNode && bStartLine)
+ {
+ SwTxtNode* pEndNd = pPaM->GetNode()->GetTxtNode();
+ const xub_StrLen nDropCapLen = pPreviousNode->GetTxt().Len();
+
+ // Need to reset the font size and text position for the dropcap
+ {
+ SwPaM aTmp(*pEndNd, 0, *pEndNd, nDropCapLen+1);
+ pCtrlStck->Delete(aTmp);
+ }
+
+ // Get the default document dropcap which we can use as our template
+ const SwFmtDrop* defaultDrop =
+ (const SwFmtDrop*) GetFmtAttr(RES_PARATR_DROP);
+ SwFmtDrop aDrop(*defaultDrop);
+
+ aDrop.GetLines() = nDropLines;
+ aDrop.GetDistance() = nDistance;
+ aDrop.GetChars() = writer_cast<sal_uInt8>(nDropCapLen);
+ // Word has no concept of a "whole word dropcap"
+ aDrop.GetWholeWord() = false;
+
+ if (pFmt)
+ aDrop.SetCharFmt(const_cast<SwCharFmt*>(pFmt));
+ else if(pNewSwCharFmt)
+ aDrop.SetCharFmt(const_cast<SwCharFmt*>(pNewSwCharFmt));
+
+ SwPosition aStart(*pEndNd);
+ pCtrlStck->NewAttr(aStart, aDrop);
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_DROP);
+ pPreviousNode = 0;
+ }
+ else if (bDropCap)
+ {
+ // If we have found a dropcap store the textnode
+ pPreviousNode = pPaM->GetNode()->GetTxtNode();
+
+ const sal_uInt8 *pDCS;
+
+ if (bVer67)
+ pDCS = pPlcxMan->GetPapPLCF()->HasSprm(46);
+ else
+ pDCS = pPlcxMan->GetPapPLCF()->HasSprm(0x442C);
+
+ if (pDCS)
+ nDropLines = (*pDCS) >> 3;
+ else // There is no Drop Cap Specifier hence no dropcap
+ pPreviousNode = 0;
+
+ if (const sal_uInt8 *pDistance = pPlcxMan->GetPapPLCF()->HasSprm(0x842F))
+ nDistance = SVBT16ToShort( pDistance );
+ else
+ nDistance = 0;
+
+ const SwFmtCharFmt *pSwFmtCharFmt = 0;
+
+ if(pAktItemSet)
+ pSwFmtCharFmt = &(ItemGet<SwFmtCharFmt>(*pAktItemSet, RES_TXTATR_CHARFMT));
+
+ if(pSwFmtCharFmt)
+ pFmt = pSwFmtCharFmt->GetCharFmt();
+
+ if(pAktItemSet && !pFmt)
+ {
+ String sPrefix(CREATE_CONST_ASC( "WW8Dropcap"));
+ sPrefix += String::CreateFromInt32( nDropCap++ );
+ pNewSwCharFmt = rDoc.MakeCharFmt(sPrefix, (SwCharFmt*)rDoc.GetDfltCharFmt());
+ pAktItemSet->ClearItem(RES_CHRATR_ESCAPEMENT);
+ pNewSwCharFmt->SetFmtAttr( *pAktItemSet );
+ }
+
+ delete pAktItemSet;
+ pAktItemSet = 0;
+ bDropCap=false;
+ }
+
+ if (bStartLine || bWasTabRowEnd)
+ {
+ // alle 64 CRs aufrufen not for Header u. ae.
+ if ((nCrCount++ & 0x40) == 0 && nType == MAN_MAINTEXT)
+ {
+ nProgress = (sal_uInt16)( l * 100 / nTextLen );
+ ::SetProgressState(nProgress, mpDocShell); // Update
+ }
+ }
+
+ // If we have encountered a 0x0c which indicates either section of
+ // pagebreak then look it up to see if it is a section break, and
+ // if it is not then insert a page break. If it is a section break
+ // it will be handled as such in the ReadAttrs of the next loop
+ if (bPgSecBreak)
+ {
+ // We need only to see if a section is ending at this cp,
+ // the plcf will already be sitting on the correct location
+ // if it is there.
+ WW8PLCFxDesc aTemp;
+ aTemp.nStartPos = aTemp.nEndPos = WW8_CP_MAX;
+ if (pPlcxMan->GetSepPLCF())
+ pPlcxMan->GetSepPLCF()->GetSprms(&aTemp);
+ if ((aTemp.nStartPos != l) && (aTemp.nEndPos != l))
+ {
+ // #i39251# - insert text node for page break, if no one inserted.
+ // #i43118# - refine condition: the anchor
+ // control stack has to have entries, otherwise it's not needed
+ // to insert a text node.
+ if ( !bStartLine && pAnchorStck->Count() > 0 )
+ {
+ AppendTxtNode(*pPaM->GetPoint());
+ }
+ // <--
+ rDoc.InsertPoolItem(*pPaM,
+ SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK), 0);
+ bFirstParaOfPage = true;//xushanchuan add for issue106569
+ bPgSecBreak = false;
+ }
+ }
+ }
+
+ if (pPaM->GetPoint()->nContent.GetIndex())
+ AppendTxtNode(*pPaM->GetPoint());
+
+ if (!bInHyperlink)
+ bJoined = JoinNode(*pPaM);
+
+ CloseAttrEnds();
+
+ delete pPlcxMan, pPlcxMan = 0;
+ maTracer.LeaveEnvironment(eContext);
+ return bJoined;
+}
+
+/***************************************************************************
+# class SwWW8ImplReader
+#**************************************************************************/
+
+SwWW8ImplReader::SwWW8ImplReader(sal_uInt8 nVersionPara, SvStorage* pStorage,
+ SvStream* pSt, SwDoc& rD, const String& rBaseURL, bool bNewDoc) :
+ mpDocShell(rD.GetDocShell()),
+ maTracer(*(mpDocShell->GetMedium())),
+ pStg(pStorage),
+ pStrm(pSt),
+ pTableStream(0),
+ pDataStream(0),
+ rDoc(rD),
+ maSectionManager(*this),
+ maInsertedTables(rD),
+ maSectionNameGenerator(rD,CREATE_CONST_ASC("WW")),
+ maGrfNameGenerator(bNewDoc,String('G')),
+ maParaStyleMapper(rD),
+ maCharStyleMapper(rD),
+ maTxtNodesHavingFirstLineOfstSet(), // #i103711#
+ maTxtNodesHavingLeftIndentSet(), // #i105414#
+ pMSDffManager(0),
+ mpAtnNames(0),
+ pAuthorInfos(0),
+ sBaseURL(rBaseURL),
+ m_bRegardHindiDigits( false ),
+ mbNewDoc(bNewDoc),
+ nDropCap(0),
+ nIdctHint(0),
+ bBidi(false),
+ bReadTable(false)
+{
+ pStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ nWantedVersion = nVersionPara;
+ pCtrlStck = 0;
+ mpRedlineStack = 0;
+ pReffedStck = 0;
+ pReffingStck = 0;
+ pAnchorStck = 0;
+ pFonts = 0;
+ pSBase = 0;
+ pPlcxMan = 0;
+ pStyles = 0;
+ pAktColl = 0;
+ pLstManager = 0;
+ pAktItemSet = 0;
+ pCollA = 0;
+ pDfltTxtFmtColl = 0;
+ pStandardFmtColl = 0;
+ pHdFt = 0;
+ pWFlyPara = 0;
+ pSFlyPara = 0;
+ pFlyFmtOfJustInsertedGraphic = 0;
+ pFmtOfJustInsertedApo = 0;
+ pPreviousNumPaM = 0;
+ pPrevNumRule = 0;
+ nColls = nAktColl = 0;
+ nObjLocFc = nPicLocFc = 0;
+ nInTable=0;
+ bReadNoTbl = bPgSecBreak = bSpec = bObj = bTxbxFlySection
+ = bHasBorder = bSymbol = bIgnoreText
+ = bWasTabRowEnd = bWasTabCellEnd = false;
+ bShdTxtCol = bCharShdTxtCol = bAnl = bHdFtFtnEdn = bFtnEdn
+ = bIsHeader = bIsFooter = bIsUnicode = bCpxStyle = bStyNormal =
+ bWWBugNormal = false;
+
+ mpPostProcessAttrsInfo = 0;
+
+ bNoAttrImport = bPgChpLevel = bEmbeddObj = false;
+ bAktAND_fNumberAcross = false;
+ bNoLnNumYet = true;
+ bInHyperlink = false;
+ bWasParaEnd = false;
+ bDropCap = false;
+ bFirstPara = true;
+ bFirstParaOfPage = false;//xushanchuan add for issue106569
+ bParaAutoBefore = false;
+ bParaAutoAfter = false;
+ nProgress = 0;
+ nSwNumLevel = nWwNumType = 0xff;
+ pTableDesc = 0;
+ pNumOlst = 0;
+ pNode_FLY_AT_PARA = 0;
+ pDrawModel = 0;
+ pDrawPg = 0;
+ mpDrawEditEngine = 0;
+ pWWZOrder = 0;
+ pFormImpl = 0;
+ mpChosenOutlineNumRule = 0;
+ pNumFldType = 0;
+ nFldNum = 0;
+
+ nLFOPosition = USHRT_MAX;
+ nListLevel = WW8ListManager::nMaxLevel;
+ eHardCharSet = RTL_TEXTENCODING_DONTKNOW;
+
+ nPgChpDelim = nPgChpLevel = 0;
+
+ maApos.push_back(false);
+}
+
+void SwWW8ImplReader::DeleteStk(SwFltControlStack* pStck)
+{
+ if( pStck )
+ {
+ pStck->SetAttr( *pPaM->GetPoint(), 0, false);
+ pStck->SetAttr( *pPaM->GetPoint(), 0, false);
+ delete pStck;
+ }
+ else
+ {
+ OSL_ENSURE( !this, "WW-Stack bereits geloescht" );
+ }
+}
+
+void wwSectionManager::SetSegmentToPageDesc(const wwSection &rSection,
+ bool bTitlePage, bool bIgnoreCols)
+{
+ SwPageDesc &rPage = bTitlePage ? *rSection.mpTitlePage : *rSection.mpPage;
+
+ SetNumberingType(rSection, rPage);
+
+ SwFrmFmt &rFmt = rPage.GetMaster();
+
+ if (mrReader.pWDop->fUseBackGroundInAllmodes && mrReader.pMSDffManager)
+ {
+ Rectangle aRect(0, 0, 100, 100); //A dummy, we don't care about the size
+ SvxMSDffImportData aData(aRect);
+ SdrObject* pObject = 0;
+ if (mrReader.pMSDffManager->GetShape(0x401, pObject, aData))
+ {
+ SvxMSDffImportRec * pRec = aData.GetRecord(0);
+
+ // Only handle shape if it is a background shape
+ if ((pRec->nFlags & 0x400) != 0)
+ {
+ SfxItemSet aSet(rFmt.GetAttrSet());
+ mrReader.MatchSdrItemsIntoFlySet(pObject, aSet, mso_lineSimple,
+ mso_lineSolid, mso_sptRectangle, aRect);
+ rFmt.SetFmtAttr(aSet.Get(RES_BACKGROUND));
+ }
+ }
+ }
+ wwULSpaceData aULData;
+ GetPageULData(rSection, bTitlePage, aULData);
+ SetPageULSpaceItems(rFmt, aULData, rSection);
+
+ SetPage(rPage, rFmt, rSection, bIgnoreCols);
+
+ bool bSetBorder = false;
+ switch (rSection.maSep.pgbApplyTo)
+ {
+ case 0:
+ case 3:
+ bSetBorder = true;
+ break;
+ case 1:
+ bSetBorder = bTitlePage;
+ break;
+ case 2:
+ bSetBorder = !bTitlePage;
+ break;
+ }
+ if (bSetBorder)
+ mrReader.SetPageBorder(rFmt, rSection);
+
+ mrReader.SetDocumentGrid(rFmt, rSection);
+}
+
+void wwSectionManager::SetUseOn(wwSection &rSection)
+{
+ bool bEven = (rSection.maSep.grpfIhdt & (WW8_HEADER_EVEN|WW8_FOOTER_EVEN)) ?
+ true : false;
+
+ bool bMirror = mrReader.pWDop->fMirrorMargins ||
+ mrReader.pWDop->doptypography.f2on1;
+
+ UseOnPage eUseBase = bMirror ? nsUseOnPage::PD_MIRROR : nsUseOnPage::PD_ALL;
+ UseOnPage eUse = eUseBase;
+ if (!bEven)
+ eUse = (UseOnPage)(eUse | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE);
+
+ OSL_ENSURE(rSection.mpPage, "Makes no sense to call me with no pages to set");
+ if (rSection.mpPage)
+ rSection.mpPage->WriteUseOn(eUse);
+ if (rSection.mpTitlePage)
+ {
+ rSection.mpTitlePage->WriteUseOn(
+ (UseOnPage) (eUseBase | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE));
+ }
+}
+
+//Set the page descriptor on this node, handle the different cases for a text
+//node or a table
+void GiveNodePageDesc(SwNodeIndex &rIdx, const SwFmtPageDesc &rPgDesc,
+ SwDoc &rDoc)
+{
+ /*
+ If its a table here, apply the pagebreak to the table
+ properties, otherwise we add it to the para at this
+ position
+ */
+ if (rIdx.GetNode().IsTableNode())
+ {
+ SwTable& rTable =
+ rIdx.GetNode().GetTableNode()->GetTable();
+ SwFrmFmt* pApply = rTable.GetFrmFmt();
+ OSL_ENSURE(pApply, "impossible");
+ if (pApply)
+ pApply->SetFmtAttr(rPgDesc);
+ }
+ else
+ {
+ SwPosition aPamStart(rIdx);
+ aPamStart.nContent.Assign(
+ rIdx.GetNode().GetCntntNode(), 0);
+ SwPaM aPage(aPamStart);
+
+ rDoc.InsertPoolItem(aPage, rPgDesc, 0);
+ }
+}
+
+//Map a word section with to either one or two writer page descriptors
+//depending on if the word section has a title page
+SwFmtPageDesc wwSectionManager::SetSwFmtPageDesc(mySegIter &rIter,
+ mySegIter &rStart, bool bIgnoreCols)
+{
+ SwFmtPageDesc aEmpty;
+ // Always read title page header/footer data - it could be used by following sections
+ {
+ if (IsNewDoc() && rIter == rStart)
+ {
+ rIter->mpTitlePage =
+ mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_FIRST);
+ }
+ else
+ {
+ sal_uInt16 nPos = mrReader.rDoc.MakePageDesc(
+ ViewShell::GetShellRes()->GetPageDescName(mnDesc, ShellResource::FIRST_PAGE)
+ , 0, false);
+ rIter->mpTitlePage = &mrReader.rDoc._GetPageDesc(nPos);
+ }
+ OSL_ENSURE(rIter->mpTitlePage, "no page!");
+ if (!rIter->mpTitlePage)
+ return aEmpty;
+
+ SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
+ }
+
+ if (IsNewDoc() && rIter == rStart)
+ {
+ rIter->mpPage =
+ mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_STANDARD);
+ }
+ else
+ {
+ sal_uInt16 nPos = mrReader.rDoc.MakePageDesc(
+ ViewShell::GetShellRes()->GetPageDescName(mnDesc, ShellResource::NORMAL_PAGE),
+ rIter->mpTitlePage, false);
+ rIter->mpPage = &mrReader.rDoc._GetPageDesc(nPos);
+ }
+ OSL_ENSURE(rIter->mpPage, "no page!");
+ if (!rIter->mpPage)
+ return aEmpty;
+
+ //Set page before hd/ft
+ const wwSection *pPrevious = 0;
+ if (rIter != rStart)
+ pPrevious = &(*(rIter-1));
+ SetHdFt(*rIter, std::distance(rStart, rIter), pPrevious);
+ SetUseOn(*rIter);
+
+ //Set hd/ft after set page
+ if (rIter->mpTitlePage)
+ SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
+ SetSegmentToPageDesc(*rIter, false, bIgnoreCols);
+
+ SwFmtPageDesc aRet(rIter->HasTitlePage() ?
+ rIter->mpTitlePage : rIter->mpPage);
+
+ rIter->mpPage->SetFollow(rIter->mpPage);
+
+ if (rIter->mpTitlePage)
+ rIter->mpTitlePage->SetFollow(rIter->mpPage);
+
+ if (rIter->PageRestartNo())
+ aRet.SetNumOffset(rIter->PageStartAt());
+
+ ++mnDesc;
+ return aRet;
+}
+
+bool wwSectionManager::IsNewDoc() const
+{
+ return mrReader.mbNewDoc;
+}
+
+void wwSectionManager::InsertSegments()
+{
+ const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
+ sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
+ mySegIter aEnd = maSegments.end();
+ mySegIter aStart = maSegments.begin();
+ for (mySegIter aIter = aStart; aIter != aEnd; ++aIter)
+ {
+ // If the section is of type "New column" (0x01), then simply insert a column break
+ if ( aIter->maSep.bkc == 1 )
+ {
+ SwPaM start( aIter->maStart );
+ mrReader.rDoc.InsertPoolItem( start, SvxFmtBreakItem(SVX_BREAK_COLUMN_BEFORE, RES_BREAK), 0);
+ continue;
+ }
+
+ mySegIter aNext = aIter+1;
+ mySegIter aPrev = (aIter == aStart) ? aIter : aIter-1;
+
+ // If two following sections are different in following properties, Word will interprete a continuous
+ // section break between them as if it was a section break next page.
+ bool bThisAndPreviousAreCompatible = ((aIter->GetPageWidth() == aPrev->GetPageWidth()) &&
+ (aIter->GetPageHeight() == aPrev->GetPageHeight()) && (aIter->IsLandScape() == aPrev->IsLandScape()));
+
+ bool bInsertSection = (aIter != aStart) ? (aIter->IsContinous() && bThisAndPreviousAreCompatible): false;
+ bool bInsertPageDesc = !bInsertSection;
+ bool bProtected = SectionIsProtected(*aIter); // do we really need this ?? I guess I have a different logic in editshell which disales this...
+ if (bUseEnhFields && mrReader.pWDop->fProtEnabled && aIter->IsNotProtected())
+ {
+ // here we have the special case that the whole document is protected, with the execption of this section.
+ // I want to address this when I do the section rework, so for the moment we disable the overall protection then...
+ mrReader.rDoc.set(IDocumentSettingAccess::PROTECT_FORM, false );
+ }
+
+
+ if (bInsertPageDesc)
+ {
+ /*
+ If a cont section follows this section then we won't be
+ creating a page desc with 2+ cols as we cannot host a one
+ col section in a 2+ col pagedesc and make it look like
+ word. But if the current section actually has columns then
+ we are forced to insert a section here as well as a page
+ descriptor.
+ */
+
+ bool bIgnoreCols = false;
+ bool bThisAndNextAreCompatible = (aNext != aEnd) ? ((aIter->GetPageWidth() == aNext->GetPageWidth()) &&
+ (aIter->GetPageHeight() == aNext->GetPageHeight()) && (aIter->IsLandScape() == aNext->IsLandScape())) : true;
+
+ if (((aNext != aEnd && aNext->IsContinous() && bThisAndNextAreCompatible) || bProtected))
+ {
+ bIgnoreCols = true;
+ if ((aIter->NoCols() > 1) || bProtected)
+ bInsertSection = true;
+ }
+
+ SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, bIgnoreCols));
+ if (!aDesc.GetPageDesc())
+ continue;
+
+ // special case handling for odd/even section break
+ // a) as before create a new page style for the section break
+ // b) set Layout of generated page style to right/left ( according
+ // to section break odd/even )
+ // c) create a new style to follow the break page style
+ if ( aIter->maSep.bkc == 3 || aIter->maSep.bkc == 4 )
+ {
+ // SetSwFmtPageDesc calls some methods that could
+ // modify aIter (e.g. wwSection ).
+ // Since we call SetSwFmtPageDesc below to generate the
+ // 'Following' style of the Break style, it is safer
+ // to take a copy of the contents of aIter.
+ wwSection aTmpSection = *aIter;
+ // create a new following page style
+ SwFmtPageDesc aFollow(SetSwFmtPageDesc(aIter, aStart, bIgnoreCols));
+ // restore any contents of aIter trashed by SetSwFmtPageDesc
+ *aIter = aTmpSection;
+
+ // Handle the section break
+ UseOnPage eUseOnPage = nsUseOnPage::PD_LEFT;
+ if ( aIter->maSep.bkc == 4 ) // Odd ( right ) Section break
+ eUseOnPage = nsUseOnPage::PD_RIGHT;
+
+ aDesc.GetPageDesc()->WriteUseOn( eUseOnPage );
+ aDesc.GetPageDesc()->SetFollow( aFollow.GetPageDesc() );
+ }
+
+ GiveNodePageDesc(aIter->maStart, aDesc, mrReader.rDoc);
+ }
+
+ SwTxtNode* pTxtNd = 0;
+ if (bInsertSection)
+ {
+ //Start getting the bounds of this section
+ SwPaM aSectPaM(*mrReader.pPaM);
+ SwNodeIndex aAnchor(aSectPaM.GetPoint()->nNode);
+ if (aNext != aEnd)
+ {
+ aAnchor = aNext->maStart;
+ aSectPaM.GetPoint()->nNode = aAnchor;
+ aSectPaM.GetPoint()->nContent.Assign(
+ aNext->maStart.GetNode().GetCntntNode(), 0);
+ aSectPaM.Move(fnMoveBackward);
+ }
+
+ const SwPosition* pPos = aSectPaM.GetPoint();
+ SwTxtNode const*const pSttNd = pPos->nNode.GetNode().GetTxtNode();
+ const SwTableNode* pTableNd = pSttNd ? pSttNd->FindTableNode() : 0;
+ if (pTableNd)
+ {
+ pTxtNd =
+ mrReader.rDoc.GetNodes().MakeTxtNode(aAnchor,
+ mrReader.rDoc.GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
+
+ aSectPaM.GetPoint()->nNode = SwNodeIndex(*pTxtNd);
+ aSectPaM.GetPoint()->nContent.Assign(
+ aSectPaM.GetCntntNode(), 0);
+ }
+
+ aSectPaM.SetMark();
+
+ aSectPaM.GetPoint()->nNode = aIter->maStart;
+ aSectPaM.GetPoint()->nContent.Assign(
+ aSectPaM.GetCntntNode(), 0);
+ //End getting the bounds of this section, quite a job eh ?
+
+ SwSectionFmt *pRet = InsertSection(aSectPaM, *aIter);
+ //The last section if continous is always unbalanced
+ if (pRet)
+ {
+ //Set the columns to be UnBalanced if that compatability option
+ //is set
+ if (mrReader.pWDop->fNoColumnBalance)
+ pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
+ else
+ {
+ //Otherwise set to unbalanced if the following section is
+ //not continuous, (which also means that the last section
+ //is unbalanced)
+ if (aNext == aEnd || !aNext->IsContinous())
+ pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
+ }
+ }
+
+ bool bHasOwnHdFt = false;
+ /*
+ In this nightmare scenario the continuous section has its own
+ headers and footers so we will try and find a hard page break
+ between here and the end of the section and put the headers and
+ footers there.
+ */
+ if (!bInsertPageDesc)
+ {
+ bHasOwnHdFt =
+ mrReader.HasOwnHeaderFooter(
+ aIter->maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST),
+ aIter->maSep.grpfIhdt, std::distance(aStart, aIter)
+ );
+ }
+ if (bHasOwnHdFt)
+ {
+ // #i40766# Need to cache the page descriptor in case there is
+ // no page break in the section
+ SwPageDesc *pOrig = aIter->mpPage;
+ SwPageDesc *pOrigTitle = aIter->mpTitlePage;
+ bool bFailed = true;
+ SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, true));
+ if (aDesc.GetPageDesc())
+ {
+ sal_uLong nStart = aSectPaM.Start()->nNode.GetIndex();
+ sal_uLong nEnd = aSectPaM.End()->nNode.GetIndex();
+ for(; nStart <= nEnd; ++nStart)
+ {
+ SwNode* pNode = mrReader.rDoc.GetNodes()[nStart];
+ if (!pNode)
+ continue;
+ if (sw::util::HasPageBreak(*pNode))
+ {
+ SwNodeIndex aIdx(*pNode);
+ GiveNodePageDesc(aIdx, aDesc, mrReader.rDoc);
+ bFailed = false;
+ break;
+ }
+ }
+ }
+ if(bFailed)
+ {
+ aIter->mpPage = pOrig;
+ aIter->mpTitlePage = pOrigTitle;
+ }
+ }
+ }
+
+ if (pTxtNd)
+ {
+ SwNodeIndex aIdx(*pTxtNd);
+ SwPosition aPos(aIdx);
+ SwPaM aTest(aPos);
+ mrReader.rDoc.DelFullPara(aTest);
+ pTxtNd = 0;
+ }
+ }
+}
+
+void SwWW8ImplReader::StoreMacroCmds()
+{
+ if (pWwFib->lcbCmds)
+ {
+ maTracer.Log(sw::log::eContainsWordBasic);
+
+ pTableStream->Seek(pWwFib->fcCmds);
+
+ uno::Reference < embed::XStorage > xRoot(mpDocShell->GetStorage());
+
+ if (!xRoot.is())
+ return;
+
+ try
+ {
+ uno::Reference < io::XStream > xStream =
+ xRoot->openStreamElement( CREATE_CONST_ASC(SL::aMSMacroCmds), embed::ElementModes::READWRITE );
+ SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xStream );
+
+ sal_uInt8 *pBuffer = new sal_uInt8[pWwFib->lcbCmds];
+ pTableStream->Read(pBuffer, pWwFib->lcbCmds);
+ pStream->Write(pBuffer, pWwFib->lcbCmds);
+ delete[] pBuffer;
+ delete pStream;
+ }
+ catch ( uno::Exception& )
+ {
+ }
+ }
+}
+
+void SwWW8ImplReader::ReadDocVars()
+{
+ std::vector<String> aDocVarStrings;
+ std::vector<ww::bytes> aDocVarStringIds;
+ std::vector<String> aDocValueStrings;
+ WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcStwUser,
+ pWwFib->lcbStwUser, bVer67 ? 2 : 0, eStructCharSet,
+ aDocVarStrings, &aDocVarStringIds, &aDocValueStrings);
+ if (!bVer67) {
+ using namespace ::com::sun::star;
+
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
+ uno::Reference<beans::XPropertyContainer> xUserDefinedProps =
+ xDocProps->getUserDefinedProperties();
+ DBG_ASSERT(xUserDefinedProps.is(), "UserDefinedProperties is null");
+
+ for(size_t i=0; i<aDocVarStrings.size(); i++)
+ {
+ uno::Any aDefaultValue;
+ ::rtl::OUString name(aDocVarStrings[i]);
+ uno::Any aValue;
+ aValue <<= ::rtl::OUString(aDocValueStrings[i]);
+ try {
+ xUserDefinedProps->addProperty( name,
+ beans::PropertyAttribute::REMOVEABLE,
+ aValue );
+ } catch (uno::Exception &) {
+ // ignore
+ }
+ }
+ }
+}
+
+//-----------------------------------------
+// Document Info
+//-----------------------------------------
+
+void SwWW8ImplReader::ReadDocInfo()
+{
+ if( pStg )
+ {
+ uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
+ mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
+ uno::Reference<document::XDocumentProperties> xDocProps(
+ xDPS->getDocumentProperties());
+ DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
+
+ if (xDocProps.is()) {
+ if ( pWwFib->fDot )
+ {
+ rtl::OUString sTemplateURL;
+ SfxMedium* pMedium = mpDocShell->GetMedium();
+ if ( pMedium )
+ {
+ rtl::OUString aName = pMedium->GetName();
+ INetURLObject aURL( aName );
+ sTemplateURL = aURL.GetMainURL(INetURLObject::DECODE_TO_IURI);
+ if ( sTemplateURL.getLength() > 0 )
+ xDocProps->setTemplateURL( sTemplateURL );
+ }
+ }
+ else if (pWwFib->lcbSttbfAssoc) // not a template, and has a SttbfAssoc
+ {
+ long nCur = pTableStream->Tell();
+ Sttb aSttb;
+ pTableStream->Seek( pWwFib->fcSttbfAssoc ); // point at tgc record
+ if (!aSttb.Read( pTableStream ) )
+ OSL_TRACE("** Read of SttbAssoc data failed!!!! ");
+ pTableStream->Seek( nCur ); // return to previous position, is that necessary?
+#if DEBUG
+ aSttb.Print( stderr );
+#endif
+ String sPath = aSttb.getStringAtIndex( 0x1 );
+ String aURL;
+ // attempt to convert to url ( won't work for obvious reasons on linux
+ if ( sPath.Len() )
+ ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sPath, aURL );
+ if ( aURL.Len() )
+ xDocProps->setTemplateURL( aURL );
+ else
+ xDocProps->setTemplateURL( sPath );
+
+ }
+ sfx2::LoadOlePropertySet(xDocProps, pStg);
+ }
+ }
+}
+
+void lcl_createTemplateToProjectEntry( const uno::Reference< container::XNameContainer >& xPrjNameCache, const rtl::OUString& sTemplatePathOrURL, const rtl::OUString& sVBAProjName )
+{
+ if ( xPrjNameCache.is() )
+ {
+ INetURLObject aObj;
+ aObj.SetURL( sTemplatePathOrURL );
+ bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
+ rtl::OUString aURL;
+ if ( bIsURL )
+ aURL = sTemplatePathOrURL;
+ else
+ {
+ osl::FileBase::getFileURLFromSystemPath( sTemplatePathOrURL, aURL );
+ aObj.SetURL( aURL );
+ }
+ try
+ {
+ rtl::OUString templateNameWithExt = aObj.GetLastName();
+ rtl::OUString templateName;
+ sal_Int32 nIndex = templateNameWithExt.lastIndexOf( '.' );
+ if ( nIndex != -1 )
+ {
+ templateName = templateNameWithExt.copy( 0, nIndex );
+ xPrjNameCache->insertByName( templateName, uno::makeAny( sVBAProjName ) );
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+}
+
+class WW8Customizations
+{
+ SvStream* mpTableStream;
+ WW8Fib mWw8Fib;
+public:
+ WW8Customizations( SvStream*, WW8Fib& );
+ bool Import( SwDocShell* pShell );
+};
+
+WW8Customizations::WW8Customizations( SvStream* pTableStream, WW8Fib& rFib ) : mpTableStream(pTableStream), mWw8Fib( rFib )
+{
+}
+
+bool WW8Customizations::Import( SwDocShell* pShell )
+{
+ if ( mWw8Fib.lcbCmds == 0 )
+ return false;
+ Tcg aTCG;
+ long nCur = mpTableStream->Tell();
+ mpTableStream->Seek( mWw8Fib.fcCmds ); // point at tgc record
+ bool bReadResult = aTCG.Read( mpTableStream );
+ mpTableStream->Seek( nCur ); // return to previous position, is that necessary?
+ if ( !bReadResult )
+ {
+ OSL_TRACE("** Read of Customization data failed!!!! ");
+ return false;
+ }
+#if DEBUG
+ aTCG.Print( stderr );
+#endif
+ return aTCG.ImportCustomToolBar( *pShell );
+}
+
+bool SwWW8ImplReader::ReadGlobalTemplateSettings( const rtl::OUString& sCreatedFrom, const uno::Reference< container::XNameContainer >& xPrjNameCache )
+{
+ SvtPathOptions aPathOpt;
+ String aAddinPath = aPathOpt.GetAddinPath();
+ uno::Sequence< rtl::OUString > sGlobalTemplates;
+
+ // first get the autoload addins in the directory STARTUP
+ uno::Reference< ucb::XSimpleFileAccess > xSFA( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.SimpleFileAccess")) ), uno::UNO_QUERY_THROW );
+
+ if( xSFA->isFolder( aAddinPath ) )
+ sGlobalTemplates = xSFA->getFolderContents( aAddinPath, sal_False );
+
+ sal_Int32 nEntries = sGlobalTemplates.getLength();
+ bool bRes = true;
+ for ( sal_Int32 i=0; i<nEntries; ++i )
+ {
+ INetURLObject aObj;
+ aObj.SetURL( sGlobalTemplates[ i ] );
+ bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
+ rtl::OUString aURL;
+ if ( bIsURL )
+ aURL = sGlobalTemplates[ i ];
+ else
+ osl::FileBase::getFileURLFromSystemPath( sGlobalTemplates[ i ], aURL );
+ if ( !aURL.endsWithIgnoreAsciiCaseAsciiL( ".dot", 4 ) || ( sCreatedFrom.getLength() && sCreatedFrom.equals( aURL ) ) )
+ continue; // don't try and read the same document as ourselves
+
+ SotStorageRef rRoot = new SotStorage( aURL, STREAM_STD_READWRITE, STORAGE_TRANSACTED );
+
+ BasicProjImportHelper aBasicImporter( *mpDocShell );
+ // Import vba via oox filter
+ aBasicImporter.import();
+
+ lcl_createTemplateToProjectEntry( xPrjNameCache, aURL, aBasicImporter.getProjectName() );
+ // Read toolbars & menus
+ SvStorageStreamRef refMainStream = rRoot->OpenSotStream( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("WordDocument") ) );
+ refMainStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ WW8Fib aWwFib( *refMainStream, 8 );
+ SvStorageStreamRef xTableStream = rRoot->OpenSotStream(String::CreateFromAscii( aWwFib.fWhichTblStm ? SL::a1Table : SL::a0Table), STREAM_STD_READ);
+
+ if (xTableStream.Is() && SVSTREAM_OK == xTableStream->GetError())
+ {
+ xTableStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ WW8Customizations aGblCustomisations( xTableStream, aWwFib );
+ aGblCustomisations.Import( mpDocShell );
+ }
+ }
+ return bRes;
+}
+
+sal_uLong SwWW8ImplReader::CoreLoad(WW8Glossary *pGloss, const SwPosition &rPos)
+{
+ sal_uLong nErrRet = 0;
+
+ if (mbNewDoc && pStg && !pGloss)
+ ReadDocInfo();
+
+ ::ww8::WW8FibData * pFibData = new ::ww8::WW8FibData();
+
+ if (pWwFib->fReadOnlyRecommended)
+ pFibData->setReadOnlyRecommended(true);
+ else
+ pFibData->setReadOnlyRecommended(false);
+
+ if (pWwFib->fWriteReservation)
+ pFibData->setWriteReservation(true);
+ else
+ pFibData->setWriteReservation(false);
+
+ ::sw::tExternalDataPointer pExternalFibData(pFibData);
+
+ rDoc.setExternalData(::sw::FIB, pExternalFibData);
+
+ ::sw::tExternalDataPointer pSttbfAsoc
+ (new ::ww8::WW8Sttb<ww8::WW8Struct>(*pTableStream, pWwFib->fcSttbfAssoc, pWwFib->lcbSttbfAssoc));
+
+ rDoc.setExternalData(::sw::STTBF_ASSOC, pSttbfAsoc);
+
+ if (pWwFib->fWriteReservation || pWwFib->fReadOnlyRecommended)
+ {
+ SwDocShell * pDocShell = rDoc.GetDocShell();
+ if (pDocShell)
+ pDocShell->SetReadOnlyUI(sal_True);
+ }
+
+ pPaM = new SwPaM(rPos);
+
+ pCtrlStck = new SwWW8FltControlStack( &rDoc, nFieldFlags, *this );
+
+ mpRedlineStack = new sw::util::RedlineStack(rDoc);
+
+ /*
+ RefFldStck: Keeps track of bookmarks which may be inserted as
+ variables intstead.
+ */
+ pReffedStck = new SwFltEndStack(&rDoc, nFieldFlags);
+ pReffingStck = new SwWW8FltRefStack(&rDoc, nFieldFlags);
+
+ pAnchorStck = new SwWW8FltAnchorStack(&rDoc, nFieldFlags);
+
+ sal_uInt16 nPageDescOffset = rDoc.GetPageDescCnt();
+
+ SwNodeIndex aSttNdIdx( rDoc.GetNodes() );
+ SwRelNumRuleSpaces aRelNumRule(rDoc, mbNewDoc);
+
+ sal_uInt16 eMode = nsRedlineMode_t::REDLINE_SHOW_INSERT;
+
+ mpSprmParser = new wwSprmParser(pWwFib->GetFIBVersion());
+
+ // praktische Hilfsvariablen besetzen:
+ bVer6 = (6 == pWwFib->nVersion);
+ bVer7 = (7 == pWwFib->nVersion);
+ bVer67 = bVer6 || bVer7;
+ bVer8 = (8 == pWwFib->nVersion);
+
+ eTextCharSet = WW8Fib::GetFIBCharset(pWwFib->chse);
+ eStructCharSet = WW8Fib::GetFIBCharset(pWwFib->chseTables);
+
+ bWWBugNormal = pWwFib->nProduct == 0xc03d;
+
+ if (!mbNewDoc)
+ aSttNdIdx = pPaM->GetPoint()->nNode;
+
+ ::StartProgress(STR_STATSTR_W4WREAD, 0, 100, mpDocShell);
+
+ // read Font Table
+ pFonts = new WW8Fonts( *pTableStream, *pWwFib );
+
+ // Document Properties
+ pWDop = new WW8Dop( *pTableStream, pWwFib->nFib, pWwFib->fcDop,
+ pWwFib->lcbDop );
+
+ if (mbNewDoc)
+ ImportDop();
+
+ /*
+ Import revisioning data: author names
+ */
+ if( pWwFib->lcbSttbfRMark )
+ {
+ ReadRevMarkAuthorStrTabl( *pTableStream,
+ pWwFib->fcSttbfRMark,
+ pWwFib->lcbSttbfRMark, rDoc );
+ }
+
+ // M.M. Initialize our String/ID map for Linked Sections
+ std::vector<String> aLinkStrings;
+ std::vector<ww::bytes> aStringIds;
+
+ WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcSttbFnm,
+ pWwFib->lcbSttbFnm, bVer67 ? 2 : 0, eStructCharSet,
+ aLinkStrings, &aStringIds);
+
+ for (size_t i=0; i < aLinkStrings.size(); ++i)
+ {
+ ww::bytes stringId = aStringIds[i];
+ WW8_STRINGID *stringIdStruct = (WW8_STRINGID*)(&stringId[0]);
+ aLinkStringMap[SVBT16ToShort(stringIdStruct->nStringId)] =
+ aLinkStrings[i];
+ }
+
+ ReadDocVars(); // import document variables as meta information.
+
+ ::SetProgressState(nProgress, mpDocShell); // Update
+
+ pLstManager = new WW8ListManager( *pTableStream, *this );
+
+ /*
+ zuerst(!) alle Styles importieren (siehe WW8PAR2.CXX)
+ VOR dem Import der Listen !!
+ */
+ ::SetProgressState(nProgress, mpDocShell); // Update
+ pStyles = new WW8RStyle( *pWwFib, this ); // Styles
+ pStyles->Import();
+
+ /*
+ zu guter Letzt: (siehe ebenfalls WW8PAR3.CXX)
+ ===============
+ alle Styles durchgehen und ggfs. zugehoeriges Listen-Format
+ anhaengen NACH dem Import der Styles und NACH dem Import der
+ Listen !!
+ */
+ ::SetProgressState(nProgress, mpDocShell); // Update
+ pStyles->PostProcessStyles();
+
+ if (pCollA)
+ SetOutLineStyles();
+
+ pSBase = new WW8ScannerBase(pStrm,pTableStream,pDataStream,pWwFib);
+
+ static const SvxExtNumType eNumTA[16] =
+ {
+ SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,
+ SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N,
+ SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
+ SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
+ SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
+ SVX_NUM_ARABIC, SVX_NUM_ARABIC
+ };
+
+ if (pSBase->AreThereFootnotes())
+ {
+ static const SwFtnNum eNumA[4] =
+ {
+ FTNNUM_DOC, FTNNUM_CHAPTER, FTNNUM_PAGE, FTNNUM_DOC
+ };
+
+ SwFtnInfo aInfo;
+ aInfo = rDoc.GetFtnInfo(); // Copy-Ctor privat
+
+ aInfo.ePos = FTNPOS_PAGE;
+ aInfo.eNum = eNumA[pWDop->rncFtn];
+ aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcFtnRef]) );
+ if( pWDop->nFtn )
+ aInfo.nFtnOffset = pWDop->nFtn - 1;
+ rDoc.SetFtnInfo( aInfo );
+ }
+ if( pSBase->AreThereEndnotes() )
+ {
+ SwEndNoteInfo aInfo;
+ aInfo = rDoc.GetEndNoteInfo(); // parallel zu Ftn
+
+ aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcEdnRef]) );
+ if( pWDop->nEdn )
+ aInfo.nFtnOffset = pWDop->nEdn - 1;
+ rDoc.SetEndNoteInfo( aInfo );
+ }
+
+ if( pWwFib->lcbPlcfhdd )
+ pHdFt = new WW8PLCF_HdFt( pTableStream, *pWwFib, *pWDop );
+
+ if (!mbNewDoc)
+ {
+ // in ein Dokument einfuegen ?
+ // Da immer ganze Zeile eingelesen werden, muessen
+ // evtl. Zeilen eingefuegt / aufgebrochen werden
+ //
+ const SwPosition* pPos = pPaM->GetPoint();
+ SwTxtNode const*const pSttNd = pPos->nNode.GetNode().GetTxtNode();
+
+ sal_uInt16 nCntPos = pPos->nContent.GetIndex();
+
+ // EinfuegePos nicht in leerer Zeile
+ if( nCntPos && pSttNd->GetTxt().Len() )
+ rDoc.SplitNode( *pPos, false ); // neue Zeile erzeugen
+
+ if( pSttNd->GetTxt().Len() )
+ { // EinfuegePos nicht am Ende der Zeile
+ rDoc.SplitNode( *pPos, false ); // neue Zeile
+ pPaM->Move( fnMoveBackward ); // gehe in leere Zeile
+ }
+
+ // verhinder das Einlesen von Tabellen in Fussnoten / Tabellen
+ sal_uLong nNd = pPos->nNode.GetIndex();
+ bReadNoTbl = 0 != pSttNd->FindTableNode() ||
+ ( nNd < rDoc.GetNodes().GetEndOfInserts().GetIndex() &&
+ rDoc.GetNodes().GetEndOfInserts().StartOfSectionIndex()
+ < nNd );
+
+ }
+
+ ::SetProgressState(nProgress, mpDocShell); // Update
+
+ // loop for each glossary entry and add dummy section node
+ if (pGloss)
+ {
+ WW8PLCF aPlc(pTableStream, pWwFib->fcPlcfglsy, pWwFib->lcbPlcfglsy, 0);
+
+ WW8_CP nStart, nEnd;
+ void* pDummy;
+
+ for (int i=0;i<pGloss->GetNoStrings();i++,aPlc++)
+ {
+ SwNodeIndex aIdx( rDoc.GetNodes().GetEndOfContent());
+ SwTxtFmtColl* pColl =
+ rDoc.GetTxtCollFromPool(RES_POOLCOLL_STANDARD,
+ false);
+ SwStartNode *pNode =
+ rDoc.GetNodes().MakeTextSection(aIdx,
+ SwNormalStartNode,pColl);
+ pPaM->GetPoint()->nNode = pNode->GetIndex()+1;
+ pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(),0);
+ aPlc.Get( nStart, nEnd, pDummy );
+ ReadText(nStart,nEnd-nStart-1,MAN_MAINTEXT);
+ }
+ }
+ else //ordinary case
+ {
+ if (mbNewDoc && pStg && !pGloss) /*meaningless for a glossary, cmc*/
+ {
+ mpDocShell->SetIsTemplate( pWwFib->fDot ); // point at tgc record
+ maTracer.EnterEnvironment(sw::log::eMacros);
+ uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( mpDocShell->GetModel(), uno::UNO_QUERY_THROW );
+ uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW );
+ uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
+
+ rtl::OUString sCreatedFrom = xDocProps->getTemplateURL();
+ uno::Reference< container::XNameContainer > xPrjNameCache;
+ uno::Reference< lang::XMultiServiceFactory> xSF(mpDocShell->GetModel(), uno::UNO_QUERY);
+ if ( xSF.is() )
+ xPrjNameCache.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAProjectNameProvider" ) ) ), uno::UNO_QUERY );
+
+ // Read Global templates
+ ReadGlobalTemplateSettings( sCreatedFrom, xPrjNameCache );
+
+ // Create and insert Word vba Globals
+ uno::Any aGlobs;
+ uno::Sequence< uno::Any > aArgs(1);
+ aArgs[ 0 ] <<= mpDocShell->GetModel();
+ aGlobs <<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ooo.vba.word.Globals")), aArgs );
+ BasicManager *pBasicMan = mpDocShell->GetBasicManager();
+ if (pBasicMan)
+ pBasicMan->SetGlobalUNOConstant( "VBAGlobals", aGlobs );
+
+ BasicProjImportHelper aBasicImporter( *mpDocShell );
+ // Import vba via oox filter
+ bool bRet = aBasicImporter.import();
+
+ lcl_createTemplateToProjectEntry( xPrjNameCache, sCreatedFrom, aBasicImporter.getProjectName() );
+ WW8Customizations aCustomisations( pTableStream, *pWwFib );
+ aCustomisations.Import( mpDocShell );
+
+ if( bRet )
+ {
+ maTracer.Log(sw::log::eContainsVisualBasic);
+ rDoc.SetContainsMSVBasic(true);
+ }
+
+ StoreMacroCmds();
+
+ maTracer.LeaveEnvironment(sw::log::eMacros);
+ }
+ ReadText(0, pWwFib->ccpText, MAN_MAINTEXT);
+
+ }
+
+ ::SetProgressState(nProgress, mpDocShell); // Update
+
+ if (pDrawPg && pMSDffManager && pMSDffManager->GetShapeOrders())
+ {
+ // Hilfsarray zum Verketten der (statt SdrTxtObj) eingefuegten
+ // Rahmen
+ SvxMSDffShapeTxBxSort aTxBxSort;
+
+ // korrekte Z-Order der eingelesen Escher-Objekte sicherstellen
+ sal_uInt16 nShapeCount = pMSDffManager->GetShapeOrders()->Count();
+
+ for (sal_uInt16 nShapeNum=0; nShapeNum < nShapeCount; nShapeNum++)
+ {
+ SvxMSDffShapeOrder *pOrder =
+ pMSDffManager->GetShapeOrders()->GetObject(nShapeNum);
+ // Pointer in neues Sort-Array einfuegen
+ if (pOrder->nTxBxComp && pOrder->pFly)
+ aTxBxSort.Insert(pOrder);
+ }
+ // zu verkettende Rahmen jetzt verketten
+ sal_uInt16 nTxBxCount = aTxBxSort.Count();
+ if( nTxBxCount )
+ {
+ SwFmtChain aChain;
+ for (sal_uInt16 nTxBxNum=0; nTxBxNum < nTxBxCount; nTxBxNum++)
+ {
+ SvxMSDffShapeOrder *pOrder =
+ aTxBxSort.GetObject(nTxBxNum);
+
+ // Fly-Frame-Formate initialisieren
+ SwFlyFrmFmt* pFlyFmt = pOrder->pFly;
+ SwFlyFrmFmt* pNextFlyFmt = 0;
+ SwFlyFrmFmt* pPrevFlyFmt = 0;
+ // ggfs. Nachfolger ermitteln
+ if( 1+nTxBxNum < nTxBxCount )
+ {
+ SvxMSDffShapeOrder *pNextOrder =
+ aTxBxSort.GetObject(nTxBxNum+1);
+ if ((0xFFFF0000 & pOrder->nTxBxComp)
+ == (0xFFFF0000 & pNextOrder->nTxBxComp))
+ pNextFlyFmt = pNextOrder->pFly;
+ }
+ // ggfs. Vorgaenger ermitteln
+ if( nTxBxNum )
+ {
+ SvxMSDffShapeOrder *pPrevOrder =
+ aTxBxSort.GetObject(nTxBxNum-1);
+ if ((0xFFFF0000 & pOrder->nTxBxComp)
+ == (0xFFFF0000 & pPrevOrder->nTxBxComp))
+ pPrevFlyFmt = pPrevOrder->pFly;
+ }
+ // Falls Nachfolger oder Vorgaenger vorhanden,
+ // die Verkettung am Fly-Frame-Format eintragen
+ if (pNextFlyFmt || pPrevFlyFmt)
+ {
+ aChain.SetNext( pNextFlyFmt );
+ aChain.SetPrev( pPrevFlyFmt );
+ pFlyFmt->SetFmtAttr( aChain );
+ }
+ }
+
+ }
+
+ }
+
+ if (mbNewDoc)
+ {
+ if( pWDop->fRevMarking )
+ eMode |= nsRedlineMode_t::REDLINE_ON;
+ if( pWDop->fRMView )
+ eMode |= nsRedlineMode_t::REDLINE_SHOW_DELETE;
+ }
+
+ maInsertedTables.DelAndMakeTblFrms();
+ maSectionManager.InsertSegments();
+
+ if (pCollA)
+ delete[] pCollA;
+
+ DELETEZ( pStyles );
+
+ if( pFormImpl )
+ DeleteFormImpl();
+ GrafikDtor();
+ DELETEZ( pMSDffManager );
+ DELETEZ( pHdFt );
+ DELETEZ( pLstManager );
+ DELETEZ( pSBase );
+ delete pWDop;
+ DELETEZ( pFonts );
+ delete mpAtnNames;
+ DELETEZ( pAuthorInfos );
+ delete mpSprmParser;
+ ::EndProgress(mpDocShell);
+
+ pDataStream = 0;
+ pTableStream = 0;
+
+ DeleteCtrlStk();
+ mpRedlineStack->closeall(*pPaM->GetPoint());
+ delete mpRedlineStack;
+ DeleteAnchorStk();
+ DeleteRefStks();
+
+ UpdateFields();
+
+ // delete the pam before the call for hide all redlines (Bug 73683)
+ if (mbNewDoc)
+ rDoc.SetRedlineMode((RedlineMode_t)( eMode ));
+
+ UpdatePageDescs(rDoc, nPageDescOffset);
+
+ delete pPaM, pPaM = 0;
+ return nErrRet;
+}
+
+sal_uLong SwWW8ImplReader::SetSubStreams(SvStorageStreamRef &rTableStream,
+ SvStorageStreamRef &rDataStream)
+{
+ sal_uLong nErrRet = 0;
+ // 6 stands for "6 OR 7", 7 stand for "ONLY 7"
+ switch (pWwFib->nVersion)
+ {
+ case 6:
+ case 7:
+ pTableStream = pStrm;
+ pDataStream = pStrm;
+ break;
+ case 8:
+ if(!pStg)
+ {
+ OSL_ENSURE( pStg, "Version 8 muss immer einen Storage haben!" );
+ nErrRet = ERR_SWG_READ_ERROR;
+ break;
+ }
+
+ rTableStream = pStg->OpenSotStream( String::CreateFromAscii(
+ pWwFib->fWhichTblStm ? SL::a1Table : SL::a0Table),
+ STREAM_STD_READ);
+
+ pTableStream = &rTableStream;
+ pTableStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+
+ rDataStream = pStg->OpenSotStream(CREATE_CONST_ASC(SL::aData),
+ STREAM_STD_READ | STREAM_NOCREATE );
+
+ if (rDataStream.Is() && SVSTREAM_OK == rDataStream->GetError())
+ {
+ pDataStream = &rDataStream;
+ pDataStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
+ }
+ else
+ pDataStream = pStrm;
+ break;
+ default:
+ // Programm-Fehler!
+ OSL_ENSURE( !this, "Es wurde vergessen, nVersion zu kodieren!" );
+ nErrRet = ERR_SWG_READ_ERROR;
+ break;
+ }
+ return nErrRet;
+}
+
+namespace
+{
+ utl::TempFile *MakeTemp(SvFileStream &rSt)
+ {
+ utl::TempFile *pT = new utl::TempFile;
+ pT->EnableKillingFile();
+ rSt.Open(pT->GetFileName(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE);
+ return pT;
+ }
+
+#define WW_BLOCKSIZE 0x200
+
+ void DecryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
+ {
+ rIn.Seek(STREAM_SEEK_TO_END);
+ const sal_Size nLen = rIn.Tell();
+ rIn.Seek(0);
+
+ sal_uInt8 in[WW_BLOCKSIZE];
+ for (sal_Size nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
+ {
+ sal_Size nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI;
+ rIn.Read(in, nBS);
+ rCtx.InitCipher(nBlock);
+ rCtx.Decode(in, nBS, in, nBS);
+ rOut.Write(in, nBS);
+ }
+ }
+
+ void DecryptXOR(msfilter::MSCodec_XorWord95 &rCtx, SvStream &rIn, SvStream &rOut)
+ {
+ sal_uLong nSt = rIn.Tell();
+ rIn.Seek(STREAM_SEEK_TO_END);
+ sal_uLong nLen = rIn.Tell();
+ rIn.Seek(nSt);
+
+ rCtx.InitCipher();
+ rCtx.Skip(nSt);
+
+ sal_uInt8 in[0x4096];
+ for (sal_uLong nI = nSt; nI < nLen; nI += 0x4096)
+ {
+ sal_uLong nBS = (nLen - nI > 0x4096 ) ? 0x4096 : nLen - nI;
+ rIn.Read(in, nBS);
+ rCtx.Decode(in, nBS);
+ rOut.Write(in, nBS);
+ }
+ }
+
+ //moan, copy and paste :-(
+ String QueryPasswordForMedium(SfxMedium& rMedium)
+ {
+ String aPassw;
+
+ using namespace com::sun::star;
+
+ const SfxItemSet* pSet = rMedium.GetItemSet();
+ const SfxPoolItem *pPasswordItem;
+
+ if(pSet && SFX_ITEM_SET == pSet->GetItemState(SID_PASSWORD, sal_True, &pPasswordItem))
+ aPassw = ((const SfxStringItem *)pPasswordItem)->GetValue();
+ else
+ {
+ try
+ {
+ uno::Reference< task::XInteractionHandler > xHandler( rMedium.GetInteractionHandler() );
+ if( xHandler.is() )
+ {
+ ::comphelper::DocPasswordRequest* pRequest = new ::comphelper::DocPasswordRequest(
+ ::comphelper::DocPasswordRequestType_MS, task::PasswordRequestMode_PASSWORD_ENTER,
+ INetURLObject( rMedium.GetOrigURL() ).GetName( INetURLObject::DECODE_WITH_CHARSET ) );
+ uno::Reference< task::XInteractionRequest > xRequest( pRequest );
+
+ xHandler->handle( xRequest );
+
+ if( pRequest->isPassword() )
+ aPassw = pRequest->getPassword();
+ }
+ }
+ catch( uno::Exception& )
+ {
+ }
+ }
+
+ return aPassw;
+ }
+
+ uno::Sequence< beans::NamedValue > InitXorWord95Codec( ::msfilter::MSCodec_XorWord95& rCodec, SfxMedium& rMedium, WW8Fib* pWwFib )
+ {
+ uno::Sequence< beans::NamedValue > aEncryptionData;
+ SFX_ITEMSET_ARG( rMedium.GetItemSet(), pEncryptionData, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
+ if ( pEncryptionData && ( pEncryptionData->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
+ aEncryptionData.realloc( 0 );
+
+ if ( !aEncryptionData.getLength() )
+ {
+ String sUniPassword = QueryPasswordForMedium( rMedium );
+
+ ByteString sPassword(sUniPassword, WW8Fib::GetFIBCharset( pWwFib->chseTables ) );
+
+ xub_StrLen nLen = sPassword.Len();
+ if( nLen <= 15 )
+ {
+ sal_uInt8 pPassword[16];
+ memset( pPassword, 0, sizeof( pPassword ) );
+
+ for (xub_StrLen nChar = 0; nChar < sPassword.Len(); ++nChar )
+ pPassword[nChar] = sPassword.GetChar(nChar);
+
+ rCodec.InitKey( pPassword );
+ aEncryptionData = rCodec.GetEncryptionData();
+
+ // the export supports RC4 algorithm only, so we have to generate the related EncryptionData as well,
+ // so that Save can export the document without asking for a password;
+ // as result there will be EncryptionData for both algorithms in the MediaDescriptor
+ ::msfilter::MSCodec_Std97 aCodec97;
+
+ // Generate random number with a seed of time as salt.
+ TimeValue aTime;
+ osl_getSystemTime( &aTime );
+ rtlRandomPool aRandomPool = rtl_random_createPool();
+ rtl_random_addBytes ( aRandomPool, &aTime, 8 );
+
+ sal_uInt8 pDocId[ 16 ];
+ rtl_random_getBytes( aRandomPool, pDocId, 16 );
+
+ rtl_random_destroyPool( aRandomPool );
+
+ sal_uInt16 pStd97Pass[16];
+ memset( pStd97Pass, 0, sizeof( pStd97Pass ) );
+ for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
+ pStd97Pass[nChar] = sUniPassword.GetChar(nChar);
+
+ aCodec97.InitKey( pStd97Pass, pDocId );
+
+ // merge the EncryptionData, there should be no conflicts
+ ::comphelper::SequenceAsHashMap aEncryptionHash( aEncryptionData );
+ aEncryptionHash.update( ::comphelper::SequenceAsHashMap( aCodec97.GetEncryptionData() ) );
+ aEncryptionHash >> aEncryptionData;
+ }
+ }
+
+ return aEncryptionData;
+ }
+
+ uno::Sequence< beans::NamedValue > InitStd97Codec( ::msfilter::MSCodec_Std97& rCodec, sal_uInt8 pDocId[16], SfxMedium& rMedium )
+ {
+ uno::Sequence< beans::NamedValue > aEncryptionData;
+ SFX_ITEMSET_ARG( rMedium.GetItemSet(), pEncryptionData, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
+ if ( pEncryptionData && ( pEncryptionData->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
+ aEncryptionData.realloc( 0 );
+
+ if ( !aEncryptionData.getLength() )
+ {
+ String sUniPassword = QueryPasswordForMedium( rMedium );
+
+ xub_StrLen nLen = sUniPassword.Len();
+ if ( nLen <= 15 )
+ {
+ sal_Unicode pPassword[16];
+ memset( pPassword, 0, sizeof( pPassword ) );
+ for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
+ pPassword[nChar] = sUniPassword.GetChar(nChar);
+
+ rCodec.InitKey( pPassword, pDocId );
+ aEncryptionData = rCodec.GetEncryptionData();
+ }
+ }
+
+ return aEncryptionData;
+ }
+}
+
+sal_uLong SwWW8ImplReader::LoadThroughDecryption(SwPaM& rPaM ,WW8Glossary *pGloss)
+{
+ sal_uLong nErrRet = 0;
+ if (pGloss)
+ pWwFib = pGloss->GetFib();
+ else
+ pWwFib = new WW8Fib(*pStrm, nWantedVersion);
+
+ if (pWwFib->nFibError)
+ nErrRet = ERR_SWG_READ_ERROR;
+
+ SvStorageStreamRef xTableStream, xDataStream;
+
+ if (!nErrRet)
+ nErrRet = SetSubStreams(xTableStream, xDataStream);
+
+ utl::TempFile *pTempMain = 0;
+ utl::TempFile *pTempTable = 0;
+ utl::TempFile *pTempData = 0;
+ SvFileStream aDecryptMain;
+ SvFileStream aDecryptTable;
+ SvFileStream aDecryptData;
+
+ bool bDecrypt = false;
+ enum {RC4, XOR, Other} eAlgo = Other;
+ if (pWwFib->fEncrypted && !nErrRet)
+ {
+ if (!pGloss)
+ {
+ bDecrypt = true;
+ if (8 != pWwFib->nVersion)
+ eAlgo = XOR;
+ else
+ {
+ if (pWwFib->nKey != 0)
+ eAlgo = XOR;
+ else
+ {
+ pTableStream->Seek(0);
+ sal_uInt32 nEncType;
+ *pTableStream >> nEncType;
+ if (nEncType == 0x10001)
+ eAlgo = RC4;
+ }
+ }
+ }
+ }
+
+ if (bDecrypt)
+ {
+ nErrRet = ERRCODE_SVX_WRONGPASS;
+ SfxMedium* pMedium = mpDocShell->GetMedium();
+
+ if ( pMedium )
+ {
+ switch (eAlgo)
+ {
+ default:
+ nErrRet = ERRCODE_SVX_READ_FILTER_CRYPT;
+ break;
+ case XOR:
+ {
+ msfilter::MSCodec_XorWord95 aCtx;
+ uno::Sequence< beans::NamedValue > aEncryptionData = InitXorWord95Codec( aCtx, *pMedium, pWwFib );
+
+ // if initialization has failed the EncryptionData should be empty
+ if ( aEncryptionData.getLength() && aCtx.VerifyKey( pWwFib->nKey, pWwFib->nHash ) )
+ {
+ nErrRet = 0;
+ pTempMain = MakeTemp(aDecryptMain);
+
+ pStrm->Seek(0);
+ size_t nUnencryptedHdr =
+ (8 == pWwFib->nVersion) ? 0x44 : 0x34;
+ sal_uInt8 *pIn = new sal_uInt8[nUnencryptedHdr];
+ pStrm->Read(pIn, nUnencryptedHdr);
+ aDecryptMain.Write(pIn, nUnencryptedHdr);
+ delete [] pIn;
+
+ DecryptXOR(aCtx, *pStrm, aDecryptMain);
+
+ if (!pTableStream || pTableStream == pStrm)
+ pTableStream = &aDecryptMain;
+ else
+ {
+ pTempTable = MakeTemp(aDecryptTable);
+ DecryptXOR(aCtx, *pTableStream, aDecryptTable);
+ pTableStream = &aDecryptTable;
+ }
+
+ if (!pDataStream || pDataStream == pStrm)
+ pDataStream = &aDecryptMain;
+ else
+ {
+ pTempData = MakeTemp(aDecryptData);
+ DecryptXOR(aCtx, *pDataStream, aDecryptData);
+ pDataStream = &aDecryptData;
+ }
+
+ pMedium->GetItemSet()->ClearItem( SID_PASSWORD );
+ pMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
+ }
+ }
+ break;
+ case RC4:
+ {
+ msfilter::MSCodec_Std97 aCtx;
+
+ sal_uInt8 aDocId[ 16 ];
+ pTableStream->Read(aDocId, 16);
+ sal_uInt8 aSaltData[ 16 ];
+ pTableStream->Read(aSaltData, 16);
+ sal_uInt8 aSaltHash[ 16 ];
+ pTableStream->Read(aSaltHash, 16);
+
+ // if initialization has failed the EncryptionData should be empty
+ uno::Sequence< beans::NamedValue > aEncryptionData = InitStd97Codec( aCtx, aDocId, *pMedium );
+ if ( aEncryptionData.getLength() && aCtx.VerifyKey( aSaltData, aSaltHash ) )
+ {
+ nErrRet = 0;
+
+ pTempMain = MakeTemp(aDecryptMain);
+
+ pStrm->Seek(0);
+ const sal_Size nUnencryptedHdr = 0x44;
+ sal_uInt8 *pIn = new sal_uInt8[nUnencryptedHdr];
+ pStrm->Read(pIn, nUnencryptedHdr);
+
+ DecryptRC4(aCtx, *pStrm, aDecryptMain);
+
+ aDecryptMain.Seek(0);
+ aDecryptMain.Write(pIn, nUnencryptedHdr);
+ delete [] pIn;
+
+
+ pTempTable = MakeTemp(aDecryptTable);
+ DecryptRC4(aCtx, *pTableStream, aDecryptTable);
+ pTableStream = &aDecryptTable;
+
+ if (!pDataStream || pDataStream == pStrm)
+ pDataStream = &aDecryptMain;
+ else
+ {
+ pTempData = MakeTemp(aDecryptData);
+ DecryptRC4(aCtx, *pDataStream, aDecryptData);
+ pDataStream = &aDecryptData;
+ }
+
+ pMedium->GetItemSet()->ClearItem( SID_PASSWORD );
+ pMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
+ }
+ }
+ break;
+ }
+ }
+
+ if (nErrRet == 0)
+ {
+ pStrm = &aDecryptMain;
+
+ delete pWwFib;
+ pWwFib = new WW8Fib(*pStrm, nWantedVersion);
+ if (pWwFib->nFibError)
+ nErrRet = ERR_SWG_READ_ERROR;
+ }
+ }
+
+ if (!nErrRet)
+ nErrRet = CoreLoad(pGloss, *rPaM.GetPoint());
+
+ delete pTempMain;
+ delete pTempTable;
+ delete pTempData;
+
+ if (!pGloss)
+ delete pWwFib;
+ return nErrRet;
+}
+
+class outlineeq : public std::unary_function<const SwTxtFmtColl*, bool>
+{
+private:
+ sal_uInt8 mnNum;
+public:
+ outlineeq(sal_uInt8 nNum) : mnNum(nNum) {}
+ bool operator()(const SwTxtFmtColl *pTest) const
+ {
+ return pTest->IsAssignedToListLevelOfOutlineStyle() && pTest->GetAssignedOutlineStyleLevel() == mnNum; //<-end,zhaojianwei
+ }
+};
+
+void SwWW8ImplReader::SetOutLineStyles()
+{
+ /*
+ #i3674# & #101291# Load new document and insert document cases.
+ */
+ SwNumRule aOutlineRule(*rDoc.GetOutlineNumRule());
+ // #i53044,i53213#
+ // <mpChosenOutlineNumRule> has to be set to point to local variable
+ // <aOutlineRule>, because its used below to be compared this <&aOutlineRule>.
+ // But at the end of the method <mpChosenOutlineNumRule> has to be set to
+ // <rDoc.GetOutlineNumRule()>, because <aOutlineRule> will be destroyed.
+ mpChosenOutlineNumRule = &aOutlineRule;
+ // <--
+
+ sw::ParaStyles aOutLined(sw::util::GetParaStyles(rDoc));
+ // #i98791# - sorting algorithm adjusted
+ sw::util::SortByAssignedOutlineStyleListLevel(aOutLined);
+
+ typedef sw::ParaStyleIter myParaStyleIter;
+ /*
+ If we are inserted into a document then don't clobber existing existing
+ levels.
+ */
+ sal_uInt16 nFlagsStyleOutlLevel = 0;
+ if (!mbNewDoc)
+ {
+ // #i70748# - backward iteration needed due to the outline level attribute
+ sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend();
+ for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter)
+ // <--
+ {
+ if ((*aIter)->IsAssignedToListLevelOfOutlineStyle())
+ nFlagsStyleOutlLevel |= 1 << (*aIter)->GetAssignedOutlineStyleLevel();//<-end,zhaojianwei
+ else
+ break;
+ }
+ }
+ else
+ {
+ /*
+ Only import *one* of the possible multiple outline numbering rules, so
+ pick the one that affects most styles. If we're not importing a new
+ document, we got to stick with what is already there.
+ */
+ // use index in text format collection array <pCollA>
+ // as key of the outline numbering map <aRuleMap>
+ // instead of the memory pointer of the outline numbering rule
+ // to assure that, if two outline numbering rule affect the same
+ // count of text formats, always the same outline numbering rule is chosen.
+ std::map<sal_uInt16, int>aRuleMap;
+ typedef std::map<sal_uInt16, int>::iterator myIter;
+ for (sal_uInt16 nI = 0; nI < nColls; ++nI)
+ {
+ SwWW8StyInf& rSI = pCollA[ nI ];
+ if (
+ (MAXLEVEL > rSI.nOutlineLevel) && rSI.pOutlineNumrule &&
+ rSI.pFmt
+ )
+ {
+ myIter aIter = aRuleMap.find(nI);
+ if (aIter == aRuleMap.end())
+ {
+ aRuleMap[nI] = 1;
+ }
+ else
+ ++(aIter->second);
+ }
+ }
+
+ int nMax = 0;
+ myIter aEnd2 = aRuleMap.end();
+ for (myIter aIter = aRuleMap.begin(); aIter != aEnd2; ++aIter++)
+ {
+ if (aIter->second > nMax)
+ {
+ nMax = aIter->second;
+ mpChosenOutlineNumRule = pCollA[ aIter->first ].pOutlineNumrule;
+ }
+ }
+ // <--
+
+ OSL_ENSURE(mpChosenOutlineNumRule, "Impossible");
+ if (mpChosenOutlineNumRule)
+ aOutlineRule = *mpChosenOutlineNumRule;
+
+ if (mpChosenOutlineNumRule != &aOutlineRule)
+ {
+ // #i70748# - backward iteration needed due to the outline level attribute
+ sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend();
+ for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter)
+ // <--
+ {
+ if((*aIter)->IsAssignedToListLevelOfOutlineStyle())
+ (*aIter)->DeleteAssignmentToListLevelOfOutlineStyle(); //<-end
+
+ else
+ break;
+ }
+ }
+ }
+
+ sal_uInt16 nOldFlags = nFlagsStyleOutlLevel;
+
+ for (sal_uInt16 nI = 0; nI < nColls; ++nI)
+ {
+ SwWW8StyInf& rSI = pCollA[nI];
+
+ if (rSI.IsOutlineNumbered())
+ {
+ sal_uInt16 nAktFlags = 1 << rSI.nOutlineLevel;
+ if (
+ (nAktFlags & nFlagsStyleOutlLevel) ||
+ (rSI.pOutlineNumrule != mpChosenOutlineNumRule)
+ )
+ {
+ /*
+ If our spot is already taken by something we can't replace
+ then don't insert and remove our outline level.
+ */
+ rSI.pFmt->SetFmtAttr(
+ SwNumRuleItem( rSI.pOutlineNumrule->GetName() ) );
+ ((SwTxtFmtColl*)rSI.pFmt)->DeleteAssignmentToListLevelOfOutlineStyle();//#outline level,zhaojianwei
+ }
+ else
+ {
+ /*
+ If there is a style already set for this outline
+ numbering level and its not a style set by us already
+ then we can remove it outline numbering.
+ (its one of the default headings in a new document
+ so we can clobber it)
+ Of course if we are being inserted into a document that
+ already has some set we can't do this, thats covered by
+ the list of level in nFlagsStyleOutlLevel to ignore.
+ */
+ outlineeq aCmp(rSI.nOutlineLevel);
+ myParaStyleIter aResult = std::find_if(aOutLined.begin(),
+ aOutLined.end(), aCmp);
+
+ myParaStyleIter aEnd = aOutLined.end();
+ while (aResult != aEnd && aCmp(*aResult))
+ {
+ (*aResult)->DeleteAssignmentToListLevelOfOutlineStyle();
+ ++aResult;
+ }
+
+ /*
+ #i1886#
+ I believe that when a list is registered onto a winword
+ style which is an outline numbering style (i.e.
+ nOutlineLevel is set) that the style of numbering is for
+ the level is indexed by the *list* level that was
+ registered on that style, and not the outlinenumbering
+ level, which is probably a logical sequencing, and not a
+ physical mapping into the list style reged on that outline
+ style.
+ */
+ sal_uInt8 nFromLevel = rSI.nListLevel;
+ sal_uInt8 nToLevel = rSI.nOutlineLevel;
+ const SwNumFmt& rRule=rSI.pOutlineNumrule->Get(nFromLevel);
+ aOutlineRule.Set(nToLevel, rRule);
+ ((SwTxtFmtColl*)rSI.pFmt)->AssignToListLevelOfOutlineStyle(nToLevel); //<-end,zhaojianwei
+ // If there are more styles on this level ignore them
+ nFlagsStyleOutlLevel |= nAktFlags;
+ }
+ }
+ }
+ if (nOldFlags != nFlagsStyleOutlLevel)
+ rDoc.SetOutlineNumRule(aOutlineRule);
+ // #i53044,i53213#
+ if ( mpChosenOutlineNumRule == &aOutlineRule )
+ {
+ mpChosenOutlineNumRule = rDoc.GetOutlineNumRule();
+ }
+ // <--
+}
+
+const String* SwWW8ImplReader::GetAnnotationAuthor(sal_uInt16 nIdx)
+{
+ if (!mpAtnNames && pWwFib->lcbGrpStAtnOwners)
+ {
+ // Authoren bestimmen: steht im TableStream
+ mpAtnNames = new ::std::vector<String>;
+ SvStream& rStrm = *pTableStream;
+
+ long nOldPos = rStrm.Tell();
+ rStrm.Seek( pWwFib->fcGrpStAtnOwners );
+
+ long nRead = 0, nCount = pWwFib->lcbGrpStAtnOwners;
+ while (nRead < nCount)
+ {
+ if( bVer67 )
+ {
+ mpAtnNames->push_back(WW8ReadPString(rStrm, false));
+ nRead += mpAtnNames->rbegin()->Len() + 1; // Laenge + sal_uInt8 Count
+ }
+ else
+ {
+ mpAtnNames->push_back(WW8Read_xstz(rStrm, 0, false));
+ // UNICode: doppelte Laenge + sal_uInt16 Count
+ nRead += mpAtnNames->rbegin()->Len() * 2 + 2;
+ }
+ }
+ rStrm.Seek( nOldPos );
+ }
+
+ const String *pRet = 0;
+ if (mpAtnNames && nIdx < mpAtnNames->size())
+ pRet = &((*mpAtnNames)[nIdx]);
+ return pRet;
+}
+
+sal_uLong SwWW8ImplReader::LoadDoc( SwPaM& rPaM,WW8Glossary *pGloss)
+{
+ sal_uLong nErrRet = 0;
+
+ {
+ static const sal_Char* aNames[ 13 ] = {
+ "WinWord/WW", "WinWord/WW8", "WinWord/WWFT",
+ "WinWord/WWFLX", "WinWord/WWFLY",
+ "WinWord/WWF",
+ "WinWord/WWFA0", "WinWord/WWFA1", "WinWord/WWFA2",
+ "WinWord/WWFB0", "WinWord/WWFB1", "WinWord/WWFB2",
+ "WinWord/RegardHindiDigits"
+ };
+ sal_uInt32 aVal[ 13 ];
+
+ SwFilterOptions aOpt( 13, aNames, aVal );
+
+ nIniFlags = aVal[ 0 ];
+ nIniFlags1= aVal[ 1 ];
+ // schiebt Flys um x twips nach rechts o. links
+ nIniFlyDx = aVal[ 3 ];
+ nIniFlyDy = aVal[ 4 ];
+
+ nFieldFlags = aVal[ 5 ];
+ nFieldTagAlways[0] = aVal[ 6 ];
+ nFieldTagAlways[1] = aVal[ 7 ];
+ nFieldTagAlways[2] = aVal[ 8 ];
+ nFieldTagBad[0] = aVal[ 9 ];
+ nFieldTagBad[1] = aVal[ 10 ];
+ nFieldTagBad[2] = aVal[ 11 ];
+ m_bRegardHindiDigits = aVal[ 12 ] > 0;
+ }
+
+ sal_uInt16 nMagic;
+ *pStrm >> nMagic;
+
+ // beachte: 6 steht fuer "6 ODER 7", 7 steht fuer "NUR 7"
+ switch (nWantedVersion)
+ {
+ case 6:
+ case 7:
+ if (
+ (0xa5dc != nMagic && 0xa5db != nMagic) &&
+ (nMagic < 0xa697 || nMagic > 0xa699)
+ )
+ {
+ // teste auf eigenen 97-Fake!
+ if (pStg && 0xa5ec == nMagic)
+ {
+ sal_uLong nCurPos = pStrm->Tell();
+ if (pStrm->Seek(nCurPos + 22))
+ {
+ sal_uInt32 nfcMin;
+ *pStrm >> nfcMin;
+ if (0x300 != nfcMin)
+ nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
+ }
+ pStrm->Seek( nCurPos );
+ }
+ else
+ nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
+ }
+ break;
+ case 8:
+ if (0xa5ec != nMagic)
+ nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
+ break;
+ default:
+ nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
+ OSL_ENSURE( !this, "Es wurde vergessen, nVersion zu kodieren!" );
+ break;
+ }
+
+ if (!nErrRet)
+ nErrRet = LoadThroughDecryption(rPaM ,pGloss);
+
+ rDoc.PropagateOutlineRule();
+
+ return nErrRet;
+}
+
+extern "C" SAL_DLLPUBLIC_EXPORT Reader* SAL_CALL ImportDOC()
+{
+ return new WW8Reader();
+}
+
+sal_uLong WW8Reader::OpenMainStream( SvStorageStreamRef& rRef, sal_uInt16& rBuffSize )
+{
+ sal_uLong nRet = ERR_SWG_READ_ERROR;
+ OSL_ENSURE( pStg, "wo ist mein Storage?" );
+ rRef = pStg->OpenSotStream(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("WordDocument")),
+ STREAM_READ | STREAM_SHARE_DENYALL);
+
+ if( rRef.Is() )
+ {
+ if( SVSTREAM_OK == rRef->GetError() )
+ {
+ sal_uInt16 nOld = rRef->GetBufferSize();
+ rRef->SetBufferSize( rBuffSize );
+ rBuffSize = nOld;
+ nRet = 0;
+ }
+ else
+ nRet = rRef->GetError();
+ }
+ return nRet;
+}
+
+sal_uLong WW8Reader::Read(SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & /* FileName */)
+{
+ sal_uInt16 nOldBuffSize = 32768;
+ bool bNew = !bInsertMode; // Neues Doc ( kein Einfuegen )
+
+
+ SvStorageStreamRef refStrm; // damit uns keiner den Stream klaut
+ SvStream* pIn = pStrm;
+
+ sal_uLong nRet = 0;
+ sal_uInt8 nVersion = 8;
+
+ String sFltName = GetFltName();
+ if( sFltName.EqualsAscii( "WW6" ) )
+ {
+ if (pStrm)
+ nVersion = 6;
+ else
+ {
+ OSL_ENSURE(!this, "WinWord 95 Reader-Read ohne Stream");
+ nRet = ERR_SWG_READ_ERROR;
+ }
+ }
+ else
+ {
+ if( sFltName.EqualsAscii( "CWW6" ) )
+ nVersion = 6;
+ else if( sFltName.EqualsAscii( "CWW7" ) )
+ nVersion = 7;
+
+ if( pStg )
+ {
+ nRet = OpenMainStream( refStrm, nOldBuffSize );
+ pIn = &refStrm;
+ }
+ else
+ {
+ OSL_ENSURE(!this, "WinWord 95/97 Reader-Read ohne Storage");
+ nRet = ERR_SWG_READ_ERROR;
+ }
+ }
+
+ if( !nRet )
+ {
+ // Alle Ueberschriften sind normalerweise ohne Kapitelnummer.
+ // Darum hier explizit abschalten weil das Default jetzt wieder auf AN ist.
+ if (bNew)
+ {
+ Reader::SetNoOutlineNum( rDoc );
+ // MIB 27.09.96: Umrandung uns Abstaende aus Frm-Vorlagen entf.
+ Reader::ResetFrmFmts( rDoc );
+ }
+ SwWW8ImplReader* pRdr = new SwWW8ImplReader(nVersion, pStg, pIn, rDoc,
+ rBaseURL, bNew);
+ try
+ {
+ nRet = pRdr->LoadDoc( rPam );
+ }
+ catch( const std::exception& )
+ {
+ nRet = ERR_WW8_NO_WW8_FILE_ERR;
+ }
+ delete pRdr;
+
+ if( refStrm.Is() )
+ {
+ refStrm->SetBufferSize( nOldBuffSize );
+ refStrm.Clear();
+ }
+ else if (pIn)
+ pIn->ResetError();
+
+ }
+ return nRet;
+}
+
+int WW8Reader::GetReaderType()
+{
+ return SW_STORAGE_READER | SW_STREAM_READER;
+}
+
+sal_Bool WW8Reader::HasGlossaries() const
+{
+ return true;
+}
+
+sal_Bool WW8Reader::ReadGlossaries(SwTextBlocks& rBlocks, sal_Bool bSaveRelFiles) const
+{
+ bool bRet=false;
+
+ WW8Reader *pThis = const_cast<WW8Reader *>(this);
+
+ sal_uInt16 nOldBuffSize = 32768;
+ SvStorageStreamRef refStrm;
+ if (!pThis->OpenMainStream(refStrm, nOldBuffSize))
+ {
+ WW8Glossary aGloss( refStrm, 8, pStg );
+ bRet = aGloss.Load( rBlocks, bSaveRelFiles ? true : false);
+ }
+ return bRet ? true : false;
+}
+
+sal_Bool SwMSDffManager::GetOLEStorageName(long nOLEId, String& rStorageName,
+ SvStorageRef& rSrcStorage, uno::Reference < embed::XStorage >& rDestStorage) const
+{
+ bool bRet = false;
+
+ long nPictureId = 0;
+ if (rReader.pStg)
+ {
+ // dann holen wir uns mal ueber den TextBox-PLCF die richtigen
+ // Char Start-/End-Positionen. In dem Bereich sollte dann
+ // das EinbettenFeld und die entsprechenden Sprms zu finden
+ // sein. Wir brauchen hier aber nur das Sprm fuer die Picture Id
+ long nOldPos = rReader.pStrm->Tell();
+ {
+ // #i32596# - consider return value of method
+ // <rReader.GetTxbxTextSttEndCp(..)>. If it returns false, method
+ // wasn't successful. Thus, continue in this case.
+ // Note: Ask MM for initialization of <nStartCp> and <nEndCp>.
+ // Note: Ask MM about assertions in method <rReader.GetTxbxTextSttEndCp(..)>.
+ WW8_CP nStartCp, nEndCp;
+ if ( rReader.GetTxbxTextSttEndCp(nStartCp, nEndCp,
+ static_cast<sal_uInt16>((nOLEId >> 16) & 0xFFFF),
+ static_cast<sal_uInt16>(nOLEId & 0xFFFF)) )
+ {
+ WW8PLCFxSaveAll aSave;
+ memset( &aSave, 0, sizeof( aSave ) );
+ rReader.pPlcxMan->SaveAllPLCFx( aSave );
+
+ nStartCp += rReader.nDrawCpO;
+ nEndCp += rReader.nDrawCpO;
+ WW8PLCFx_Cp_FKP* pChp = rReader.pPlcxMan->GetChpPLCF();
+ wwSprmParser aSprmParser(rReader.pWwFib->GetFIBVersion());
+ while (nStartCp <= nEndCp && !nPictureId)
+ {
+ WW8PLCFxDesc aDesc;
+ pChp->SeekPos( nStartCp );
+ pChp->GetSprms( &aDesc );
+
+ if (aDesc.nSprmsLen && aDesc.pMemPos) // Attribut(e) vorhanden
+ {
+ long nLen = aDesc.nSprmsLen;
+ const sal_uInt8* pSprm = aDesc.pMemPos;
+
+ while (nLen >= 2 && !nPictureId)
+ {
+ sal_uInt16 nId = aSprmParser.GetSprmId(pSprm);
+ sal_uInt16 nSL = aSprmParser.GetSprmSize(nId, pSprm);
+
+ if( nLen < nSL )
+ break; // nicht mehr genug Bytes uebrig
+
+ if( 0x6A03 == nId && 0 < nLen )
+ {
+ nPictureId = SVBT32ToUInt32(pSprm +
+ aSprmParser.DistanceToData(nId));
+ bRet = true;
+ }
+ pSprm += nSL;
+ nLen -= nSL;
+ }
+ }
+ nStartCp = aDesc.nEndPos;
+ }
+
+ rReader.pPlcxMan->RestoreAllPLCFx( aSave );
+ }
+ // <--
+ }
+ rReader.pStrm->Seek( nOldPos );
+ }
+
+ if( bRet )
+ {
+ rStorageName = '_';
+ rStorageName += String::CreateFromInt32(nPictureId);
+ rSrcStorage = rReader.pStg->OpenSotStorage(CREATE_CONST_ASC(
+ SL::aObjectPool));
+ if (!rReader.mpDocShell)
+ bRet=false;
+ else
+ rDestStorage = rReader.mpDocShell->GetStorage();
+ }
+ return bRet;
+}
+
+sal_Bool SwMSDffManager::ShapeHasText(sal_uLong, sal_uLong) const
+{
+ // Zur Zeit des Einlesens einer einzelnen Box, die womoeglich Teil einer
+ // Gruppe ist, liegen noch nicht genuegend Informationen vor, um
+ // entscheiden zu koennen, ob wir sie nicht doch als Textfeld benoetigen.
+ // Also vorsichtshalber mal alle umwandeln:
+ return true;
+}
+
+bool SwWW8ImplReader::InEqualOrHigherApo(int nLvl) const
+{
+ if (nLvl)
+ --nLvl;
+ // #i60827#
+ // check size of <maApos> to assure that <maApos.begin() + nLvl> can be performed.
+ if ( sal::static_int_cast< sal_Int32>(nLvl) >= sal::static_int_cast< sal_Int32>(maApos.size()) )
+ {
+ return false;
+ }
+ // <--
+ mycApoIter aIter = std::find(maApos.begin() + nLvl, maApos.end(), true);
+ if (aIter != maApos.end())
+ return true;
+ else
+ return false;
+}
+
+bool SwWW8ImplReader::InEqualApo(int nLvl) const
+{
+ //If we are in a table, see if an apo was inserted at the level below
+ //the table.
+ if (nLvl)
+ --nLvl;
+ return maApos[nLvl];
+}
+
+namespace sw
+{
+ namespace hack
+ {
+ Position::Position(const SwPosition &rPos)
+ : maPtNode(rPos.nNode), mnPtCntnt(rPos.nContent.GetIndex())
+ {
+ }
+
+ Position::Position(const Position &rPos)
+ : maPtNode(rPos.maPtNode), mnPtCntnt(rPos.mnPtCntnt)
+ {
+ }
+
+ Position::operator SwPosition() const
+ {
+ SwPosition aRet(maPtNode);
+ aRet.nContent.Assign(maPtNode.GetNode().GetCntntNode(), mnPtCntnt);
+ return aRet;
+ }
+ }
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par.hxx b/sw/source/filter/ww8/ww8par.hxx
new file mode 100644
index 000000000000..2851b8860a3a
--- /dev/null
+++ b/sw/source/filter/ww8/ww8par.hxx
@@ -0,0 +1,1630 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WW8PAR_HXX
+#define _WW8PAR_HXX
+
+#include <tools/string.hxx>
+#include <filter/msfilter/msdffimp.hxx>
+#include <filter/msfilter/msocximex.hxx>
+#include <editeng/frmdir.hxx>
+#include <fltshell.hxx> // fuer den Attribut Stack
+
+#include <vector>
+#include <stack>
+#include <deque>
+#include <map>
+#include <utility>
+
+#include "tracer.hxx"
+#include "ww8struc.hxx" // WW8_BRC
+#include "ww8scan.hxx" // WW8Fib
+#include "ww8glsy.hxx"
+#include "wrtww8.hxx"
+#include "../inc/msfilter.hxx"
+#include <xmloff/odffields.hxx>
+#include <IMark.hxx>
+
+class SwDoc;
+class SwPaM;
+class SfxPoolItem;
+class SwTxtFmtColl;
+class SwPageDesc;
+class SvxBoxItem;
+class SwFmt;
+class SwNodeIndex;
+class SwFlyFrmFmt;
+class SwAttrSet;
+class SwNumRule;
+class SwFrmFmt;
+class Writer;
+class SwFmtFld;
+class SwWW8StyInf;
+class WW8Fib;
+class WW8PLCFMan;
+struct WW8PLCFManResult;
+class WW8RStyle;
+class WW8PLCF_HdFt;
+class WW8Dop;
+class WW8ScannerBase;
+struct WW8FieldDesc;
+struct WW8FlyPara;
+struct WW8SwFlyPara;
+struct WW8_PIC;
+class WW8TabDesc;
+struct WW8_SHD;
+struct WW8_OLST;
+class SwNumFmt;
+struct WW8_ANLD;
+struct WW8_ANLV;
+struct WW8_DO;
+struct WW8_DPHEAD;
+struct WW8_FSPA;
+class SdrModel;
+class SdrPage;
+class SdrObject;
+class SdrTextObj;
+class Size;
+class EditEngine;
+struct SwPosition;
+class WW8ReaderSave;
+struct WW8PicDesc;
+class Graphic;
+class SwFieldType;
+class SvStorage;
+// alt: class SvStorageRef;
+class SwAttrSet;
+class GDIMetaFile;
+struct ESelection;
+class SfxItemSet;
+class _ReadFieldParams;
+class wwZOrderer;
+class OutlinerParaObject;
+
+namespace com{namespace sun {namespace star{
+ namespace beans{ class XPropertySet;}
+ namespace form { class XFormComponent;}
+ namespace drawing{class XShape;}
+ namespace lang{class XMultiServiceFactory;}
+}}}
+
+// defines nur fuer die WW8-variable der INI-Datei
+#define WW8FL_NO_TEXT 1
+#define WW8FL_NO_STYLES 2
+#define WW8FL_NO_ZSTYLES 4 // keine Zeichenstyles importieren
+#define WW8FL_NO_GRAF 0x80
+
+// falls gestetzt, werden fuer Writer-Def-Styles neue Styles mit den
+// WW8-Def-Style-Eigenschaften erzeugt, statt die Writer-Standards zu
+// ueberschreiben
+#define WW8FL_NO_DEFSTYLES 0x400
+
+#define WW8FL_NO_OUTLINE 0x1000
+#define WW8FL_NO_IMPLPASP 0x4000 // no implicit para space
+#define WW8FL_NO_GRAFLAYER 0x8000
+
+// Zusatz-Filter-Flags, gueltig ab Winword 8
+#define WW8FL_NO_FLY_FOR_TXBX 1
+
+//-----------------------------------------
+// Listen-Manager (ab Ver8)
+//-----------------------------------------
+
+struct WW8LFOInfo;
+typedef WW8LFOInfo* WW8LFOInfo_Ptr;
+// Redlining: match WinWord author ids to StarWriter author ids
+struct WW8OleMap;
+typedef WW8OleMap* WW8OleMap_Ptr;
+
+SV_DECL_PTRARR_DEL(WW8LFOInfos,WW8LFOInfo_Ptr,16,16)
+// SV_DECL_PTRARR_SORT_DEL(WW8AuthorInfos, WW8AuthorInfo_Ptr,16,16)
+SV_DECL_PTRARR_SORT_DEL(WW8OleMaps, WW8OleMap_Ptr,16,16)
+
+class WW8Reader : public StgReader
+{
+ virtual sal_uLong Read(SwDoc &, const String& rBaseURL, SwPaM &,const String &);
+ sal_uLong OpenMainStream( SvStorageStreamRef& rRef, sal_uInt16& rBuffSize );
+public:
+ virtual int GetReaderType();
+
+ virtual sal_Bool HasGlossaries() const;
+ virtual sal_Bool ReadGlossaries( SwTextBlocks&, sal_Bool bSaveRelFiles ) const;
+};
+
+struct WW8OleMap
+{
+ sal_uInt32 mnWWid;
+ String msStorageName;
+
+ WW8OleMap(sal_uInt32 nWWid)
+ : mnWWid(nWWid) {}
+
+ WW8OleMap(sal_uInt32 nWWid, String sStorageName)
+ : mnWWid(nWWid), msStorageName(sStorageName) {}
+
+ bool operator==(const WW8OleMap & rEntry) const
+ {
+ return (mnWWid == rEntry.mnWWid);
+ }
+ bool operator<(const WW8OleMap & rEntry) const
+ {
+ return (mnWWid < rEntry.mnWWid);
+ }
+};
+
+class SwWW8ImplReader;
+struct WW8LSTInfo;
+class WW8ListManager
+{
+public:
+ WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_);
+ //Min and Max possible List Levels in Word
+ enum ListLevel {nMinLevel=1, nMaxLevel=9};
+ //the rParaSprms returns back the original word paragraph indent
+ //sprms which were attached to the original numbering format
+ SwNumRule* GetNumRuleForActivation(sal_uInt16 nLFOPosition, const sal_uInt8 nLevel,
+ std::vector<sal_uInt8> &rParaSprms, SwTxtNode *pNode=0);
+ SwNumRule* CreateNextRule(bool bSimple);
+ ~WW8ListManager();
+private:
+ wwSprmParser maSprmParser;
+ SwWW8ImplReader& rReader;
+ SwDoc& rDoc;
+ const WW8Fib& rFib;
+ SvStream& rSt;
+ std::vector<WW8LSTInfo* > maLSTInfos;
+ WW8LFOInfos* pLFOInfos;// D. aus PLF LFO, sortiert genau wie im WW8 Stream
+ sal_uInt16 nUniqueList; // current number for creating unique list names
+ sal_uInt8* GrpprlHasSprm(sal_uInt16 nId, sal_uInt8& rSprms, sal_uInt8 nLen);
+ WW8LSTInfo* GetLSTByListId( sal_uInt32 nIdLst ) const;
+ //the rParaSprms returns back the original word paragraph indent
+ //sprms which are attached to this numbering level
+ bool ReadLVL(SwNumFmt& rNumFmt, SfxItemSet*& rpItemSet, sal_uInt16 nLevelStyle,
+ bool bSetStartNo, std::deque<bool> &rNotReallyThere, sal_uInt16 nLevel,
+ std::vector<sal_uInt8> &rParaSprms);
+
+ // Zeichenattribute aus GrpprlChpx
+ typedef SfxItemSet* WW8aISet[nMaxLevel];
+ // Zeichen Style Pointer
+ typedef SwCharFmt* WW8aCFmt[nMaxLevel];
+
+ void AdjustLVL(sal_uInt8 nLevel, SwNumRule& rNumRule, WW8aISet& rListItemSet,
+ WW8aCFmt& aCharFmt, bool& bNewCharFmtCreated,
+ String aPrefix = aEmptyStr);
+
+ //No copying
+ WW8ListManager(const WW8ListManager&);
+ WW8ListManager& operator=(const WW8ListManager&);
+ sal_uInt16 nLastLFOPosition;
+};
+
+//-----------------------------------------
+// Stack
+//-----------------------------------------
+class SwWW8FltControlStack : public SwFltControlStack
+{
+private:
+ SwWW8ImplReader& rReader;
+ sal_uInt16 nToggleAttrFlags;
+ sal_uInt16 nToggleBiDiAttrFlags;
+ //No copying
+ SwWW8FltControlStack(const SwWW8FltControlStack&);
+ SwWW8FltControlStack& operator=(const SwWW8FltControlStack&);
+ const SwNumFmt* GetNumFmtFromStack(const SwPosition &rPos,
+ const SwTxtNode &rTxtNode);
+protected:
+ virtual void SetAttrInDoc(const SwPosition& rTmpPos,
+ SwFltStackEntry* pEntry);
+
+public:
+ SwWW8FltControlStack(SwDoc* pDo, sal_uLong nFieldFl, SwWW8ImplReader& rReader_ )
+ : SwFltControlStack( pDo, nFieldFl ), rReader( rReader_ ),
+ nToggleAttrFlags(0), nToggleBiDiAttrFlags(0)
+ {}
+
+ void NewAttr(const SwPosition& rPos, const SfxPoolItem& rAttr);
+
+ virtual void SetAttr(const SwPosition& rPos, sal_uInt16 nAttrId=0, sal_Bool bTstEnde=sal_True, long nHand=LONG_MAX, sal_Bool consumedByField=sal_False);
+
+ void SetToggleAttr(sal_uInt8 nId, bool bOn)
+ {
+ if( bOn )
+ nToggleAttrFlags |= (1 << nId);
+ else
+ nToggleAttrFlags &= ~(1 << nId);
+ }
+
+ sal_uInt16 GetToggleAttrFlags() const { return nToggleAttrFlags; }
+
+ void SetToggleBiDiAttr(sal_uInt8 nId, bool bOn)
+ {
+ if( bOn )
+ nToggleBiDiAttrFlags |= (1 << nId);
+ else
+ nToggleBiDiAttrFlags &= ~(1 << nId);
+ }
+
+ sal_uInt16 GetToggleBiDiAttrFlags() const { return nToggleBiDiAttrFlags; }
+ void SetToggleAttrFlags(sal_uInt16 nFlags) { nToggleAttrFlags = nFlags; }
+ void SetToggleBiDiAttrFlags(sal_uInt16 nFlags) {nToggleBiDiAttrFlags = nFlags;}
+
+ const SfxPoolItem* GetFmtAttr(const SwPosition& rPos, sal_uInt16 nWhich);
+ const SfxPoolItem* GetStackAttr(const SwPosition& rPos, sal_uInt16 nWhich);
+};
+
+//The only thing this is for is RES_FLTR_ANCHOR, anything else is an error.
+//For graphics whose anchoring position would otherwise be automatically moved
+//along by the insertion of text.
+class SwWW8FltAnchorStack : public SwFltControlStack
+{
+public:
+ SwWW8FltAnchorStack(SwDoc* pDo, sal_uLong nFieldFl)
+ : SwFltControlStack( pDo, nFieldFl ) {}
+ void AddAnchor(const SwPosition& rPos,SwFrmFmt *pFmt);
+ void Flush();
+private:
+ //No copying
+ SwWW8FltAnchorStack(const SwWW8FltAnchorStack&);
+ SwWW8FltAnchorStack& operator=(const SwWW8FltAnchorStack&);
+};
+
+//For fields whose handling cannot be fully resolved until we hit the end of
+//the document.
+class Position
+{
+public:
+ SwNodeIndex maMkNode;
+ SwNodeIndex maPtNode;
+ xub_StrLen mnMkCntnt;
+ xub_StrLen mnPtCntnt;
+ Position(const SwPaM &rPaM);
+ Position(const Position &rEntry);
+private:
+ //No assignment
+ Position& operator=(const Position&);
+};
+
+class SwWW8FltRefStack : public SwFltEndStack
+{
+public:
+ SwWW8FltRefStack(SwDoc* pDo, sal_uLong nFieldFl)
+ : SwFltEndStack( pDo, nFieldFl )
+ {}
+ bool IsFtnEdnBkmField(const SwFmtFld& rFmtFld, sal_uInt16& rBkmNo);
+
+ struct ltstr
+ {
+ bool operator()(const String &r1, const String &r2) const
+ {
+ return r1.CompareIgnoreCaseToAscii(r2) == COMPARE_LESS;
+ }
+ };
+ //Keep track of variable names created with fields, and the bookmark
+ //mapped to their position, hopefully the same, but very possibly
+ //an additional pseudo bookmark
+ std::map<String, String, ltstr> aFieldVarNames;
+protected:
+ SwFltStackEntry *RefToVar(const SwField* pFld,SwFltStackEntry *pEntry);
+ virtual void SetAttrInDoc(const SwPosition& rTmpPos,
+ SwFltStackEntry* pEntry);
+private:
+ //No copying
+ SwWW8FltRefStack(const SwWW8FltRefStack&);
+ SwWW8FltRefStack& operator=(const SwWW8FltRefStack&);
+};
+
+
+namespace sw
+{
+ namespace hack
+ {
+ class Position
+ {
+ private:
+ SwNodeIndex maPtNode;
+ xub_StrLen mnPtCntnt;
+ public:
+ Position(const SwPosition &rPos);
+ Position(const Position &rPos);
+ operator SwPosition() const;
+ SwNodeIndex GetPtNode() { return maPtNode; };
+ xub_StrLen GetPtCntnt() { return mnPtCntnt; };
+ };
+ }
+}
+
+class FieldEntry
+{
+ private:
+ ::rtl::OUString msBookmarkName;
+ ::rtl::OUString msMarkType;
+ ::rtl::OUString msMarkCode;
+ ::sw::mark::IFieldmark::parameter_map_t maParams;
+
+ public:
+ sw::hack::Position maStartPos;
+ sal_uInt16 mnFieldId;
+ sal_uLong mnObjLocFc;
+ FieldEntry(SwPosition &rPos, sal_uInt16 nFieldId) throw();
+ FieldEntry(const FieldEntry &rOther) throw();
+ FieldEntry &operator=(const FieldEntry &rOther) throw();
+ void Swap(FieldEntry &rOther) throw();
+
+ SwNodeIndex GetPtNode() { return maStartPos.GetPtNode(); };
+ xub_StrLen GetPtCntnt() { return maStartPos.GetPtCntnt(); };
+
+ ::rtl::OUString GetBookmarkName();
+ ::rtl::OUString GetBookmarkType();
+ ::rtl::OUString GetBookmarkCode();
+ void SetBookmarkName(::rtl::OUString bookmarkName);
+ void SetBookmarkType(::rtl::OUString bookmarkType);
+ void SetBookmarkCode(::rtl::OUString bookmarkCode);
+ ::sw::mark::IFieldmark::parameter_map_t& getParameters();
+};
+
+
+//-----------------------------------------
+// Mini-Merker fuer einige Flags
+//-----------------------------------------
+class WW8ReaderSave
+{
+private:
+ WW8PLCFxSaveAll maPLCFxSave;
+ SwPosition maTmpPos;
+ std::deque<bool> maOldApos;
+ std::deque<FieldEntry> maOldFieldStack;
+ SwWW8FltControlStack* mpOldStck;
+ SwWW8FltAnchorStack* mpOldAnchorStck;
+ sw::util::RedlineStack *mpOldRedlines;
+ WW8PLCFMan* mpOldPlcxMan;
+ WW8FlyPara* mpWFlyPara;
+ WW8SwFlyPara* mpSFlyPara;
+ SwPaM* mpPreviousNumPaM;
+ const SwNumRule* mpPrevNumRule;
+ WW8TabDesc* mpTableDesc;
+ int mnInTable;
+ sal_uInt16 mnAktColl;
+ sal_Unicode mcSymbol;
+ bool mbIgnoreText;
+ bool mbSymbol;
+ bool mbHdFtFtnEdn;
+ bool mbTxbxFlySection;
+ bool mbAnl;
+ bool mbInHyperlink;
+ bool mbPgSecBreak;
+ bool mbWasParaEnd;
+ bool mbHasBorder;
+ bool mbFirstPara;
+public:
+ WW8ReaderSave(SwWW8ImplReader* pRdr, WW8_CP nStart=-1);
+ void Restore(SwWW8ImplReader* pRdr);
+ const SwPosition &GetStartPos() const { return maTmpPos; }
+};
+
+enum eF_ResT{ FLD_OK, FLD_TEXT, FLD_TAGIGN, FLD_TAGTXT, FLD_READ_FSPA };
+
+class SwWW8Shade
+{
+public:
+ Color aColor;
+ SwWW8Shade(bool bVer67, const WW8_SHD& rSHD);
+ SwWW8Shade(ColorData nFore, ColorData nBack, sal_uInt16 nIndex)
+ {
+ SetShade(nFore, nBack, nIndex);
+ }
+private:
+ void SetShade(ColorData nFore, ColorData nBack, sal_uInt16 nIndex);
+};
+
+
+//-----------------------------------------
+// Formulas
+//-----------------------------------------
+enum SwWw8ControlType
+{
+ WW8_CT_EDIT,
+ WW8_CT_CHECKBOX,
+ WW8_CT_DROPDOWN
+};
+
+
+class WW8FormulaControl : public OCX_Control
+{
+protected:
+ SwWW8ImplReader &rRdr;
+public:
+ WW8FormulaControl(const String& rN, SwWW8ImplReader &rR)
+ : OCX_Control(rN), rRdr(rR), fUnknown(0), fDropdownIndex(0),
+ fToolTip(0), fNoMark(0), fUseSize(0), fNumbersOnly(0), fDateOnly(0),
+ fUnused(0), nSize(0), hpsCheckBox(20), nChecked(0)
+ {
+ }
+ sal_uInt8 fUnknown:2;
+ sal_uInt8 fDropdownIndex:6;
+ sal_uInt8 fToolTip:1;
+ sal_uInt8 fNoMark:1;
+ sal_uInt8 fUseSize:1;
+ sal_uInt8 fNumbersOnly:1;
+ sal_uInt8 fDateOnly:1;
+ sal_uInt8 fUnused:3;
+ sal_uInt16 nSize;
+
+ sal_uInt16 hpsCheckBox;
+ sal_uInt16 nChecked;
+ sal_uInt16 nDefaultChecked;
+
+ String sTitle;
+ String sDefault;
+ String sFormatting;
+ String sHelp;
+ String sToolTip;
+ std::vector<String> maListEntries;
+ virtual ~WW8FormulaControl() {}
+ void FormulaRead(SwWw8ControlType nWhich,SvStream *pD);
+private:
+ //No copying
+ WW8FormulaControl(const WW8FormulaControl&);
+ WW8FormulaControl& operator=(const WW8FormulaControl&);
+};
+
+class WW8FormulaCheckBox : public WW8FormulaControl
+{
+private:
+ //No copying
+ WW8FormulaCheckBox(const WW8FormulaCheckBox&);
+ WW8FormulaCheckBox& operator=(const WW8FormulaCheckBox&);
+
+ using OCX_Control::Import;
+
+public:
+ WW8FormulaCheckBox(SwWW8ImplReader &rR);
+
+ virtual sal_Bool Import(const com::sun::star::uno::Reference <
+ com::sun::star::lang::XMultiServiceFactory> &rServiceFactory,
+ com::sun::star::uno::Reference <
+ com::sun::star::form::XFormComponent> &rFComp,
+ com::sun::star::awt::Size &rSz);
+};
+
+class WW8FormulaListBox : public WW8FormulaControl
+{
+private:
+ //No copying
+ WW8FormulaListBox(const WW8FormulaListBox&);
+ WW8FormulaListBox& operator=(const WW8FormulaListBox&);
+
+ using OCX_Control::Import;
+
+public:
+ WW8FormulaListBox(SwWW8ImplReader &rR);
+
+ virtual sal_Bool Import(const com::sun::star::uno::Reference <
+ com::sun::star::lang::XMultiServiceFactory> &rServiceFactory,
+ com::sun::star::uno::Reference <
+ com::sun::star::form::XFormComponent> &rFComp,
+ com::sun::star::awt::Size &rSz);
+};
+
+class WW8FormulaEditBox : public WW8FormulaControl
+{
+private:
+ //No copying
+ WW8FormulaEditBox(const WW8FormulaEditBox&);
+ WW8FormulaEditBox& operator=(const WW8FormulaEditBox&);
+public:
+ WW8FormulaEditBox(SwWW8ImplReader &rR);
+};
+
+class SwMSConvertControls: public SvxMSConvertOCXControls
+{
+public:
+ SwMSConvertControls( SfxObjectShell *pDSh,SwPaM *pP ) :
+ SvxMSConvertOCXControls( pDSh,pP ) {}
+ virtual sal_Bool InsertFormula( WW8FormulaControl &rFormula);
+ virtual sal_Bool InsertControl(const com::sun::star::uno::Reference<
+ com::sun::star::form::XFormComponent >& rFComp,
+ const ::com::sun::star::awt::Size& rSize,
+ com::sun::star::uno::Reference <
+ com::sun::star::drawing::XShape > *pShape,sal_Bool bFloatingCtrl);
+ bool ExportControl(WW8Export &rWrt, const SdrObject *pObj);
+};
+
+class SwMSDffManager : public SvxMSDffManager
+{
+private:
+ SwWW8ImplReader& rReader;
+ SvStream *pFallbackStream;
+ List *pOldEscherBlipCache;
+
+ virtual sal_Bool GetOLEStorageName( long nOLEId, String& rStorageName,
+ SvStorageRef& rSrcStorage, com::sun::star::uno::Reference < com::sun::star::embed::XStorage >& rDestStorage ) const;
+ virtual sal_Bool ShapeHasText( sal_uLong nShapeId, sal_uLong nFilePos ) const;
+ // #i32596# - new parameter <_nCalledByGroup>, which
+ // indicates, if the OLE object is imported inside a group object
+ virtual SdrObject* ImportOLE( long nOLEId,
+ const Graphic& rGrf,
+ const Rectangle& rBoundRect,
+ const Rectangle& rVisArea,
+ const int _nCalledByGroup,
+ sal_Int64 nAspect ) const;
+ // <--
+
+ //No copying
+ SwMSDffManager(const SwMSDffManager&);
+ SwMSDffManager& operator=(const SwMSDffManager&);
+public:
+ static sal_uInt32 GetFilterFlags();
+ static sal_Int32 GetEscherLineMatch(MSO_LineStyle eStyle, MSO_SPT eShapeType,
+ sal_Int32 &rThick);
+ SwMSDffManager( SwWW8ImplReader& rRdr );
+ void DisableFallbackStream();
+ void EnableFallbackStream();
+protected:
+ virtual SdrObject* ProcessObj( SvStream& rSt, DffObjData& rObjData, void* pData, Rectangle& rTextRect, SdrObject* pObj );
+};
+
+
+class wwSection
+{
+public:
+ wwSection(const SwPosition &rPos);
+ SEPr maSep;
+ WW8_BRC brc[4];
+ SwNodeIndex maStart;
+ SwSection *mpSection;
+ SwPageDesc *mpTitlePage;
+ SwPageDesc *mpPage;
+ SvxFrameDirection meDir;
+ short mLinkId;
+
+ sal_uInt32 nPgWidth;
+ sal_uInt32 nPgLeft;
+ sal_uInt32 nPgRight;
+
+ sal_uInt8 mnBorders;
+ bool mbHasFootnote;
+ void SetDirection();
+ void SetLinkId(short sLinkId) { mLinkId = sLinkId; }
+ bool DoesContainFootnote() const { return mbHasFootnote; }
+ bool IsContinous() const { return maSep.bkc == 0; }
+ bool IsLinked() const { return mLinkId != 0; }
+ bool IsNotProtected() const { return maSep.fUnlocked != 0; }
+ bool IsVertical() const;
+ sal_Int16 NoCols() const { return maSep.ccolM1 + 1; }
+ sal_Int32 StandardColSeperation() const { return maSep.dxaColumns; }
+ bool HasTitlePage() const { return maSep.fTitlePage ? true : false; }
+ sal_uInt16 PageStartAt() const { return maSep.pgnStart; }
+ bool PageRestartNo() const { return maSep.fPgnRestart ? true : false; }
+ bool IsBiDi() const { return maSep.fBiDi ? true : false; }
+ sal_uInt32 GetPageWidth() const { return nPgWidth; }
+ sal_uInt32 GetTextAreaWidth() const
+ { return GetPageWidth() - GetPageLeft() - GetPageRight(); }
+ sal_uInt32 GetPageHeight() const { return maSep.yaPage; }
+ sal_uInt32 GetPageLeft() const { return nPgLeft; }
+ sal_uInt32 GetPageRight() const { return nPgRight; }
+ bool IsLandScape() const { return maSep.dmOrientPage ? true : false; }
+ bool IsFixedHeightHeader() const { return maSep.dyaTop < 0; }
+ bool IsFixedHeightFooter() const { return maSep.dyaBottom < 0; }
+};
+
+class wwSectionManager
+{
+private:
+ /*
+ A queue of the ms sections in the document
+ */
+ SwWW8ImplReader& mrReader;
+ std::deque<wwSection> maSegments;
+ typedef ::std::deque<wwSection>::iterator mySegIter;
+ typedef ::std::deque<wwSection>::reverse_iterator mySegrIter;
+
+ //Num of page desc's entered into the document
+ sal_uInt16 mnDesc;
+
+ struct wwULSpaceData
+ {
+ bool bHasHeader, bHasFooter;
+ sal_uInt32 nSwHLo, nSwFUp, nSwUp, nSwLo;
+ wwULSpaceData() : bHasHeader(false), bHasFooter(false) {}
+ };
+
+ void SetSegmentToPageDesc(const wwSection &rSection, bool bTitlePage,
+ bool bIgnoreCols);
+
+ void GetPageULData(const wwSection &rNewSection, bool bFirst,
+ wwULSpaceData& rData) const;
+ void SetPageULSpaceItems(SwFrmFmt &rFmt, wwULSpaceData& rData,
+ const wwSection &rSection) const;
+
+ void SetPage(SwPageDesc &rPageDesc, SwFrmFmt &rFmt,
+ const wwSection &rSection, bool bIgnoreCols) const;
+
+ void SetNumberingType(const wwSection &rNewSection, SwPageDesc &rPageDesc)
+ const;
+
+ void SetUseOn(wwSection &rSection);
+ void SetHdFt(wwSection &rSection, int nSect, const wwSection *pPrevious);
+
+ SwSectionFmt *InsertSection(SwPaM& rMyPaM, wwSection &rSection);
+ bool SetCols(SwFrmFmt &rFmt, const wwSection &rSection,
+ sal_uInt32 nNettoWidth) const;
+ bool SectionIsProtected(const wwSection &rSection) const;
+ void SetLeftRight(wwSection &rSection);
+ bool IsNewDoc() const;
+ /*
+ The segment we're inserting, the start of the segments container, and the
+ nodeindex of where we want the page break to (normally the segments start
+ position
+ */
+ SwFmtPageDesc SetSwFmtPageDesc(mySegIter &rIter, mySegIter &rStart,
+ bool bIgnoreCols);
+
+ //No copying
+ wwSectionManager(const wwSectionManager&);
+ wwSectionManager& operator=(const wwSectionManager&);
+public:
+ wwSectionManager(SwWW8ImplReader &rReader) : mrReader(rReader), mnDesc(0)
+ {};
+ void SetCurrentSectionHasFootnote();
+ bool CurrentSectionIsVertical() const;
+ bool CurrentSectionIsProtected() const;
+ void PrependedInlineNode(const SwPosition &rPos, const SwNode &rNode);
+ sal_uInt16 CurrentSectionColCount() const;
+ bool WillHavePageDescHere(SwNodeIndex aIdx) const;
+ void CreateSep(const long nTxtPos, bool bMustHaveBreak);
+ void InsertSegments();
+ void JoinNode(const SwPosition &rPos, const SwNode &rNode);
+ sal_uInt32 GetPageLeft() const;
+ sal_uInt32 GetPageRight() const;
+ sal_uInt32 GetPageWidth() const;
+ sal_uInt32 GetWWPageTopMargin() const;
+ bool empty() const { return maSegments.empty(); }
+ sal_uInt32 GetTextAreaWidth() const;
+};
+
+class wwFrameNamer
+{
+private:
+ String msSeed;
+ int mnImportedGraphicsCount;
+ bool mbIsDisabled;
+ //No copying
+ wwFrameNamer(const wwFrameNamer&);
+ wwFrameNamer& operator=(const wwFrameNamer&);
+public:
+ void SetUniqueGraphName(SwFrmFmt *pFrmFmt,const String &rFixedPart);
+ wwFrameNamer(bool bIsDisabled, const String &rSeed)
+ : msSeed(rSeed), mnImportedGraphicsCount(0), mbIsDisabled(bIsDisabled)
+ { }
+};
+
+class wwSectionNamer
+{
+private:
+ const SwDoc &mrDoc;
+ String msFileLinkSeed;
+ int mnFileSectionNo;
+ //No copying
+ wwSectionNamer(const wwSectionNamer&);
+ wwSectionNamer& operator=(const wwSectionNamer&);
+public:
+ String UniqueName();
+ wwSectionNamer(const SwDoc &rDoc, const String &rSeed)
+ : mrDoc(rDoc), msFileLinkSeed(rSeed), mnFileSectionNo(0)
+ { }
+};
+
+class FtnDescriptor
+{
+public:
+ ManTypes meType;
+ bool mbAutoNum;
+ WW8_CP mnStartCp;
+ WW8_CP mnLen;
+};
+
+struct ApoTestResults
+{
+ bool mbStartApo;
+ bool mbStopApo;
+ const sal_uInt8* mpSprm37;
+ const sal_uInt8* mpSprm29;
+ WW8FlyPara* mpStyleApo;
+ ApoTestResults() :
+ mbStartApo(false), mbStopApo(false), mpSprm37(0), mpSprm29(0),
+ mpStyleApo(0) {}
+ bool HasStartStop() const { return (mbStartApo || mbStopApo); }
+ bool HasFrame() const { return (mpSprm29 || mpSprm37 || mpStyleApo); }
+};
+
+struct ANLDRuleMap
+{
+ SwNumRule* mpOutlineNumRule; // WinWord 6 numbering, varient 1
+ SwNumRule* mpNumberingNumRule; // WinWord 6 numbering, varient 2
+ SwNumRule* GetNumRule(sal_uInt8 nNumType);
+ void SetNumRule(SwNumRule*, sal_uInt8 nNumType);
+ ANLDRuleMap() : mpOutlineNumRule(0), mpNumberingNumRule(0) {}
+};
+
+struct SprmReadInfo;
+class SwDocShell;
+struct WW8PostProcessAttrsInfo
+{
+ bool mbCopy;
+ WW8_CP mnCpStart;
+ WW8_CP mnCpEnd;
+ SwPaM mPaM;
+ SfxItemSet mItemSet;
+
+ WW8PostProcessAttrsInfo(WW8_CP nCpStart, WW8_CP nCpEnd, SwPaM & rPaM);
+};
+
+//-----------------------------------------
+// Storage-Reader
+//-----------------------------------------
+class SwWW8ImplReader
+{
+private:
+ SwDocShell *mpDocShell; // The Real DocShell
+
+friend class WW8RStyle;
+friend class WW8TabDesc;
+friend class WW8ReaderSave;
+friend struct WW8FlyPara;
+friend struct WW8SwFlyPara;
+friend class WW8FlySet;
+friend class SwMSDffManager;
+friend class SwWW8FltControlStack;
+friend class WW8FormulaControl;
+friend class wwSectionManager;
+
+public:
+ /*
+ To log unimplemented features
+ */
+ sw::log::Tracer maTracer;
+private:
+
+ SvStorage* pStg; // Input-Storage
+ SvStream* pStrm; // Input-(Storage)Stream
+ SvStream* pTableStream; // Input-(Storage)Stream
+ SvStream* pDataStream; // Input-(Storage)Stream
+
+// allgemeines
+ SwDoc& rDoc;
+ SwPaM* pPaM;
+
+ SwWW8FltControlStack* pCtrlStck; // Stack fuer die Attribute
+
+ /*
+ This stack is for redlines, because their sequence of discovery can
+ be out of order of their order of insertion into the document.
+ */
+ sw::util::RedlineStack *mpRedlineStack;
+
+ /*
+ This stack is for fields that get referneced later, e.g. BookMarks and TOX.
+ They get inserted at the end of the document, it is the same stack for
+ headers/footers/main text/textboxes/tables etc...
+ */
+ SwFltEndStack *pReffedStck;
+
+ /*
+ This stack is for fields whose true conversion cannot be determined until
+ the end of the document, it is the same stack for headers/footers/main
+ text/textboxes/tables etc... They are things that reference other things
+ e.g. NoteRef and Ref, they are processed after pReffedStck
+ */
+ SwWW8FltRefStack *pReffingStck;
+
+ /*
+ For graphics anchors. Determines the graphics whose anchors are in the
+ current paragraph, and works around the difficulty in inserting a graphic
+ anchored to character before a character to be anchored to has been
+ inserted. Is emptied at the end of each paragraph.
+ */
+ SwWW8FltAnchorStack* pAnchorStck;
+
+ /*
+ A stack of fields identifiers to keep track of any open fields that need
+ to be closed. Generally word fields are inserted as writer fields as soon
+ as they are encountered, and so their end point is normally unimportant.
+ But hyperlink fields need to be applied as attributes to text and it is
+ far easier and safer to set the end point of an attribute when we
+ encounter the end marker of the field instead of caculating in advance
+ where the end point will fall, to do so fully correctly duplicates the
+ main logic of the filter itself.
+ */
+ std::deque<FieldEntry> maFieldStack;
+ typedef std::deque<FieldEntry>::const_iterator mycFieldIter;
+
+ /*
+ A stack of open footnotes. Should only be one in it at any time.
+ */
+ std::deque<FtnDescriptor> maFtnStack;
+
+ /*
+ A queue of the ms sections in the document
+ */
+ wwSectionManager maSectionManager;
+
+ /*
+ A map of of tables to their follow nodes for use in inserting tables into
+ already existing document, i.e. insert file
+ */
+ sw::util::InsertedTablesManager maInsertedTables;
+
+ /*
+ Creates unique names to give to (file link) sections (WW1/WW2/...)
+ */
+ wwSectionNamer maSectionNameGenerator;
+
+ /*
+ Knows how to split a series of bytes into sprms and their arguments
+ */
+ wwSprmParser *mpSprmParser;
+
+ /*
+ Creates unique names to give to graphics
+ */
+ wwFrameNamer maGrfNameGenerator;
+
+ /*
+ Knows which writer style a given word style should be imported as.
+ */
+ sw::util::ParaStyleMapper maParaStyleMapper;
+ sw::util::CharStyleMapper maCharStyleMapper;
+
+ /*
+ Stack of textencoding being used as we progress through the document text
+ */
+ std::stack<rtl_TextEncoding> maFontSrcCharSets;
+ std::stack<rtl_TextEncoding> maFontSrcCJKCharSets;
+
+ /*
+ Winword numbering gets imported as SwNumRules, there is a problem that
+ winword can have multiple outline numberings, only one gets chosen as
+ the writer outline numbering rule. The one that gets chosen is set here
+ as mpChosenOutlineNumRule
+ */
+ SwNumRule *mpChosenOutlineNumRule;
+
+ SwMSConvertControls *pFormImpl; // Control-Implementierung
+
+ SwFlyFrmFmt* pFlyFmtOfJustInsertedGraphic;
+ SwFrmFmt* pFmtOfJustInsertedApo;
+ SwPaM* pPreviousNumPaM;
+ const SwNumRule* pPrevNumRule;
+
+ //Keep track of APO environments
+ std::deque<bool> maApos;
+ typedef std::deque<bool>::const_iterator mycApoIter;
+ /*
+ Keep track of generated Ruby character formats we we can minimize the
+ number of character formats created
+ */
+ std::vector<const SwCharFmt*> aRubyCharFmts;
+
+ WW8PostProcessAttrsInfo * mpPostProcessAttrsInfo;
+
+ WW8Fib* pWwFib;
+ WW8Fonts* pFonts;
+ WW8Dop* pWDop;
+ WW8ListManager* pLstManager;
+ WW8ScannerBase* pSBase;
+ WW8PLCFMan* pPlcxMan;
+ std::map<short, String> aLinkStringMap;
+
+ std::set<const SwNode*> maTxtNodesHavingFirstLineOfstSet; // #i103711#
+ std::set<const SwNode*> maTxtNodesHavingLeftIndentSet; // #i105414#
+
+ WW8RStyle* pStyles; // Pointer auf die Style-Einleseklasse
+ SwFmt* pAktColl; // gerade zu erzeugende Collection
+ // ( ist ausserhalb einer Style-Def immer 0 )
+ SfxItemSet* pAktItemSet;// gerade einzulesende Zeichenattribute
+ // (ausserhalb des WW8ListManager Ctor's immer 0)
+ SwWW8StyInf* pCollA; // UEbersetzungs-Array der Styles
+ const SwTxtFmtColl* pDfltTxtFmtColl; // Default
+ SwFmt* pStandardFmtColl;// "Standard"
+
+ WW8PLCF_HdFt* pHdFt; // Pointer auf Header / Footer - Scannerklasse
+
+ WW8FlyPara* pWFlyPara; // WW-Parameter
+ WW8SwFlyPara* pSFlyPara; // daraus erzeugte Sw-Parameter
+
+ WW8TabDesc* pTableDesc; // Beschreibung der Tabelleneigenschaften
+ //Keep track of tables within tables
+ std::stack<WW8TabDesc*> maTableStack;
+
+ ANLDRuleMap maANLDRules;
+ WW8_OLST* pNumOlst; // Gliederung im Text
+
+ SwNode* pNode_FLY_AT_PARA; // set: WW8SwFlyPara() read: CreateSwTable()
+
+ SdrModel* pDrawModel;
+ SdrPage* pDrawPg;
+ EditEngine* mpDrawEditEngine;
+ wwZOrderer *pWWZOrder;
+
+ SwFieldType* pNumFldType; // fuer Nummernkreis
+
+ SwMSDffManager* pMSDffManager;
+
+ std::vector<String>* mpAtnNames;
+
+ sw::util::AuthorInfos* pAuthorInfos;
+ String sBaseURL;
+
+ // Ini-Flags:
+ sal_uLong nIniFlags; // Flags aus der writer.ini
+ sal_uLong nIniFlags1; // dito ( zusaetzliche Flags )
+ sal_uLong nFieldFlags; // dito fuer Feldern
+ sal_uLong nFieldTagAlways[3]; // dito fuers Taggen von Feldern
+ sal_uLong nFieldTagBad[3]; // dito fuers Taggen von nicht importierbaren F.
+ bool m_bRegardHindiDigits; // import digits in CTL scripts as Hindi numbers
+
+ WW8_CP nDrawCpO; // Anfang der Txbx-SubDocs
+
+ sal_uLong nPicLocFc; // Picture Location in File (FC)
+ sal_uLong nObjLocFc; // Object Location in File (FC)
+
+ sal_Int32 nIniFlyDx; // X-Verschiebung von Flys
+ sal_Int32 nIniFlyDy; // Y-Verschiebung von Flys
+
+ rtl_TextEncoding eTextCharSet; // Default charset for Text
+ rtl_TextEncoding eStructCharSet; // rtl_TextEncoding for structures
+ rtl_TextEncoding eHardCharSet; // Hard rtl_TextEncoding-Attribute
+ sal_uInt16 nProgress; // %-Angabe fuer Progressbar
+ sal_uInt16 nColls; // Groesse des Arrays
+ sal_uInt16 nAktColl; // gemaess WW-Zaehlung
+ sal_uInt16 nFldNum; // laufende Nummer dafuer
+ sal_uInt16 nLFOPosition;
+
+ short nCharFmt; // gemaess WW-Zaehlung, <0 fuer keine
+
+ short nDrawXOfs, nDrawYOfs;
+ short nDrawXOfs2, nDrawYOfs2;
+
+ sal_Unicode cSymbol; // aktuell einzulesendes Symbolzeichen
+
+
+ sal_uInt8 nWantedVersion; // urspruenglich vom Writer
+ // angeforderte WW-Doc-Version
+
+
+ sal_uInt8 nSwNumLevel; // LevelNummer fuer Outline / Nummerierung
+ sal_uInt8 nWwNumType; // Gliederung / Nummerg / Aufzaehlg
+ sal_uInt8 nListLevel;
+
+ sal_uInt8 nPgChpDelim; // ChapterDelim from PageNum
+ sal_uInt8 nPgChpLevel; // ChapterLevel of Heading from PageNum
+
+ bool mbNewDoc; // Neues Dokument ?
+ bool bReadNoTbl; // Keine Tabellen
+ bool bPgSecBreak; // Page- oder Sectionbreak ist noch einzufuegen
+ bool bSpec; // Special-Char im Text folgt
+ bool bObj; // Obj im Text
+ bool bTxbxFlySection; // FlyFrame, der als Ersatz fuer Winword Textbox eingefuegt wurde
+ bool bHasBorder; // fuer Buendelung der Border
+ bool bSymbol; // z.B. Symbol statt Times
+ bool bIgnoreText; // z.B. fuer FieldVanish
+ int nInTable; // wird gerade eine Tabelle eingelesen
+ bool bWasTabRowEnd; // Tabelle : Row End Mark
+ bool bWasTabCellEnd; // table: Cell End Mark
+
+ bool bShdTxtCol; // Textfarbe indirekt gesetzt ( Hintergrund sw )
+ bool bCharShdTxtCol; // Textfarbe indirekt gesetzt ( Zeichenhintergrund sw )
+ bool bAnl; // Nummerierung in Bearbeitung
+ // Anl heisst Autonumber level
+
+ bool bHdFtFtnEdn; // Spezialtext: Kopf- Fuss- usw.
+ bool bFtnEdn; // Fussnote oder Endnote
+ bool bIsHeader; // Text aus Header wird gelesen ( Zeilenhoehe )
+ bool bIsFooter; // Text aus Footer wird gelesen ( Zeilenhoehe )
+
+ bool bIsUnicode; // aktuelles Text-Stueck ist als 2-Bytiger-Unicode kodiert
+ // bitte NICHT als Bitfeld kodieren!
+
+ bool bCpxStyle; // Style im Complex Part
+ bool bStyNormal; // Style mit Id 0 wird gelesen
+ bool bWWBugNormal; // WW-Version nit Bug Dya in Style Normal
+ bool bNoAttrImport; // Attribute ignorieren zum Ignorieren v. Styles
+ bool bInHyperlink; // Sonderfall zum einlesen eines 0x01
+ // siehe: SwWW8ImplReader::Read_F_Hyperlink()
+ bool bWasParaEnd;
+
+ // praktische Hilfsvariablen:
+ bool bVer67; // ( (6 == nVersion) || (7 == nVersion) );
+ bool bVer6; // (6 == nVersion);
+ bool bVer7; // (7 == nVersion);
+ bool bVer8; // (8 == nVersion);
+
+ bool bPgChpLevel; // ChapterLevel of Heading from PageNum
+ bool bEmbeddObj; // EmbeddField gelesen
+
+ bool bAktAND_fNumberAcross; // current active Annotated List Deskriptor - ROW flag
+
+ bool bNoLnNumYet; // no Line Numbering has been activated yet (we import
+ // the very 1st Line Numbering and ignore the rest)
+
+ bool bFirstPara; // first paragraph?
+ bool bFirstParaOfPage;//cs2c--xushanchuan add for bug11210
+ bool bParaAutoBefore;
+ bool bParaAutoAfter;
+
+ bool bDropCap;
+ int nDropCap;
+
+ int nIdctHint;
+ bool bBidi;
+ bool bReadTable;
+ boost::shared_ptr<SwPaM> mpTableEndPaM;
+
+//---------------------------------------------
+
+ const SprmReadInfo& GetSprmReadInfo(sal_uInt16 nId) const;
+
+ bool StyleExists(int nColl) const { return (nColl < nColls); }
+ SwWW8StyInf *GetStyle(sal_uInt16 nColl) const;
+ void AppendTxtNode(SwPosition& rPos);
+
+ void Read_HdFt(bool bIsTitle, int nSect, const SwPageDesc *pPrev,
+ const wwSection &rSection);
+ void Read_HdFtText(long nStartCp, long nLen, SwFrmFmt* pHdFtFmt);
+ void Read_HdFtTextAsHackedFrame(long nStart, long nLen,
+ SwFrmFmt &rHdFtFmt, sal_uInt16 nPageWidth);
+
+ bool isValid_HdFt_CP(WW8_CP nHeaderCP) const;
+
+ bool HasOwnHeaderFooter(sal_uInt8 nWhichItems, sal_uInt8 grpfIhdt, int nSect);
+
+ void HandleLineNumbering(const wwSection &rSection);
+
+ void CopyPageDescHdFt( const SwPageDesc* pOrgPageDesc,
+ SwPageDesc* pNewPageDesc, sal_uInt8 nCode );
+
+ void DeleteStk(SwFltControlStack* prStck);
+ void DeleteCtrlStk() { DeleteStk( pCtrlStck ); pCtrlStck = 0; }
+ void DeleteRefStks()
+ {
+ DeleteStk( pReffedStck );
+ pReffedStck = 0;
+ DeleteStk( pReffingStck );
+ pReffingStck = 0;
+ }
+ void DeleteAnchorStk() { DeleteStk( pAnchorStck ); pAnchorStck = 0; }
+ void emulateMSWordAddTextToParagraph(const rtl::OUString& rAddString);
+ void simpleAddTextToParagraph(const String& rAddString);
+ bool HandlePageBreakChar();
+ bool ReadChar(long nPosCp, long nCpOfs);
+ bool ReadPlainChars(WW8_CP& rPos, long nEnd, long nCpOfs);
+ bool ReadChars(WW8_CP& rPos, WW8_CP nNextAttr, long nTextEnd, long nCpOfs);
+ bool LangUsesHindiNumbers(sal_uInt16 nLang);
+ sal_Unicode TranslateToHindiNumbers(sal_Unicode);
+
+ void SetDocumentGrid(SwFrmFmt &rFmt, const wwSection &rSection);
+
+ void ProcessAktCollChange(WW8PLCFManResult& rRes, bool* pStartAttr,
+ bool bCallProcessSpecial);
+ long ReadTextAttr(WW8_CP& rTxtPos, bool& rbStartLine);
+ void ReadAttrs(WW8_CP& rNext, WW8_CP& rTxtPos, bool& rbStartLine);
+ void CloseAttrEnds();
+ bool ReadText(long nStartCp, long nTextLen, ManTypes nType);
+
+ void ReadRevMarkAuthorStrTabl( SvStream& rStrm, sal_Int32 nTblPos,
+ sal_Int32 nTblSiz, SwDoc& rDoc );
+
+ void Read_HdFtFtnText( const SwNodeIndex* pSttIdx, long nStartCp,
+ long nLen, ManTypes nType );
+
+ void ImportTox( int nFldId, String aStr );
+
+ void EndSprm( sal_uInt16 nId );
+ // #i103711#
+ // #i105414#
+ void NewAttr( const SfxPoolItem& rAttr,
+ const bool bFirstLineOfStSet = false,
+ const bool bLeftIndentSet = false );
+ // <--
+
+ bool GetFontParams(sal_uInt16, FontFamily&, String&, FontPitch&,
+ rtl_TextEncoding&);
+ bool SetNewFontAttr(sal_uInt16 nFCode, bool bSetEnums, sal_uInt16 nWhich);
+ void ResetCharSetVars();
+ void ResetCJKCharSetVars();
+
+ const SfxPoolItem* GetFmtAttr( sal_uInt16 nWhich );
+ bool JoinNode(SwPaM &rPam, bool bStealAttr = false);
+
+ bool IsBorder(const WW8_BRC* pbrc, bool bChkBtwn = false) const;
+
+ //Set closest writer border equivalent into rBox from pbrc, optionally
+ //recording true winword dimensions in pSizeArray. nSetBorders to mark a
+ //border which has been previously set to a value and for which becoming
+ //empty is valid. Set bCheBtwn to work with paragraphs that have a special
+ //between paragraphs border
+
+ // Note #i20672# we can't properly support between lines so best to ignore
+ // them for now
+ bool SetBorder(SvxBoxItem& rBox, const WW8_BRC* pbrc, short *pSizeArray=0,
+ sal_uInt8 nSetBorders=0xFF) const;
+ void GetBorderDistance(const WW8_BRC* pbrc, Rectangle& rInnerDist) const;
+ sal_uInt16 GetParagraphAutoSpace(bool fDontUseHTMLAutoSpacing);
+ bool SetShadow(SvxShadowItem& rShadow, const short *pSizeArray,
+ const WW8_BRC *pbrc) const;
+ //returns true is a shadow was set
+ bool SetFlyBordersShadow(SfxItemSet& rFlySet, const WW8_BRC *pbrc,
+ short *SizeArray=0) const;
+ void SetPageBorder(SwFrmFmt &rFmt, const wwSection &rSection) const;
+
+ sal_Int32 MatchSdrBoxIntoFlyBoxItem( const Color& rLineColor,
+ MSO_LineStyle eLineStyle, MSO_LineDashing eDashing, MSO_SPT eShapeType, sal_Int32 &rLineWidth,
+ SvxBoxItem& rBox );
+ void MatchSdrItemsIntoFlySet( SdrObject* pSdrObj, SfxItemSet &aFlySet,
+ MSO_LineStyle eLineStyle, MSO_LineDashing eDashing, MSO_SPT eShapeType, Rectangle &rInnerDist );
+ void AdjustLRWrapForWordMargins(const SvxMSDffImportRec &rRecord,
+ SvxLRSpaceItem &rLR);
+ void AdjustULWrapForWordMargins(const SvxMSDffImportRec &rRecord,
+ SvxULSpaceItem &rUL);
+ void MapWrapIntoFlyFmt(SvxMSDffImportRec* pRecord, SwFrmFmt* pFlyFmt);
+
+ void SetAttributesAtGrfNode( SvxMSDffImportRec* pRecord, SwFrmFmt *pFlyFmt,
+ WW8_FSPA *pF );
+
+ bool IsDropCap();
+ bool IsListOrDropcap() { return (!pAktItemSet || bDropCap); };
+
+ WW8FlyPara *ConstructApo(const ApoTestResults &rApo,
+ const WW8_TablePos *pTabPos);
+ bool StartApo(const ApoTestResults &rApo, const WW8_TablePos *pTabPos);
+ void StopApo();
+ bool TestSameApo(const ApoTestResults &rApo, const WW8_TablePos *pTabPos);
+ ApoTestResults TestApo(int nCellLevel, bool bTableRowEnd,
+ const WW8_TablePos *pTabPos);
+
+ void EndSpecial();
+ bool ProcessSpecial(bool &rbReSync, WW8_CP nStartCp);
+ sal_uInt16 TabRowSprm(int nLevel) const;
+
+ bool ReadGrafFile(String& rFileName, Graphic*& rpGraphic,
+ const WW8_PIC& rPic, SvStream* pSt, sal_uLong nFilePos, bool* pDelIt);
+
+ void ReplaceObj(const SdrObject &rReplaceTextObj,
+ SdrObject &rSubObj);
+
+ SwFlyFrmFmt* MakeGrafNotInCntnt(const WW8PicDesc& rPD,
+ const Graphic* pGraph, const String& rFileName,
+ const SfxItemSet& rGrfSet);
+
+ SwFrmFmt* MakeGrafInCntnt(const WW8_PIC& rPic, const WW8PicDesc& rPD,
+ const Graphic* pGraph, const String& rFileName,
+ const SfxItemSet& rGrfSet);
+
+ SwFrmFmt *AddAutoAnchor(SwFrmFmt *pFmt);
+ SwFrmFmt* ImportGraf1(WW8_PIC& rPic, SvStream* pSt, sal_uLong nFilePos);
+ SwFrmFmt* ImportGraf(SdrTextObj* pTextObj = 0, SwFrmFmt* pFlyFmt = 0);
+
+ SdrObject* ImportOleBase( Graphic& rGraph, const Graphic* pGrf=0,
+ const SfxItemSet* pFlySet=0, const Rectangle& aVisArea = Rectangle() );
+
+ SwFrmFmt* ImportOle( const Graphic* = 0, const SfxItemSet* pFlySet = 0,
+ const SfxItemSet* pGrfSet = 0, const Rectangle& aVisArea = Rectangle() );
+ SwFlyFrmFmt* InsertOle(SdrOle2Obj &rObject, const SfxItemSet &rFlySet,
+ const SfxItemSet &rGrfSet);
+
+ bool ImportFormulaControl(WW8FormulaControl &rBox,WW8_CP nStart,
+ SwWw8ControlType nWhich);
+
+ void ImportDop();
+
+ //This converts MS Asian Typography information into OOo's
+ void ImportDopTypography(const WW8DopTypography &rTypo);
+
+ sal_uLong LoadThroughDecryption(SwPaM& rPaM ,WW8Glossary *pGloss);
+ sal_uLong SetSubStreams(SvStorageStreamRef &rTableStream, SvStorageStreamRef &rDataStream);
+ sal_uLong CoreLoad(WW8Glossary *pGloss, const SwPosition &rPos);
+
+ void ReadDocVars();
+
+ bool StartTable(WW8_CP nStartCp);
+ bool InEqualApo(int nLvl) const;
+ bool InLocalApo() const { return InEqualApo(nInTable); }
+ bool InEqualOrHigherApo(int nLvl) const;
+ bool InAnyApo() const { return InEqualOrHigherApo(1); }
+ void TabCellEnd();
+ void StopTable();
+ short GetTableLeft();
+ bool IsInvalidOrToBeMergedTabCell() const;
+
+// Nummerierungen / Aufzaehlungen ( Autonumbered List Data Descriptor )
+// Liste: ANLD ( Autonumbered List Data Descriptor )
+// eine Ebene: ANLV ( Autonumber Level Descriptor )
+//
+// Chg7-8:
+// Listen sind in WW8 eigene Strukturen, die ueber folgende drei Tabellen
+// verwaltet werden: rglst, hpllfo und hsttbListNames
+// die Strukturen hierfuer sind: LSTF, LVLF, LFO LFOLVL
+
+ void SetAnlvStrings(SwNumFmt &rNum, WW8_ANLV &rAV, const sal_uInt8* pTxt,
+ bool bOutline);
+ void SetAnld(SwNumRule* pNumR, WW8_ANLD* pAD, sal_uInt8 nSwLevel, bool bOutLine);
+ void SetNumOlst( SwNumRule* pNumR, WW8_OLST* pO, sal_uInt8 nSwLevel );
+ SwNumRule* GetStyRule();
+
+ void StartAnl(const sal_uInt8* pSprm13);
+ void NextAnlLine(const sal_uInt8* pSprm13);
+ void StopAllAnl(bool bGoBack = true);
+ void StopAnlToRestart(sal_uInt8 nType, bool bGoBack = true);
+
+// GrafikLayer
+
+ bool ReadGrafStart(void* pData, short nDataSiz, WW8_DPHEAD* pHd,
+ const WW8_DO* pDo, SfxAllItemSet &rSet);
+ SdrObject *ReadLine(WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet);
+ SdrObject *ReadRect(WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet);
+ SdrObject *ReadElipse(WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet);
+ SdrObject *ReadArc(WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet);
+ SdrObject *ReadPolyLine(WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet);
+ ESelection GetESelection( long nCpStart, long nCpEnd );
+ void InsertTxbxStyAttrs( SfxItemSet& rS, sal_uInt16 nColl );
+ void InsertAttrsAsDrawingAttrs(long nStartCp, long nEndCp, ManTypes eType, bool bONLYnPicLocFc=false);
+
+ bool GetTxbxTextSttEndCp(WW8_CP& rStartCp, WW8_CP& rEndCp, sal_uInt16 nTxBxS,
+ sal_uInt16 nSequence);
+ bool GetRangeAsDrawingString(String& rString, long StartCp, long nEndCp, ManTypes eType);
+ OutlinerParaObject* ImportAsOutliner(String &rString, WW8_CP nStartCp, WW8_CP nEndCp, ManTypes eType);
+ SwFrmFmt* InsertTxbxText(SdrTextObj* pTextObj, Size* pObjSiz,
+ sal_uInt16 nTxBxS, sal_uInt16 nSequence, long nPosCp, SwFrmFmt* pFlyFmt,
+ bool bMakeSdrGrafObj, bool& rbEraseTextObj,
+ bool* pbTestTxbxContainsText = 0, long* pnStartCp = 0,
+ long* pnEndCp = 0, bool* pbContainsGraphics = 0,
+ SvxMSDffImportRec* pRecord = 0);
+ bool TxbxChainContainsRealText( sal_uInt16 nTxBxS,
+ long& rStartCp,
+ long& rEndCp );
+ SdrObject *ReadTxtBox(WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet);
+ SdrObject *ReadCaptionBox(WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet);
+ SdrObject *ReadGroup(WW8_DPHEAD* pHd, const WW8_DO* pDo,
+ SfxAllItemSet &rSet);
+ SdrObject *ReadGrafPrimitive(short& rLeft, const WW8_DO* pDo,
+ SfxAllItemSet &rSet);
+ void ReadGrafLayer1( WW8PLCFspecial* pPF, long nGrafAnchorCp );
+ SdrObject* CreateContactObject(SwFrmFmt* pFlyFmt);
+ RndStdIds ProcessEscherAlign(SvxMSDffImportRec* pRecord, WW8_FSPA *pFSPA,
+ SfxItemSet &rFlySet, bool bOrgObjectWasReplace);
+ bool MiserableRTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
+ sal_Int16 eHoriOri, sal_Int16 eHoriRel);
+ SwFrmFmt* Read_GrafLayer( long nGrafAnchorCp );
+ SwFlyFrmFmt* ImportReplaceableDrawables( SdrObject* &rpObject,
+ SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord, WW8_FSPA *pF,
+ SfxItemSet &rFlySet );
+ SwFlyFrmFmt *ConvertDrawTextToFly( SdrObject* &rpObject,
+ SdrObject* &rpOurNewObject, SvxMSDffImportRec* pRecord,
+ RndStdIds eAnchor, WW8_FSPA *pF, SfxItemSet &rFlySet );
+ SwFrmFmt* MungeTextIntoDrawBox(SdrObject* pTrueObject,
+ SvxMSDffImportRec *pRecord, long nGrafAnchorCp, SwFrmFmt *pRetFrmFmt);
+
+ void GrafikCtor();
+ void GrafikDtor();
+
+// anderes
+ String GetFieldResult( WW8FieldDesc* pF );
+ void MakeTagString( String& rStr, const String& rOrg );
+ void UpdateFields();
+ void ConvertFFileName( String& rName, const String& rRaw );
+ long Read_F_Tag( WW8FieldDesc* pF );
+ void InsertTagField( const sal_uInt16 nId, const String& rTagText );
+ long ImportExtSprm(WW8PLCFManResult* pRes);
+ void EndExtSprm(sal_uInt16 nSprmId);
+ void ReadDocInfo();
+
+// Ver8-Listen
+
+ void RegisterNumFmtOnTxtNode(sal_uInt16 nActLFO, sal_uInt8 nActLevel,
+ bool bSetAttr = true);
+ void RegisterNumFmtOnStyle(sal_uInt16 nStyle);
+ void SetStylesList(sal_uInt16 nStyle, sal_uInt16 nActLFO,
+ sal_uInt8 nActLevel);
+ void RegisterNumFmt(sal_uInt16 nActLFO, sal_uInt8 nActLevel);
+
+// spaeter zu ersetzen durch Aufruf in entsprechend erweiterten SvxMSDffManager
+
+ const String* GetAnnotationAuthor(sal_uInt16 nIdx);
+
+ // Schnittstellen fuer die Toggle-Attribute
+ void SetToggleAttr(sal_uInt8 nAttrId, bool bOn);
+ void SetToggleBiDiAttr(sal_uInt8 nAttrId, bool bOn);
+ void _ChkToggleAttr( sal_uInt16 nOldStyle81Mask, sal_uInt16 nNewStyle81Mask );
+
+ void ChkToggleAttr( sal_uInt16 nOldStyle81Mask, sal_uInt16 nNewStyle81Mask )
+ {
+ if( nOldStyle81Mask != nNewStyle81Mask &&
+ pCtrlStck->GetToggleAttrFlags() )
+ _ChkToggleAttr( nOldStyle81Mask, nNewStyle81Mask );
+ }
+
+ void _ChkToggleBiDiAttr( sal_uInt16 nOldStyle81Mask, sal_uInt16 nNewStyle81Mask );
+
+ void ChkToggleBiDiAttr( sal_uInt16 nOldStyle81Mask, sal_uInt16 nNewStyle81Mask )
+ {
+ if( nOldStyle81Mask != nNewStyle81Mask &&
+ pCtrlStck->GetToggleBiDiAttrFlags() )
+ _ChkToggleBiDiAttr( nOldStyle81Mask, nNewStyle81Mask );
+ }
+
+ void PopTableDesc();
+ void MoveInsideFly(const SwFrmFmt *pFlyFmt);
+ SwTwips MoveOutsideFly(SwFrmFmt *pFlyFmt, const SwPosition &rPos,
+ bool bTableJoin = true);
+
+ void SetOutLineStyles();
+
+ bool SetSpacing(SwPaM &rMyPam, int nSpace, bool bIsUpper);
+ bool SetUpperSpacing(SwPaM &pMyPam, int nSpace);
+ bool SetLowerSpacing(SwPaM &rMyPam, int nSpace);
+
+ bool IsInlineEscherHack() const
+ {return !maFieldStack.empty() ? maFieldStack.back().mnFieldId == 95 : false; };
+
+ void StoreMacroCmds();
+
+ // #i84783#
+ // determine object attribute "Layout in Table Cell"
+ bool IsObjectLayoutInTableCell( const sal_uInt32 nLayoutInTableCell ) const;
+ // <--
+ bool ReadGlobalTemplateSettings( const rtl::OUString& sCreatedFrom, const com::sun::star::uno::Reference< com::sun::star::container::XNameContainer >& xPrjNameMap );
+ //No copying
+ SwWW8ImplReader(const SwWW8ImplReader &);
+ SwWW8ImplReader& operator=(const SwWW8ImplReader&);
+public: // eigentlich private, geht aber leider nur public
+ sal_uInt16 GetToggleAttrFlags() const;
+ sal_uInt16 GetToggleBiDiAttrFlags() const;
+ void SetToggleAttrFlags(sal_uInt16 nFlags);
+ void SetToggleBiDiAttrFlags(sal_uInt16 nFlags);
+
+
+ long Read_Ftn(WW8PLCFManResult* pRes);
+ sal_uInt16 End_Ftn();
+ long Read_Field(WW8PLCFManResult* pRes);
+ sal_uInt16 End_Field();
+ long Read_Book(WW8PLCFManResult*);
+ long Read_And(WW8PLCFManResult* pRes);
+
+ // Attribute
+
+ void Read_Special(sal_uInt16, const sal_uInt8*, short nLen);
+ void Read_Obj(sal_uInt16, const sal_uInt8*, short nLen);
+ void Read_PicLoc(sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_BoldUsw(sal_uInt16 nId, const sal_uInt8*, short nLen);
+ void Read_Bidi(sal_uInt16 nId, const sal_uInt8*, short nLen);
+ void Read_BoldBiDiUsw(sal_uInt16 nId, const sal_uInt8*, short nLen);
+ void Read_SubSuper( sal_uInt16, const sal_uInt8*, short nLen );
+ bool ConvertSubToGraphicPlacement();
+ SwFrmFmt *ContainsSingleInlineGraphic(const SwPaM &rRegion);
+ void Read_SubSuperProp( sal_uInt16, const sal_uInt8*, short nLen );
+ void Read_Underline( sal_uInt16, const sal_uInt8*, short nLen );
+ void Read_TxtColor( sal_uInt16, const sal_uInt8*, short nLen );
+ void openFont(sal_uInt16 nFCode, sal_uInt16 nId);
+ void closeFont(sal_uInt16 nId);
+ void Read_FontCode( sal_uInt16, const sal_uInt8*, short nLen );
+ void Read_FontSize( sal_uInt16, const sal_uInt8*, short nLen );
+ void Read_CharSet(sal_uInt16 , const sal_uInt8* pData, short nLen);
+ void Read_Language( sal_uInt16, const sal_uInt8*, short nLen );
+ void Read_CColl( sal_uInt16, const sal_uInt8*, short nLen );
+ void Read_Kern( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_FontKern( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_Emphasis( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_ScaleWidth( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_Relief( sal_uInt16, const sal_uInt8* pData, short nLen);
+ void Read_TxtAnim( sal_uInt16, const sal_uInt8* pData, short nLen);
+
+ void Read_NoLineNumb( sal_uInt16 nId, const sal_uInt8* pData, short nLen );
+
+ void Read_LR( sal_uInt16 nId, const sal_uInt8*, short nLen );
+ void Read_UL( sal_uInt16 nId, const sal_uInt8*, short nLen );
+ void Read_ParaAutoBefore(sal_uInt16 , const sal_uInt8 *pData, short nLen);
+ void Read_ParaAutoAfter(sal_uInt16 , const sal_uInt8 *pData, short nLen);
+ void Read_DontAddEqual(sal_uInt16 , const sal_uInt8 *pData, short nLen);
+ void Read_LineSpace( sal_uInt16, const sal_uInt8*, short nLen );
+ void Read_Justify(sal_uInt16, const sal_uInt8*, short nLen);
+ void Read_IdctHint(sal_uInt16, const sal_uInt8*, short nLen);
+ bool IsRightToLeft();
+ void Read_RTLJustify(sal_uInt16, const sal_uInt8*, short nLen);
+ void Read_Hyphenation( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_WidowControl( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_AlignFont( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_UsePgsuSettings( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_KeepLines( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_KeepParas( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_BreakBefore( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_Apo(sal_uInt16 nId, const sal_uInt8* pData, short nLen);
+ void Read_ApoPPC(sal_uInt16, const sal_uInt8* pData, short);
+
+ void Read_BoolItem( sal_uInt16 nId, const sal_uInt8*, short nLen );
+
+ void Read_Border( sal_uInt16 nId, const sal_uInt8* pData, short nLen );
+ void Read_Tab( sal_uInt16 nId, const sal_uInt8* pData, short nLen );
+ void Read_Symbol(sal_uInt16, const sal_uInt8* pData, short nLen);
+ void Read_FldVanish( sal_uInt16 nId, const sal_uInt8* pData, short nLen );
+
+ // Revision Marks ( == Redlining )
+
+ // insert or delete content (change char attributes resp.)
+ void Read_CRevisionMark(RedlineType_t eType, const sal_uInt8* pData, short nLen);
+ // insert new content
+ void Read_CFRMark(sal_uInt16 , const sal_uInt8* pData, short nLen);
+ // delete old content
+ void Read_CFRMarkDel(sal_uInt16 , const sal_uInt8* pData, short nLen);
+ // change properties of content (e.g. char formating)
+ void Read_CPropRMark(sal_uInt16 , const sal_uInt8* pData, short nLen); // complex!
+
+
+ void Read_TabRowEnd( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_TabCellEnd( sal_uInt16, const sal_uInt8* pData, short nLen );
+ static bool ParseTabPos(WW8_TablePos *aTabPos, WW8PLCFx_Cp_FKP* pPap);
+ void Read_Shade( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_ANLevelNo( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_ANLevelDesc( sal_uInt16, const sal_uInt8* pData, short nLen );
+
+ // Gliederungsebene Ver8
+ void Read_POutLvl(sal_uInt16, const sal_uInt8* pData, short nLen);
+
+ void Read_OLST( sal_uInt16, const sal_uInt8* pData, short nLen );
+
+ void Read_CharShadow( sal_uInt16, const sal_uInt8* pData, short nLen );
+ void Read_CharHighlight( sal_uInt16, const sal_uInt8* pData, short nLen );
+ // Ver8-Listen
+
+ void Read_ListLevel( sal_uInt16 nId, const sal_uInt8* pData, short nLen);
+ void Read_LFOPosition( sal_uInt16 nId, const sal_uInt8* pData, short nLen);
+ bool SetTxtFmtCollAndListLevel(const SwPaM& rRg, SwWW8StyInf& rStyleInfo);
+
+ void Read_StyleCode(sal_uInt16, const sal_uInt8* pData, short nLen);
+ void Read_Majority(sal_uInt16, const sal_uInt8* , short );
+ void Read_DoubleLine_Rotate( sal_uInt16, const sal_uInt8* pDATA, short nLen);
+
+ void Read_TxtForeColor(sal_uInt16, const sal_uInt8* pData, short nLen);
+ void Read_TxtBackColor(sal_uInt16, const sal_uInt8* pData, short nLen);
+ void Read_ParaBackColor(sal_uInt16, const sal_uInt8* pData, short nLen);
+ void Read_ParaBiDi(sal_uInt16, const sal_uInt8* pData, short nLen);
+ static sal_uInt32 ExtractColour(const sal_uInt8* &rpData, bool bVer67);
+
+ long MapBookmarkVariables(const WW8FieldDesc* pF,String &rOrigName,
+ const String &rData);
+ String GetMappedBookmark(const String &rOrigName);
+
+ // Felder
+ eF_ResT Read_F_Input(WW8FieldDesc*, String& rStr);
+ eF_ResT Read_F_InputVar(WW8FieldDesc*, String& rStr);
+ eF_ResT Read_F_ANumber( WW8FieldDesc*, String& );
+ eF_ResT Read_F_DocInfo( WW8FieldDesc* pF, String& rStr );
+ eF_ResT Read_F_Author( WW8FieldDesc*, String& );
+ eF_ResT Read_F_TemplName( WW8FieldDesc*, String& );
+ short GetTimeDatePara(String& rStr, sal_uInt32& rFormat, sal_uInt16 &rLang,
+ int nWhichDefault, bool bHijri = false);
+ bool ForceFieldLanguage(SwField &rFld, sal_uInt16 nLang);
+ eF_ResT Read_F_DateTime( WW8FieldDesc*, String& rStr );
+ eF_ResT Read_F_FileName( WW8FieldDesc*, String& rStr);
+ eF_ResT Read_F_Anz( WW8FieldDesc* pF, String& );
+ eF_ResT Read_F_CurPage( WW8FieldDesc*, String& );
+ eF_ResT Read_F_Ref( WW8FieldDesc* pF, String& );
+
+ eF_ResT Read_F_Set( WW8FieldDesc*, String& rStr );
+ eF_ResT Read_F_PgRef( WW8FieldDesc*, String& rStr );
+ eF_ResT Read_F_NoteReference( WW8FieldDesc* pF, String& rStr );
+
+ eF_ResT Read_F_Tox( WW8FieldDesc* pF, String& rStr );
+ bool AddExtraOutlinesAsExtraStyles(SwTOXBase& rBase);
+ eF_ResT Read_F_Symbol( WW8FieldDesc*, String& rStr );
+ eF_ResT Read_F_Embedd( WW8FieldDesc*, String& rStr );
+ eF_ResT Read_F_FormTextBox( WW8FieldDesc* pF, String& rStr);
+ eF_ResT Read_F_FormCheckBox( WW8FieldDesc* pF, String& rStr );
+ eF_ResT Read_F_FormListBox( WW8FieldDesc* pF, String& rStr);
+ com::sun::star::awt::Size MiserableDropDownFormHack(const String &rString,
+ com::sun::star::uno::Reference<com::sun::star::beans::XPropertySet>&
+ rPropSet);
+
+ eF_ResT Read_F_Macro( WW8FieldDesc*, String& rStr);
+ eF_ResT Read_F_DBField( WW8FieldDesc*, String& rStr );
+ eF_ResT Read_F_DBNext( WW8FieldDesc*, String& );
+ eF_ResT Read_F_DBNum( WW8FieldDesc*, String& );
+ eF_ResT Read_F_Equation( WW8FieldDesc*, String& );
+ void Read_SubF_Ruby( _ReadFieldParams& rReadParam);
+ void Read_SubF_Combined( _ReadFieldParams& rReadParam);
+ eF_ResT Read_F_IncludePicture( WW8FieldDesc*, String& rStr );
+ eF_ResT Read_F_IncludeText( WW8FieldDesc*, String& rStr );
+ eF_ResT Read_F_Seq( WW8FieldDesc*, String& rStr );
+
+ eF_ResT Read_F_OCX(WW8FieldDesc*, String&);
+ eF_ResT Read_F_Hyperlink(WW8FieldDesc*, String& rStr);
+ eF_ResT Read_F_Shape(WW8FieldDesc* pF, String& rStr);
+ eF_ResT Read_F_HTMLControl( WW8FieldDesc* pF, String& rStr);
+
+
+ void DeleteFormImpl();
+
+ short ImportSprm( const sal_uInt8* pPos, sal_uInt16 nId = 0 );
+
+ bool SearchRowEnd(WW8PLCFx_Cp_FKP* pPap,WW8_CP &rStartCp, int nLevel) const;
+
+ const WW8Fib& GetFib() const { return *pWwFib; }
+ SwDoc& GetDoc() const { return rDoc; }
+ sal_uInt16 GetNAktColl() const { return nAktColl; }
+ void SetNAktColl( sal_uInt16 nColl ) { nAktColl = nColl; }
+ void SetAktItemSet( SfxItemSet* pItemSet ) { pAktItemSet = pItemSet; }
+ sal_uInt16 StyleUsingLFO( sal_uInt16 nLFOIndex ) const ;
+ const SwFmt* GetStyleWithOrgWWName( String& rName ) const ;
+
+ static bool GetPictGrafFromStream(Graphic& rGraphic, SvStream& rSrc);
+ static void PicRead( SvStream *pDataStream, WW8_PIC *pPic, bool bVer67);
+ static bool ImportOleWMF( SvStorageRef xSrc1, GDIMetaFile &rWMF,
+ long &rX, long &rY);
+ static ColorData GetCol(sal_uInt8 nIco);
+
+ SwWW8ImplReader( sal_uInt8 nVersionPara, SvStorage* pStorage, SvStream* pSt,
+ SwDoc& rD, const String& rBaseURL, bool bNewDoc );
+
+ const String& GetBaseURL() const { return sBaseURL; }
+ // Laden eines kompletten DocFiles
+ sal_uLong LoadDoc( SwPaM&,WW8Glossary *pGloss=0);
+ CharSet GetCurrentCharSet();
+ CharSet GetCurrentCJKCharSet();
+
+ void PostProcessAttrs();
+};
+
+bool CanUseRemoteLink(const String &rGrfName);
+void UseListIndent(SwWW8StyInf &rStyle, const SwNumFmt &rFmt);
+void SetStyleIndent(SwWW8StyInf &rStyleInfo, const SwNumFmt &rFmt);
+// #i103711#
+// #i105414#
+void SyncIndentWithList( SvxLRSpaceItem &rLR,
+ const SwNumFmt &rFmt,
+ const bool bFirstLineOfStSet,
+ const bool bLeftIndentSet );
+// <--
+long GetListFirstLineIndent(const SwNumFmt &rFmt);
+String BookmarkToWriter(const String &rBookmark);
+bool RTLGraphicsHack(SwTwips &rLeft, SwTwips nWidth,
+ sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
+ SwTwips nPageRight, SwTwips nPageSize);
+void MatchEscherMirrorIntoFlySet(const SvxMSDffImportRec &rRecord,
+ SfxItemSet &rFlySet);
+bool RTLDrawingsHack(long &rLeft, long nWidth,
+ sal_Int16 eHoriOri, sal_Int16 eHoriRel, SwTwips nPageLeft,
+ SwTwips nPageRight, SwTwips nPageSize);
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par2.cxx b/sw/source/filter/ww8/ww8par2.cxx
new file mode 100644
index 000000000000..681f415f199e
--- /dev/null
+++ b/sw/source/filter/ww8/ww8par2.cxx
@@ -0,0 +1,4644 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <tools/solar.h>
+#include <vcl/vclenum.hxx>
+#include <vcl/font.hxx>
+#include <hintids.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/hyznitem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <msfilter.hxx>
+#include <pam.hxx> // fuer SwPam
+#include <doc.hxx>
+#include <docary.hxx>
+#include <ndtxt.hxx> // class SwTxtNode
+#include <paratr.hxx> // SwNumRuleItem
+#include <poolfmt.hxx> // RES_POOLCOLL_STANDARD
+#include <swtable.hxx> // class SwTableLines, ...
+#include <tblsel.hxx> // class _SwSelBox
+#include <mdiexp.hxx>
+#include <fmtpdsc.hxx>
+#include <txtftn.hxx>
+#include <frmfmt.hxx>
+#include <ftnidx.hxx>
+#include <fmtftn.hxx>
+#include <charfmt.hxx>
+#include <SwStyleNameMapper.hxx>
+#include <fltshell.hxx> // fuer den Attribut Stack
+#include <fmtanchr.hxx>
+#include <fmtrowsplt.hxx>
+#include <fmtfollowtextflow.hxx> // #i33818#
+#include <numrule.hxx>
+#include "../inc/wwstyles.hxx"
+#include "writerhelper.hxx"
+#include "ww8struc.hxx" // struct TC
+#include "ww8par.hxx"
+#include "ww8par2.hxx"
+
+#include <frmatr.hxx>
+
+#include <iostream>
+
+#define MAX_COL 64 // WW6-Beschreibung: 32, WW6-UI: 31 & WW8-UI: 63!
+
+using namespace ::com::sun::star;
+
+
+class WW8SelBoxInfo: public SwSelBoxes_SAR
+{
+private:
+ WW8SelBoxInfo(const WW8SelBoxInfo&);
+ WW8SelBoxInfo& operator=(const WW8SelBoxInfo&);
+public:
+ short nGroupXStart;
+ short nGroupWidth;
+ bool bGroupLocked;
+
+ WW8SelBoxInfo(short nXCenter, short nWidth)
+ : nGroupXStart( nXCenter ), nGroupWidth( nWidth ), bGroupLocked(false)
+ {}
+};
+
+typedef WW8SelBoxInfo* WW8SelBoxInfoPtr;
+
+SV_DECL_PTRARR_DEL(WW8MergeGroups, WW8SelBoxInfoPtr, 16,16)
+SV_IMPL_PTRARR(WW8MergeGroups, WW8SelBoxInfoPtr)
+
+struct WW8TabBandDesc
+{
+ WW8TabBandDesc* pNextBand;
+ short nGapHalf;
+ short mnDefaultLeft;
+ short mnDefaultTop;
+ short mnDefaultRight;
+ short mnDefaultBottom;
+ bool mbHasSpacing;
+ short nLineHeight;
+ short nRows;
+ sal_uInt16 maDirections[MAX_COL + 1];
+ short nCenter[MAX_COL + 1]; // X-Rand aller Zellen dieses Bandes
+ short nWidth[MAX_COL + 1]; // Laenge aller Zellen dieses Bandes
+ short nWwCols; // sal_uInt8 wuerde reichen, alignment -> short
+ short nSwCols; // SW: so viele Spalten fuer den Writer
+ bool bLEmptyCol; // SW: Links eine leere Zusatz-Spalte
+ bool bREmptyCol; // SW: dito rechts
+ bool bCantSplit;
+ bool bCantSplit90;
+ WW8_TCell* pTCs;
+ sal_uInt8 nOverrideSpacing[MAX_COL + 1];
+ short nOverrideValues[MAX_COL + 1][4];
+ WW8_SHD* pSHDs;
+ sal_uInt32* pNewSHDs;
+ WW8_BRC aDefBrcs[6];
+
+ bool bExist[MAX_COL]; // Existiert diese Zelle ?
+ sal_uInt8 nTransCell[MAX_COL + 2]; // UEbersetzung WW-Index -> SW-Index
+
+ WW8TabBandDesc();
+ WW8TabBandDesc(WW8TabBandDesc& rBand); // tief kopieren
+ ~WW8TabBandDesc();
+ static void setcelldefaults(WW8_TCell *pCells, short nCells);
+ void ReadDef(bool bVer67, const sal_uInt8* pS);
+ void ProcessDirection(const sal_uInt8* pParams);
+ void ProcessSprmTSetBRC(bool bVer67, const sal_uInt8* pParamsTSetBRC);
+ void ProcessSprmTTableBorders(bool bVer67, const sal_uInt8* pParams);
+ void ProcessSprmTDxaCol(const sal_uInt8* pParamsTDxaCol);
+ void ProcessSprmTDelete(const sal_uInt8* pParamsTDelete);
+ void ProcessSprmTInsert(const sal_uInt8* pParamsTInsert);
+ void ProcessSpacing(const sal_uInt8* pParamsTInsert);
+ void ProcessSpecificSpacing(const sal_uInt8* pParamsTInsert);
+ void ReadShd(const sal_uInt8* pS );
+ void ReadNewShd(const sal_uInt8* pS, bool bVer67);
+
+ enum wwDIR {wwTOP = 0, wwLEFT = 1, wwBOTTOM = 2, wwRIGHT = 3};
+};
+
+WW8TabBandDesc::WW8TabBandDesc()
+{
+ memset(this, 0, sizeof(*this));
+ for (size_t i = 0; i < sizeof(maDirections)/sizeof(sal_uInt16); ++i)
+ maDirections[i] = 4;
+}
+
+WW8TabBandDesc::~WW8TabBandDesc()
+{
+ delete[] pTCs;
+ delete[] pSHDs;
+ delete[] pNewSHDs;
+}
+
+class WW8TabDesc
+{
+ std::vector<String> aNumRuleNames;
+ sw::util::RedlineStack *mpOldRedlineStack;
+
+ SwWW8ImplReader* pIo;
+
+ WW8TabBandDesc* pFirstBand;
+ WW8TabBandDesc* pActBand;
+
+ SwPosition* pTmpPos;
+
+ SwTableNode* pTblNd; // Tabellen-Node
+ const SwTableLines* pTabLines; // Zeilen-Array davon
+ SwTableLine* pTabLine; // akt. Zeile
+ SwTableBoxes* pTabBoxes; // Boxen-Array in akt. Zeile
+ SwTableBox* pTabBox; // akt. Zelle
+
+ WW8MergeGroups* pMergeGroups; // Listen aller zu verknuepfenden Zellen
+
+ WW8_TCell* pAktWWCell;
+
+ short nRows;
+ short nDefaultSwCols;
+ short nBands;
+ short nMinLeft;
+ short nConvertedLeft;
+ short nMaxRight;
+ short nSwWidth;
+ short nPreferredWidth;
+ short nOrgDxaLeft;
+
+ bool bOk;
+ bool bClaimLineFmt;
+ sal_Int16 eOri;
+ bool bIsBiDi;
+ // 2. allgemeine Verwaltungsinfo
+ short nAktRow;
+ short nAktBandRow; // SW: in dieser Zeile des akt. Bandes bin ich
+ // 3. Verwaltungsinfo fuer Writer
+ short nAktCol;
+
+ sal_uInt16 nRowsToRepeat;
+
+ // 4. Methoden
+
+ sal_uInt16 GetLogicalWWCol() const;
+ void SetTabBorders( SwTableBox* pBox, short nIdx );
+ void SetTabShades( SwTableBox* pBox, short nWwIdx );
+ void SetTabVertAlign( SwTableBox* pBox, short nWwIdx );
+ void SetTabDirection( SwTableBox* pBox, short nWwIdx );
+ void CalcDefaults();
+ bool SetPamInCell(short nWwCol, bool bPam);
+ void InsertCells( short nIns );
+ void AdjustNewBand();
+
+ // durchsucht pMergeGroups, meldet Index der ersten, passenden Gruppe bzw.
+ // -1 Details siehe bei der Implementierung
+ bool FindMergeGroup(short nX1, short nWidth, bool bExact, short& nMGrIdx);
+
+ // einzelne Box ggfs. in eine Merge-Gruppe aufnehmen
+ // (die Merge-Gruppen werden dann spaeter auf einen Schlag abgearbeitet)
+ SwTableBox* UpdateTableMergeGroup(WW8_TCell& rCell,
+ WW8SelBoxInfo* pActGroup, SwTableBox* pActBox, sal_uInt16 nCol );
+ void StartMiserableHackForUnsupportedDirection(short nWwCol);
+ void EndMiserableHackForUnsupportedDirection(short nWwCol);
+ //No copying
+ WW8TabDesc(const WW8TabDesc&);
+ WW8TabDesc &operator=(const WW8TabDesc&);
+public:
+ const SwTable* pTable; // Tabelle
+ SwPosition* pParentPos;
+ SwFlyFrmFmt* pFlyFmt;
+ SfxItemSet aItemSet;
+ bool IsValidCell(short nCol) const;
+ bool InFirstParaInCell() const;
+
+ WW8TabDesc( SwWW8ImplReader* pIoClass, WW8_CP nStartCp );
+ bool Ok() const { return bOk; }
+ void CreateSwTable();
+ void UseSwTable();
+ void SetSizePosition(SwFrmFmt* pFrmFmt);
+ void TableCellEnd();
+ void MoveOutsideTable();
+ void ParkPaM();
+ void FinishSwTable();
+ void MergeCells();
+ short GetMinLeft() const { return nConvertedLeft; }
+ ~WW8TabDesc();
+ SwPosition *GetPos() { return pTmpPos; }
+
+ const WW8_TCell* GetAktWWCell() const { return pAktWWCell; }
+ short GetAktCol() const { return nAktCol; }
+ // find name of numrule valid for current WW-COL
+ const String& GetNumRuleName() const;
+ void SetNumRuleName( const String& rName );
+
+ sw::util::RedlineStack* getOldRedlineStack(){ return mpOldRedlineStack; }
+};
+
+void sw::util::RedlineStack::close( const SwPosition& rPos,
+ RedlineType_t eType, WW8TabDesc* pTabDesc )
+{
+ // If the redline type is not found in the redline stack, we have to check if there has been
+ // a tabledesc and to check its saved redline stack, too. (#136939, #i68139)
+ if( !close( rPos, eType ) )
+ {
+ if( pTabDesc && pTabDesc->getOldRedlineStack() )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( pTabDesc->getOldRedlineStack()->close(rPos, eType), "close without open!");
+#else
+ pTabDesc->getOldRedlineStack()->close( rPos, eType );
+#endif
+ }
+ }
+}
+
+
+void wwSectionManager::SetCurrentSectionHasFootnote()
+{
+ OSL_ENSURE(!maSegments.empty(),
+ "should not be possible, must be at least one segment");
+ if (!maSegments.empty())
+ maSegments.back().mbHasFootnote = true;
+}
+
+bool wwSectionManager::CurrentSectionIsVertical() const
+{
+ OSL_ENSURE(!maSegments.empty(),
+ "should not be possible, must be at least one segment");
+ if (!maSegments.empty())
+ return maSegments.back().IsVertical();
+ return false;
+}
+
+bool wwSectionManager::CurrentSectionIsProtected() const
+{
+ OSL_ENSURE(!maSegments.empty(),
+ "should not be possible, must be at least one segment");
+ if (!maSegments.empty())
+ return SectionIsProtected(maSegments.back());
+ return false;
+}
+
+sal_uInt32 wwSectionManager::GetPageLeft() const
+{
+ return !maSegments.empty() ? maSegments.back().nPgLeft : 0;
+}
+
+sal_uInt32 wwSectionManager::GetPageRight() const
+{
+ return !maSegments.empty() ? maSegments.back().nPgRight : 0;
+}
+
+sal_uInt32 wwSectionManager::GetPageWidth() const
+{
+ return !maSegments.empty() ? maSegments.back().GetPageWidth() : 0;
+}
+
+sal_uInt32 wwSectionManager::GetTextAreaWidth() const
+{
+ return !maSegments.empty() ? maSegments.back().GetTextAreaWidth() : 0;
+}
+
+sal_uInt32 wwSectionManager::GetWWPageTopMargin() const
+{
+ return !maSegments.empty() ? maSegments.back().maSep.dyaTop : 0;
+}
+
+sal_uInt16 SwWW8ImplReader::End_Ftn()
+{
+ /*
+ Ignoring Footnote outside of the normal Text. People will put footnotes
+ into field results and field commands.
+ */
+ if (bIgnoreText ||
+ pPaM->GetPoint()->nNode < rDoc.GetNodes().GetEndOfExtras().GetIndex())
+ {
+ return 0;
+ }
+
+ OSL_ENSURE(!maFtnStack.empty(), "footnote end without start");
+ if (maFtnStack.empty())
+ return 0;
+
+ bool bFtEdOk = false;
+ const FtnDescriptor &rDesc = maFtnStack.back();
+
+ //Get the footnote character and remove it from the txtnode. We'll
+ //replace it with the footnote
+ SwTxtNode* pTxt = pPaM->GetNode()->GetTxtNode();
+ xub_StrLen nPos = pPaM->GetPoint()->nContent.GetIndex();
+
+ String sChar;
+ SwTxtAttr* pFN = 0;
+ //There should have been a footnote char, we will replace this.
+ if (pTxt && nPos)
+ {
+ sChar.Append(pTxt->GetTxt().GetChar(--nPos));
+ pPaM->SetMark();
+ pPaM->GetMark()->nContent--;
+ rDoc.DeleteRange( *pPaM );
+ pPaM->DeleteMark();
+ SwFmtFtn aFtn(rDesc.meType == MAN_EDN);
+ pFN = pTxt->InsertItem(aFtn, nPos, nPos);
+ }
+ OSL_ENSURE(pFN, "Probleme beim Anlegen des Fussnoten-Textes");
+ if (pFN)
+ {
+
+ SwPosition aTmpPos( *pPaM->GetPoint() ); // merke alte Cursorposition
+ WW8PLCFxSaveAll aSave;
+ pPlcxMan->SaveAllPLCFx( aSave );
+ WW8PLCFMan* pOldPlcxMan = pPlcxMan;
+
+ const SwNodeIndex* pSttIdx = ((SwTxtFtn*)pFN)->GetStartNode();
+ OSL_ENSURE(pSttIdx, "Probleme beim Anlegen des Fussnoten-Textes");
+
+ ((SwTxtFtn*)pFN)->SetSeqNo( rDoc.GetFtnIdxs().Count() );
+
+ bool bOld = bFtnEdn;
+ bFtnEdn = true;
+
+ // read content of Ft-/End-Note
+ Read_HdFtFtnText( pSttIdx, rDesc.mnStartCp, rDesc.mnLen, rDesc.meType);
+ bFtEdOk = true;
+ bFtnEdn = bOld;
+
+ OSL_ENSURE(sChar.Len()==1 && ((rDesc.mbAutoNum == (sChar.GetChar(0) == 2))),
+ "footnote autonumbering must be 0x02, and everthing else must not be");
+
+ // If no automatic numbering use the following char from the main text
+ // as the footnote number
+ if (!rDesc.mbAutoNum)
+ ((SwTxtFtn*)pFN)->SetNumber(0, &sChar);
+
+ /*
+ Delete the footnote char from the footnote if its at the beginning
+ as usual. Might not be if the user has already deleted it, e.g.
+ #i14737#
+ */
+ SwNodeIndex& rNIdx = pPaM->GetPoint()->nNode;
+ rNIdx = pSttIdx->GetIndex() + 1;
+ SwTxtNode* pTNd = rNIdx.GetNode().GetTxtNode();
+ if (pTNd && pTNd->GetTxt().Len() && sChar.Len())
+ {
+ if (pTNd->GetTxt().GetChar(0) == sChar.GetChar(0))
+ {
+ pPaM->GetPoint()->nContent.Assign( pTNd, 0 );
+ pPaM->SetMark();
+ // Strip out tabs we may have inserted on export #i24762#
+ if (pTNd->GetTxt().GetChar(1) == 0x09)
+ pPaM->GetMark()->nContent++;
+ pPaM->GetMark()->nContent++;
+ pReffingStck->Delete(*pPaM);
+ rDoc.DeleteRange( *pPaM );
+ pPaM->DeleteMark();
+ }
+ }
+
+ *pPaM->GetPoint() = aTmpPos; // restore Cursor
+
+ pPlcxMan = pOldPlcxMan; // Restore attributes
+ pPlcxMan->RestoreAllPLCFx( aSave );
+ }
+
+ if (bFtEdOk)
+ maSectionManager.SetCurrentSectionHasFootnote();
+
+ maFtnStack.pop_back();
+ return 0;
+}
+
+long SwWW8ImplReader::Read_Ftn(WW8PLCFManResult* pRes)
+{
+ /*
+ Ignoring Footnote outside of the normal Text. People will put footnotes
+ into field results and field commands.
+ */
+ if (bIgnoreText ||
+ pPaM->GetPoint()->nNode < rDoc.GetNodes().GetEndOfExtras().GetIndex())
+ {
+ return 0;
+ }
+
+ FtnDescriptor aDesc;
+ aDesc.mbAutoNum = true;
+ if (eEDN == pRes->nSprmId)
+ {
+ aDesc.meType = MAN_EDN;
+ if (pPlcxMan->GetEdn())
+ aDesc.mbAutoNum = 0 != *(short*)pPlcxMan->GetEdn()->GetData();
+ }
+ else
+ {
+ aDesc.meType = MAN_FTN;
+ if (pPlcxMan->GetFtn())
+ aDesc.mbAutoNum = 0 != *(short*)pPlcxMan->GetFtn()->GetData();
+ }
+
+ aDesc.mnStartCp = pRes->nCp2OrIdx;
+ aDesc.mnLen = pRes->nMemLen;
+
+ maFtnStack.push_back(aDesc);
+
+ return 0;
+}
+
+bool SwWW8ImplReader::SearchRowEnd(WW8PLCFx_Cp_FKP* pPap, WW8_CP &rStartCp,
+ int nLevel) const
+{
+ WW8PLCFxDesc aRes;
+ aRes.pMemPos = 0;
+ aRes.nEndPos = rStartCp;
+
+ while (pPap->HasFkp() && rStartCp != WW8_CP_MAX)
+ {
+ if (pPap->Where() != WW8_CP_MAX)
+ {
+ const sal_uInt8* pB = pPap->HasSprm(TabRowSprm(nLevel));
+ if (pB && *pB == 1)
+ {
+ const sal_uInt8 *pLevel = 0;
+ if (0 != (pLevel = pPap->HasSprm(0x6649)))
+ {
+ if (nLevel + 1 == *pLevel)
+ return true;
+ }
+ else
+ {
+ OSL_ENSURE(!nLevel || pLevel, "sublevel without level sprm");
+ return true; // RowEnd found
+ }
+ }
+ }
+
+ aRes.nStartPos = aRes.nEndPos;
+ aRes.pMemPos = 0;
+ //Seek to our next block of properties
+ if (!(pPap->SeekPos(aRes.nStartPos)))
+ {
+ aRes.nEndPos = WW8_CP_MAX;
+ pPap->SetDirty(true);
+ }
+ pPap->GetSprms(&aRes);
+ pPap->SetDirty(false);
+ //Update our aRes to get the new starting point of the next properties
+ rStartCp = aRes.nEndPos;
+ }
+
+ return false;
+}
+
+ApoTestResults SwWW8ImplReader::TestApo(int nCellLevel, bool bTableRowEnd,
+ const WW8_TablePos *pTabPos)
+{
+ const WW8_TablePos *pTopLevelTable = nCellLevel <= 1 ? pTabPos : 0;
+ ApoTestResults aRet;
+ // Frame in Style Definition (word appears to ignore them if inside an
+ // text autoshape)
+ if (!bTxbxFlySection)
+ aRet.mpStyleApo = StyleExists(nAktColl) ? pCollA[nAktColl].pWWFly : 0;
+
+ /*
+ #i1140#
+ If I have a table and apply a style to one of its frames that should cause
+ a paragraph that its applied to it to only exist as a seperate floating
+ frame, then the behavour depends on which cell that it has been applied
+ to. If its the first cell of a row then the whole table row jumps into the
+ new frame, if its not then then the paragraph attributes are applied
+ "except" for the floating frame stuff. i.e. its ignored. So if theres a
+ table, and we're not in the first cell then we ignore the fact that the
+ paragraph style wants to be in a different frame.
+
+ This sort of mindbending inconsistency is surely why frames are deprecated
+ in word 97 onwards and hidden away from the user
+
+
+ #i1532# & #i5379#
+ If we are already a table in a frame then we must grab the para properties
+ to see if we are still in that frame.
+ */
+
+ aRet.mpSprm37 = pPlcxMan->HasParaSprm( bVer67 ? 37 : 0x2423 );
+ aRet.mpSprm29 = pPlcxMan->HasParaSprm( bVer67 ? 29 : 0x261B );
+
+ // Is there some frame data here
+ bool bNowApo = aRet.HasFrame() || pTopLevelTable;
+ if (bNowApo)
+ {
+ if (WW8FlyPara *pTest = ConstructApo(aRet, pTabPos))
+ delete pTest;
+ else
+ bNowApo = false;
+ }
+
+ bool bTestAllowed = !bTxbxFlySection && !bTableRowEnd;
+ if (bTestAllowed)
+ {
+ //Test is allowed if there is no table.
+ //Otherwise only allowed if we are in the
+ //first paragraph of the first cell of a row.
+ //(And only if the row we are inside is at the
+ //same level as the previous row, think tables
+ //in tables)
+ if (nCellLevel == nInTable)
+ {
+
+ if (!nInTable)
+ bTestAllowed = true;
+ else
+ {
+ if (!pTableDesc)
+ {
+ OSL_ENSURE(pTableDesc, "What!");
+ bTestAllowed = false;
+ }
+ else
+ {
+ // #i39468#
+ // If current cell isn't valid, the test is allowed.
+ // The cell isn't valid, if e.g. there is a new row
+ // <pTableDesc->nAktRow> >= <pTableDesc->pTabLines->Count()>
+ bTestAllowed =
+ pTableDesc->GetAktCol() == 0 &&
+ ( !pTableDesc->IsValidCell( pTableDesc->GetAktCol() ) ||
+ pTableDesc->InFirstParaInCell() );
+ // <--
+ }
+ }
+ }
+ }
+
+ if (!bTestAllowed)
+ return aRet;
+
+ aRet.mbStartApo = bNowApo && !InAnyApo(); // APO-start
+ aRet.mbStopApo = InEqualOrHigherApo(nCellLevel) && !bNowApo; // APO-end
+
+ //If it happens that we are in a table, then if its not the first cell
+ //then any attributes that might otherwise cause the contents to jump
+ //into another frame don't matter, a table row sticks together as one
+ //unit no matter what else happens. So if we are not in a table at
+ //all, or if we are in the first cell then test that the last frame
+ //data is the same as the current one
+ if (bNowApo && InEqualApo(nCellLevel))
+ {
+ // two bordering eachother
+ if (!TestSameApo(aRet, pTabPos))
+ aRet.mbStopApo = aRet.mbStartApo = true;
+ }
+
+ return aRet;
+}
+//---------------------------------------------------------------------
+// Hilfroutinen fuer Kapitelnummerierung und Aufzaehlung / Gliederung
+//---------------------------------------------------------------------
+
+static void SetBaseAnlv(SwNumFmt &rNum, WW8_ANLV &rAV, sal_uInt8 nSwLevel )
+{
+ static SvxExtNumType eNumA[8] = { SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,
+ SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N, SVX_NUM_ARABIC,
+ SVX_NUM_ARABIC, SVX_NUM_ARABIC };
+
+ static SvxAdjust eAdjA[4] = { SVX_ADJUST_LEFT,
+ SVX_ADJUST_RIGHT, SVX_ADJUST_LEFT, SVX_ADJUST_LEFT };
+// eigentlich folgende 2, aber Writer-UI bietet es nicht an
+// SVX_ADJUST_CENTER, SVX_ADJUST_BLOCKLINE };
+
+ rNum.SetNumberingType( static_cast< sal_Int16 >(( SVBT8ToByte( rAV.nfc ) < 8 ) ?
+ eNumA[SVBT8ToByte( rAV.nfc ) ] : SVX_NUM_NUMBER_NONE) );
+ if ((SVBT8ToByte(rAV.aBits1 ) & 0x4) >> 2)
+ rNum.SetIncludeUpperLevels(nSwLevel + 1);
+ rNum.SetStart( SVBT16ToShort( rAV.iStartAt ) );
+ rNum.SetNumAdjust( eAdjA[SVBT8ToByte( rAV.aBits1 ) & 0x3] );
+
+ rNum.SetCharTextDistance( SVBT16ToShort( rAV.dxaSpace ) );
+ sal_Int16 nIndent = Abs((sal_Int16)SVBT16ToShort( rAV.dxaIndent ));
+ if( SVBT8ToByte( rAV.aBits1 ) & 0x08 ) //fHang
+ {
+ rNum.SetFirstLineOffset( -nIndent );
+ rNum.SetLSpace( nIndent );
+ rNum.SetAbsLSpace( nIndent );
+ }
+ else
+ rNum.SetCharTextDistance( nIndent ); // Breite der Nummer fehlt
+
+ if( SVBT8ToByte( rAV.nfc ) == 5 || SVBT8ToByte( rAV.nfc ) == 7 )
+ {
+ String sP( rNum.GetSuffix() );
+ sP.Insert( '.', 0 );
+ rNum.SetSuffix( sP ); // Ordinalzahlen
+ }
+}
+
+void SwWW8ImplReader::SetAnlvStrings(SwNumFmt &rNum, WW8_ANLV &rAV,
+ const sal_uInt8* pTxt, bool bOutline)
+{
+ bool bInsert = false; // Default
+ CharSet eCharSet = eStructCharSet;
+
+ const WW8_FFN* pF = pFonts->GetFont(SVBT16ToShort(rAV.ftc)); // FontInfo
+ bool bListSymbol = pF && ( pF->chs == 2 ); // Symbol/WingDings/...
+
+ String sTxt;
+ if (bVer67)
+ {
+ sTxt = String( (sal_Char*)pTxt, SVBT8ToByte( rAV.cbTextBefore )
+ + SVBT8ToByte( rAV.cbTextAfter ), eCharSet );
+ }
+ else
+ {
+ for(xub_StrLen i = SVBT8ToByte(rAV.cbTextBefore);
+ i < SVBT8ToByte(rAV.cbTextAfter); ++i, pTxt += 2)
+ {
+ sTxt.Append(SVBT16ToShort(*(SVBT16*)pTxt));
+ }
+ }
+
+ if( bOutline )
+ { // Gliederung
+ if( !rNum.GetIncludeUpperLevels() // es sind <= 1 Nummern anzuzeigen
+ || rNum.GetNumberingType() == SVX_NUM_NUMBER_NONE ){ // oder dieser Level hat keine
+ // eigenen Ziffern
+ bInsert = true; // -> dann uebernehme Zeichen
+
+ // replace by simple Bullet ?
+ if( bListSymbol )
+ //cBulletChar benutzen, damit auf dem MAC richtig gemappt wird
+ sTxt.Fill( SVBT8ToByte( rAV.cbTextBefore )
+ + SVBT8ToByte( rAV.cbTextAfter ), cBulletChar );
+ }
+ }
+ else
+ { // Nummerierung / Aufzaehlung
+ bInsert = true;
+ if( bListSymbol )
+ {
+ FontFamily eFamily;
+ String aName;
+ FontPitch ePitch;
+
+ if( GetFontParams( SVBT16ToShort( rAV.ftc ), eFamily, aName,
+ ePitch, eCharSet ) ){
+
+ Font aFont;
+ aFont.SetName( aName );
+ aFont.SetFamily( eFamily );
+
+ aFont.SetCharSet( eCharSet );
+ rNum.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+
+ rNum.SetBulletFont( &aFont );
+
+ // take only the very first character
+ if( rAV.cbTextBefore || rAV.cbTextAfter)
+ rNum.SetBulletChar( sTxt.GetChar( 0 ) );
+ else
+ rNum.SetBulletChar( 0x2190 );
+ }
+ }
+ }
+ if( bInsert )
+ {
+ if( rAV.cbTextBefore )
+ {
+ String sP( sTxt.Copy( 0, SVBT8ToByte( rAV.cbTextBefore ) ) );
+ rNum.SetPrefix( sP );
+ }
+ if( SVBT8ToByte( rAV.cbTextAfter ) )
+ {
+ String sP( rNum.GetSuffix() );
+ sP.Insert( sTxt.Copy( SVBT8ToByte( rAV.cbTextBefore ),
+ SVBT8ToByte( rAV.cbTextAfter ) ) );
+ rNum.SetSuffix( sP );
+ }
+// Die Zeichen vor und hinter mehreren Ziffern koennen leider nicht uebernommen
+// werden, da sie der Writer ganz anders behandelt und das Ergebnis i.A.
+// schlechter als ohne waere.
+ }
+}
+
+// SetAnld bekommt einen WW-ANLD-Descriptor und einen Level und modifiziert
+// die durch pNumR anggebeben NumRules. Wird benutzt fuer alles ausser
+// Gliederung im Text
+void SwWW8ImplReader::SetAnld(SwNumRule* pNumR, WW8_ANLD* pAD, sal_uInt8 nSwLevel,
+ bool bOutLine)
+{
+ SwNumFmt aNF;
+ if (pAD)
+ { // Es gibt einen Anld-Sprm
+ bAktAND_fNumberAcross = 0 != SVBT8ToByte( pAD->fNumberAcross );
+ WW8_ANLV &rAV = pAD->eAnlv;
+ SetBaseAnlv(aNF, rAV, nSwLevel); // Setze Basis-Format
+ SetAnlvStrings(aNF, rAV, pAD->rgchAnld, bOutLine );// und Rest
+ }
+ pNumR->Set(nSwLevel, aNF);
+}
+
+//-------------------------------------------------------
+// Kapitelnummerierung und Kapitelbullets
+//-------------------------------------------------------
+// Kapitelnummerierung findet in Styledefinionen statt. Sprm 13 gibt den Level
+// an, Sprm 12 den Inhalt
+
+SwNumRule* SwWW8ImplReader::GetStyRule()
+{
+ if( pStyles->pStyRule ) // Bullet-Style bereits vorhanden
+ return pStyles->pStyRule;
+
+ const String aBaseName(CREATE_CONST_ASC( "WW8StyleNum" ));
+ const String aName( rDoc.GetUniqueNumRuleName( &aBaseName, false) );
+
+ // #i86652#
+ sal_uInt16 nRul = rDoc.MakeNumRule( aName, 0, sal_False,
+ SvxNumberFormat::LABEL_ALIGNMENT );
+ // <--
+ pStyles->pStyRule = rDoc.GetNumRuleTbl()[nRul];
+ // Auto == false-> Nummerierungsvorlage
+ pStyles->pStyRule->SetAutoRule(false);
+
+ return pStyles->pStyRule;
+}
+
+// Sprm 13
+void SwWW8ImplReader::Read_ANLevelNo( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ nSwNumLevel = 0xff; // Default: ungueltig
+
+ if( nLen <= 0 )
+ return;
+
+ // StyleDef ?
+ if( pAktColl )
+ {
+ // nur fuer SwTxtFmtColl, nicht CharFmt
+ // WW: 0 = no Numbering
+ SwWW8StyInf * pColl = GetStyle(nAktColl);
+ if (pColl != NULL && pColl->bColl && *pData)
+ {
+ // Bereich WW:1..9 -> SW:0..8 keine Aufzaehlung / Nummerierung
+
+ if (*pData <= MAXLEVEL && *pData <= 9)
+ {
+ nSwNumLevel = *pData - 1;
+ if (!bNoAttrImport)
+ ((SwTxtFmtColl*)pAktColl)->AssignToListLevelOfOutlineStyle( nSwNumLevel ); //<-end,zhaojianwei
+ // Bei WW-NoNumbering koennte auch NO_NUMBERING gesetzt
+ // werden. ( Bei normaler Nummerierung muss NO_NUM gesetzt
+ // werden: NO_NUM : Nummerierungs-Pause,
+ // NO_NUMBERING : ueberhaupt keine Nummerierung )
+
+ }
+ else if( *pData == 10 || *pData == 11 )
+ {
+ // Typ merken, der Rest geschieht bei Sprm 12
+ pStyles->nWwNumLevel = *pData;
+ }
+ }
+ }
+ else
+ {
+ //Not StyleDef
+ if (!bAnl)
+ StartAnl(pData); // Anfang der Gliederung / Aufzaehlung
+ NextAnlLine(pData);
+ }
+}
+
+void SwWW8ImplReader::Read_ANLevelDesc( sal_uInt16, const sal_uInt8* pData, short nLen ) // Sprm 12
+{
+ {
+ SwWW8StyInf * pStyInf = GetStyle(nAktColl);
+ if( !pAktColl || nLen <= 0 // nur bei Styledef
+ || (pStyInf && !pStyInf->bColl) // CharFmt -> ignorieren
+ || ( nIniFlags & WW8FL_NO_OUTLINE ) ){
+ nSwNumLevel = 0xff;
+ return;
+ }
+ }
+
+ if( nSwNumLevel <= MAXLEVEL // Bereich WW:1..9 -> SW:0..8
+ && nSwNumLevel <= 9 ){ // keine Aufzaehlung / Nummerierung
+
+ // Falls bereits direkt oder durch
+ // Vererbung NumruleItems gesetzt sind,
+ // dann jetzt ausschalten
+ pAktColl->SetFmtAttr( SwNumRuleItem() );
+
+ String aName(CREATE_CONST_ASC( "Outline" ));
+ SwNumRule aNR( rDoc.GetUniqueNumRuleName( &aName ),
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
+ OUTLINE_RULE );
+ aNR = *rDoc.GetOutlineNumRule();
+
+ SetAnld(&aNR, (WW8_ANLD*)pData, nSwNumLevel, true);
+
+ // fehlende Level muessen nicht aufgefuellt werden
+
+ rDoc.SetOutlineNumRule( aNR );
+ }else if( pStyles->nWwNumLevel == 10 || pStyles->nWwNumLevel == 11 ){
+ SwNumRule* pNR = GetStyRule();
+ SetAnld(pNR, (WW8_ANLD*)pData, 0, false);
+ pAktColl->SetFmtAttr( SwNumRuleItem( pNR->GetName() ) );
+
+ SwWW8StyInf * pStyInf = GetStyle(nAktColl);
+ if (pStyInf != NULL)
+ pStyInf->bHasStyNumRule = true;
+ }
+}
+
+//-----------------------------------------
+// Nummerierung / Aufzaehlung
+//-----------------------------------------
+
+// SetNumOlst() traegt die Numrules fuer diese Zeile ins SwNumFmt ein
+// ( nur fuer Gliederungen im Text; Aufzaehlungen / Nummerierungen laufen
+// ueber ANLDs )
+// dabei wird die Info aus dem OLST geholt und nicht aus dem ANLD ( s.u. )
+void SwWW8ImplReader::SetNumOlst(SwNumRule* pNumR, WW8_OLST* pO, sal_uInt8 nSwLevel)
+{
+ SwNumFmt aNF;
+ WW8_ANLV &rAV = pO->rganlv[nSwLevel];
+ SetBaseAnlv(aNF, rAV, nSwLevel);
+ // ... und then the Strings
+ int nTxtOfs = 0;
+ sal_uInt8 i;
+ WW8_ANLV* pAV1; // search String-Positions
+ for (i = 0, pAV1 = pO->rganlv; i < nSwLevel; ++i, ++pAV1)
+ {
+ nTxtOfs += SVBT8ToByte(pAV1->cbTextBefore)
+ + SVBT8ToByte(pAV1->cbTextAfter);
+ }
+
+ if (!bVer67)
+ nTxtOfs *= 2;
+ SetAnlvStrings(aNF, rAV, pO->rgch + nTxtOfs, true); // und rein
+ pNumR->Set(nSwLevel, aNF);
+}
+
+// der OLST kommt am Anfang jeder Section, die Gliederungen enthaelt. Die ANLDs,
+// die an jeder Gliederungszeile haengen, enthalten nur Stuss, also werden die
+// OLSTs waehrend der Section gemerkt, damit die Informationen beim Auftreten
+// von Gliederungsabsaetzen zugreifbar ist.
+void SwWW8ImplReader::Read_OLST( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if (nLen <= 0)
+ {
+ delete pNumOlst, pNumOlst = 0;
+ return;
+ }
+ if (pNumOlst)
+ delete pNumOlst; // nur sicherheitshalber
+ pNumOlst = new WW8_OLST;
+ if( nLen < sal::static_int_cast< sal_Int32 >(sizeof( WW8_OLST )) ) // auffuellen, falls zu kurz
+ memset( pNumOlst, 0, sizeof( *pNumOlst ) );
+ *pNumOlst = *(WW8_OLST*)pData;
+}
+
+WW8LvlType GetNumType(sal_uInt8 nWwLevelNo)
+{
+ WW8LvlType nRet = WW8_None;
+ if( nWwLevelNo == 12 )
+ nRet = WW8_Pause;
+ else if( nWwLevelNo == 10 )
+ nRet = WW8_Numbering;
+ else if( nWwLevelNo == 11 )
+ nRet = WW8_Sequence;
+ else if( nWwLevelNo > 0 && nWwLevelNo <= 9 )
+ nRet = WW8_Outline;
+ return nRet;
+}
+
+SwNumRule *ANLDRuleMap::GetNumRule(sal_uInt8 nNumType)
+{
+ return (WW8_Numbering == nNumType ? mpNumberingNumRule : mpOutlineNumRule);
+}
+
+void ANLDRuleMap::SetNumRule(SwNumRule *pRule, sal_uInt8 nNumType)
+{
+ if (WW8_Numbering == nNumType)
+ mpNumberingNumRule = pRule;
+ else
+ mpOutlineNumRule = pRule;
+}
+
+
+// StartAnl wird am Anfang eines Zeilenbereichs gerufen,
+// der Gliederung / Nummerierung / Aufzaehlung enthaelt
+void SwWW8ImplReader::StartAnl(const sal_uInt8* pSprm13)
+{
+ bAktAND_fNumberAcross = false;
+
+ sal_uInt8 nT = static_cast< sal_uInt8 >(GetNumType(*pSprm13));
+ if (nT == WW8_Pause || nT == WW8_None)
+ return;
+
+ nWwNumType = nT;
+ SwNumRule *pNumRule = maANLDRules.GetNumRule(nWwNumType);
+
+ // check for COL numbering:
+ const sal_uInt8* pS12 = 0;// sprmAnld
+ String sNumRule;
+
+ if (pTableDesc)
+ {
+ sNumRule = pTableDesc->GetNumRuleName();
+ if (sNumRule.Len())
+ {
+ pNumRule = rDoc.FindNumRulePtr(sNumRule);
+ if (!pNumRule)
+ sNumRule.Erase();
+ else
+ {
+ // this is ROW numbering ?
+ pS12 = pPlcxMan->HasParaSprm(bVer67 ? 12 : 0xC63E); // sprmAnld
+ if (pS12 && 0 != SVBT8ToByte(((WW8_ANLD*)pS12)->fNumberAcross))
+ sNumRule.Erase();
+ }
+ }
+ }
+
+ SwWW8StyInf * pStyInf = GetStyle(nAktColl);
+ if (!sNumRule.Len() && pStyInf->bHasStyNumRule)
+ {
+ sNumRule = pStyInf->pFmt->GetNumRule().GetValue();
+ pNumRule = rDoc.FindNumRulePtr(sNumRule);
+ if (!pNumRule)
+ sNumRule.Erase();
+ }
+
+ if (!sNumRule.Len())
+ {
+ if (!pNumRule)
+ {
+ // #i86652#
+ pNumRule = rDoc.GetNumRuleTbl()[
+ rDoc.MakeNumRule( sNumRule, 0, sal_False,
+ SvxNumberFormat::LABEL_ALIGNMENT ) ];
+ // <--
+ }
+ if (pTableDesc)
+ {
+ if (!pS12)
+ pS12 = pPlcxMan->HasParaSprm(bVer67 ? 12 : 0xC63E); // sprmAnld
+ if (!pS12 || !SVBT8ToByte( ((WW8_ANLD*)pS12)->fNumberAcross))
+ pTableDesc->SetNumRuleName(pNumRule->GetName());
+ }
+ }
+
+ bAnl = true;
+
+ // NumRules ueber Stack setzen
+ pCtrlStck->NewAttr(*pPaM->GetPoint(),
+ SfxStringItem(RES_FLTR_NUMRULE, pNumRule->GetName()));
+
+ maANLDRules.SetNumRule(pNumRule, nWwNumType);
+}
+
+// NextAnlLine() wird fuer jede Zeile einer
+// Gliederung / Nummerierung / Aufzaehlung einmal gerufen
+void SwWW8ImplReader::NextAnlLine(const sal_uInt8* pSprm13)
+{
+ if (!bAnl)
+ return;
+
+ SwNumRule *pNumRule = maANLDRules.GetNumRule(nWwNumType);
+
+ // pNd->UpdateNum ohne Regelwerk gibt GPF spaetestens beim Speichern als
+ // sdw3
+
+ // WW:10 = Nummerierung -> SW:0 & WW:11 = Auffzaehlung -> SW:0
+ if (*pSprm13 == 10 || *pSprm13 == 11)
+ {
+ nSwNumLevel = 0;
+ if (!pNumRule->GetNumFmt(nSwNumLevel))
+ {
+ // noch nicht definiert
+ // sprmAnld o. 0
+ const sal_uInt8* pS12 = pPlcxMan->HasParaSprm(bVer67 ? 12 : 0xC63E);
+ SetAnld(pNumRule, (WW8_ANLD*)pS12, nSwNumLevel, false);
+ }
+ }
+ else if( *pSprm13 > 0 && *pSprm13 <= MAXLEVEL ) // Bereich WW:1..9 -> SW:0..8
+ {
+ nSwNumLevel = *pSprm13 - 1; // Gliederung
+ // noch nicht definiert
+ if (!pNumRule->GetNumFmt(nSwNumLevel))
+ {
+ if (pNumOlst) // es gab ein OLST
+ {
+ //Assure upper levels are set, #i9556#
+ for (sal_uInt8 nI = 0; nI < nSwNumLevel; ++nI)
+ {
+ if (!pNumRule->GetNumFmt(nI))
+ SetNumOlst(pNumRule, pNumOlst, nI);
+ }
+
+ SetNumOlst(pNumRule, pNumOlst , nSwNumLevel);
+ }
+ else // kein Olst, nimm Anld
+ {
+ // sprmAnld
+ const sal_uInt8* pS12 = pPlcxMan->HasParaSprm(bVer67 ? 12 : 0xC63E);
+ SetAnld(pNumRule, (WW8_ANLD*)pS12, nSwNumLevel, false);
+ }
+ }
+ }
+ else
+ nSwNumLevel = 0xff; // keine Nummer
+
+ SwTxtNode* pNd = pPaM->GetNode()->GetTxtNode();
+ if (nSwNumLevel < MAXLEVEL)
+ pNd->SetAttrListLevel( nSwNumLevel );
+ else
+ {
+ pNd->SetAttrListLevel(0);
+ pNd->SetCountedInList( false );
+ }
+}
+
+void SwWW8ImplReader::StopAllAnl(bool bGoBack)
+{
+ //Of course we're not restarting, but we'll make use of our knowledge
+ //of the implementation to do it.
+ StopAnlToRestart(WW8_None, bGoBack);
+}
+
+void SwWW8ImplReader::StopAnlToRestart(sal_uInt8 nNewType, bool bGoBack)
+{
+ if (bGoBack)
+ {
+ SwPosition aTmpPos(*pPaM->GetPoint());
+ pPaM->Move(fnMoveBackward, fnGoCntnt);
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_NUMRULE);
+ *pPaM->GetPoint() = aTmpPos;
+ }
+ else
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_NUMRULE);
+
+ maANLDRules.mpNumberingNumRule = 0;
+ /*
+ #i18816#
+ my take on this problem is that moving either way from an outline to a
+ numbering doesn't halt the outline, while the numbering is always halted
+ */
+ bool bNumberingNotStopOutline =
+ (((nWwNumType == WW8_Outline) && (nNewType == WW8_Numbering)) ||
+ ((nWwNumType == WW8_Numbering) && (nNewType == WW8_Outline)));
+ if (!bNumberingNotStopOutline)
+ maANLDRules.mpOutlineNumRule = 0;
+
+ nSwNumLevel = 0xff;
+ nWwNumType = WW8_None;
+ bAnl = false;
+}
+
+WW8TabBandDesc::WW8TabBandDesc( WW8TabBandDesc& rBand )
+{
+ *this = rBand;
+ if( rBand.pTCs )
+ {
+ pTCs = new WW8_TCell[nWwCols];
+ memcpy( pTCs, rBand.pTCs, nWwCols * sizeof( WW8_TCell ) );
+ }
+ if( rBand.pSHDs )
+ {
+ pSHDs = new WW8_SHD[nWwCols];
+ memcpy( pSHDs, rBand.pSHDs, nWwCols * sizeof( WW8_SHD ) );
+ }
+ if( rBand.pNewSHDs )
+ {
+ pNewSHDs = new sal_uInt32[nWwCols];
+ memcpy(pNewSHDs, rBand.pNewSHDs, nWwCols * sizeof(sal_uInt32));
+ }
+ memcpy(aDefBrcs, rBand.aDefBrcs, sizeof(aDefBrcs));
+}
+
+// ReadDef liest die Zellenpositionen und ggfs die Umrandungen eines Bandes ein
+void WW8TabBandDesc::ReadDef(bool bVer67, const sal_uInt8* pS)
+{
+ if (!bVer67)
+ pS++;
+
+ short nLen = (sal_Int16)SVBT16ToShort( pS - 2 ); // nicht schoen
+
+ sal_uInt8 nCols = *pS; // Anzahl der Zellen
+ short nOldCols = nWwCols;
+
+ if( nCols > MAX_COL )
+ return;
+
+ nWwCols = nCols;
+
+ const sal_uInt8* pT = &pS[1];
+ nLen --;
+ int i;
+ for(i=0; i<=nCols; i++, pT+=2 )
+ nCenter[i] = (sal_Int16)SVBT16ToShort( pT ); // X-Raender
+ nLen -= 2 * ( nCols + 1 );
+ if( nCols != nOldCols ) // andere Spaltenzahl
+ {
+ delete[] pTCs, pTCs = 0;
+ delete[] pSHDs, pSHDs = 0;
+ delete[] pNewSHDs, pNewSHDs = 0;
+ }
+
+ short nFileCols = nLen / ( bVer67 ? 10 : 20 ); // wirklich abgespeichert
+
+ if (!pTCs && nCols)
+ {
+ // lege leere TCs an
+ pTCs = new WW8_TCell[nCols];
+ setcelldefaults(pTCs,nCols);
+ }
+
+ short nColsToRead = nFileCols;
+ if (nColsToRead > nCols)
+ nColsToRead = nCols;
+
+ if( nColsToRead )
+ {
+ // lies TCs ein
+
+ /*
+ Achtung: ab Ver8 ist ein reserve-ushort je TC eingefuegt und auch
+ der Border-Code ist doppelt so gross, daher ist hier
+ kein simples kopieren moeglich,
+ d.h.: pTCs[i] = *pTc; geht leider nicht.
+ ---
+ Vorteil: Arbeitstruktur ist jetzt viel bequemer zu handhaben!
+ */
+ WW8_TCell* pAktTC = pTCs;
+ if( bVer67 )
+ {
+ WW8_TCellVer6* pTc = (WW8_TCellVer6*)pT;
+ for(i=0; i<nColsToRead; i++, ++pAktTC,++pTc)
+ {
+ if( i < nColsToRead )
+ { // TC aus File ?
+ sal_uInt8 aBits1 = SVBT8ToByte( pTc->aBits1Ver6 );
+ pAktTC->bFirstMerged = ( ( aBits1 & 0x01 ) != 0 );
+ pAktTC->bMerged = ( ( aBits1 & 0x02 ) != 0 );
+ memcpy( pAktTC->rgbrc[ WW8_TOP ].aBits1,
+ pTc->rgbrcVer6[ WW8_TOP ].aBits1, sizeof( SVBT16 ) );
+ memcpy( pAktTC->rgbrc[ WW8_LEFT ].aBits1,
+ pTc->rgbrcVer6[ WW8_LEFT ].aBits1, sizeof( SVBT16 ) );
+ memcpy( pAktTC->rgbrc[ WW8_BOT ].aBits1,
+ pTc->rgbrcVer6[ WW8_BOT ].aBits1, sizeof( SVBT16 ) );
+ memcpy( pAktTC->rgbrc[ WW8_RIGHT ].aBits1,
+ pTc->rgbrcVer6[ WW8_RIGHT ].aBits1, sizeof( SVBT16 ) );
+ if( ( pAktTC->bMerged )
+ && ( i > 0 ) )
+ {
+ // Cell gemerged -> merken
+ //bWWMergedVer6[i] = true;
+ memcpy( pTCs[i-1].rgbrc[ WW8_RIGHT ].aBits1,
+ pTc->rgbrcVer6[ WW8_RIGHT ].aBits1, sizeof( SVBT16 ) );
+ // right Border in vorige Zelle uebernehmen
+ // Hier darf bExist nicht auf false gesetzt werden, da WW
+ // in den Textboxen diese Zellen nicht mitzaehlt....
+ }
+ }
+ }
+ }
+ else
+ {
+ WW8_TCellVer8* pTc = (WW8_TCellVer8*)pT;
+ for (int k = 0; k < nColsToRead; ++k, ++pAktTC, ++pTc )
+ {
+ sal_uInt16 aBits1 = SVBT16ToShort( pTc->aBits1Ver8 );
+ pAktTC->bFirstMerged = ( ( aBits1 & 0x0001 ) != 0 );
+ pAktTC->bMerged = ( ( aBits1 & 0x0002 ) != 0 );
+ pAktTC->bVertical = ( ( aBits1 & 0x0004 ) != 0 );
+ pAktTC->bBackward = ( ( aBits1 & 0x0008 ) != 0 );
+ pAktTC->bRotateFont = ( ( aBits1 & 0x0010 ) != 0 );
+ pAktTC->bVertMerge = ( ( aBits1 & 0x0020 ) != 0 );
+ pAktTC->bVertRestart = ( ( aBits1 & 0x0040 ) != 0 );
+ pAktTC->nVertAlign = ( ( aBits1 & 0x0180 ) >> 7 );
+ // am Rande: im aBits1 verstecken sich noch 7 Reserve-Bits,
+ // anschliessend folgen noch 16 weitere Reserve-Bits
+
+ // In Version 8 koennen wir alle Bordercodes auf einmal kopieren!
+ memcpy( pAktTC->rgbrc, pTc->rgbrcVer8, 4 * sizeof( WW8_BRC ) );
+ }
+ }
+
+ // #i25071 In '97 text direction appears to be only set using TC properties
+ // not with sprmTTextFlow so we need to cycle through the maDirections and
+ // double check any non-default directions
+ for (int k = 0; k < nCols; ++k)
+ {
+ if(maDirections[k] == 4)
+ {
+ if(pTCs[k].bVertical)
+ {
+ if(pTCs[k].bBackward)
+ maDirections[k] = 3;
+ else
+ maDirections[k] = 1;
+ }
+ }
+ }
+
+
+ }
+}
+
+void WW8TabBandDesc::ProcessSprmTSetBRC(bool bVer67, const sal_uInt8* pParamsTSetBRC)
+{
+ if( pParamsTSetBRC && pTCs ) // set one or more cell border(s)
+ {
+ sal_uInt8 nitcFirst= pParamsTSetBRC[0];// first col to be changed
+ sal_uInt8 nitcLim = pParamsTSetBRC[1];// (last col to be changed)+1
+ sal_uInt8 nFlag = *(pParamsTSetBRC+2);
+
+ if (nitcFirst >= nWwCols)
+ return;
+
+ if (nitcLim > nWwCols)
+ nitcLim = nWwCols;
+
+ bool bChangeRight = (nFlag & 0x08) ? true : false;
+ bool bChangeBottom = (nFlag & 0x04) ? true : false;
+ bool bChangeLeft = (nFlag & 0x02) ? true : false;
+ bool bChangeTop = (nFlag & 0x01) ? true : false;
+
+ WW8_TCell* pAktTC = pTCs + nitcFirst;
+ if( bVer67 )
+ {
+ WW8_BRCVer6* pBRC = (WW8_BRCVer6*)(pParamsTSetBRC+3);
+
+ for( int i = nitcFirst; i < nitcLim; i++, ++pAktTC )
+ {
+ if( bChangeTop )
+ memcpy( pAktTC->rgbrc[ WW8_TOP ].aBits1,
+ pBRC->aBits1,
+ sizeof( SVBT16 ) );
+ if( bChangeLeft )
+ memcpy( pAktTC->rgbrc[ WW8_LEFT ].aBits1,
+ pBRC->aBits1,
+ sizeof( SVBT16 ) );
+ if( bChangeBottom )
+ memcpy( pAktTC->rgbrc[ WW8_BOT ].aBits1,
+ pBRC->aBits1,
+ sizeof( SVBT16 ) );
+ if( bChangeRight )
+ memcpy( pAktTC->rgbrc[ WW8_RIGHT].aBits1,
+ pBRC->aBits1,
+ sizeof( SVBT16 ) );
+ }
+ }
+ else
+ {
+ WW8_BRC* pBRC = (WW8_BRC*)(pParamsTSetBRC+3);
+
+ for( int i = nitcFirst; i < nitcLim; i++, ++pAktTC )
+ {
+ if( bChangeTop )
+ memcpy( pAktTC->rgbrc[ WW8_TOP ].aBits1,
+ pBRC->aBits1,
+ sizeof( WW8_BRC ) );
+ if( bChangeLeft )
+ memcpy( pAktTC->rgbrc[ WW8_LEFT ].aBits1,
+ pBRC->aBits1,
+ sizeof( WW8_BRC ) );
+ if( bChangeBottom )
+ memcpy( pAktTC->rgbrc[ WW8_BOT ].aBits1,
+ pBRC->aBits1,
+ sizeof( WW8_BRC ) );
+ if( bChangeRight )
+ memcpy( pAktTC->rgbrc[ WW8_RIGHT].aBits1,
+ pBRC->aBits1,
+ sizeof( WW8_BRC ) );
+ }
+
+
+
+ }
+ }
+}
+
+void WW8TabBandDesc::ProcessSprmTTableBorders(bool bVer67, const sal_uInt8* pParams)
+{
+ // sprmTTableBorders
+ if( bVer67 )
+ {
+ for( int i = 0; i < 6; ++i )
+ {
+ aDefBrcs[i].aBits1[0] = pParams[ 2*i ];
+ aDefBrcs[i].aBits1[1] = pParams[ 1+2*i ];
+ }
+ }
+ else // aDefBrcs = *(BRC(*)[6])pS;
+ memcpy( aDefBrcs, pParams, 24 );
+}
+
+void WW8TabBandDesc::ProcessSprmTDxaCol(const sal_uInt8* pParamsTDxaCol)
+{
+ // sprmTDxaCol (opcode 0x7623) changes the width of cells
+ // whose index is within a certain range to be a certain value.
+
+ if( nWwCols && pParamsTDxaCol ) // set one or more cell length(s)
+ {
+ sal_uInt8 nitcFirst= pParamsTDxaCol[0]; // first col to be changed
+ sal_uInt8 nitcLim = pParamsTDxaCol[1]; // (last col to be changed)+1
+ short nDxaCol = (sal_Int16)SVBT16ToShort( pParamsTDxaCol + 2 );
+ short nOrgWidth;
+ short nDelta;
+
+ for( int i = nitcFirst; (i < nitcLim) && (i < nWwCols); i++ )
+ {
+ nOrgWidth = nCenter[i+1] - nCenter[i];
+ nDelta = nDxaCol - nOrgWidth;
+ for( int j = i+1; j <= nWwCols; j++ )
+ {
+ nCenter[j] = nCenter[j] + nDelta;
+ }
+ }
+ }
+}
+
+void WW8TabBandDesc::ProcessSprmTInsert(const sal_uInt8* pParamsTInsert)
+{
+ if( nWwCols && pParamsTInsert ) // set one or more cell length(s)
+ {
+ sal_uInt8 nitcInsert = pParamsTInsert[0]; // position at which to insert
+ if (nitcInsert >= MAX_COL) // cannot insert into cell outside max possible index
+ return;
+ sal_uInt8 nctc = pParamsTInsert[1]; // number of cells
+ sal_uInt16 ndxaCol = SVBT16ToShort( pParamsTInsert+2 );
+
+ short nNewWwCols;
+ if (nitcInsert > nWwCols)
+ {
+ nNewWwCols = nitcInsert+nctc;
+ //if new count would be outside max possible count, clip it, and calc a new replacement
+ //legal nctc
+ if (nNewWwCols > MAX_COL)
+ {
+ nNewWwCols = MAX_COL;
+ nctc = ::sal::static_int_cast<sal_uInt8>(nNewWwCols-nitcInsert);
+ }
+ }
+ else
+ {
+ nNewWwCols = nWwCols+nctc;
+ //if new count would be outside max possible count, clip it, and calc a new replacement
+ //legal nctc
+ if (nNewWwCols > MAX_COL)
+ {
+ nNewWwCols = MAX_COL;
+ nctc = ::sal::static_int_cast<sal_uInt8>(nNewWwCols-nWwCols);
+ }
+ }
+
+ WW8_TCell *pTC2s = new WW8_TCell[nNewWwCols];
+ setcelldefaults(pTC2s, nNewWwCols);
+
+ if (pTCs)
+ {
+ memcpy( pTC2s, pTCs, nWwCols * sizeof( WW8_TCell ) );
+ delete[] pTCs;
+ }
+ pTCs = pTC2s;
+
+ //If we have to move some cells
+ if (nitcInsert <= nWwCols)
+ {
+ // adjust the left x-position of the dummy at the very end
+ nCenter[nWwCols + nctc] = nCenter[nWwCols]+nctc*ndxaCol;
+ for( int i = nWwCols-1; i >= nitcInsert; i--)
+ {
+ // adjust the left x-position
+ nCenter[i + nctc] = nCenter[i]+nctc*ndxaCol;
+
+ // adjust the cell's borders
+ pTCs[i + nctc] = pTCs[i];
+ }
+ }
+
+ //if itcMac is larger than full size, fill in missing ones first
+ for( int i = nWwCols; i > nitcInsert+nWwCols; i--)
+ nCenter[i] = i ? (nCenter[i - 1]+ndxaCol) : 0;
+
+ //now add in our new cells
+ for( int j = 0;j < nctc; j++)
+ nCenter[j + nitcInsert] = (j + nitcInsert) ? (nCenter[j + nitcInsert -1]+ndxaCol) : 0;
+
+ nWwCols = nNewWwCols;
+ }
+}
+
+void WW8TabBandDesc::ProcessDirection(const sal_uInt8* pParams)
+{
+ sal_uInt8 nStartCell = *pParams++;
+ sal_uInt8 nEndCell = *pParams++;
+ sal_uInt16 nCode = SVBT16ToShort(pParams);
+
+ OSL_ENSURE(nStartCell < nEndCell, "not as I thought");
+ OSL_ENSURE(nEndCell < MAX_COL + 1, "not as I thought");
+ if (nStartCell > MAX_COL)
+ return;
+ if (nEndCell > MAX_COL + 1)
+ nEndCell = MAX_COL + 1;
+
+ for (;nStartCell < nEndCell; ++nStartCell)
+ maDirections[nStartCell] = nCode;
+}
+
+void WW8TabBandDesc::ProcessSpacing(const sal_uInt8* pParams)
+{
+ sal_uInt8 nLen = pParams ? *(pParams - 1) : 0;
+ OSL_ENSURE(nLen == 6, "Unexpected spacing len");
+ if (nLen != 6)
+ return;
+ mbHasSpacing=true;
+#if OSL_DEBUG_LEVEL > 1
+ sal_uInt8 nWhichCell = *pParams;
+ OSL_ENSURE(nWhichCell == 0, "Expected cell to be 0!");
+#endif
+ ++pParams; //Skip which cell
+ ++pParams; //unknown byte
+
+ sal_uInt8 nSideBits = *pParams++;
+ OSL_ENSURE(nSideBits < 0x10, "Unexpected value for nSideBits");
+ ++pParams; //unknown byte
+ sal_uInt16 nValue = SVBT16ToShort( pParams );
+ for (int i = wwTOP; i <= wwRIGHT; i++)
+ {
+ switch (nSideBits & (1 << i))
+ {
+ case 1 << wwTOP:
+ mnDefaultTop = nValue;
+ break;
+ case 1 << wwLEFT:
+ mnDefaultLeft = nValue;
+ break;
+ case 1 << wwBOTTOM:
+ mnDefaultBottom = nValue;
+ break;
+ case 1 << wwRIGHT:
+ mnDefaultRight = nValue;
+ break;
+ case 0:
+ break;
+ default:
+ OSL_ENSURE(!this, "Impossible");
+ break;
+ }
+ }
+}
+
+void WW8TabBandDesc::ProcessSpecificSpacing(const sal_uInt8* pParams)
+{
+ sal_uInt8 nLen = pParams ? *(pParams - 1) : 0;
+ OSL_ENSURE(nLen == 6, "Unexpected spacing len");
+ if (nLen != 6)
+ return;
+ sal_uInt8 nWhichCell = *pParams++;
+ OSL_ENSURE(nWhichCell < MAX_COL + 1, "Cell out of range in spacings");
+ if (nWhichCell >= MAX_COL + 1)
+ return;
+
+ ++pParams; //unknown byte
+ sal_uInt8 nSideBits = *pParams++;
+ OSL_ENSURE(nSideBits < 0x10, "Unexpected value for nSideBits");
+ nOverrideSpacing[nWhichCell] |= nSideBits;
+
+ OSL_ENSURE(nOverrideSpacing[nWhichCell] < 0x10,
+ "Unexpected value for nSideBits");
+#if OSL_DEBUG_LEVEL > 1
+ sal_uInt8 nUnknown2 = *pParams;
+ OSL_ENSURE(nUnknown2 == 0x3, "Unexpected value for spacing2");
+
+#endif
+ ++pParams;
+ sal_uInt16 nValue = SVBT16ToShort( pParams );
+
+ for (int i=0; i < 4; i++)
+ {
+ if (nSideBits & (1 << i))
+ nOverrideValues[nWhichCell][i] = nValue;
+ }
+}
+
+void WW8TabBandDesc::ProcessSprmTDelete(const sal_uInt8* pParamsTDelete)
+{
+ if( nWwCols && pParamsTDelete ) // set one or more cell length(s)
+ {
+ sal_uInt8 nitcFirst= pParamsTDelete[0]; // first col to be deleted
+ if (nitcFirst >= nWwCols) // first index to delete from doesn't exist
+ return;
+ sal_uInt8 nitcLim = pParamsTDelete[1]; // (last col to be deleted)+1
+ if (nitcLim <= nitcFirst) // second index to delete to is not greater than first index
+ return;
+
+ /*
+ * sprmTDelete causes any rgdxaCenter and rgtc entries whose index is
+ * greater than or equal to itcLim to be moved
+ */
+ int nShlCnt = nWwCols - nitcLim; // count of cells to be shifted
+
+ if (nShlCnt >= 0) //There exist entries whose index is greater than or equal to itcLim
+ {
+ WW8_TCell* pAktTC = pTCs + nitcFirst;
+ int i = 0;
+ while( i < nShlCnt )
+ {
+ // adjust the left x-position
+ nCenter[nitcFirst + i] = nCenter[nitcLim + i];
+
+ // adjust the cell's borders
+ *pAktTC = pTCs[ nitcLim + i];
+
+ ++i;
+ ++pAktTC;
+ }
+ // adjust the left x-position of the dummy at the very end
+ nCenter[nitcFirst + i] = nCenter[nitcLim + i];
+ }
+
+ short nCellsDeleted = nitcLim - nitcFirst;
+ //clip delete request to available number of cells
+ if (nCellsDeleted > nWwCols)
+ nCellsDeleted = nWwCols;
+ nWwCols -= nCellsDeleted;
+ }
+}
+
+// ReadShd liest ggfs die Hintergrundfarben einer Zeile ein.
+// Es muss vorher ReadDef aufgerufen worden sein
+void WW8TabBandDesc::ReadShd(const sal_uInt8* pS )
+{
+ sal_uInt8 nLen = pS ? *(pS - 1) : 0;
+ if( !nLen )
+ return;
+
+ if( !pSHDs )
+ {
+ pSHDs = new WW8_SHD[nWwCols];
+ memset( pSHDs, 0, nWwCols * sizeof( WW8_SHD ) );
+ }
+
+ short nAnz = nLen >> 1;
+ if (nAnz > nWwCols)
+ nAnz = nWwCols;
+
+ SVBT16* pShd;
+ int i;
+ for(i=0, pShd = (SVBT16*)pS; i<nAnz; i++, pShd++ )
+ pSHDs[i].SetWWValue( *pShd );
+}
+
+void WW8TabBandDesc::ReadNewShd(const sal_uInt8* pS, bool bVer67)
+{
+ sal_uInt8 nLen = pS ? *(pS - 1) : 0;
+ if (!nLen)
+ return;
+
+ if (!pNewSHDs)
+ pNewSHDs = new sal_uInt32[nWwCols];
+
+ short nAnz = nLen / 10; //10 bytes each
+ if (nAnz > nWwCols)
+ nAnz = nWwCols;
+
+ int i=0;
+ while (i < nAnz)
+ pNewSHDs[i++] = SwWW8ImplReader::ExtractColour(pS, bVer67);
+
+ while (i < nWwCols)
+ pNewSHDs[i++] = COL_AUTO;
+}
+
+void WW8TabBandDesc::setcelldefaults(WW8_TCell *pCells, short nCols)
+{
+ memset( pCells, 0, nCols * sizeof( WW8_TCell ) );
+}
+
+const sal_uInt8 *HasTabCellSprm(WW8PLCFx_Cp_FKP* pPap, bool bVer67)
+{
+ const sal_uInt8 *pParams;
+ if (bVer67)
+ pParams = pPap->HasSprm(24);
+ else
+ {
+ if (0 == (pParams = pPap->HasSprm(0x244B)))
+ pParams = pPap->HasSprm(0x2416);
+ }
+ return pParams;
+}
+
+enum wwTableSprm
+{
+ sprmNil,
+
+ sprmTTableWidth,sprmTTextFlow, sprmTFCantSplit, sprmTFCantSplit90,sprmTJc, sprmTFBiDi, sprmTDefTable,
+ sprmTDyaRowHeight, sprmTDefTableShd, sprmTDxaLeft, sprmTSetBrc,
+ sprmTDxaCol, sprmTInsert, sprmTDelete, sprmTTableHeader,
+ sprmTDxaGapHalf, sprmTTableBorders,
+
+ sprmTDefTableNewShd, sprmTSpacing, sprmTNewSpacing
+};
+
+wwTableSprm GetTableSprm(sal_uInt16 nId, ww::WordVersion eVer)
+{
+ switch (eVer)
+ {
+ case ww::eWW8:
+ switch (nId)
+ {
+ case 0xF614:
+ return sprmTTableWidth;
+ case 0x7629:
+ return sprmTTextFlow;
+ case 0x3403:
+ return sprmTFCantSplit;
+ case 0x3404:
+ return sprmTTableHeader;
+ case 0x3466:
+ return sprmTFCantSplit90;
+ case 0x5400:
+ return sprmTJc;
+ case 0x560B:
+ return sprmTFBiDi;
+ case 0x5622:
+ return sprmTDelete;
+ case 0x7621:
+ return sprmTInsert;
+ case 0x7623:
+ return sprmTDxaCol;
+ case 0x9407:
+ return sprmTDyaRowHeight;
+ case 0x9601:
+ return sprmTDxaLeft;
+ case 0x9602:
+ return sprmTDxaGapHalf;
+ case 0xD605:
+ return sprmTTableBorders;
+ case 0xD608:
+ return sprmTDefTable;
+ case 0xD609:
+ return sprmTDefTableShd;
+ case 0xD612:
+ return sprmTDefTableNewShd;
+ case 0xD620:
+ return sprmTSetBrc;
+ case 0xD632:
+ return sprmTSpacing;
+ case 0xD634:
+ return sprmTNewSpacing;
+ }
+ break;
+ case ww::eWW7:
+ case ww::eWW6:
+ switch (nId)
+ {
+ case 182:
+ return sprmTJc;
+ case 183:
+ return sprmTDxaLeft;
+ case 184:
+ return sprmTDxaGapHalf;
+ case 186:
+ return sprmTTableHeader;
+ case 187:
+ return sprmTTableBorders;
+ case 189:
+ return sprmTDyaRowHeight;
+ case 190:
+ return sprmTDefTable;
+ case 191:
+ return sprmTDefTableShd;
+ case 193:
+ return sprmTSetBrc;
+ case 194:
+ return sprmTInsert;
+ case 195:
+ return sprmTDelete;
+ case 196:
+ return sprmTDxaCol;
+ }
+ break;
+ case ww::eWW2:
+ switch (nId)
+ {
+ case 146:
+ return sprmTJc;
+ case 147:
+ return sprmTDxaLeft;
+ case 148:
+ return sprmTDxaGapHalf;
+ case 153:
+ return sprmTDyaRowHeight;
+ case 154:
+ return sprmTDefTable;
+ case 155:
+ return sprmTDefTableShd;
+ case 157:
+ return sprmTSetBrc;
+ case 158:
+ return sprmTInsert;
+ case 159:
+ return sprmTDelete;
+ case 160:
+ return sprmTDxaCol;
+ }
+ break;
+ }
+ return sprmNil;
+}
+
+WW8TabDesc::WW8TabDesc(SwWW8ImplReader* pIoClass, WW8_CP nStartCp) :
+ mpOldRedlineStack(0),
+ pIo(pIoClass),
+ pFirstBand(0),
+ pActBand(0),
+ pTmpPos(0),
+ pTblNd(0),
+ pTabLines(0),
+ pTabLine(0),
+ pTabBoxes(0),
+ pTabBox(0),
+ pMergeGroups(0),
+ pAktWWCell(0),
+ nRows(0),
+ nDefaultSwCols(0),
+ nBands(0),
+ nMinLeft(0),
+ nConvertedLeft(0),
+ nMaxRight(0),
+ nSwWidth(0),
+ nPreferredWidth(0),
+ nOrgDxaLeft(0),
+ bOk(true),
+ bClaimLineFmt(false),
+ eOri(text::HoriOrientation::NONE),
+ bIsBiDi(false),
+ nAktRow(0),
+ nAktBandRow(0),
+ nAktCol(0),
+ nRowsToRepeat(0),
+ pTable(0),
+ pParentPos(0),
+ pFlyFmt(0),
+ aItemSet(pIo->rDoc.GetAttrPool(),RES_FRMATR_BEGIN,RES_FRMATR_END-1)
+{
+ pIo->bAktAND_fNumberAcross = false;
+
+ static const sal_Int16 aOriArr[] =
+ {
+ text::HoriOrientation::LEFT, text::HoriOrientation::CENTER, text::HoriOrientation::RIGHT, text::HoriOrientation::CENTER
+ };
+
+ bool bOldVer = ww::IsSevenMinus(pIo->GetFib().GetFIBVersion());
+ WW8_TablePos aTabPos;
+
+ WW8PLCFxSave1 aSave;
+ pIo->pPlcxMan->GetPap()->Save( aSave );
+
+ WW8PLCFx_Cp_FKP* pPap = pIo->pPlcxMan->GetPapPLCF();
+
+ eOri = text::HoriOrientation::LEFT;
+
+ WW8TabBandDesc* pNewBand = new WW8TabBandDesc;
+
+ wwSprmParser aSprmParser(pIo->GetFib().GetFIBVersion());
+
+ // process pPap until end of table found
+ do
+ {
+ short nTabeDxaNew = SHRT_MAX;
+ bool bTabRowJustRead = false;
+ const sal_uInt8* pShadeSprm = 0;
+ const sal_uInt8* pNewShadeSprm = 0;
+ WW8_TablePos *pTabPos = 0;
+
+ // Suche Ende einer TabZeile
+ if(!(pIo->SearchRowEnd(pPap, nStartCp, pIo->nInTable)))
+ {
+ bOk = false;
+ break;
+ }
+
+ // Get the SPRM chains:
+ // first from PAP and then from PCD (of the Piece Table)
+ WW8PLCFxDesc aDesc;
+ pPap->GetSprms( &aDesc );
+ WW8SprmIter aSprmIter(aDesc.pMemPos, aDesc.nSprmsLen, aSprmParser);
+
+ const sal_uInt8* pParams = aSprmIter.GetAktParams();
+ for (int nLoop = 0; nLoop < 2; ++nLoop)
+ {
+ bool bRepeatedSprm = false;
+ while (aSprmIter.GetSprms() && 0 != (pParams = aSprmIter.GetAktParams()))
+ {
+ sal_uInt16 nId = aSprmIter.GetAktId();
+ wwTableSprm eSprm = GetTableSprm(nId, pIo->GetFib().GetFIBVersion());
+ switch (eSprm)
+ {
+ case sprmTTableWidth:
+ {
+ const sal_uInt8 b0 = pParams[0];
+ const sal_uInt8 b1 = pParams[1];
+ const sal_uInt8 b2 = pParams[2];
+ if (b0 == 3) // Twips
+ nPreferredWidth = b2 * 0x100 + b1;
+ }
+ break;
+ case sprmTTextFlow:
+ pNewBand->ProcessDirection(pParams);
+ break;
+ case sprmTFCantSplit:
+ pNewBand->bCantSplit = *pParams;
+ bClaimLineFmt = true;
+ break;
+ case sprmTFCantSplit90:
+ pNewBand->bCantSplit90 = *pParams;
+ bClaimLineFmt = true;
+ break;
+ case sprmTTableBorders:
+ pNewBand->ProcessSprmTTableBorders(bOldVer, pParams);
+ break;
+ case sprmTTableHeader:
+ if (!bRepeatedSprm)
+ {
+ nRowsToRepeat++;
+ bRepeatedSprm = true;
+ }
+ break;
+ case sprmTJc:
+ // sprmTJc - Justification Code
+ if (nRows == 0)
+ eOri = aOriArr[*pParams & 0x3];
+ break;
+ case sprmTFBiDi:
+ bIsBiDi = SVBT16ToShort(pParams) ? true : false;
+ break;
+ case sprmTDxaGapHalf:
+ pNewBand->nGapHalf = (sal_Int16)SVBT16ToShort( pParams );
+ break;
+ case sprmTDyaRowHeight:
+ pNewBand->nLineHeight = (sal_Int16)SVBT16ToShort( pParams );
+ bClaimLineFmt = true;
+ break;
+ case sprmTDefTable:
+ pNewBand->ReadDef(bOldVer, pParams);
+ bTabRowJustRead = true;
+ break;
+ case sprmTDefTableShd:
+ pShadeSprm = pParams;
+ break;
+ case sprmTDefTableNewShd:
+ pNewShadeSprm = pParams;
+ break;
+ case sprmTDxaLeft:
+ // our Writer cannot shift single table lines
+ // horizontally so we have to find the smallest
+ // parameter (meaning the left-most position) and then
+ // shift the whole table to that margin (see below)
+ {
+ short nDxaNew = (sal_Int16)SVBT16ToShort( pParams );
+ nOrgDxaLeft = nDxaNew;
+ if( nDxaNew < nTabeDxaNew )
+ nTabeDxaNew = nDxaNew;
+ }
+ break;
+ case sprmTSetBrc:
+ pNewBand->ProcessSprmTSetBRC(bOldVer, pParams);
+ break;
+ case sprmTDxaCol:
+ pNewBand->ProcessSprmTDxaCol(pParams);
+ break;
+ case sprmTInsert:
+ pNewBand->ProcessSprmTInsert(pParams);
+ break;
+ case sprmTDelete:
+ pNewBand->ProcessSprmTDelete(pParams);
+ break;
+ case sprmTNewSpacing:
+ pNewBand->ProcessSpacing(pParams);
+ break;
+ case sprmTSpacing:
+ pNewBand->ProcessSpecificSpacing(pParams);
+ break;
+ default:
+ ;
+ }
+ aSprmIter.advance();
+ }
+
+ if( !nLoop )
+ {
+ pPap->GetPCDSprms( aDesc );
+ aSprmIter.SetSprms( aDesc.pMemPos, aDesc.nSprmsLen );
+ }
+ }
+
+ // WW-Tabellen koennen Fly-Wechsel beinhalten daher hier
+ // Tabellen abbrechen und neu beginnen noch steht *pPap noch vor
+ // TabRowEnd, daher kann TestApo() mit letztem Parameter false und
+ // damit wirksam gerufen werden.
+
+ if (bTabRowJustRead)
+ {
+ if (pShadeSprm)
+ pNewBand->ReadShd(pShadeSprm);
+ if (pNewShadeSprm)
+ pNewBand->ReadNewShd(pNewShadeSprm, bOldVer);
+ }
+
+ if( nTabeDxaNew < SHRT_MAX )
+ {
+ short* pCenter = pNewBand->nCenter;
+ short firstDxaCenter = *pCenter;
+ for( int i = 0; i < pNewBand->nWwCols; i++, ++pCenter )
+ {
+ // #i30298# Use sprmTDxaLeft to adjust the left indent
+ // #i40461# Use dxaGapHalf during calculation
+ *pCenter +=
+ (nTabeDxaNew - (firstDxaCenter + pNewBand->nGapHalf));
+ }
+ }
+
+ if (!pActBand)
+ pActBand = pFirstBand = pNewBand;
+ else
+ {
+ pActBand->pNextBand = pNewBand;
+ pActBand = pNewBand;
+ }
+ nBands++;
+
+ pNewBand = new WW8TabBandDesc;
+
+ nRows++;
+ pActBand->nRows++;
+
+ //Seek our pap to its next block of properties
+ WW8PLCFxDesc aRes;
+ aRes.pMemPos = 0;
+ aRes.nStartPos = nStartCp;
+
+ if (!(pPap->SeekPos(aRes.nStartPos)))
+ {
+ aRes.nEndPos = WW8_CP_MAX;
+ pPap->SetDirty(true);
+ }
+ pPap->GetSprms(&aRes);
+ pPap->SetDirty(false);
+
+ //Are we at the end of available properties
+ if (
+ !pPap->HasFkp() || pPap->Where() == WW8_CP_MAX ||
+ aRes.nStartPos == WW8_CP_MAX
+ )
+ {
+ bOk = false;
+ break;
+ }
+
+ //Are we still in a table cell
+ pParams = HasTabCellSprm(pPap, bOldVer);
+ const sal_uInt8 *pLevel = pPap->HasSprm(0x6649);
+ // InTable
+ if (!pParams || (1 != *pParams) ||
+ (pLevel && (*pLevel <= pIo->nInTable)))
+ {
+ break;
+ }
+
+ //Get the end of row new table positioning data
+ WW8_CP nMyStartCp=nStartCp;
+ if (pIo->SearchRowEnd(pPap, nMyStartCp, pIo->nInTable))
+ if (SwWW8ImplReader::ParseTabPos(&aTabPos, pPap))
+ pTabPos = &aTabPos;
+
+ //Move back to this cell
+ aRes.pMemPos = 0;
+ aRes.nStartPos = nStartCp;
+
+ // PlcxMan currently points too far ahead so we need to bring
+ // it back to where we are trying to make a table
+ pIo->pPlcxMan->GetPap()->nOrigStartPos = aRes.nStartPos;
+ if (!(pPap->SeekPos(aRes.nStartPos)))
+ {
+ aRes.nEndPos = WW8_CP_MAX;
+ pPap->SetDirty(true);
+ }
+ pPap->GetSprms(&aRes);
+ pPap->SetDirty(false);
+
+ //Does this row match up with the last row closely enough to be
+ //considered part of the same table
+ ApoTestResults aApo = pIo->TestApo(pIo->nInTable + 1, false, pTabPos);
+
+ /*
+ ##513##, #79474# If this is not sufficent, then we should look at
+ sprmPD{y|x}aAbs as our indicator that the following set of rows is not
+ part of this table, but instead is an absolutely positioned table
+ outside of this one
+ */
+ if (aApo.mbStopApo)
+ break;
+ if (aApo.mbStartApo)
+ {
+ //if there really is a fly here, and not a "null" fly then break.
+ WW8FlyPara *pNewFly = pIo->ConstructApo(aApo, pTabPos);
+ if (pNewFly)
+ delete pNewFly;
+ else
+ break;
+ }
+
+ nStartCp = aRes.nEndPos;
+ }
+ while( 1 );
+
+ if( bOk )
+ {
+ if( pActBand->nRows > 1 )
+ {
+ // Letztes Band hat mehr als 1 Zeile
+ delete pNewBand;
+ pNewBand = new WW8TabBandDesc( *pActBand ); // neues machen
+ pActBand->nRows--; // wegen Sonderbehandlung Raender-Defaults
+ pNewBand->nRows = 1;
+ pActBand->pNextBand = pNewBand; // am Ende einschleifen
+ nBands++;
+ pNewBand = 0; // nicht loeschen
+ }
+ CalcDefaults();
+ }
+ delete pNewBand;
+
+ pIo->pPlcxMan->GetPap()->Restore( aSave );
+}
+
+WW8TabDesc::~WW8TabDesc()
+{
+ WW8TabBandDesc* pR = pFirstBand;
+ while(pR)
+ {
+ WW8TabBandDesc* pR2 = pR->pNextBand;
+ delete pR;
+ pR = pR2;
+ }
+
+ delete pParentPos;
+ delete pMergeGroups;
+}
+
+void WW8TabDesc::CalcDefaults()
+{
+ short nMinCols = SHRT_MAX;
+ WW8TabBandDesc* pR;
+
+ nMinLeft = SHRT_MAX;
+ nMaxRight = SHRT_MIN;
+
+ /*
+ If we are an honestly inline centered table, then the normal rules of
+ engagement for left and right margins do not apply. The multiple rows are
+ centered regardless of the actual placement of rows, so we cannot have
+ mismatched rows as is possible in other configurations.
+
+ e.g. change the example bugdoc in word from text wrapping of none (inline)
+ to around (in frame (bApo)) and the table splits into two very disjoint
+ rows as the beginning point of each row are very different
+ */
+ if ((!pIo->InLocalApo()) && (eOri == text::HoriOrientation::CENTER))
+ {
+ for (pR = pFirstBand; pR; pR = pR->pNextBand)
+ for( short i = pR->nWwCols; i >= 0; --i)
+ pR->nCenter[i] = pR->nCenter[i] - pR->nCenter[0];
+ }
+
+ // 1. Durchlauf: aeusserste L- und R-Grenzen finden
+ for( pR = pFirstBand; pR; pR = pR->pNextBand )
+ {
+ if( pR->nCenter[0] < nMinLeft )
+ nMinLeft = pR->nCenter[0];
+
+ for( short i = 0; i < pR->nWwCols; i++ )
+ {
+ /*
+ If the margins are so large as to make the displayable
+ area inside them smaller than the minimum allowed then adjust the
+ width to fit. But only do it if the two cells are not the exact
+ same value, if they are then the cell does not really exist and will
+ be blended together into the same cell through the use of the
+ nTrans(late) array.
+ #i28333# If the nGapHalf is greater than the cell width best to ignore it
+ */
+ int nCellWidth = pR->nCenter[i+1] - pR->nCenter[i];
+ if (nCellWidth && ((nCellWidth - pR->nGapHalf*2) < MINLAY) && pR->nGapHalf < nCellWidth)
+ {
+ pR->nCenter[i+1] = pR->nCenter[i]+MINLAY+pR->nGapHalf * 2;
+ }
+ }
+
+ if( pR->nCenter[pR->nWwCols] > nMaxRight )
+ nMaxRight = pR->nCenter[pR->nWwCols];
+ }
+ nSwWidth = nMaxRight - nMinLeft;
+
+ // If the table is right aligned we need to align all rows to the
+ // row that has the furthest right point
+
+ if(eOri == text::HoriOrientation::RIGHT)
+ {
+ for( pR = pFirstBand; pR; pR = pR->pNextBand )
+ {
+ int adjust = nMaxRight - pR->nCenter[pR->nWwCols];
+ for( short i = 0; i < pR->nWwCols + 1; i++ )
+ {
+ pR->nCenter[i] = static_cast< short >(pR->nCenter[i] + adjust);
+ }
+
+ }
+ }
+
+ // 2. Durchlauf: Zahl der Writer-Spalten feststellen Die Zahl der Writer
+ // Spalten kann um bis zu 2 hoeher sein als im WW, da der SW im Gegensatz
+ // zu WW keine ausgefransten linken und rechten Raender kann und diese
+ // durch leere Boxen aufgefuellt werden. Durch nichtexistente Zellen
+ // koennen auch Zellen wegfallen
+
+ // 3. Durchlauf: Wo noetig die Umrandungen durch die Defaults ersetzen
+ nConvertedLeft = nMinLeft;
+
+ short nLeftMaxThickness = 0, nRightMaxThickness=0;
+ for( pR = pFirstBand ; pR; pR = pR->pNextBand )
+ {
+ if( !pR->pTCs )
+ {
+ pR->pTCs = new WW8_TCell[ pR->nWwCols ];
+ memset( pR->pTCs, 0, pR->nWwCols * sizeof( WW8_TCell ) );
+ }
+ for (int k = 0; k < pR->nWwCols; ++k)
+ {
+ WW8_TCell* pT = &pR->pTCs[k];
+ int i, j;
+ for( i = 0; i < 4; i ++ )
+ {
+ if (pT->rgbrc[i].IsZeroed(pIo->bVer67))
+ {
+ // if shadow is set, its invalid
+ j = i;
+ switch( i )
+ {
+ case 0:
+ // Aussen oben / Innen waagerecht
+ j = (pR == pFirstBand) ? 0 : 4;
+ break;
+ case 1:
+ // Aussen links / Innen senkrecht
+ j = k ? 5 : 1;
+ break;
+ case 2:
+ // Aussen unten / Innen waagerecht
+ j = pR->pNextBand ? 4 : 2;
+ break;
+ case 3:
+ // Aussen rechts/ Innen senkrecht
+ j = (k == pR->nWwCols - 1) ? 3 : 5;
+ break;
+ }
+ // mangel mit Defaults ueber
+ pT->rgbrc[i] = pR->aDefBrcs[j];
+ }
+ }
+ }
+ if (pR->nWwCols)
+ {
+ /*
+ Similiar to graphics and other elements word does not totally
+ factor the width of the border into its calculations of size, we
+ do so we must adjust out widths and other dimensions to fit. It
+ appears that what occurs is that the last cell's right margin if
+ the margin width that is not calculated into winwords table
+ dimensions, so in that case increase the table to include the
+ extra width of the right margin.
+ */
+ if ( pIo->bVer67 ?
+ !(SVBT16ToShort(pR->pTCs[pR->nWwCols-1].rgbrc[3].aBits1) & 0x20)
+ : !(SVBT16ToShort(pR->pTCs[pR->nWwCols-1].rgbrc[3].aBits2) & 0x2000))
+ {
+ short nThickness = pR->pTCs[pR->nWwCols-1].rgbrc[3].
+ DetermineBorderProperties(pIo->bVer67);
+ pR->nCenter[pR->nWwCols] = pR->nCenter[pR->nWwCols] + nThickness;
+ if (nThickness > nRightMaxThickness)
+ nRightMaxThickness = nThickness;
+ }
+
+ /*
+ The left space of the table is in nMinLeft, but again this
+ does not consider the margin thickness to its left in the
+ placement value, so get the thickness of the left border,
+ half is placed to the left of the nominal left side, and
+ half to the right.
+ */
+ if ( pIo->bVer67 ?
+ !(SVBT16ToShort(pR->pTCs[0].rgbrc[1].aBits1) & 0x20)
+ : !(SVBT16ToShort(pR->pTCs[0].rgbrc[1].aBits2) & 0x2000))
+ {
+ short nThickness = pR->pTCs[0].rgbrc[1].
+ DetermineBorderProperties(pIo->bVer67);
+ if (nThickness > nLeftMaxThickness)
+ nLeftMaxThickness = nThickness;
+ }
+ }
+ }
+ nSwWidth = nSwWidth + nRightMaxThickness;
+ nMaxRight = nMaxRight + nRightMaxThickness;
+ nConvertedLeft = nMinLeft-(nLeftMaxThickness/2);
+
+ for( pR = pFirstBand; pR; pR = pR->pNextBand )
+ {
+ pR->nSwCols = pR->nWwCols;
+ pR->bLEmptyCol = pR->nCenter[0] - nMinLeft >= MINLAY;
+ pR->bREmptyCol = (nMaxRight - pR->nCenter[pR->nWwCols] - nRightMaxThickness) >= MINLAY;
+
+ short nAddCols = pR->bLEmptyCol + pR->bREmptyCol;
+ sal_uInt16 i;
+ sal_uInt16 j = ( pR->bLEmptyCol ) ? 1 : 0;
+ for (i = 0; i < pR->nWwCols; ++i)
+ {
+ pR->nTransCell[i] = (sal_Int8)j;
+ if ( pR->nCenter[i] < pR->nCenter[i+1] )
+ {
+ pR->bExist[i] = true;
+ j++;
+ }
+ else
+ {
+ pR->bExist[i] = false;
+ nAddCols--;
+ }
+ }
+
+ OSL_ENSURE(i,"no columns in row ?");
+
+ /*
+ If the last cell was "false" then there is no valid cell following it,
+ so the default mapping forward wont't work. So map it (and
+ contigious invalid cells backwards to the last valid cell instead.
+ */
+ if (i && pR->bExist[i-1] == false)
+ {
+ sal_uInt16 k=i-1;
+ while (k && pR->bExist[k] == false)
+ k--;
+ for (sal_uInt16 n=k+1;n<i;n++)
+ pR->nTransCell[n] = pR->nTransCell[k];
+ }
+
+ pR->nTransCell[i++] = (sal_Int8)(j++); // Wird u.a. wegen bREmptyCol um
+ pR->nTransCell[i] = (sal_Int8)j; // max. 2 ueberindiziert
+
+ pR->nSwCols = pR->nSwCols + nAddCols;
+ if( pR->nSwCols < nMinCols )
+ nMinCols = pR->nSwCols;
+ }
+
+ /*
+ #i9718#
+ Find the largest of the borders on cells that adjoin top bottom and remove
+ the val from the top and put in on the bottom cell. I can't seem to make
+ disjoint upper and lowers to see what happens there.
+ */
+
+ if ((nMinLeft && !bIsBiDi && text::HoriOrientation::LEFT == eOri) ||
+ (nMinLeft != -108 && bIsBiDi && text::HoriOrientation::RIGHT == eOri)) // Word sets the first nCenter value to -108 when no indent is used
+ eOri = text::HoriOrientation::LEFT_AND_WIDTH; // absolutely positioned
+
+ nDefaultSwCols = nMinCols; // da Zellen einfuegen billiger ist als Mergen
+ if( nDefaultSwCols == 0 )
+ bOk = false;
+ pActBand = pFirstBand;
+ nAktBandRow = 0;
+ OSL_ENSURE( pActBand, "pActBand ist 0" );
+}
+
+void WW8TabDesc::SetSizePosition(SwFrmFmt* pFrmFmt)
+{
+ SwFrmFmt* pApply = pFrmFmt;
+ if (!pApply )
+ pApply = pTable->GetFrmFmt();
+ OSL_ENSURE(pApply,"No frame");
+ pApply->SetFmtAttr(aItemSet);
+ if (pFrmFmt)
+ {
+ SwFmtFrmSize aSize = pFrmFmt->GetFrmSize();
+ aSize.SetHeightSizeType(ATT_MIN_SIZE);
+ aSize.SetHeight(MINLAY);
+ pFrmFmt->SetFmtAttr(aSize);
+ pTable->GetFrmFmt()->SetFmtAttr(SwFmtHoriOrient(0,text::HoriOrientation::FULL));
+ }
+}
+
+void wwSectionManager::PrependedInlineNode(const SwPosition &rPos,
+ const SwNode &rNode)
+{
+ OSL_ENSURE(!maSegments.empty(),
+ "should not be possible, must be at least one segment");
+ if ((!maSegments.empty()) && (maSegments.back().maStart == rPos.nNode))
+ maSegments.back().maStart = SwNodeIndex(rNode);
+}
+
+void WW8TabDesc::CreateSwTable()
+{
+ ::SetProgressState(pIo->nProgress, pIo->mpDocShell); // Update
+
+ // if there is already some content on the Node append new node to ensure
+ // that this content remains ABOVE the table
+ SwPosition* pPoint = pIo->pPaM->GetPoint();
+ bool bInsNode = pPoint->nContent.GetIndex() ? true : false;
+ bool bSetMinHeight = false;
+
+ /*
+ #i8062#
+ Set fly anchor to its anchor pos, so that if a table starts immediately
+ at this position a new node will be inserted before inserting the table.
+ */
+ if (!bInsNode && pIo->pFmtOfJustInsertedApo)
+ {
+ const SwPosition* pAPos =
+ pIo->pFmtOfJustInsertedApo->GetAnchor().GetCntntAnchor();
+ if (pAPos && &pAPos->nNode.GetNode() == &pPoint->nNode.GetNode())
+ {
+ bInsNode = true;
+ bSetMinHeight = true;
+
+ SwFmtSurround aSur(pIo->pFmtOfJustInsertedApo->GetSurround());
+ aSur.SetAnchorOnly(true);
+ pIo->pFmtOfJustInsertedApo->SetFmtAttr(aSur);
+ }
+ }
+
+ if (bSetMinHeight == true)
+ {
+ // minimize Fontsize to minimize height growth of the header/footer
+ // set font size to 1 point to minimize y-growth of Hd/Ft
+ SvxFontHeightItem aSz(20, 100, RES_CHRATR_FONTSIZE);
+ pIo->NewAttr( aSz );
+ pIo->pCtrlStck->SetAttr(*pPoint, RES_CHRATR_FONTSIZE);
+ }
+
+ if (bInsNode)
+ pIo->AppendTxtNode(*pPoint);
+
+ pTmpPos = new SwPosition( *pIo->pPaM->GetPoint() );
+
+ // Die Tabelle ist beim Einfuegen noch recht klein: Zahl der Spalten ist
+ // die kleinste Spaltenanzahl des Originals, da Spalten einfuegen
+ // schneller geht als Loeschen Zahl der Zeilen ist die Zahl der Baender,
+ // da sich die (identischen) Zeilen eines Bandes prima duplizieren lassen
+ pTable = pIo->rDoc.InsertTable(
+ SwInsertTableOptions( tabopts::HEADLINE_NO_BORDER, 0 ),
+ *pTmpPos, nBands, nDefaultSwCols, eOri, 0, 0, sal_False, sal_True );
+
+ OSL_ENSURE(pTable && pTable->GetFrmFmt(), "insert table failed");
+ if (!pTable || !pTable->GetFrmFmt())
+ return;
+
+ SwTableNode* pTableNode = pTable->GetTableNode();
+ OSL_ENSURE(pTableNode, "no table node!");
+ if (pTableNode)
+ {
+ pIo->maSectionManager.PrependedInlineNode(*pIo->pPaM->GetPoint(),
+ *pTableNode);
+ }
+
+ // Abfrage, ob im Node, in dem die Tabelle eingefuegt werden soll, bereits
+ // ein Pagedesc steht. Dann wuerde der PageDesc in die naechste Zeile
+ // hinter der Tabelle rutschen, wo er nichts zu suchen hat. -> loeschen
+ // und spaeter an das Tabellenformat setzen
+ if (SwTxtNode *const pNd = pTmpPos->nNode.GetNode().GetTxtNode())
+ {
+ if (const SfxItemSet* pSet = pNd->GetpSwAttrSet())
+ {
+ SfxPoolItem *pSetAttr = 0;
+ const SfxPoolItem* pItem;
+ if (SFX_ITEM_SET == pSet->GetItemState(RES_BREAK, false, &pItem))
+ {
+ pSetAttr = new SvxFmtBreakItem( *(SvxFmtBreakItem*)pItem );
+ pNd->ResetAttr( RES_BREAK );
+ }
+
+ // evtl den PageDesc/Break jetzt an der Tabelle setzen
+ if (pSetAttr)
+ {
+ aItemSet.Put(*pSetAttr);
+ delete pSetAttr;
+ }
+ }
+ }
+
+ // Gesamtbreite der Tabelle
+ if( nMaxRight - nMinLeft > MINLAY * nDefaultSwCols )
+ {
+ pTable->GetFrmFmt()->SetFmtAttr(SwFmtFrmSize(ATT_FIX_SIZE, nSwWidth));
+ aItemSet.Put(SwFmtFrmSize(ATT_FIX_SIZE, nSwWidth));
+ }
+
+ SvxFrameDirectionItem aDirection(
+ bIsBiDi ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR );
+ pTable->GetFrmFmt()->SetFmtAttr(aDirection);
+
+ if (text::HoriOrientation::LEFT_AND_WIDTH == eOri)
+ {
+ if (!pIo->nInTable && pIo->InLocalApo() && pIo->pSFlyPara->pFlyFmt &&
+ GetMinLeft())
+ {
+ //If we are inside a frame and we have a border, the frames
+ //placement does not consider the tables border, which word
+ //displays outside the frame, so adjust here.
+ SwFmtHoriOrient aHori(pIo->pSFlyPara->pFlyFmt->GetHoriOrient());
+ sal_Int16 eHori = aHori.GetHoriOrient();
+ if ((eHori == text::HoriOrientation::NONE) || (eHori == text::HoriOrientation::LEFT) ||
+ (eHori == text::HoriOrientation::LEFT_AND_WIDTH))
+ {
+ //With multiple table, use last table settings. Perhaps
+ //the maximum is what word does ?
+ aHori.SetPos(pIo->pSFlyPara->nXPos + GetMinLeft());
+ aHori.SetHoriOrient(text::HoriOrientation::NONE);
+ pIo->pSFlyPara->pFlyFmt->SetFmtAttr(aHori);
+ }
+ }
+ else
+ {
+ //If bApo is set, then this table is being placed in a floating
+ //frame, and the frame matches the left and right *lines* of the
+ //table, so the space to the left of the table isn't to be used
+ //inside the frame, in word the dialog involved greys out the
+ //ability to set the margin.
+ SvxLRSpaceItem aL( RES_LR_SPACE );
+ // set right to original DxaLeft (i28656)
+
+ long nLeft = 0;
+ if (!bIsBiDi)
+ nLeft = GetMinLeft();
+ else
+ {
+ if (nPreferredWidth)
+ {
+ nLeft = pIo->maSectionManager.GetTextAreaWidth();
+ nLeft = nLeft - nPreferredWidth - nOrgDxaLeft;
+ }
+ else
+ nLeft = -GetMinLeft();
+ }
+
+ aL.SetLeft(nLeft);
+
+ aItemSet.Put(aL);
+ }
+ }
+
+ mpOldRedlineStack = pIo->mpRedlineStack;
+ pIo->mpRedlineStack = new sw::util::RedlineStack(pIo->rDoc);
+}
+
+void WW8TabDesc::UseSwTable()
+{
+ // globale Varis initialisieren
+ pTabLines = &pTable->GetTabLines();
+ nAktRow = nAktCol = nAktBandRow = 0;
+
+ pTblNd = (SwTableNode*)(*pTabLines)[0]->GetTabBoxes()[0]->
+ GetSttNd()->FindTableNode();
+ OSL_ENSURE( pTblNd, "wo ist mein TabellenNode" );
+
+ // #i69519# - Restrict rows to repeat to a decent value
+ if ( nRowsToRepeat == static_cast<sal_uInt16>(nRows) )
+ nRowsToRepeat = 1;
+
+ pTblNd->GetTable().SetRowsToRepeat( nRowsToRepeat );
+ // ggfs. Zusatz-Zellen einfuegen u.dgl.
+ AdjustNewBand();
+
+ WW8DupProperties aDup(pIo->rDoc,pIo->pCtrlStck);
+ pIo->pCtrlStck->SetAttr(*pIo->pPaM->GetPoint(), 0, false);
+
+ // jetzt den PaM korrekt setzen und ggfs. erste Mergegruppe vorbereiten...
+ SetPamInCell(nAktCol, true);
+ aDup.Insert(*pIo->pPaM->GetPoint());
+
+ pIo->bWasTabRowEnd = false;
+ pIo->bWasTabCellEnd = false;
+}
+
+void WW8TabDesc::MergeCells()
+{
+ short nRow;
+
+ for (pActBand=pFirstBand, nRow=0; pActBand; pActBand=pActBand->pNextBand)
+ {
+ //
+ // ggfs. aktuelle Box in entsprechende Merge-Gruppe eintragen
+ //
+ if( pActBand->pTCs )
+ {
+ for( short j = 0; j < pActBand->nRows; j++, nRow++ )
+ for( short i = 0; i < pActBand->nWwCols; i++ )
+ {
+ WW8SelBoxInfoPtr pActMGroup = 0;
+ //
+ // ggfs. eine neue Merge-Gruppe beginnen
+ //
+ OSL_ENSURE(nRow < pTabLines->Count(),
+ "Too few lines, table ended early");
+ if (nRow >= pTabLines->Count())
+ return;
+ pTabLine = (*pTabLines)[ nRow ];
+ pTabBoxes = &pTabLine->GetTabBoxes();
+
+ sal_uInt16 nCol = pActBand->nTransCell[ i ];
+ if (!pActBand->bExist[i])
+ continue;
+ OSL_ENSURE(nCol < pTabBoxes->Count(),
+ "Too few columns, table ended early");
+ if (nCol >= pTabBoxes->Count())
+ return;
+ pTabBox = (*pTabBoxes)[nCol];
+ WW8_TCell& rCell = pActBand->pTCs[ i ];
+ // ist dies die obere, linke-Zelle einer Merge-Gruppe ?
+
+ bool bMerge = false;
+ if ( rCell.bVertRestart && !rCell.bMerged )
+ bMerge = true;
+ else if (rCell.bFirstMerged && pActBand->bExist[i])
+ {
+ // Some tests to avoid merging cells which previously were
+ // declared invalid because of sharing the exact same dimensions
+ // as their previous cell
+
+ //If theres anything underneath/above we're ok.
+ if (rCell.bVertMerge || rCell.bVertRestart)
+ bMerge = true;
+ else
+ {
+ //If its a hori merge only, and the only things in
+ //it are invalid cells then its already taken care
+ //of, so don't merge.
+ for (sal_uInt16 i2 = i+1; i2 < pActBand->nWwCols; i2++ )
+ if (pActBand->pTCs[ i2 ].bMerged &&
+ !pActBand->pTCs[ i2 ].bFirstMerged )
+ {
+ if (pActBand->bExist[i2])
+ {
+ bMerge = true;
+ break;
+ }
+ }
+ else
+ break;
+ }
+ }
+
+
+ if (bMerge)
+ {
+ short nX1 = pActBand->nCenter[ i ];
+ short nWidth = pActBand->nWidth[ i ];
+
+ // 0. falls noetig das Array fuer die Merge-Gruppen
+ // anlegen
+ if( !pMergeGroups )
+ pMergeGroups = new WW8MergeGroups;
+
+ // 2. aktuelle Merge-Gruppe anlegen
+ pActMGroup = new WW8SelBoxInfo( nX1, nWidth );
+
+ // determine size of new merge group
+ // before inserted the new merge group.
+ // Needed to correctly locked previously created merge groups.
+ // Gesamtbreite ermitteln und zuweisen
+ short nSizCell = pActBand->nWidth[ i ];
+ for (sal_uInt16 i2 = i+1; i2 < pActBand->nWwCols; i2++ )
+ if (pActBand->pTCs[ i2 ].bMerged &&
+ !pActBand->pTCs[ i2 ].bFirstMerged )
+ {
+ nSizCell = nSizCell + pActBand->nWidth[ i2 ];
+ }
+ else
+ break;
+ pActMGroup->nGroupWidth = nSizCell;
+ // <--
+
+ // locked previously created merge groups,
+ // after determining the size for the new merge group.
+ // 1. ggfs. alte Mergegruppe(n) schliessen, die
+ // den von unserer neuen Gruppe betroffenen
+ // X-Bereich ueberdecken
+ short nMGrIdx;
+ while ( FindMergeGroup( nX1, pActMGroup->nGroupWidth,
+ false, nMGrIdx ) )
+ {
+ (*pMergeGroups)[ nMGrIdx ]->bGroupLocked = true;
+ }
+ // <--
+
+ // 3. und in Gruppen-Array eintragen
+ pMergeGroups->Insert(pActMGroup, pMergeGroups->Count());
+ }
+
+ // ggfs. akt. Box zu einer Merge-Gruppe hinzufuegen (dies
+ // kann eine soeben angelegte, oder eine andere Gruppe
+ // sein)
+ UpdateTableMergeGroup( rCell, pActMGroup, pTabBox, i );
+ }
+ }
+ }
+}
+
+//There is a limbo area in word at the end of the row marker
+//where properties can live in word, there is no location in
+//writer equivalent, so try and park the cursor in the best
+//match, see #i23022#/#i18644#
+void WW8TabDesc::ParkPaM()
+{
+ SwTableBox *pTabBox2 = 0;
+ short nRow = nAktRow + 1;
+ if (nRow < pTabLines->Count())
+ {
+ if (SwTableLine *pLine = (*pTabLines)[nRow])
+ {
+ SwTableBoxes &rBoxes = pLine->GetTabBoxes();
+ pTabBox2 = rBoxes.Count() ? rBoxes[0] : 0;
+ }
+ }
+
+ if (!pTabBox2 || !pTabBox2->GetSttNd())
+ {
+ MoveOutsideTable();
+ return;
+ }
+
+ if (pIo->pPaM->GetPoint()->nNode != pTabBox2->GetSttIdx() + 1)
+ {
+ pIo->pPaM->GetPoint()->nNode = pTabBox2->GetSttIdx() + 1;
+ pIo->pPaM->GetPoint()->nContent.Assign(pIo->pPaM->GetCntntNode(), 0);
+ pIo->rDoc.SetTxtFmtColl(*pIo->pPaM, (SwTxtFmtColl*)pIo->pDfltTxtFmtColl);
+ }
+}
+
+void WW8TabDesc::MoveOutsideTable()
+{
+ OSL_ENSURE(pTmpPos && pIo, "I've forgotten where the table is anchored");
+ if (pTmpPos && pIo)
+ *pIo->pPaM->GetPoint() = *pTmpPos;
+}
+
+void WW8TabDesc::FinishSwTable()
+{
+ pIo->mpRedlineStack->closeall(*pIo->pPaM->GetPoint());
+ delete pIo->mpRedlineStack;
+ pIo->mpRedlineStack = mpOldRedlineStack;
+ mpOldRedlineStack = 0;
+
+ WW8DupProperties aDup(pIo->rDoc,pIo->pCtrlStck);
+ pIo->pCtrlStck->SetAttr( *pIo->pPaM->GetPoint(), 0, false);
+
+ MoveOutsideTable();
+ delete pTmpPos, pTmpPos = 0;
+
+ aDup.Insert(*pIo->pPaM->GetPoint());
+
+ pIo->bWasTabRowEnd = false;
+ pIo->bWasTabCellEnd = false;
+
+ pIo->maInsertedTables.InsertTable(*pTblNd, *pIo->pPaM);
+
+ MergeCells();
+
+ // falls noetig, zu mergende Zellen gruppenweise zusammenfassen
+ if( pMergeGroups )
+ {
+ // bearbeite alle Merge-Gruppen nacheinander
+ WW8SelBoxInfo* pActMGroup;
+ sal_uInt16 nActBoxCount;
+
+ for (sal_uInt16 iGr = 0; iGr < pMergeGroups->Count(); ++iGr)
+ {
+ pActMGroup = (*pMergeGroups)[ iGr ];
+ nActBoxCount = pActMGroup->Count();
+
+ if( ( 1 < nActBoxCount ) && pActMGroup && (*pActMGroup)[ 0 ] )
+ {
+ const sal_uInt16 nRowSpan = pActMGroup->Count();
+ for (sal_uInt16 n = 0; n < nRowSpan; ++n)
+ {
+ SwTableBox* pCurrentBox = (*pActMGroup)[n];
+ const long nRowSpanSet = n == 0 ?
+ nRowSpan :
+ ((-1) * (nRowSpan - n));
+ pCurrentBox->setRowSpan( nRowSpanSet );
+ }
+ }
+ }
+ pIo->pFmtOfJustInsertedApo = 0;
+ DELETEZ( pMergeGroups );
+ }
+}
+
+
+// durchsucht pMergeGroups, meldet Index der ersten, passenden Gruppe bzw. -1
+//
+// Parameter: nXcenter = Mittenposition der anfragenden Box
+// nWidth = Breite der anfragenden Box
+// bExact = Flag, ob Box in dieser Gruppe passen muss,
+// oder diese nur zu tangieren braucht
+//
+bool WW8TabDesc::FindMergeGroup(short nX1, short nWidth, bool bExact,
+ short& nMGrIdx)
+{
+ nMGrIdx = -1;
+ if( pMergeGroups )
+ {
+ // noch als gueltig angesehener Bereich in der Naehe der Grenzen
+ const short nToleranz = 4;
+ // die aktuell untersuchte Gruppe
+ WW8SelBoxInfoPtr pActGroup;
+ // Boxgrenzen
+ short nX2 = nX1 + nWidth;
+ // ungefaehre Gruppengrenzen
+ short nGrX1;
+ short nGrX2;
+
+ // improvement: search backwards
+ for ( short iGr = pMergeGroups->Count() - 1; iGr >= 0; --iGr )
+ {
+ // die aktuell untersuchte Gruppe
+ pActGroup = (*pMergeGroups)[ iGr ];
+ if (!pActGroup->bGroupLocked)
+ {
+ // ungefaehre Gruppengrenzen mit Toleranz nach *aussen* hin
+ nGrX1 = pActGroup->nGroupXStart - nToleranz;
+ nGrX2 = pActGroup->nGroupXStart
+ +pActGroup->nGroupWidth + nToleranz;
+ //
+ // Falls Box reinpasst, melde auf jeden Fall den Erfolg
+ //
+ if( ( nX1 > nGrX1 ) && ( nX2 < nGrX2 ) )
+ {
+ nMGrIdx = iGr; break;
+ }
+ //
+ // hat die Box Bereiche mit der Gruppe gemeinsam?
+ //
+ if( !bExact )
+ {
+ // melde Erfolg, wenn nX1 *oder* nX2 innerhalb der Gruppe liegen
+ if( ( ( nX1 > nGrX1 )
+ && ( nX1 < nGrX2 - 2*nToleranz ) )
+ || ( ( nX2 > nGrX1 + 2*nToleranz )
+ && ( nX2 < nGrX2 ) )
+ // oder nX1 und nX2 die Gruppe umfassen
+ || ( ( nX1 <=nGrX1 )
+ && ( nX2 >=nGrX2 ) ) )
+ {
+ nMGrIdx = iGr; break;
+ }
+ }
+ }
+ }
+ }
+ return ( -1 < nMGrIdx );
+}
+
+bool WW8TabDesc::IsValidCell(short nCol) const
+{
+ return pActBand->bExist[nCol] && (sal_uInt16)nAktRow < pTabLines->Count();
+}
+
+bool WW8TabDesc::InFirstParaInCell() const
+{
+ //e.g. #i19718#
+ if (!pTabBox || !pTabBox->GetSttNd())
+ {
+ OSL_FAIL("Problem with table");
+ return false;
+ }
+
+ if (!IsValidCell(GetAktCol()))
+ return false;
+
+ if (pIo->pPaM->GetPoint()->nNode == pTabBox->GetSttIdx() + 1)
+ return true;
+
+ return false;
+}
+
+void WW8TabDesc::StartMiserableHackForUnsupportedDirection(short nWwCol)
+{
+ OSL_ENSURE(pActBand, "Impossible");
+ if (pActBand && pActBand->maDirections[nWwCol] == 3)
+ {
+ pIo->pCtrlStck->NewAttr(*pIo->pPaM->GetPoint(),
+ SvxCharRotateItem(900, false, RES_CHRATR_ROTATE));
+ }
+}
+
+void WW8TabDesc::EndMiserableHackForUnsupportedDirection(short nWwCol)
+{
+ OSL_ENSURE(pActBand, "Impossible");
+ if (pActBand && pActBand->maDirections[nWwCol] == 3)
+ pIo->pCtrlStck->SetAttr(*pIo->pPaM->GetPoint(), RES_CHRATR_ROTATE);
+}
+
+bool WW8TabDesc::SetPamInCell(short nWwCol, bool bPam)
+{
+ OSL_ENSURE( pActBand, "pActBand ist 0" );
+
+ sal_uInt16 nCol = pActBand->nTransCell[nWwCol];
+
+ if ((sal_uInt16)nAktRow >= pTabLines->Count())
+ {
+ OSL_ENSURE(!this, "Actual row bigger than expected." );
+ if (bPam)
+ MoveOutsideTable();
+ return false;
+ }
+
+ pTabLine = (*pTabLines)[nAktRow];
+ pTabBoxes = &pTabLine->GetTabBoxes();
+
+ if (nCol >= pTabBoxes->Count())
+ {
+ if (bPam)
+ {
+ // The first paragraph in a cell with upper autospacing has upper
+ // spacing set to 0
+ if (
+ pIo->bParaAutoBefore && pIo->bFirstPara &&
+ !pIo->pWDop->fDontUseHTMLAutoSpacing
+ )
+ {
+ pIo->SetUpperSpacing(*pIo->pPaM, 0);
+ }
+
+ // The last paragraph in a cell with lower autospacing has lower
+ // spacing set to 0
+ if (pIo->bParaAutoAfter && !pIo->pWDop->fDontUseHTMLAutoSpacing)
+ pIo->SetLowerSpacing(*pIo->pPaM, 0);
+
+ ParkPaM();
+ }
+ return false;
+ }
+ pTabBox = (*pTabBoxes)[nCol];
+ if( !pTabBox->GetSttNd() )
+ {
+ OSL_ENSURE(pTabBox->GetSttNd(), "Probleme beim Aufbau der Tabelle");
+ if (bPam)
+ MoveOutsideTable();
+ return false;
+ }
+ if (bPam)
+ {
+ pAktWWCell = &pActBand->pTCs[ nWwCol ];
+
+ // The first paragraph in a cell with upper autospacing has upper spacing set to 0
+ if(pIo->bParaAutoBefore && pIo->bFirstPara && !pIo->pWDop->fDontUseHTMLAutoSpacing)
+ pIo->SetUpperSpacing(*pIo->pPaM, 0);
+
+ // The last paragraph in a cell with lower autospacing has lower spacing set to 0
+ if(pIo->bParaAutoAfter && !pIo->pWDop->fDontUseHTMLAutoSpacing)
+ pIo->SetLowerSpacing(*pIo->pPaM, 0);
+
+ //We need to set the pPaM on the first cell, invalid
+ //or not so that we can collect paragraph proproties over
+ //all the cells, but in that case on the valid cell we do not
+ //want to reset the fmt properties
+ if (pIo->pPaM->GetPoint()->nNode != pTabBox->GetSttIdx() + 1)
+ {
+ pIo->pPaM->GetPoint()->nNode = pTabBox->GetSttIdx() + 1;
+ pIo->pPaM->GetPoint()->nContent.Assign(pIo->pPaM->GetCntntNode(), 0);
+ // Zur Sicherheit schon jetzt setzen, da bei den Zellen, die
+ // zum Randausgleich eingefuegt werden, sonst der Style
+ // nicht gesetzt wird.
+ pIo->rDoc.SetTxtFmtColl(*pIo->pPaM, (SwTxtFmtColl*)pIo->pDfltTxtFmtColl);
+ // uebrigens: da diese Zellen unsichtbare Hilfskonstruktionen sind,
+ // und nur dazu dienen, zerfranste Aussehen der WW-Tabelle
+ // nachzuahmen, braucht NICHT SetTxtFmtCollAndListLevel()
+ // verwendet zu werden.
+ }
+
+ // Better to turn Snap to Grid off for all paragraphs in tables
+ if(SwTxtNode *pNd = pIo->pPaM->GetNode()->GetTxtNode())
+ {
+ const SfxPoolItem &rItm = pNd->SwCntntNode::GetAttr(RES_PARATR_SNAPTOGRID);
+ SvxParaGridItem &rSnapToGrid = (SvxParaGridItem&)(rItm);
+
+ if(rSnapToGrid.GetValue())
+ {
+ SvxParaGridItem aGridItem( rSnapToGrid );
+ aGridItem.SetValue(false);
+
+ SwPosition* pGridPos = pIo->pPaM->GetPoint();
+
+ xub_StrLen nEnd = pGridPos->nContent.GetIndex();
+ pGridPos->nContent.Assign(pIo->pPaM->GetCntntNode(), 0);
+ pIo->pCtrlStck->NewAttr(*pGridPos, aGridItem);
+ pGridPos->nContent.Assign(pIo->pPaM->GetCntntNode(), nEnd);
+ pIo->pCtrlStck->SetAttr(*pGridPos, RES_PARATR_SNAPTOGRID);
+ }
+ }
+
+ StartMiserableHackForUnsupportedDirection(nWwCol);
+ }
+ return true;
+}
+
+void WW8TabDesc::InsertCells( short nIns )
+{
+ pTabLine = (*pTabLines)[nAktRow];
+ pTabBoxes = &pTabLine->GetTabBoxes();
+ pTabBox = (*pTabBoxes)[0];
+
+ pIo->rDoc.GetNodes().InsBoxen( pTblNd, pTabLine, (SwTableBoxFmt*)pTabBox->GetFrmFmt(),
+ (SwTxtFmtColl*)pIo->pDfltTxtFmtColl, 0, pTabBoxes->Count(), nIns );
+ // mit dem Dritten Parameter wird das FrmFmt der Boxen angegeben.
+ // hier kann man auch noch optimieren, um FrmFmts zu sparen
+}
+
+void WW8TabDesc::SetTabBorders(SwTableBox* pBox, short nWwIdx)
+{
+ if( nWwIdx < 0 || nWwIdx >= pActBand->nWwCols )
+ return; // kuenstlich erzeugte Zellen -> Kein Rand
+
+
+ SvxBoxItem aFmtBox( RES_BOX );
+ if (pActBand->pTCs) // neither Cell Border nor Default Border defined ?
+ {
+ WW8_TCell* pT = &pActBand->pTCs[nWwIdx];
+ if (pIo->IsBorder(pT->rgbrc))
+ pIo->SetBorder(aFmtBox, pT->rgbrc);
+ }
+
+ if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwTOP))
+ {
+ aFmtBox.SetDistance(
+ pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwTOP],
+ BOX_LINE_TOP);
+ }
+ else
+ aFmtBox.SetDistance(pActBand->mnDefaultTop, BOX_LINE_TOP);
+ if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwBOTTOM))
+ {
+ aFmtBox.SetDistance(
+ pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwBOTTOM],
+ BOX_LINE_BOTTOM);
+ }
+ else
+ aFmtBox.SetDistance(pActBand->mnDefaultBottom,BOX_LINE_BOTTOM);
+
+ // nGapHalf bedeutet bei WW ein *horizontaler* Abstand zwischen
+ // Tabellenzelle und -Inhalt
+ short nLeftDist =
+ pActBand->mbHasSpacing ? pActBand->mnDefaultLeft : pActBand->nGapHalf;
+ short nRightDist =
+ pActBand->mbHasSpacing ? pActBand->mnDefaultRight : pActBand->nGapHalf;
+ if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwLEFT))
+ {
+ aFmtBox.SetDistance(
+ pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwLEFT],
+ BOX_LINE_LEFT);
+ }
+ else
+ aFmtBox.SetDistance(nLeftDist, BOX_LINE_LEFT);
+ if (pActBand->nOverrideSpacing[nWwIdx] & (1 << WW8TabBandDesc::wwRIGHT))
+ {
+ aFmtBox.SetDistance(
+ pActBand->nOverrideValues[nWwIdx][WW8TabBandDesc::wwRIGHT],
+ BOX_LINE_RIGHT);
+ }
+ else
+ aFmtBox.SetDistance(nRightDist,BOX_LINE_RIGHT);
+
+ pBox->GetFrmFmt()->SetFmtAttr(aFmtBox);
+}
+
+void WW8TabDesc::SetTabShades( SwTableBox* pBox, short nWwIdx )
+{
+ if( nWwIdx < 0 || nWwIdx >= pActBand->nWwCols )
+ return; // kuenstlich erzeugte Zellen -> Keine Farbe
+
+ bool bFound=false;
+ if (pActBand->pNewSHDs && pActBand->pNewSHDs[nWwIdx] != COL_AUTO)
+ {
+ Color aColor(pActBand->pNewSHDs[nWwIdx]);
+ if (aColor.GetColor() == 0x00333333)
+ pIo->maTracer.Log(sw::log::eAutoColorBg);
+ pBox->GetFrmFmt()->SetFmtAttr(SvxBrushItem(aColor, RES_BACKGROUND));
+ bFound = true;
+ }
+
+ //If there was no new shades, or no new shade setting
+ if (pActBand->pSHDs && !bFound)
+ {
+ WW8_SHD& rSHD = pActBand->pSHDs[nWwIdx];
+ if (!rSHD.GetValue()) // auto
+ return;
+
+ SwWW8Shade aSh( pIo->bVer67, rSHD );
+ pBox->GetFrmFmt()->SetFmtAttr(SvxBrushItem(aSh.aColor, RES_BACKGROUND));
+ }
+}
+
+SvxFrameDirection MakeDirection(sal_uInt16 nCode, sal_Bool bIsBiDi)
+{
+ SvxFrameDirection eDir = FRMDIR_ENVIRONMENT;
+ // 1: Asian layout with rotated CJK characters
+ // 5: Asian layout
+ // 3: Western layout rotated by 90 degrees
+ // 4: Western layout
+ switch (nCode)
+ {
+ default:
+ OSL_ENSURE(eDir == 4, "unknown direction code, maybe its a bitfield");
+ case 3:
+ eDir = bIsBiDi ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP; // #i38158# - Consider RTL tables
+ break;
+ case 5:
+ eDir = FRMDIR_VERT_TOP_RIGHT;
+ break;
+ case 1:
+ eDir = FRMDIR_VERT_TOP_RIGHT;
+ break;
+ case 4:
+ eDir = bIsBiDi ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP; // #i38158# - Consider RTL tables
+ break;
+ }
+ return eDir;
+}
+
+void WW8TabDesc::SetTabDirection(SwTableBox* pBox, short nWwIdx)
+{
+ if (nWwIdx < 0 || nWwIdx >= pActBand->nWwCols)
+ return;
+ SvxFrameDirectionItem aItem(MakeDirection(pActBand->maDirections[nWwIdx], bIsBiDi), RES_FRAMEDIR);
+ pBox->GetFrmFmt()->SetFmtAttr(aItem);
+}
+
+void WW8TabDesc::SetTabVertAlign( SwTableBox* pBox, short nWwIdx )
+{
+ if( nWwIdx < 0 || nWwIdx >= pActBand->nWwCols )
+ return;
+
+ sal_Int16 eVertOri=text::VertOrientation::TOP;
+
+ if( pActBand->pTCs )
+ {
+ WW8_TCell* pT = &pActBand->pTCs[nWwIdx];
+ switch (pT->nVertAlign)
+ {
+ case 0:
+ default:
+ eVertOri = text::VertOrientation::TOP;
+ break;
+ case 1:
+ eVertOri = text::VertOrientation::CENTER;
+ break;
+ case 2:
+ eVertOri = text::VertOrientation::BOTTOM;
+ break;
+ }
+ }
+
+ pBox->GetFrmFmt()->SetFmtAttr( SwFmtVertOrient(0,eVertOri) );
+}
+
+void WW8TabDesc::AdjustNewBand()
+{
+ if( pActBand->nSwCols > nDefaultSwCols ) // Zellen splitten
+ InsertCells( pActBand->nSwCols - nDefaultSwCols );
+
+ SetPamInCell( 0, false);
+ OSL_ENSURE( pTabBoxes && pTabBoxes->Count() == (sal_uInt16)pActBand->nSwCols,
+ "Falsche Spaltenzahl in Tabelle" );
+
+ if( bClaimLineFmt )
+ {
+ pTabLine->ClaimFrmFmt(); // noetig wg. Zeilenhoehe
+ SwFmtFrmSize aF( ATT_MIN_SIZE, 0, 0 ); // default
+
+ if (pActBand->nLineHeight == 0) // 0 = Auto
+ aF.SetHeightSizeType( ATT_VAR_SIZE );
+ else
+ {
+ if (pActBand->nLineHeight < 0) // Pos = min, Neg = exakt
+ {
+ aF.SetHeightSizeType(ATT_FIX_SIZE);
+ pActBand->nLineHeight = -pActBand->nLineHeight;
+ }
+ if (pActBand->nLineHeight < MINLAY) // nicht erlaubte Zeilenhoehe
+ pActBand->nLineHeight = MINLAY;
+
+ aF.SetHeight(pActBand->nLineHeight);// Min- / Exakt-Hoehe setzen
+ }
+ pTabLine->GetFrmFmt()->SetFmtAttr(aF);
+ }
+
+ //Word stores 1 for bCantSplit if the row cannot be split, we set true if
+ //we can split the row
+ // bCantSplit: Always true for rows containing merged cells (Word <= 2000 crashes otherwise)
+ // So in case bCantSplit is true, we check for bCantSplit90, which has been introduced for
+ // Word versions >= 2002.
+ bool bSetCantSplit = pActBand->bCantSplit;
+ if(bSetCantSplit)
+ bSetCantSplit = pActBand->bCantSplit90;
+
+ pTabLine->GetFrmFmt()->SetFmtAttr(SwFmtRowSplit(!bSetCantSplit));
+
+ short i; // SW-Index
+ short j; // WW-Index
+ short nW; // Breite
+ SwFmtFrmSize aFS( ATT_FIX_SIZE );
+ j = pActBand->bLEmptyCol ? -1 : 0;
+
+ for( i = 0; i < pActBand->nSwCols; i++ )
+ {
+ // setze Zellenbreite
+ if( j < 0 )
+ nW = pActBand->nCenter[0] - nMinLeft;
+ else
+ {
+ //Set j to first non invalid cell
+ while ((j < pActBand->nWwCols) && (!pActBand->bExist[j]))
+ j++;
+
+ if( j < pActBand->nWwCols )
+ nW = pActBand->nCenter[j+1] - pActBand->nCenter[j];
+ else
+ nW = nMaxRight - pActBand->nCenter[j];
+ pActBand->nWidth[ j ] = nW;
+ }
+
+ SwTableBox* pBox = (*pTabBoxes)[i];
+ // liesse sich durch intelligentes Umhaengen der FrmFmts noch weiter
+ // verringern
+ pBox->ClaimFrmFmt();
+
+ SetTabBorders(pBox, j);
+
+ // #i18128# word has only one line between adjoining vertical cells
+ // we have to mimick this in the filter by picking the larger of the
+ // sides and using that one on one side of the line (right)
+ SvxBoxItem aCurrentBox(sw::util::ItemGet<SvxBoxItem>(*(pBox->GetFrmFmt()), RES_BOX));
+ const ::editeng::SvxBorderLine *pLeftLine = aCurrentBox.GetLine(BOX_LINE_LEFT);
+ int nCurrentRightLineWidth = 0;
+ if(pLeftLine)
+ nCurrentRightLineWidth = pLeftLine->GetScaledWidth();
+
+ if (i != 0)
+ {
+ SwTableBox* pBox2 = (*pTabBoxes)[i-1];
+ SvxBoxItem aOldBox(sw::util::ItemGet<SvxBoxItem>(*(pBox2->GetFrmFmt()), RES_BOX));
+ const ::editeng::SvxBorderLine *pRightLine = aOldBox.GetLine(BOX_LINE_RIGHT);
+ int nOldBoxRightLineWidth = 0;
+ if(pRightLine)
+ nOldBoxRightLineWidth = pRightLine->GetScaledWidth();
+
+ if(nOldBoxRightLineWidth>nCurrentRightLineWidth)
+ aCurrentBox.SetLine(aOldBox.GetLine(BOX_LINE_RIGHT), BOX_LINE_LEFT);
+
+ aOldBox.SetLine(0, BOX_LINE_RIGHT);
+ pBox2->GetFrmFmt()->SetFmtAttr(aOldBox);
+ }
+
+ pBox->GetFrmFmt()->SetFmtAttr(aCurrentBox);
+
+ SetTabVertAlign(pBox, j);
+ SetTabDirection(pBox, j);
+ if( pActBand->pSHDs || pActBand->pNewSHDs)
+ SetTabShades(pBox, j);
+ j++;
+
+ aFS.SetWidth( nW );
+ pBox->GetFrmFmt()->SetFmtAttr( aFS );
+
+ // ueberspringe nicht existente Zellen
+ while( ( j < pActBand->nWwCols ) && !pActBand->bExist[j] )
+ {
+ pActBand->nWidth[j] = pActBand->nCenter[j+1] - pActBand->nCenter[j];
+ j++;
+ }
+ }
+}
+
+void WW8TabDesc::TableCellEnd()
+{
+ ::SetProgressState(pIo->nProgress, pIo->mpDocShell); // Update
+
+ EndMiserableHackForUnsupportedDirection(nAktCol);
+
+ // neue Zeile
+ if( pIo->bWasTabRowEnd )
+ {
+ // bWasTabRowEnd will be deactivated in
+ // SwWW8ImplReader::ProcessSpecial()
+
+ sal_uInt16 iCol = GetLogicalWWCol();
+ if (iCol < aNumRuleNames.size())
+ {
+ aNumRuleNames.erase(aNumRuleNames.begin() + iCol,
+ aNumRuleNames.end());
+ }
+
+ nAktCol = 0;
+ nAktRow++;
+ nAktBandRow++;
+ OSL_ENSURE( pActBand , "pActBand ist 0" );
+ if( pActBand )
+ {
+ if( nAktRow >= nRows ) // am Tabellenende gibt's nichts sinnvolles
+ return; // mehr zu tun
+
+ bool bNewBand = nAktBandRow >= pActBand->nRows;
+ if( bNewBand )
+ { // neues Band noetig ?
+ pActBand = pActBand->pNextBand; //
+ nAktBandRow = 0;
+ OSL_ENSURE( pActBand, "pActBand ist 0" );
+ AdjustNewBand();
+ }
+ else
+ {
+ SwTableBox* pBox = (*pTabBoxes)[0];
+ SwSelBoxes aBoxes;
+ pIo->rDoc.InsertRow( pTable->SelLineFromBox( pBox, aBoxes ) );
+ }
+ }
+ }
+ else
+ { // neue Spalte ( Zelle )
+ nAktCol++;
+ }
+ SetPamInCell(nAktCol, true);
+
+ // finish Annotated Level Numbering ?
+ if (pIo->bAnl && !pIo->bAktAND_fNumberAcross)
+ pIo->StopAllAnl(IsValidCell(nAktCol));
+}
+
+// ggfs. die Box in fuer diese Col offene Merge-Gruppe eintragen
+SwTableBox* WW8TabDesc::UpdateTableMergeGroup( WW8_TCell& rCell,
+ WW8SelBoxInfo* pActGroup,
+ SwTableBox* pActBox,
+ sal_uInt16 nCol )
+{
+ // Rueckgabewert defaulten
+ SwTableBox* pResult = 0;
+
+ // pruefen, ob die Box zu mergen ist
+ // If cell is the first one to be merged, a new merge group has to be provided.
+ // E.g., it could be that a cell is the first one to be merged, but no
+ // new merge group is provided, because the potential other cell to be merged
+ // doesn't exist - see method <WW8TabDesc::MergeCells>.
+ if ( pActBand->bExist[ nCol ] &&
+ ( ( rCell.bFirstMerged && pActGroup ) ||
+ rCell.bMerged ||
+ rCell.bVertMerge ||
+ rCell.bVertRestart ) )
+ // <--
+ {
+ // passende Merge-Gruppe ermitteln
+ WW8SelBoxInfo* pTheMergeGroup = 0;
+ if( pActGroup )
+ // Gruppe uebernehmen
+ pTheMergeGroup = pActGroup;
+ else
+ {
+ // Gruppe finden
+ short nMGrIdx;
+ if( FindMergeGroup( pActBand->nCenter[ nCol ],
+ pActBand->nWidth[ nCol ], true, nMGrIdx ) )
+ pTheMergeGroup = (*pMergeGroups)[ nMGrIdx ];
+ }
+ if( pTheMergeGroup )
+ {
+ // aktuelle Box der Merge-Gruppe hinzufuegen
+ pTheMergeGroup->Insert( pActBox, pTheMergeGroup->Count() );
+
+ // Target-Box zurueckmelden
+ pResult = (*pTheMergeGroup)[ 0 ];
+ }
+ }
+ return pResult;
+}
+
+
+sal_uInt16 WW8TabDesc::GetLogicalWWCol() const // returns number of col as INDICATED within WW6 UI status line -1
+{
+ sal_uInt16 nCol = 0;
+ if( pActBand && pActBand->pTCs)
+ {
+ for( sal_uInt16 iCol = 1; iCol <= nAktCol; ++iCol )
+ {
+ if( !pActBand->pTCs[ iCol-1 ].bMerged )
+ ++nCol;
+ }
+ }
+ return nCol;
+}
+
+// find name of numrule valid for current WW-COL
+const String& WW8TabDesc::GetNumRuleName() const
+{
+ sal_uInt16 nCol = GetLogicalWWCol();
+ if (nCol < aNumRuleNames.size())
+ return aNumRuleNames[nCol];
+ else
+ return aEmptyStr;
+}
+
+void WW8TabDesc::SetNumRuleName( const String& rName )
+{
+ sal_uInt16 nCol = GetLogicalWWCol();
+ for (sal_uInt16 nSize = static_cast< sal_uInt16 >(aNumRuleNames.size()); nSize <= nCol; ++nSize)
+ aNumRuleNames.push_back(aEmptyStr);
+ aNumRuleNames[nCol] = rName;
+}
+
+bool SwWW8ImplReader::StartTable(WW8_CP nStartCp)
+{
+ // Entering a table so make sure the the FirstPara flag gets set
+ bFirstPara = true;
+ // keine rekursiven Tabellen Nicht bei EinfuegenDatei in Tabelle oder
+ // Fussnote
+ if (bReadNoTbl)
+ return false;
+
+ if (pTableDesc)
+ maTableStack.push(pTableDesc);
+
+ // #i33818# - determine absolute position object attributes,
+ // if possible. It's needed for nested tables.
+ WW8FlyPara* pTableWFlyPara( 0L );
+ WW8SwFlyPara* pTableSFlyPara( 0L );
+ // #i45301# - anchor nested table inside Writer fly frame
+ // only at-character, if absolute position object attributes are available.
+ // Thus, default anchor type is as-character anchored.
+ RndStdIds eAnchor( FLY_AS_CHAR );
+ // <--
+ if ( nInTable )
+ {
+ WW8_TablePos* pNestedTabPos( 0L );
+ WW8_TablePos aNestedTabPos;
+ WW8PLCFxSave1 aSave;
+ pPlcxMan->GetPap()->Save( aSave );
+ WW8PLCFx_Cp_FKP* pPap = pPlcxMan->GetPapPLCF();
+ WW8_CP nMyStartCp = nStartCp;
+ if ( SearchRowEnd( pPap, nMyStartCp, nInTable ) &&
+ ParseTabPos( &aNestedTabPos, pPap ) )
+ {
+ pNestedTabPos = &aNestedTabPos;
+ }
+ pPlcxMan->GetPap()->Restore( aSave );
+ if ( pNestedTabPos )
+ {
+ ApoTestResults aApo = TestApo( nInTable + 1, false, pNestedTabPos );
+ pTableWFlyPara = ConstructApo( aApo, pNestedTabPos );
+ if ( pTableWFlyPara )
+ {
+ // <WW8SwFlyPara> constructor has changed - new 4th parameter
+ // containing WW8 page top margin.
+ pTableSFlyPara = new WW8SwFlyPara(*pPaM, *this, *pTableWFlyPara,
+ maSectionManager.GetWWPageTopMargin(),
+ maSectionManager.GetPageLeft(), maSectionManager.GetTextAreaWidth(),
+ nIniFlyDx, nIniFlyDy);
+
+ // #i45301# - anchor nested table Writer fly frame at-character
+ eAnchor = FLY_AT_CHAR;
+ }
+ }
+ }
+ // <--
+
+ pTableDesc = new WW8TabDesc( this, nStartCp );
+
+ if( pTableDesc->Ok() )
+ {
+ int nNewInTable = nInTable + 1;
+ if (InEqualApo(nNewInTable))
+ {
+ OSL_ENSURE(pSFlyPara->pFlyFmt,
+ "how could we be in a local apo and have no apo");
+ }
+
+ if ((eAnchor == FLY_AT_CHAR)
+ && !maTableStack.empty() && !InEqualApo(nNewInTable) )
+ {
+ pTableDesc->pParentPos = new SwPosition(*pPaM->GetPoint());
+ SfxItemSet aItemSet(rDoc.GetAttrPool(),
+ RES_FRMATR_BEGIN, RES_FRMATR_END-1);
+ // #i33818# - anchor the Writer fly frame for the nested table at-character.
+ // #i45301#
+ SwFmtAnchor aAnchor( eAnchor );
+ aAnchor.SetAnchor( pTableDesc->pParentPos );
+ aItemSet.Put( aAnchor );
+ pTableDesc->pFlyFmt = rDoc.MakeFlySection( eAnchor,
+ pTableDesc->pParentPos, &aItemSet);
+ OSL_ENSURE( pTableDesc->pFlyFmt->GetAnchor().GetAnchorId() == eAnchor,
+ "Not the anchor type requested!" );
+ // <--
+ MoveInsideFly(pTableDesc->pFlyFmt);
+ }
+ pTableDesc->CreateSwTable();
+ if (pTableDesc->pFlyFmt)
+ {
+ pTableDesc->SetSizePosition(pTableDesc->pFlyFmt);
+ // #i33818# - Use absolute position object attributes,
+ // if existing, and apply them to the created Writer fly frame.
+ if ( pTableWFlyPara && pTableSFlyPara )
+ {
+ WW8FlySet aFlySet( *this, pTableWFlyPara, pTableSFlyPara, false );
+ SwFmtAnchor aAnchor( FLY_AT_CHAR );
+ aAnchor.SetAnchor( pTableDesc->pParentPos );
+ aFlySet.Put( aAnchor );
+ pTableDesc->pFlyFmt->SetFmtAttr( aFlySet );
+ }
+ else
+ {
+ SwFmtHoriOrient aHori =
+ pTableDesc->pTable->GetFrmFmt()->GetHoriOrient();
+ pTableDesc->pFlyFmt->SetFmtAttr(aHori);
+ pTableDesc->pFlyFmt->SetFmtAttr( SwFmtSurround( SURROUND_NONE ) );
+ }
+ // <--
+ // #i33818# - The nested table doesn't have to leave
+ // the table cell. Thus, the Writer fly frame has to follow the text flow.
+ pTableDesc->pFlyFmt->SetFmtAttr( SwFmtFollowTextFlow( sal_True ) );
+ // <--
+ }
+ else
+ pTableDesc->SetSizePosition(0);
+ pTableDesc->UseSwTable();
+ }
+ else
+ PopTableDesc();
+
+ // #i33818#
+ delete pTableWFlyPara;
+ delete pTableSFlyPara;
+ // <--
+
+ bool bSuccess = (0 != pTableDesc);
+ if (bSuccess)
+ {
+ maTracer.EnterEnvironment(sw::log::eTable, rtl::OUString::valueOf(
+ static_cast<sal_Int32>(maTableStack.size())));
+ }
+ return bSuccess;
+}
+
+bool lcl_PamContainsFly(SwPaM & rPam)
+{
+ bool bResult = false;
+ SwNodeRange aRg( rPam.Start()->nNode, rPam.End()->nNode );
+ SwDoc * pDoc = rPam.GetDoc();
+
+ sal_uInt16 n = 0;
+ SwSpzFrmFmts * pSpzFmts = pDoc->GetSpzFrmFmts();
+ sal_uInt16 nCount = pSpzFmts->Count();
+ while (!bResult && n < nCount)
+ {
+ SwFrmFmt* pFly = (*pSpzFmts)[n];
+ const SwFmtAnchor* pAnchor = &pFly->GetAnchor();
+
+ switch (pAnchor->GetAnchorId())
+ {
+ case FLY_AT_PARA:
+ case FLY_AT_CHAR:
+ {
+ const SwPosition* pAPos = pAnchor->GetCntntAnchor();
+
+ if (pAPos != NULL &&
+ aRg.aStart <= pAPos->nNode &&
+ pAPos->nNode <= aRg.aEnd)
+ {
+ bResult = true;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ ++n;
+ }
+
+ return bResult;
+}
+
+void SwWW8ImplReader::TabCellEnd()
+{
+ if (nInTable && pTableDesc)
+ pTableDesc->TableCellEnd();
+
+ bFirstPara = true; // We have come to the end of a cell so FirstPara flag
+ bReadTable = false;
+ mpTableEndPaM.reset();
+}
+
+void SwWW8ImplReader::Read_TabCellEnd( sal_uInt16, const sal_uInt8* pData, short nLen)
+{
+ if( ( nLen > 0 ) && ( *pData == 1 ) )
+ bWasTabCellEnd = true;
+}
+
+void SwWW8ImplReader::Read_TabRowEnd( sal_uInt16, const sal_uInt8* pData, short nLen ) // Sprm25
+{
+ if( ( nLen > 0 ) && ( *pData == 1 ) )
+ bWasTabRowEnd = true;
+}
+
+void SwWW8ImplReader::PopTableDesc()
+{
+ if (pTableDesc && pTableDesc->pFlyFmt)
+ {
+ MoveOutsideFly(pTableDesc->pFlyFmt,*pTableDesc->pParentPos);
+ }
+
+ delete pTableDesc;
+ if (maTableStack.empty())
+ pTableDesc = 0;
+ else
+ {
+ pTableDesc = maTableStack.top();
+ maTableStack.pop();
+ }
+}
+
+void SwWW8ImplReader::StopTable()
+{
+ maTracer.LeaveEnvironment(sw::log::eTable);
+
+ OSL_ENSURE(pTableDesc, "Panic, stop table with no table!");
+ if (!pTableDesc)
+ return;
+
+ // We are leaving a table so make sure the next paragraph doesn't think
+ // it's the first paragraph
+ bFirstPara = false;
+
+ pTableDesc->FinishSwTable();
+ PopTableDesc();
+
+ if (!maTableStack.empty())
+ {
+ maTracer.EnterEnvironment(sw::log::eTable, rtl::OUString::valueOf(
+ static_cast<sal_Int32>(maTableStack.size())));
+ }
+
+ bReadTable = true;
+ // #i101116# - Keep PaM on table end only for nested tables
+ if ( nInTable > 1 )
+ {
+ mpTableEndPaM.reset(new SwPaM(*pPaM));
+ }
+}
+
+// GetTableLeft() wird fuer absatzgebundene Grafikobjekte in Tabellen
+// gebraucht.
+// WW nimmt bei eingerueckten Tabellen den Absatzrand, der ohne Tabelle
+// gueltig waere, als Basis; SW benutzt den linken Tabellenrand.
+short SwWW8ImplReader::GetTableLeft()
+{
+ return (pTableDesc) ? pTableDesc->GetMinLeft() : 0;
+}
+
+bool SwWW8ImplReader::IsInvalidOrToBeMergedTabCell() const
+{
+ if( !pTableDesc )
+ return false;
+
+ const WW8_TCell* pCell = pTableDesc->GetAktWWCell();
+
+ return !pTableDesc->IsValidCell( pTableDesc->GetAktCol() )
+ || ( pCell
+ && ( !pCell->bFirstMerged
+ && ( pCell->bMerged
+ || ( pCell->bVertMerge
+ && !pCell->bVertRestart
+ )
+ )
+ )
+ );
+}
+
+sal_uInt16 SwWW8ImplReader::StyleUsingLFO( sal_uInt16 nLFOIndex ) const
+{
+ sal_uInt16 nRes = USHRT_MAX;
+ if( pCollA )
+ {
+ for(sal_uInt16 nI = 0; nI < pStyles->GetCount(); nI++ )
+ if( pCollA[ nI ].bValid
+ && (nLFOIndex == pCollA[ nI ].nLFOIndex) )
+ nRes = nI;
+ }
+ return nRes;
+}
+
+const SwFmt* SwWW8ImplReader::GetStyleWithOrgWWName( String& rName ) const
+{
+ SwFmt* pRet = 0;
+ if( pCollA )
+ {
+ for(sal_uInt16 nI = 0; nI < pStyles->GetCount(); nI++ )
+ if( pCollA[ nI ].bValid
+ && (rName.Equals( pCollA[ nI ].GetOrgWWName())) )
+ {
+ pRet = pCollA[ nI ].pFmt;
+ break;
+ }
+ }
+ return pRet;
+}
+
+//-----------------------------------------
+// class WW8RStyle
+//-----------------------------------------
+
+const sal_uInt8* WW8RStyle::HasParaSprm( sal_uInt16 nId ) const
+{
+ if( !pParaSprms || !nSprmsLen )
+ return 0;
+
+ const sal_uInt8* pSprms = pParaSprms;
+ sal_uInt16 i, x;
+
+ for( i=0; i < nSprmsLen; )
+ {
+ sal_uInt16 nAktId = maSprmParser.GetSprmId(pSprms);
+ // Sprm found ?
+ if( nAktId == nId )
+ return pSprms + maSprmParser.DistanceToData(nId);
+
+ x = maSprmParser.GetSprmSize(nAktId, pSprms);
+ i = i + x;
+ pSprms += x;
+ }
+ return 0; // Sprm not found
+}
+
+void WW8RStyle::ImportSprms(sal_uInt8 *pSprms, short nLen, bool bPap)
+{
+ if (!nLen)
+ return;
+
+ if( bPap )
+ {
+ pParaSprms = pSprms; // fuer HasParaSprms()
+ nSprmsLen = nLen;
+ }
+
+ while ( nLen > 0 )
+ {
+ sal_uInt16 nL1 = pIo->ImportSprm(pSprms);
+ nLen = nLen - nL1;
+ pSprms += nL1;
+ }
+
+ pParaSprms = 0;
+ nSprmsLen = 0;
+}
+
+void WW8RStyle::ImportSprms(sal_Size nPosFc, short nLen, bool bPap)
+{
+ if (!nLen)
+ return;
+
+ sal_uInt8 *pSprms = new sal_uInt8[nLen];
+
+ pStStrm->Seek(nPosFc);
+ pStStrm->Read(pSprms, nLen);
+
+ ImportSprms(pSprms, nLen, bPap);
+
+ delete[] pSprms;
+}
+
+static inline short WW8SkipOdd(SvStream* pSt )
+{
+ if ( pSt->Tell() & 0x1 )
+ {
+ sal_uInt8 c;
+ pSt->Read( &c, 1 );
+ return 1;
+ }
+ return 0;
+}
+
+static inline short WW8SkipEven(SvStream* pSt )
+{
+ if (!(pSt->Tell() & 0x1))
+ {
+ sal_uInt8 c;
+ pSt->Read( &c, 1 );
+ return 1;
+ }
+ return 0;
+}
+
+short WW8RStyle::ImportUPX(short nLen, bool bPAP, bool bOdd)
+{
+ sal_Int16 cbUPX;
+
+ if( 0 < nLen ) // Empty ?
+ {
+ if (bOdd)
+ nLen = nLen - WW8SkipEven( pStStrm );
+ else
+ nLen = nLen - WW8SkipOdd( pStStrm );
+
+ *pStStrm >> cbUPX;
+
+ nLen-=2;
+
+ if ( cbUPX > nLen )
+ cbUPX = nLen; // !cbUPX auf nLen verkleinert!
+
+ if( (1 < cbUPX) || ( (0 < cbUPX) && !bPAP ) )
+ {
+ if( bPAP )
+ {
+ sal_uInt16 id;
+ *pStStrm >> id;
+
+ cbUPX-= 2;
+ nLen-= 2;
+ }
+
+ if( 0 < cbUPX )
+ {
+ sal_Size nPos = pStStrm->Tell(); // falls etwas falsch interpretiert
+ // wird, gehts danach wieder richtig
+ ImportSprms( nPos, cbUPX, bPAP );
+
+ if ( pStStrm->Tell() != nPos + cbUPX )
+ pStStrm->Seek( nPos+cbUPX );
+
+ nLen = nLen - cbUPX;
+ }
+ }
+ }
+ return nLen;
+}
+
+void WW8RStyle::ImportGrupx(short nLen, bool bPara, bool bOdd)
+{
+ if( nLen <= 0 )
+ return;
+ if (bOdd)
+ nLen = nLen - WW8SkipEven( pStStrm );
+ else
+ nLen = nLen - WW8SkipOdd( pStStrm );
+
+ if( bPara ) // Grupx.Papx
+ nLen = ImportUPX(nLen, true, bOdd);
+ ImportUPX(nLen, false, bOdd); // Grupx.Chpx
+}
+
+WW8RStyle::WW8RStyle(WW8Fib& _rFib, SwWW8ImplReader* pI)
+ : WW8Style(*pI->pTableStream, _rFib), maSprmParser(_rFib.GetFIBVersion()),
+ pIo(pI), pStStrm(pI->pTableStream), pStyRule(0), nWwNumLevel(0)
+{
+ pIo->nColls = cstd;
+ pIo->pCollA = cstd ? new SwWW8StyInf[ cstd ] : NULL; // Style-UEbersetzung WW->SW
+}
+
+void WW8RStyle::Set1StyleDefaults()
+{
+ // see #i25247#, #i25561#, #i48064#, #i92341# for default font
+ if (!bCJKFontChanged) // Style no CJK Font? set the default
+ pIo->SetNewFontAttr(ftcFE, true, RES_CHRATR_CJK_FONT);
+
+ if (!bCTLFontChanged) // Style no CTL Font? set the default
+ pIo->SetNewFontAttr(ftcBi, true, RES_CHRATR_CTL_FONT);
+
+ // western 2nd to make western charset conversion the default
+ if (!bFontChanged) // Style has no Font? set the default,
+ {
+ pIo->SetNewFontAttr(ftcAsci, true, RES_CHRATR_FONT);
+ }
+
+ if( !pIo->bNoAttrImport )
+ {
+ // Style has no text color set, winword default is auto
+ if ( !bTxtColChanged )
+ pIo->pAktColl->SetFmtAttr(SvxColorItem(Color(COL_AUTO), RES_CHRATR_COLOR));
+
+ // Style has no FontSize ? WinWord Default is 10pt for western and asian
+ if( !bFSizeChanged )
+ {
+ SvxFontHeightItem aAttr(200, 100, RES_CHRATR_FONTSIZE);
+ pIo->pAktColl->SetFmtAttr(aAttr);
+ aAttr.SetWhich(RES_CHRATR_CJK_FONTSIZE);
+ pIo->pAktColl->SetFmtAttr(aAttr);
+ }
+
+ // Style has no FontSize ? WinWord Default is 10pt for western and asian
+ if( !bFCTLSizeChanged )
+ {
+ SvxFontHeightItem aAttr(200, 100, RES_CHRATR_FONTSIZE);
+ aAttr.SetWhich(RES_CHRATR_CTL_FONTSIZE);
+ pIo->pAktColl->SetFmtAttr(aAttr);
+ }
+
+ if( pIo->pWDop->fWidowControl && !bWidowsChanged ) // Widows ?
+ {
+ pIo->pAktColl->SetFmtAttr( SvxWidowsItem( 2, RES_PARATR_WIDOWS ) );
+ pIo->pAktColl->SetFmtAttr( SvxOrphansItem( 2, RES_PARATR_ORPHANS ) );
+ }
+ }
+}
+
+bool WW8RStyle::PrepareStyle(SwWW8StyInf &rSI, ww::sti eSti, sal_uInt16 nThisStyle, sal_uInt16 nNextStyle)
+{
+ SwFmt* pColl;
+ bool bStyExist;
+ if (rSI.bColl)
+ {
+ // Para-Style
+ sw::util::ParaStyleMapper::StyleResult aResult =
+ pIo->maParaStyleMapper.GetStyle(rSI.GetOrgWWName(), eSti);
+ pColl = aResult.first;
+ bStyExist = aResult.second;
+ }
+ else
+ {
+ // Char-Style
+ sw::util::CharStyleMapper::StyleResult aResult =
+ pIo->maCharStyleMapper.GetStyle(rSI.GetOrgWWName(), eSti);
+ pColl = aResult.first;
+ bStyExist = aResult.second;
+ }
+
+ bool bImport = !bStyExist || pIo->mbNewDoc; // Inhalte Importieren ?
+ bool bOldNoImp = pIo->bNoAttrImport;
+ rSI.bImportSkipped = !bImport;
+
+ if( !bImport )
+ pIo->bNoAttrImport = true;
+ else
+ {
+ if (bStyExist)
+ {
+ pColl->ResetAllFmtAttr(); // #i73790# - method renamed
+ }
+ pColl->SetAuto(false); // nach Empfehlung JP
+ } // macht die UI aber anders
+ pIo->pAktColl = pColl;
+ rSI.pFmt = pColl; // UEbersetzung WW->SW merken
+ rSI.bImportSkipped = !bImport;
+
+ // Set Based on style
+ sal_uInt16 j = rSI.nBase;
+ if (j != nThisStyle && j < cstd )
+ {
+ SwWW8StyInf* pj = &pIo->pCollA[j];
+ if (rSI.pFmt && pj->pFmt && rSI.bColl == pj->bColl)
+ {
+ rSI.pFmt->SetDerivedFrom( pj->pFmt ); // ok, Based on eintragen
+ rSI.eLTRFontSrcCharSet = pj->eLTRFontSrcCharSet;
+ rSI.eRTLFontSrcCharSet = pj->eRTLFontSrcCharSet;
+ rSI.eCJKFontSrcCharSet = pj->eCJKFontSrcCharSet;
+ rSI.n81Flags = pj->n81Flags;
+ rSI.n81BiDiFlags = pj->n81BiDiFlags;
+ rSI.nOutlineLevel = pj->nOutlineLevel;
+ rSI.bParaAutoBefore = pj->bParaAutoBefore;
+ rSI.bParaAutoAfter = pj->bParaAutoAfter;
+
+ if (pj->pWWFly)
+ rSI.pWWFly = new WW8FlyPara(pIo->bVer67, pj->pWWFly);
+ }
+ }
+ else if( pIo->mbNewDoc && bStyExist )
+ rSI.pFmt->SetDerivedFrom(0);
+
+ rSI.nFollow = nNextStyle; // Follow merken
+
+ pStyRule = 0; // falls noetig, neu anlegen
+ bTxtColChanged = bFontChanged = bCJKFontChanged = bCTLFontChanged =
+ bFSizeChanged = bFCTLSizeChanged = bWidowsChanged = false;
+ pIo->SetNAktColl( nThisStyle );
+ pIo->bStyNormal = nThisStyle == 0;
+ return bOldNoImp;
+}
+
+void WW8RStyle::PostStyle(SwWW8StyInf &rSI, bool bOldNoImp)
+{
+ // Alle moeglichen Attribut-Flags zuruecksetzen,
+ // da es in Styles keine Attr-Enden gibt
+
+ pIo->bHasBorder = pIo->bShdTxtCol = pIo->bCharShdTxtCol
+ = pIo->bSpec = pIo->bObj = pIo->bSymbol = false;
+ pIo->nCharFmt = -1;
+
+ // If Style basiert auf Nichts oder Basis ignoriert
+ if ((rSI.nBase >= cstd || pIo->pCollA[rSI.nBase].bImportSkipped) && rSI.bColl)
+ {
+ //! Char-Styles funktionieren aus
+ // unerfindlichen Gruenden nicht
+ // -> dann evtl. harte WW-Defaults
+ // reinsetzen
+ Set1StyleDefaults();
+ }
+
+ pStyRule = 0; // zur Sicherheit
+ pIo->bStyNormal = false;
+ pIo->SetNAktColl( 0 );
+ pIo->bNoAttrImport = bOldNoImp;
+ // rasch nochmal die Listen-Merk-Felder zuruecksetzen,
+ // fuer den Fall dass sie beim einlesen des Styles verwendet wurden
+ pIo->nLFOPosition = USHRT_MAX;
+ pIo->nListLevel = WW8ListManager::nMaxLevel;
+}
+
+void WW8RStyle::Import1Style( sal_uInt16 nNr )
+{
+ SwWW8StyInf &rSI = pIo->pCollA[nNr];
+
+ if( rSI.bImported || !rSI.bValid )
+ return;
+
+ rSI.bImported = true; // jetzt schon Flag setzen
+ // verhindert endlose Rekursion
+ //
+ // gueltig und nicht NIL und noch nicht Importiert
+
+ if( rSI.nBase < cstd && !pIo->pCollA[rSI.nBase].bImported )
+ Import1Style( rSI.nBase );
+
+ pStStrm->Seek( rSI.nFilePos );
+
+ short nSkip, cbStd;
+ String sName;
+
+ WW8_STD* pStd = Read1Style( nSkip, &sName, &cbStd );// lies Style
+
+ if (pStd)
+ rSI.SetOrgWWIdent( sName, pStd->sti );
+
+ // either no Name or unused Slot or unknown Style
+
+ if ( !pStd || (0 == sName.Len()) || ((1 != pStd->sgc) && (2 != pStd->sgc)) )
+ {
+ pStStrm->SeekRel( nSkip );
+ return;
+ }
+
+ bool bOldNoImp = PrepareStyle(rSI, static_cast<ww::sti>(pStd->sti), nNr, pStd->istdNext);
+
+ // falls etwas falsch interpretiert wird, gehts danach wieder richtig
+ long nPos = pStStrm->Tell();
+
+ //Variable parts of the STD start at even byte offsets, but "inside
+ //the STD", which I take to meaning even in relation to the starting
+ //position of the STD, which matches findings in #89439#, generally it
+ //doesn't matter as the STSHI starts off nearly always on an even
+ //offset
+
+ //Import of the Style Contents
+ ImportGrupx(nSkip, pStd->sgc == 1, rSI.nFilePos & 1);
+
+ PostStyle(rSI, bOldNoImp);
+
+ pStStrm->Seek( nPos+nSkip );
+ delete pStd;
+}
+
+void WW8RStyle::RecursiveReg(sal_uInt16 nNr)
+{
+ SwWW8StyInf &rSI = pIo->pCollA[nNr];
+ if( rSI.bImported || !rSI.bValid )
+ return;
+
+ rSI.bImported = true;
+
+ if( rSI.nBase < cstd && !pIo->pCollA[rSI.nBase].bImported )
+ RecursiveReg(rSI.nBase);
+
+ pIo->RegisterNumFmtOnStyle(nNr);
+
+}
+
+/*
+ After all styles are imported then we can recursively apply numbering
+ styles to them, and change their tab stop settings if they turned out
+ to have special first line indentation.
+*/
+void WW8RStyle::PostProcessStyles()
+{
+ sal_uInt16 i;
+ /*
+ Clear all imported flags so that we can recursively apply numbering
+ formats and use it to mark handled ones
+ */
+ for (i=0; i < cstd; ++i)
+ pIo->pCollA[i].bImported = false;
+
+ /*
+ Register the num formats and tabstop changes on the styles recursively.
+ */
+
+ /*
+ In the same loop apply the tabstop changes required because we need to
+ change their location if theres a special indentation for the first line,
+ By avoiding making use of each styles margins during reading of their
+ tabstops we don't get problems with doubly adjusting tabstops that
+ are inheritied.
+ */
+ for (i=0; i < cstd; ++i)
+ {
+ if (pIo->pCollA[i].bValid)
+ {
+ RecursiveReg(i);
+ }
+ }
+}
+
+void WW8RStyle::ScanStyles() // untersucht Style-Abhaengigkeiten
+{ // und ermittelt die Filepos fuer jeden Style
+ for (sal_uInt16 i = 0; i < cstd; ++i)
+ {
+ short nSkip;
+ SwWW8StyInf &rSI = pIo->pCollA[i];
+
+ rSI.nFilePos = pStStrm->Tell(); // merke FilePos
+ WW8_STD* pStd = Read1Style( nSkip, 0, 0 ); // read STD
+ rSI.bValid = (0 != pStd);
+ if (rSI.bValid)
+ {
+ rSI.nBase = pStd->istdBase; // merke Basis
+ rSI.bColl = ( pStd->sgc == 1 ); // Para-Style
+ }
+ else
+ rSI = SwWW8StyInf();
+
+ delete pStd;
+ pStStrm->SeekRel( nSkip ); // ueberlese Namen und Sprms
+ }
+}
+
+std::vector<sal_uInt8> ChpxToSprms(const Word2CHPX &rChpx)
+{
+ std::vector<sal_uInt8> aRet;
+
+ aRet.push_back(60);
+ aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fBold) );
+
+ aRet.push_back(61);
+ aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fItalic) );
+
+ aRet.push_back(62);
+ aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fStrike) );
+
+ aRet.push_back(63);
+ aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fOutline) );
+
+ aRet.push_back(65);
+ aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fSmallCaps) );
+
+ aRet.push_back(66);
+ aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fCaps) );
+
+ aRet.push_back(67);
+ aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fVanish) );
+
+ if (rChpx.fsFtc)
+ {
+ aRet.push_back(68);
+ SVBT16 a;
+ ShortToSVBT16(rChpx.ftc, a);
+ aRet.push_back(a[1]);
+ aRet.push_back(a[0]);
+ }
+
+ if (rChpx.fsKul)
+ {
+ aRet.push_back(69);
+ aRet.push_back(rChpx.kul);
+ }
+
+ if (rChpx.fsLid)
+ {
+ aRet.push_back(72);
+ SVBT16 a;
+ ShortToSVBT16(rChpx.lid, a);
+ aRet.push_back(a[1]);
+ aRet.push_back(a[0]);
+ }
+
+ if (rChpx.fsIco)
+ {
+ aRet.push_back(73);
+ aRet.push_back(rChpx.ico);
+ }
+
+ if (rChpx.fsHps)
+ {
+ aRet.push_back(74);
+
+ SVBT16 a;
+ ShortToSVBT16(rChpx.hps, a);
+ aRet.push_back(a[0]);
+ }
+
+ if (rChpx.fsPos)
+ {
+ aRet.push_back(76);
+ aRet.push_back(rChpx.hpsPos);
+ }
+
+ aRet.push_back(80);
+ aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fBoldBi) );
+
+ aRet.push_back(81);
+ aRet.push_back( static_cast< sal_uInt8 >(128 + rChpx.fItalicBi) );
+
+ if (rChpx.fsFtcBi)
+ {
+ aRet.push_back(82);
+ SVBT16 a;
+ ShortToSVBT16(rChpx.fsFtcBi, a);
+ aRet.push_back(a[1]);
+ aRet.push_back(a[0]);
+ }
+
+ if (rChpx.fsLidBi)
+ {
+ aRet.push_back(83);
+ SVBT16 a;
+ ShortToSVBT16(rChpx.lidBi, a);
+ aRet.push_back(a[1]);
+ aRet.push_back(a[0]);
+ }
+
+ if (rChpx.fsIcoBi)
+ {
+ aRet.push_back(84);
+ aRet.push_back(rChpx.icoBi);
+ }
+
+ if (rChpx.fsHpsBi)
+ {
+ aRet.push_back(85);
+ SVBT16 a;
+ ShortToSVBT16(rChpx.hpsBi, a);
+ aRet.push_back(a[1]);
+ aRet.push_back(a[0]);
+ }
+
+ return aRet;
+}
+
+Word2CHPX ReadWord2Chpx(SvStream &rSt, sal_Size nOffset, sal_uInt8 nSize)
+{
+ Word2CHPX aChpx;
+
+ if (!nSize)
+ return aChpx;
+
+ rSt.Seek(nOffset);
+
+ sal_uInt8 nCount=0;
+
+ while (1)
+ {
+ sal_uInt8 nFlags8;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.fBold = nFlags8 & 0x01;
+ aChpx.fItalic = (nFlags8 & 0x02) >> 1;
+ aChpx.fRMarkDel = (nFlags8 & 0x04) >> 2;
+ aChpx.fOutline = (nFlags8 & 0x08) >> 3;
+ aChpx.fFldVanish = (nFlags8 & 0x10) >> 4;
+ aChpx.fSmallCaps = (nFlags8 & 0x20) >> 5;
+ aChpx.fCaps = (nFlags8 & 0x40) >> 6;
+ aChpx.fVanish = (nFlags8 & 0x80) >> 7;
+
+ if (nCount >= nSize) break;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.fRMark = nFlags8 & 0x01;
+ aChpx.fSpec = (nFlags8 & 0x02) >> 1;
+ aChpx.fStrike = (nFlags8 & 0x04) >> 2;
+ aChpx.fObj = (nFlags8 & 0x08) >> 3;
+ aChpx.fBoldBi = (nFlags8 & 0x10) >> 4;
+ aChpx.fItalicBi = (nFlags8 & 0x20) >> 5;
+ aChpx.fBiDi = (nFlags8 & 0x40) >> 6;
+ aChpx.fDiacUSico = (nFlags8 & 0x80) >> 7;
+
+ if (nCount >= nSize) break;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.fsIco = nFlags8 & 0x01;
+ aChpx.fsFtc = (nFlags8 & 0x02) >> 1;
+ aChpx.fsHps = (nFlags8 & 0x04) >> 2;
+ aChpx.fsKul = (nFlags8 & 0x08) >> 3;
+ aChpx.fsPos = (nFlags8 & 0x10) >> 4;
+ aChpx.fsSpace = (nFlags8 & 0x20) >> 5;
+ aChpx.fsLid = (nFlags8 & 0x40) >> 6;
+ aChpx.fsIcoBi = (nFlags8 & 0x80) >> 7;
+
+ if (nCount >= nSize) break;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.fsFtcBi = nFlags8 & 0x01;
+ aChpx.fsHpsBi = (nFlags8 & 0x02) >> 1;
+ aChpx.fsLidBi = (nFlags8 & 0x04) >> 2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.ftc;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.hps;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.qpsSpace = nFlags8 & 0x3F;
+ aChpx.fSysVanish = (nFlags8 & 0x40) >> 6;
+ aChpx.fNumRun = (nFlags8 & 0x80) >> 7;
+
+ if (nCount >= nSize) break;
+ rSt >> nFlags8;
+ nCount++;
+
+ aChpx.ico = nFlags8 & 0x1F;
+ aChpx.kul = (nFlags8 & 0xE0) >> 5;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.hpsPos;
+ nCount++;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.icoBi;
+ nCount++;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.lid;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.ftcBi;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.hpsBi;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.lidBi;
+ nCount+=2;
+
+ if (nCount >= nSize) break;
+ rSt >> aChpx.fcPic;
+ nCount+=4;
+
+ break;
+ }
+
+ rSt.SeekRel(nSize-nCount);
+ return aChpx;
+}
+
+namespace
+{
+ struct pxoffset { sal_Size mnOffset; sal_uInt8 mnSize; };
+}
+
+void WW8RStyle::ImportOldFormatStyles()
+{
+ for (sal_uInt16 i=0; i < cstd; ++i)
+ {
+ pIo->pCollA[i].bColl = true;
+ //every chain must end eventually at the null style (style code 222)
+ pIo->pCollA[i].nBase = 222;
+ }
+
+ rtl_TextEncoding eStructChrSet = WW8Fib::GetFIBCharset(
+ pIo->pWwFib->chseTables);
+
+ sal_uInt16 cstcStd;
+ rSt >> cstcStd;
+
+ sal_uInt16 cbName;
+ rSt >> cbName;
+ sal_uInt16 nByteCount = 2;
+ sal_uInt16 stcp=0;
+ while (nByteCount < cbName)
+ {
+ sal_uInt8 nCount;
+ rSt >> nCount;
+ nByteCount++;
+
+ sal_uInt8 stc = static_cast< sal_uInt8 >((stcp - cstcStd) & 255);
+ SwWW8StyInf &rSI = pIo->pCollA[stc];
+ if (nCount != 0xFF) // undefined style
+ {
+ String sName;
+ if (nCount == 0) // inbuilt style
+ {
+ ww::sti eSti = ww::GetCanonicalStiFromStc(stc);
+ if (const sal_Char *pStr = GetEnglishNameFromSti(eSti))
+ sName = String(pStr, RTL_TEXTENCODING_ASCII_US);
+ else
+ sName = String(CREATE_CONST_ASC("Unknown"));
+ }
+ else // user style
+ {
+ ByteString aTmp;
+ nByteCount = static_cast< sal_uInt16 >(nByteCount + SafeReadString(aTmp, nCount, rSt));
+ sName = String(aTmp, eStructChrSet);
+ }
+ rSI.SetOrgWWIdent(sName, stc);
+ rSI.bImported = true;
+ }
+ else
+ {
+ ww::sti eSti = ww::GetCanonicalStiFromStc(stc);
+ if (const sal_Char *pStr = GetEnglishNameFromSti(eSti))
+ {
+ String sName = String(pStr, RTL_TEXTENCODING_ASCII_US);
+ rSI.SetOrgWWIdent(sName, stc);
+ }
+ }
+ stcp++;
+ }
+
+ sal_uInt16 nStyles=stcp;
+
+ std::vector<pxoffset> aCHPXOffsets(stcp);
+ sal_uInt16 cbChpx;
+ rSt >> cbChpx;
+ nByteCount = 2;
+ stcp=0;
+ std::vector< std::vector<sal_uInt8> > aConvertedChpx;
+ while (nByteCount < cbChpx)
+ {
+ sal_uInt8 cb;
+ rSt >> cb;
+ nByteCount++;
+
+ aCHPXOffsets[stcp].mnSize = 0;
+
+ if (cb != 0xFF)
+ {
+ sal_uInt8 nRemainder = cb;
+
+ aCHPXOffsets[stcp].mnOffset = rSt.Tell();
+ aCHPXOffsets[stcp].mnSize = nRemainder;
+
+ Word2CHPX aChpx = ReadWord2Chpx(rSt, aCHPXOffsets[stcp].mnOffset,
+ aCHPXOffsets[stcp].mnSize);
+ aConvertedChpx.push_back( ChpxToSprms(aChpx) );
+
+ nByteCount += nRemainder;
+ }
+ else
+ aConvertedChpx.push_back( std::vector<sal_uInt8>() );
+
+ stcp++;
+ if (stcp == nStyles)
+ {
+ rSt.SeekRel(cbChpx-nByteCount);
+ nByteCount += cbChpx-nByteCount;
+ }
+ }
+
+ std::vector<pxoffset> aPAPXOffsets(stcp);
+ sal_uInt16 cbPapx;
+ rSt >> cbPapx;
+ nByteCount = 2;
+ stcp=0;
+ while (nByteCount < cbPapx)
+ {
+ sal_uInt8 cb;
+ rSt >> cb;
+ nByteCount++;
+
+ aPAPXOffsets[stcp].mnSize = 0;
+
+ if (cb != 0xFF)
+ {
+ sal_uInt8 stc2;
+ rSt >> stc2;
+ rSt.SeekRel(6);
+ nByteCount+=7;
+ sal_uInt8 nRemainder = cb-7;
+
+ aPAPXOffsets[stcp].mnOffset = rSt.Tell();
+ aPAPXOffsets[stcp].mnSize = nRemainder;
+
+ rSt.SeekRel(nRemainder);
+ nByteCount += nRemainder;
+ }
+
+ stcp++;
+
+ if (stcp == nStyles)
+ {
+ rSt.SeekRel(cbPapx-nByteCount);
+ nByteCount += cbPapx-nByteCount;
+ }
+ }
+
+ sal_uInt16 iMac;
+ rSt >> iMac;
+
+ if (iMac > nStyles) iMac = nStyles;
+
+ for (stcp = 0; stcp < iMac; ++stcp)
+ {
+ sal_uInt8 stcNext, stcBase;
+ rSt >> stcNext;
+ rSt >> stcBase;
+
+ sal_uInt8 stc = static_cast< sal_uInt8 >((stcp - cstcStd) & 255);
+
+ /*
+ #i64557# style based on itself
+ every chain must end eventually at the null style (style code 222)
+ */
+ if (stc == stcBase)
+ stcBase = 222;
+
+ SwWW8StyInf &rSI = pIo->pCollA[stc];
+ rSI.nBase = stcBase;
+
+ ww::sti eSti = ww::GetCanonicalStiFromStc(stc);
+
+ if (eSti == ww::stiNil)
+ continue;
+
+ rSI.bValid = true;
+
+ if (ww::StandardStiIsCharStyle(eSti) && !aPAPXOffsets[stcp].mnSize)
+ pIo->pCollA[stc].bColl = false;
+
+ bool bOldNoImp = PrepareStyle(rSI, eSti, stc, stcNext);
+
+ ImportSprms(aPAPXOffsets[stcp].mnOffset, aPAPXOffsets[stcp].mnSize,
+ true);
+
+ if (aConvertedChpx[stcp].size() > 0)
+ ImportSprms(&(aConvertedChpx[stcp][0]),
+ static_cast< short >(aConvertedChpx[stcp].size()),
+ false);
+
+ PostStyle(rSI, bOldNoImp);
+ }
+}
+
+void WW8RStyle::ImportNewFormatStyles()
+{
+ ScanStyles(); // Scanne Based On
+
+ for (sal_uInt16 i = 0; i < cstd; ++i) // import Styles
+ if (pIo->pCollA[i].bValid)
+ Import1Style( i );
+}
+
+void WW8RStyle::ImportStyles()
+{
+ if (ww::eWW2 == pIo->pWwFib->GetFIBVersion())
+ ImportOldFormatStyles();
+ else
+ ImportNewFormatStyles();
+}
+
+void WW8RStyle::Import()
+{
+ pIo->pDfltTxtFmtColl = pIo->rDoc.GetDfltTxtFmtColl();
+ pIo->pStandardFmtColl =
+ pIo->rDoc.GetTxtCollFromPool(RES_POOLCOLL_STANDARD, false);
+
+ if( pIo->nIniFlags & WW8FL_NO_STYLES )
+ return;
+
+ ImportStyles();
+
+ for (sal_uInt16 i = 0; i < cstd; ++i)
+ {
+ // Follow chain
+ SwWW8StyInf* pi = &pIo->pCollA[i];
+ sal_uInt16 j = pi->nFollow;
+ if( j < cstd )
+ {
+ SwWW8StyInf* pj = &pIo->pCollA[j];
+ if ( j != i // sinnvoller Index ?
+ && pi->pFmt // Format ok ?
+ && pj->pFmt // Derived-Format ok ?
+ && pi->bColl // geht nur bei Absatz-Vorlagen (WW)
+ && pj->bColl ){ // beides gleicher Typ ?
+ ( (SwTxtFmtColl*)pi->pFmt )->SetNextTxtFmtColl(
+ *(SwTxtFmtColl*)pj->pFmt ); // ok, eintragen
+ }
+ }
+ }
+// Die Sonderbehandlung zur Setzen der
+// Default-Zeichenvorlage "Absatz-Standardschriftart" ( Style-ID 65 ) fehlt
+// Sie ist aber defaultmaessig leer ( WW6 dt und US ) und von der
+// WW-UI nicht zu veraendern, so dass das nicht stoert.
+// Der Mechanismus waere folgender:
+// if( bNew ) rDoc.SetDefault( pDefCharFmt->GetAttrSet() );
+//
+ // fuer z.B. Tabellen wird ein immer gueltiger Std-Style gebraucht
+
+ if( pIo->StyleExists(0) && pIo->pCollA[0].pFmt && pIo->pCollA[0].bColl && pIo->pCollA[0].bValid )
+ pIo->pDfltTxtFmtColl = (SwTxtFmtColl*)pIo->pCollA[0].pFmt;
+ else
+ pIo->pDfltTxtFmtColl = pIo->rDoc.GetDfltTxtFmtColl();
+
+
+ // set Hyphenation flag on BASIC para-style
+ if (pIo->mbNewDoc && pIo->pStandardFmtColl)
+ {
+ if (pIo->pWDop->fAutoHyphen
+ && SFX_ITEM_SET != pIo->pStandardFmtColl->GetItemState(
+ RES_PARATR_HYPHENZONE, false) )
+ {
+ SvxHyphenZoneItem aAttr(true, RES_PARATR_HYPHENZONE);
+ aAttr.GetMinLead() = 2;
+ aAttr.GetMinTrail() = 2;
+ aAttr.GetMaxHyphens() = 0;
+
+ pIo->pStandardFmtColl->SetFmtAttr( aAttr );
+ }
+
+ /*
+ Word defaults to ltr not from environment like writer. Regardless of
+ the page/sections rtl setting the standard style lack of rtl still
+ means ltr
+ */
+ if (SFX_ITEM_SET != pIo->pStandardFmtColl->GetItemState(RES_FRAMEDIR,
+ false))
+ {
+ pIo->pStandardFmtColl->SetFmtAttr(
+ SvxFrameDirectionItem(FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR));
+ }
+ }
+
+ // wir sind jetzt nicht mehr beim Style einlesen:
+ pIo->pAktColl = 0;
+}
+
+CharSet SwWW8StyInf::GetCharSet() const
+{
+ if ((pFmt) && (pFmt->GetFrmDir().GetValue() == FRMDIR_HORI_RIGHT_TOP))
+ return eRTLFontSrcCharSet;
+ return eLTRFontSrcCharSet;
+}
+
+CharSet SwWW8StyInf::GetCJKCharSet() const
+{
+ if ((pFmt) && (pFmt->GetFrmDir().GetValue() == FRMDIR_HORI_RIGHT_TOP))
+ return eRTLFontSrcCharSet;
+ return eCJKFontSrcCharSet;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par2.hxx b/sw/source/filter/ww8/ww8par2.hxx
new file mode 100644
index 000000000000..5e3e2a8cff10
--- /dev/null
+++ b/sw/source/filter/ww8/ww8par2.hxx
@@ -0,0 +1,288 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WW8PAR2_HXX
+#define _WW8PAR2_HXX
+
+#include <swtypes.hxx> // enum RndStdIds
+#include <fmtfsize.hxx>
+#include <fmtornt.hxx>
+#include <fmtsrnd.hxx>
+#include <editeng/lrspitem.hxx>
+
+#include "ww8scan.hxx" // class WW8Style
+#include "ww8par.hxx" // WW8_BRC5
+
+class WW8RStyle;
+
+class WW8DupProperties
+{
+public:
+ WW8DupProperties(SwDoc &rDoc, SwWW8FltControlStack *pStk);
+ void Insert(const SwPosition &rPos);
+private:
+ //No copying
+ WW8DupProperties(const WW8DupProperties&);
+ WW8DupProperties& operator=(const WW8DupProperties&);
+ SwWW8FltControlStack* pCtrlStck;
+ SfxItemSet aChrSet,aParSet;
+};
+
+struct WW8FlyPara
+{ // WinWord-Attribute
+ // Achtung: *Nicht* umsortieren, da Teile mit
+ // memcmp verglichen werden
+ bool bVer67;
+ sal_Int16 nSp26, nSp27; // rohe Position
+ sal_Int16 nSp45, nSp28; // Breite / Hoehe
+ sal_Int16 nLeMgn, nRiMgn, nUpMgn, nLoMgn; // Raender
+ sal_uInt8 nSp29; // rohe Bindung + Alignment
+ sal_uInt8 nSp37; // Wrap-Mode ( 1 / 2; 0 = no Apo ? )
+ WW8_BRC5 brc; // Umrandung Top, Left, Bottom, Right, Between
+ bool bBorderLines; // Umrandungslinien
+ bool bGrafApo; // true: Dieser Rahmen dient allein dazu, die
+ // enthaltene Grafik anders als zeichengebunden
+ // zu positionieren
+ bool mbVertSet; // true if vertical positioning has been set
+ sal_uInt8 nOrigSp29;
+
+ WW8FlyPara(bool bIsVer67, const WW8FlyPara* pSrc = 0);
+ bool operator==(const WW8FlyPara& rSrc) const;
+ void Read(const sal_uInt8* pSprm29, WW8PLCFx_Cp_FKP* pPap);
+ void ReadFull(const sal_uInt8* pSprm29, SwWW8ImplReader* pIo);
+ void Read(const sal_uInt8* pSprm29, WW8RStyle* pStyle);
+ void ApplyTabPos(const WW8_TablePos *pTabPos);
+ bool IsEmpty() const;
+};
+
+struct WW8SwFlyPara
+{
+ SwFlyFrmFmt* pFlyFmt;
+
+ // 1. Teil: daraus abgeleitete Sw-Attribute
+ sal_Int16 nXPos, nYPos; // Position
+ sal_Int16 nLeMgn, nRiMgn; // Raender
+ sal_Int16 nUpMgn, nLoMgn; // Raender
+ sal_Int16 nWidth, nHeight; // Groesse
+ sal_Int16 nNettoWidth;
+
+ SwFrmSize eHeightFix; // Hoehe Fix oder Min
+ RndStdIds eAnchor; // Bindung
+ short eHRel; // Seite oder Seitenrand
+ short eVRel; // Seite oder Seitenrand
+ sal_Int16 eVAlign; // Oben, unten, mittig
+ sal_Int16 eHAlign; // links, rechts, mittig
+ SwSurround eSurround; // Wrap-Mode
+
+ sal_uInt8 nXBind, nYBind; // relativ zu was gebunden
+
+ // 2.Teil: sich waehrend des Einlesens ergebende AEnderungen
+ long nNewNettoWidth;
+ SwPosition* pMainTextPos; // um nach Apo in Haupttext zurueckzukehren
+ sal_uInt16 nLineSpace; // LineSpace in tw fuer Graf-Apos
+ bool bAutoWidth;
+ bool bToggelPos;
+
+ // add parameter <nWWPgTop> - WW8's page top margin
+ WW8SwFlyPara( SwPaM& rPaM,
+ SwWW8ImplReader& rIo,
+ WW8FlyPara& rWW,
+ const sal_uInt32 nWWPgTop,
+ const sal_uInt32 nPgLeft,
+ const sal_uInt32 nPgWidth,
+ const sal_Int32 nIniFlyDx,
+ const sal_Int32 nIniFlyDy );
+
+ void BoxUpWidth( long nWidth );
+ SwWW8FltAnchorStack *pOldAnchorStck;
+};
+
+class SwWW8StyInf
+{
+ String sWWStyleName;
+ sal_uInt16 nWWStyleId;
+public:
+ rtl_TextEncoding eLTRFontSrcCharSet; // rtl_TextEncoding fuer den Font
+ rtl_TextEncoding eRTLFontSrcCharSet; // rtl_TextEncoding fuer den Font
+ rtl_TextEncoding eCJKFontSrcCharSet; // rtl_TextEncoding fuer den Font
+ SwFmt* pFmt;
+ WW8FlyPara* pWWFly;
+ SwNumRule* pOutlineNumrule;
+ long nFilePos;
+ sal_uInt16 nBase;
+ sal_uInt16 nFollow;
+ sal_uInt16 nLFOIndex;
+ sal_uInt8 nListLevel;
+ sal_uInt8 nOutlineLevel; // falls Gliederungs-Style
+ sal_uInt16 n81Flags; // Fuer Bold, Italic, ...
+ sal_uInt16 n81BiDiFlags; // Fuer Bold, Italic, ...
+ SvxLRSpaceItem maWordLR;
+ bool bValid; // leer oder Valid
+ bool bImported; // fuers rekursive Importieren
+ bool bColl; // true-> pFmt ist SwTxtFmtColl
+ bool bImportSkipped; // nur true bei !bNewDoc && vorh. Style
+ bool bHasStyNumRule; // true-> Benannter NumRule in Style
+ bool bHasBrokenWW6List; // true-> WW8+ style has a WW7- list
+ bool bListReleventIndentSet; //true if this style's indent has
+ //been explicitly set, it's set to the value
+ //of pFmt->GetItemState(RES_LR_SPACE, false)
+ //if it was possible to get the ItemState
+ //for L of the LR space independantly
+ bool bParaAutoBefore; // For Auto spacing before a paragraph
+ bool bParaAutoAfter; // For Auto Spacing after a paragraph
+
+ SwWW8StyInf() :
+ sWWStyleName( aEmptyStr ),
+ nWWStyleId( 0 ),
+ eLTRFontSrcCharSet(0),
+ eRTLFontSrcCharSet(0),
+ eCJKFontSrcCharSet(0),
+ pFmt( 0 ),
+ pWWFly( 0 ),
+ pOutlineNumrule( 0 ),
+ nFilePos( 0 ),
+ nBase( 0 ),
+ nFollow( 0 ),
+ nLFOIndex( USHRT_MAX ),
+ nListLevel(WW8ListManager::nMaxLevel),
+ nOutlineLevel( MAXLEVEL ),
+ n81Flags( 0 ),
+ n81BiDiFlags(0),
+ maWordLR( RES_LR_SPACE ),
+ bValid(false),
+ bImported(false),
+ bColl(false),
+ bImportSkipped(false),
+ bHasStyNumRule(false),
+ bHasBrokenWW6List(false),
+ bListReleventIndentSet(false),
+ bParaAutoBefore(false),
+ bParaAutoAfter(false)
+
+ {}
+
+ ~SwWW8StyInf()
+ {
+ delete pWWFly;
+ }
+
+ void SetOrgWWIdent( const String& rName, const sal_uInt16 nId )
+ {
+ sWWStyleName = rName;
+ nWWStyleId = nId;
+ }
+ sal_uInt16 GetWWStyleId() const { return nWWStyleId; }
+ const String& GetOrgWWName() const
+ {
+ return sWWStyleName;
+ }
+ bool IsOutline() const
+ {
+ return (pFmt && (MAXLEVEL > nOutlineLevel));
+ }
+ bool IsOutlineNumbered() const
+ {
+ return pOutlineNumrule && IsOutline();
+ }
+ const SwNumRule* GetOutlineNumrule() const
+ {
+ return pOutlineNumrule;
+ }
+ CharSet GetCharSet() const;
+ CharSet GetCJKCharSet() const;
+};
+
+class WW8RStyle: public WW8Style
+{
+friend class SwWW8ImplReader;
+ wwSprmParser maSprmParser;
+ SwWW8ImplReader* pIo; // Parser-Klasse
+ SvStream* pStStrm; // Input-File
+
+ SwNumRule* pStyRule; // Bullets und Aufzaehlungen in Styles
+
+ sal_uInt8* pParaSprms; // alle ParaSprms des UPX falls UPX.Papx
+ sal_uInt16 nSprmsLen; // Laenge davon
+
+ sal_uInt8 nWwNumLevel; // fuer Bullets und Aufzaehlungen in Styles
+
+ bool bTxtColChanged;
+ bool bFontChanged; // For Simulating Default-Font
+ bool bCJKFontChanged; // For Simulating Default-CJK Font
+ bool bCTLFontChanged; // For Simulating Default-CTL Font
+ bool bFSizeChanged; // For Simulating Default-FontSize
+ bool bFCTLSizeChanged; // For Simulating Default-CTL FontSize
+ bool bWidowsChanged; // For Simulating Default-Widows / Orphans
+
+ void ImportSprms(sal_Size nPosFc, short nLen, bool bPap);
+ void ImportSprms(sal_uInt8 *pSprms, short nLen, bool bPap);
+ void ImportGrupx(short nLen, bool bPara, bool bOdd);
+ short ImportUPX(short nLen, bool bPAP, bool bOdd);
+
+ void Set1StyleDefaults();
+ void Import1Style(sal_uInt16 nNr);
+ void RecursiveReg(sal_uInt16 nNr);
+
+ void ImportStyles();
+
+ void ImportNewFormatStyles();
+ void ScanStyles();
+ void ImportOldFormatStyles();
+
+ bool PrepareStyle(SwWW8StyInf &rSI, ww::sti eSti, sal_uInt16 nThisStyle, sal_uInt16 nNextStyle);
+ void PostStyle(SwWW8StyInf &rSI, bool bOldNoImp);
+
+ //No copying
+ WW8RStyle(const WW8RStyle&);
+ WW8RStyle& operator=(const WW8RStyle&);
+public:
+ WW8RStyle( WW8Fib& rFib, SwWW8ImplReader* pI );
+ void Import();
+ void PostProcessStyles();
+ const sal_uInt8* HasParaSprm( sal_uInt16 nId ) const;
+};
+
+class WW8FlySet: public SfxItemSet
+{
+private:
+ //No copying
+ const WW8FlySet& operator=(const WW8FlySet&);
+ void Init(const SwWW8ImplReader& rReader, const SwPaM* pPaM);
+public:
+ WW8FlySet(SwWW8ImplReader& rReader, const WW8FlyPara* pFW,
+ const WW8SwFlyPara* pFS, bool bGraf);
+ WW8FlySet(SwWW8ImplReader& rReader, const SwPaM* pPaM, const WW8_PIC& rPic,
+ long nWidth, long nHeight);
+};
+
+enum WW8LvlType {WW8_None, WW8_Outline, WW8_Numbering, WW8_Sequence, WW8_Pause};
+
+WW8LvlType GetNumType(sal_uInt8 nWwLevelNo);
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par3.cxx b/sw/source/filter/ww8/ww8par3.cxx
new file mode 100644
index 000000000000..6d014a08a61a
--- /dev/null
+++ b/sw/source/filter/ww8/ww8par3.cxx
@@ -0,0 +1,2613 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <svl/itemiter.hxx>
+#include <vcl/svapp.hxx>
+#include <vcl/outdev.hxx>
+
+#include <toolkit/helper/vclunohelper.hxx>
+#include <com/sun/star/form/XFormsSupplier.hpp>
+#include <com/sun/star/form/XForm.hpp>
+#include <com/sun/star/form/XImageProducerSupplier.hpp>
+#include <com/sun/star/form/XFormController.hpp>
+#include <com/sun/star/frame/XStorable.hpp>
+#include <com/sun/star/frame/XModel.hpp>
+#include <com/sun/star/drawing/XConnectableShape.hpp>
+#include <com/sun/star/drawing/XConnectorShape.hpp>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <com/sun/star/drawing/XControlShape.hpp>
+#include <com/sun/star/drawing/XShapeAligner.hpp>
+#include <com/sun/star/drawing/XShapeGroup.hpp>
+#include <com/sun/star/drawing/XUniversalShapeDescriptor.hpp>
+#include <com/sun/star/drawing/XShapeMirror.hpp>
+#include <com/sun/star/drawing/XShapeArranger.hpp>
+#include <com/sun/star/drawing/XDrawPage.hpp>
+#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/container/XIndexContainer.hpp>
+#include <com/sun/star/text/VertOrientation.hpp>
+#include <com/sun/star/text/TextContentAnchorType.hpp>
+#include <comphelper/extract.hxx>
+#include <comphelper/stlunosequence.hxx>
+#include <com/sun/star/beans/XPropertyContainer.hpp>
+#include <com/sun/star/beans/PropertyAttribute.hpp>
+
+#include <algorithm>
+#include <functional>
+#include <hintids.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/postitem.hxx>
+#include <filter/msfilter/msocximex.hxx>
+#include <unotextrange.hxx>
+#include <doc.hxx>
+#include <docary.hxx>
+#include <docsh.hxx>
+#include <numrule.hxx>
+#include <paratr.hxx>
+#include <charatr.hxx>
+#include <charfmt.hxx>
+#include <ndtxt.hxx>
+#include <expfld.hxx>
+#include <fmtfld.hxx>
+#include <flddropdown.hxx>
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "ww8par.hxx"
+#include "ww8par2.hxx" // wg. Listen-Attributen in Styles
+
+#include <IMark.hxx>
+#include <unotools/fltrcfg.hxx>
+#include <xmloff/odffields.hxx>
+
+#include <stdio.h>
+
+using namespace com::sun::star;
+using namespace sw::util;
+using namespace sw::types;
+using namespace sw::mark;
+
+//-----------------------------------------
+// UNO-Controls
+//-----------------------------------------
+
+//cmc, OCX i.e. word 97 form controls
+eF_ResT SwWW8ImplReader::Read_F_OCX( WW8FieldDesc*, String& )
+{
+ if( bObj && nPicLocFc )
+ nObjLocFc = nPicLocFc;
+ bEmbeddObj = true;
+ return FLD_TEXT;
+}
+
+eF_ResT SwWW8ImplReader::Read_F_FormTextBox( WW8FieldDesc* pF, String& rStr )
+{
+ WW8FormulaEditBox aFormula(*this);
+
+ if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1))) {
+ ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_EDIT);
+ }
+
+ /*
+ Here we have a small complication. This formula control contains
+ the default text that is displayed if you edit the form field in
+ the "default text" area. But MSOffice does not display that
+ information, instead it display the result of the field,
+ MSOffice just uses the default text of the control as its
+ initial value for the displayed default text. So we will swap in
+ the field result into the formula here in place of the default
+ text.
+ */
+
+ const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
+ sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
+
+ if (!bUseEnhFields) {
+ aFormula.sDefault = GetFieldResult(pF);
+
+ SwInputField aFld((SwInputFieldType*)rDoc.GetSysFldType( RES_INPUTFLD ),
+ aFormula.sDefault , aFormula.sTitle , INP_TXT, 0 );
+ aFld.SetHelp(aFormula.sHelp);
+ aFld.SetToolTip(aFormula.sToolTip);
+
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
+ return FLD_OK;
+ } else {
+ WW8PLCFx_Book* pB = pPlcxMan->GetBook();
+ String aBookmarkName;
+ if (pB!=NULL) {
+ WW8_CP currentCP=pF->nSCode;
+ WW8_CP currentLen=pF->nLen;
+
+ sal_uInt16 bkmFindIdx;
+ String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx);
+
+ if (aBookmarkFind.Len()>0) {
+ pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark bookmark as consumed, such that tl'll not get inserted as a "normal" bookmark again
+ if (aBookmarkFind.Len()>0) {
+ aBookmarkName=aBookmarkFind;
+ }
+ }
+ }
+
+ if (pB!=NULL && aBookmarkName.Len()==0) {
+ aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle);
+ }
+
+
+ if (aBookmarkName.Len()>0) {
+ maFieldStack.back().SetBookmarkName(aBookmarkName);
+ maFieldStack.back().SetBookmarkType(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMTEXT)));
+ maFieldStack.back().getParameters()[::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Description"))] = uno::makeAny(::rtl::OUString(aFormula.sToolTip));
+ maFieldStack.back().getParameters()[::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Name"))] = uno::makeAny(::rtl::OUString(aFormula.sTitle));
+ }
+ return FLD_TEXT;
+ }
+}
+
+eF_ResT SwWW8ImplReader::Read_F_FormCheckBox( WW8FieldDesc* pF, String& rStr )
+{
+ WW8FormulaCheckBox aFormula(*this);
+
+ if (!pFormImpl)
+ pFormImpl = new SwMSConvertControls(mpDocShell, pPaM);
+
+ if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1)))
+ ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_CHECKBOX);
+ const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
+ sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
+
+ if (!bUseEnhFields) {
+ pFormImpl->InsertFormula(aFormula);
+ return FLD_OK;
+ } else {
+ String aBookmarkName;
+ WW8PLCFx_Book* pB = pPlcxMan->GetBook();
+ if (pB!=NULL) {
+ WW8_CP currentCP=pF->nSCode;
+ WW8_CP currentLen=pF->nLen;
+
+ sal_uInt16 bkmFindIdx;
+ String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx);
+
+ if (aBookmarkFind.Len()>0) {
+ pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark as consumed by field
+ if (aBookmarkFind.Len()>0) {
+ aBookmarkName=aBookmarkFind;
+ }
+ }
+ }
+
+ if (pB!=NULL && aBookmarkName.Len()==0) {
+ aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle);
+ }
+
+ if (aBookmarkName.Len()>0)
+ {
+ IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
+ IFieldmark* pFieldmark = dynamic_cast<IFieldmark*>( pMarksAccess->makeNoTextFieldBookmark(
+ *pPaM, aBookmarkName,
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_FORMCHECKBOX )) ) );
+ OSL_ENSURE(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
+ if (pFieldmark!=NULL) {
+ IFieldmark::parameter_map_t* const pParameters = pFieldmark->GetParameters();
+ ICheckboxFieldmark* pCheckboxFm = reinterpret_cast<ICheckboxFieldmark*>(pFieldmark);
+ (*pParameters)[::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMCHECKBOX_NAME))] = uno::makeAny(::rtl::OUString(aFormula.sTitle));
+ (*pParameters)[::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMCHECKBOX_HELPTEXT))] = uno::makeAny(::rtl::OUString(aFormula.sToolTip));
+
+ if(pCheckboxFm)
+ pCheckboxFm->SetChecked(aFormula.nChecked);
+ // set field data here...
+ }
+ }
+ return FLD_OK;
+ }
+}
+
+eF_ResT SwWW8ImplReader::Read_F_FormListBox( WW8FieldDesc* pF, String& rStr)
+{
+ WW8FormulaListBox aFormula(*this);
+
+ if (0x01 == rStr.GetChar(writer_cast<xub_StrLen>(pF->nLCode-1)))
+ ImportFormulaControl(aFormula,pF->nSCode+pF->nLCode-1, WW8_CT_DROPDOWN);
+
+ const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
+ sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
+
+ if (!bUseEnhFields)
+ {
+ SwDropDownField aFld((SwDropDownFieldType*)rDoc.GetSysFldType(RES_DROPDOWN));
+
+ aFld.SetName(aFormula.sTitle);
+ aFld.SetHelp(aFormula.sHelp);
+ aFld.SetToolTip(aFormula.sToolTip);
+
+ if (!aFormula.maListEntries.empty())
+ {
+ aFld.SetItems(aFormula.maListEntries);
+ int nIndex = aFormula.fDropdownIndex < aFormula.maListEntries.size() ? aFormula.fDropdownIndex : 0;
+ aFld.SetSelectedItem(aFormula.maListEntries[nIndex]);
+ }
+
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
+ return FLD_OK;
+ }
+ else
+ {
+ // TODO: review me
+ String aBookmarkName;
+ WW8PLCFx_Book* pB = pPlcxMan->GetBook();
+ if (pB!=NULL)
+ {
+ WW8_CP currentCP=pF->nSCode;
+ WW8_CP currentLen=pF->nLen;
+
+ sal_uInt16 bkmFindIdx;
+ String aBookmarkFind=pB->GetBookmark(currentCP-1, currentCP+currentLen-1, bkmFindIdx);
+
+ if (aBookmarkFind.Len()>0)
+ {
+ pB->SetStatus(bkmFindIdx, BOOK_FIELD); // mark as consumed by field
+ if (aBookmarkFind.Len()>0)
+ aBookmarkName=aBookmarkFind;
+ }
+ }
+
+ if (pB!=NULL && aBookmarkName.Len()==0)
+ aBookmarkName=pB->GetUniqueBookmarkName(aFormula.sTitle);
+
+ if (aBookmarkName.Len()>0)
+ {
+ IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
+ IFieldmark *pFieldmark = dynamic_cast<IFieldmark*>(
+ pMarksAccess->makeNoTextFieldBookmark( *pPaM, aBookmarkName,
+ ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_FORMDROPDOWN )) ) );
+ OSL_ENSURE(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
+ if ( pFieldmark != NULL )
+ {
+ uno::Sequence< ::rtl::OUString > vListEntries(aFormula.maListEntries.size());
+ ::std::copy(aFormula.maListEntries.begin(), aFormula.maListEntries.end(), ::comphelper::stl_begin(vListEntries));
+ (*pFieldmark->GetParameters())[::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_LISTENTRY))] = uno::makeAny(vListEntries);
+ sal_Int32 nIndex = aFormula.fDropdownIndex < aFormula.maListEntries.size() ? aFormula.fDropdownIndex : 0;
+ (*pFieldmark->GetParameters())[::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMDROPDOWN_RESULT))] = uno::makeAny(nIndex);
+ // set field data here...
+ }
+ }
+
+ return FLD_OK;
+ }
+}
+
+eF_ResT SwWW8ImplReader::Read_F_HTMLControl(WW8FieldDesc*, String&)
+{
+ if( bObj && nPicLocFc )
+ nObjLocFc = nPicLocFc;
+ bEmbeddObj = true;
+ return FLD_TEXT;
+}
+
+void SwWW8ImplReader::DeleteFormImpl()
+{
+ delete pFormImpl, pFormImpl = 0;
+}
+
+//----------------------------------------------------------------------------
+// WW8ListManager oeffentliche Methoden stehen ganz am Ende
+//------------------------- ============ --------------- ============ --------
+
+
+
+// Hilfs-Deklarationen ///////////////////////////////////////////////////////
+//
+// Style Id's for each level
+typedef sal_uInt16 WW8aIdSty[WW8ListManager::nMaxLevel];
+// Zeichenattribute aus GrpprlChpx
+typedef SfxItemSet* WW8aISet[WW8ListManager::nMaxLevel];
+// Zeichen Style Pointer
+typedef SwCharFmt* WW8aCFmt[WW8ListManager::nMaxLevel];
+
+struct WW8LST // nur DIE Eintraege, die WIR benoetigen!
+{
+ WW8aIdSty aIdSty; // Style Id's for each level,
+ // nIStDNil if no style linked
+ sal_uInt32 nIdLst; // Unique List ID
+ sal_uInt32 nTplC; // Unique template code - Was ist das bloss?
+ sal_uInt8 bSimpleList:1; // Flag: Liste hat nur EINEN Level
+ sal_uInt8 bRestartHdn:1; // WW6-Kompatibilitaets-Flag:
+ // true if the list should start numbering over
+}; // at the beginning of each section
+
+struct WW8LFO // nur DIE Eintraege, die WIR benoetigen!
+{
+ SwNumRule* pNumRule; // Parent NumRule
+ sal_uInt32 nIdLst; // Unique List ID
+ sal_uInt8 nLfoLvl; // count of levels whose format is overridden
+ bool bSimpleList;
+};
+
+struct WW8LVL // nur DIE Eintraege, die WIR benoetigen!
+{
+ long nStartAt; // start at value for this value
+ long nV6DxaSpace;// Ver6-Compatible: min Space between Num anf text::Paragraph
+ long nV6Indent; // Ver6-Compatible: Breite des Prefix Textes; ggfs. zur
+ // Definition d. Erstzl.einzug nutzen!
+ // Absatzattribute aus GrpprlPapx
+ sal_uInt16 nDxaLeft; // linker Einzug
+ short nDxaLeft1; // Erstzeilen-Einzug
+
+ sal_uInt8 nNFC; // number format code
+ // Offset der Feldkodes im Num-X-String
+ sal_uInt8 aOfsNumsXCH[WW8ListManager::nMaxLevel];
+ sal_uInt8 nLenGrpprlChpx; // length, in bytes, of the LVL's grpprlChpx
+ sal_uInt8 nLenGrpprlPapx; // length, in bytes, of the LVL's grpprlPapx
+ sal_uInt8 nAlign: 2; // alignment (left, right, centered) of the number
+ sal_uInt8 bLegal: 1; // egal
+ sal_uInt8 bNoRest:1; // egal
+ sal_uInt8 bV6Prev:1; // Ver6-Compatible: number will include previous levels
+ sal_uInt8 bV6PrSp:1; // Ver6-Compatible: egal
+ sal_uInt8 bV6: 1; // falls true , beachte die V6-Compatible Eintraege!
+ sal_uInt8 bDummy: 1; // (macht das Byte voll)
+
+};
+
+struct WW8LFOLVL
+{
+ long nStartAt; // start-at value if bFormat==false and bStartAt == true
+ // (if bFormat==true, the start-at is stored in the LVL)
+ sal_uInt8 nLevel; // the level to be overridden
+ // dieses Byte ist _absichtlich_ nicht in das folgende Byte hineingepackt !!
+ // (siehe Kommentar unten bei struct WW8LFOInfo)
+
+ sal_uInt8 bStartAt :1; // true if the start-at value is overridden
+ sal_uInt8 bFormat :1; // true if the formatting is overriden
+
+ WW8LFOLVL() :
+ nStartAt(1), nLevel(0), bStartAt(1), bFormat(0) {}
+};
+
+// in den ListenInfos zu speichernde Daten ///////////////////////////////////
+//
+struct WW8LSTInfo // sortiert nach nIdLst (in WW8 verwendete Listen-Id)
+{
+ std::vector<ww::bytes> maParaSprms;
+ WW8aIdSty aIdSty; // Style Id's for each level
+ WW8aISet aItemSet; // Zeichenattribute aus GrpprlChpx
+ WW8aCFmt aCharFmt; // Zeichen Style Pointer
+
+ SwNumRule* pNumRule; // Zeiger auf entsprechende Listenvorlage im Writer
+ sal_uInt32 nIdLst; // WW8Id dieser Liste
+ sal_uInt8 bSimpleList:1;// Flag, ob diese NumRule nur einen Level verwendet
+ sal_uInt8 bUsedInDoc :1;// Flag, ob diese NumRule im Doc verwendet wird,
+ // oder beim Reader-Ende geloescht werden sollte
+
+ WW8LSTInfo(SwNumRule* pNumRule_, WW8LST& aLST)
+ : pNumRule(pNumRule_), nIdLst(aLST.nIdLst),
+ bSimpleList(aLST.bSimpleList), bUsedInDoc(0)
+ {
+ memcpy( aIdSty, aLST.aIdSty, sizeof( aIdSty ));
+ memset(&aItemSet, 0, sizeof( aItemSet ));
+ memset(&aCharFmt, 0, sizeof( aCharFmt ));
+ }
+
+};
+
+// in den ListenFormatOverrideInfos zu speichernde Daten /////////////////////
+//
+struct WW8LFOInfo // unsortiert, d.h. Reihenfolge genau wie im WW8 Stream
+{
+ std::vector<ww::bytes> maParaSprms;
+ std::vector<WW8LFOLVL> maOverrides;
+ SwNumRule* pNumRule; // Zeiger auf entsprechende Listenvorlage im Writer
+ // entweder: Liste in LSTInfos oder eigene Liste
+ // (im Ctor erstmal die aus den LSTInfos merken)
+
+ sal_uInt32 nIdLst; // WW8-Id der betreffenden Liste
+ sal_uInt8 nLfoLvl; // count of levels whose format is overridden
+ // Ja, ich natuerlich koennten wir nLfoLvl (mittels :4) noch in das folgende
+ // Byte mit hineinpacken, doch waere das eine ziemliche Fehlerquelle,
+ // an dem Tag, wo MS ihr Listenformat auf mehr als 15 Level aufbohren.
+
+ sal_uInt8 bOverride :1;// Flag, ob die NumRule nicht in maLSTInfos steht,
+ // sondern fuer pLFOInfos NEU angelegt wurde
+ sal_uInt8 bSimpleList:1;// Flag, ob diese NumRule nur einen Level verwendet
+ sal_uInt8 bUsedInDoc :1;// Flag, ob diese NumRule im Doc verwendet wird,
+ // oder beim Reader-Ende geloescht werden sollte
+ sal_uInt8 bLSTbUIDSet :1;// Flag, ob bUsedInDoc in maLSTInfos gesetzt wurde,
+ // und nicht nochmals gesetzt zu werden braucht
+ WW8LFOInfo(const WW8LFO& rLFO);
+};
+
+WW8LFOInfo::WW8LFOInfo(const WW8LFO& rLFO)
+ : maParaSprms(WW8ListManager::nMaxLevel),
+ maOverrides(WW8ListManager::nMaxLevel), pNumRule(rLFO.pNumRule),
+ nIdLst(rLFO.nIdLst), nLfoLvl(rLFO.nLfoLvl),
+ bOverride(rLFO.nLfoLvl ? true : false), bSimpleList(rLFO.bSimpleList),
+ bUsedInDoc(0), bLSTbUIDSet(0)
+{
+}
+
+SV_IMPL_PTRARR( WW8LFOInfos, WW8LFOInfo_Ptr );
+
+
+// Hilfs-Methoden ////////////////////////////////////////////////////////////
+//
+
+// finden der Sprm-Parameter-Daten, falls Sprm im Grpprl enthalten
+sal_uInt8* WW8ListManager::GrpprlHasSprm(sal_uInt16 nId, sal_uInt8& rSprms,
+ sal_uInt8 nLen)
+{
+ sal_uInt8* pSprms = &rSprms;
+ sal_uInt16 nRemLen=nLen;
+ while (nRemLen > (maSprmParser.getVersion()?1:0))
+ {
+ sal_uInt16 nAktId = maSprmParser.GetSprmId(pSprms);
+ if( nAktId == nId ) // Sprm found
+ return pSprms + maSprmParser.DistanceToData(nId);
+
+ // gib Zeiger auf Daten
+ sal_uInt16 nSize = maSprmParser.GetSprmSize(nAktId, pSprms);
+ pSprms += nSize;
+ nRemLen -= nSize;
+ }
+ return 0; // Sprm not found
+}
+
+class ListWithId : public std::unary_function<const WW8LSTInfo *, bool>
+{
+private:
+ sal_uInt32 mnIdLst;
+public:
+ explicit ListWithId(sal_uInt32 nIdLst) : mnIdLst(nIdLst) {}
+ bool operator() (const WW8LSTInfo *pEntry) const
+ { return (pEntry->nIdLst == mnIdLst); }
+};
+
+// Zugriff ueber die List-Id des LST Eintrags
+WW8LSTInfo* WW8ListManager::GetLSTByListId( sal_uInt32 nIdLst ) const
+{
+ std::vector<WW8LSTInfo *>::const_iterator aResult =
+ std::find_if(maLSTInfos.begin(),maLSTInfos.end(),ListWithId(nIdLst));
+ if (aResult == maLSTInfos.end())
+ return 0;
+ return *aResult;
+}
+
+void lcl_CopyGreaterEight(String &rDest, String &rSrc,
+ xub_StrLen nStart, xub_StrLen nLen = STRING_LEN)
+{
+ if (nLen == STRING_LEN)
+ nLen = rSrc.Len();
+ for (xub_StrLen nI = nStart; nI < nLen; ++nI)
+ {
+ sal_Unicode nChar = rSrc.GetChar(nI);
+ if (nChar > WW8ListManager::nMaxLevel)
+ rDest.Append(nChar);
+ }
+}
+
+bool WW8ListManager::ReadLVL(SwNumFmt& rNumFmt, SfxItemSet*& rpItemSet,
+ sal_uInt16 nLevelStyle, bool bSetStartNo,
+ std::deque<bool> &rNotReallyThere, sal_uInt16 nLevel,
+ ww::bytes &rParaSprms)
+{
+ sal_uInt8 aBits1(0);
+ sal_uInt16 nStartNo(0); // Start-Nr. fuer den Writer
+ SvxExtNumType eType; // Writer-Num-Typ
+ SvxAdjust eAdj; // Ausrichtung (Links/rechts/zent.)
+ sal_Unicode cBullet(0x2190); // default safe bullet
+ String sPrefix;
+ String sPostfix;
+ WW8LVL aLVL;
+ //
+ // 1. LVLF einlesen
+ //
+ memset(&aLVL, 0, sizeof( aLVL ));
+ rSt >> aLVL.nStartAt;
+ rSt >> aLVL.nNFC;
+ rSt >> aBits1;
+ if( 0 != rSt.GetError() ) return false;
+ aLVL.nAlign = (aBits1 & 0x03);
+ if( aBits1 & 0x10 ) aLVL.bV6Prev = true;
+ if( aBits1 & 0x20 ) aLVL.bV6PrSp = true;
+ if( aBits1 & 0x40 ) aLVL.bV6 = true;
+ bool bLVLOkB = true;
+ sal_uInt8 nLevelB = 0;
+ for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
+ {
+ rSt >> aLVL.aOfsNumsXCH[ nLevelB ];
+ if( 0 != rSt.GetError() )
+ {
+ bLVLOkB = false;
+ break;
+ }
+ }
+
+ if( !bLVLOkB )
+ return false;
+
+ sal_uInt8 ixchFollow(0);
+ rSt >> ixchFollow;
+ if (ixchFollow == 0)
+ rReader.maTracer.Log(sw::log::eTabInNumbering);
+ rSt >> aLVL.nV6DxaSpace;
+ rSt >> aLVL.nV6Indent;
+ rSt >> aLVL.nLenGrpprlChpx;
+ rSt >> aLVL.nLenGrpprlPapx;
+ rSt.SeekRel( 2 );
+ if( 0 != rSt.GetError()) return false;
+
+ //
+ // 2. ggfs. PAPx einlesen und nach Einzug-Werten suchen
+ //
+ short nTabPos = 0; // #i86652# - read tab setting
+ if( aLVL.nLenGrpprlPapx )
+ {
+ sal_uInt8 aGrpprlPapx[ 255 ];
+ if(aLVL.nLenGrpprlPapx != rSt.Read(&aGrpprlPapx,aLVL.nLenGrpprlPapx))
+ return false;
+ // "sprmPDxaLeft" pap.dxaLeft;dxa;word;
+ sal_uInt8* pSprm;
+ if (
+ (0 != (pSprm = GrpprlHasSprm(0x840F,aGrpprlPapx[0],aLVL.nLenGrpprlPapx))) ||
+ (0 != (pSprm = GrpprlHasSprm(0x845E,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)))
+ )
+ {
+ sal_uInt8 *pBegin = pSprm-2;
+ for(int i=0;i<4;++i)
+ rParaSprms.push_back(*pBegin++);
+ short nDxaLeft = SVBT16ToShort( pSprm );
+ aLVL.nDxaLeft = (0 < nDxaLeft) ? (sal_uInt16)nDxaLeft
+ : (sal_uInt16)(-nDxaLeft);
+ }
+
+ // "sprmPDxaLeft1" pap.dxaLeft1;dxa;word;
+ if (
+ (0 != (pSprm = GrpprlHasSprm(0x8411,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) ) ||
+ (0 != (pSprm = GrpprlHasSprm(0x8460,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) )
+ )
+ {
+ sal_uInt8 *pBegin = pSprm-2;
+ for(int i=0;i<4;++i)
+ rParaSprms.push_back(*pBegin++);
+ aLVL.nDxaLeft1 = SVBT16ToShort( pSprm );
+ }
+
+ // #i86652# - read tab setting
+ if(0 != (pSprm = GrpprlHasSprm(0xC615,aGrpprlPapx[0],aLVL.nLenGrpprlPapx)) )
+ {
+ bool bDone = false;
+ if (*(pSprm-1) == 5)
+ {
+ if (*pSprm++ == 0) //nDel
+ {
+ if (*pSprm++ == 1) //nIns
+ {
+ nTabPos = SVBT16ToShort(pSprm);
+ pSprm+=2;
+ if (*pSprm == 6) //type
+ {
+ bDone = true;
+ }
+ }
+ }
+ }
+ OSL_ENSURE(bDone, "tab setting in numbering is "
+ "of unexpected configuration");
+ (void)bDone;
+ }
+ if ( rNumFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ // If there is a tab setting with a larger value, then use that.
+ // Ideally we would allow tabs to be used in numbering fields and set
+ // this on the containing paragraph which would make it actually work
+ // most of the time.
+ if ( nTabPos != 0 )
+ {
+ const sal_uInt16 nDesired = aLVL.nDxaLeft + aLVL.nDxaLeft1;
+
+ bool bDoAdjust = false;
+ if ( nDesired < aLVL.nDxaLeft )
+ {
+ if ( nDesired < nTabPos && nTabPos < aLVL.nDxaLeft )
+ {
+ bDoAdjust = true;
+ }
+ }
+ else
+ {
+ if ( aLVL.nDxaLeft < nTabPos && nTabPos < nDesired )
+ {
+ bDoAdjust = true;
+ }
+ }
+
+ if (bDoAdjust)
+ {
+ aLVL.nDxaLeft = (0 < nTabPos)
+ ? (sal_uInt16)nTabPos
+ : (sal_uInt16)(-nTabPos);
+
+ aLVL.nDxaLeft1 = nDesired - aLVL.nDxaLeft;
+ }
+ }
+ }
+ // <--
+ }
+ //
+ // 3. ggfs. CHPx einlesen und
+ //
+ if( aLVL.nLenGrpprlChpx )
+ {
+ sal_uInt8 aGrpprlChpx[ 255 ];
+ memset(&aGrpprlChpx, 0, sizeof( aGrpprlChpx ));
+ if(aLVL.nLenGrpprlChpx != rSt.Read(&aGrpprlChpx, aLVL.nLenGrpprlChpx))
+ return false;
+ // neues ItemSet fuer die Zeichenattribute anlegen
+ rpItemSet = new SfxItemSet( rDoc.GetAttrPool(), RES_CHRATR_BEGIN,
+ RES_CHRATR_END - 1 );
+
+ // Reader-ItemSet-Pointer darauf zeigen lassen
+ rReader.SetAktItemSet( rpItemSet );
+ // Reader-Style auf den Style dieses Levels setzen
+ sal_uInt16 nOldColl = rReader.GetNAktColl();
+ sal_uInt16 nNewColl = nLevelStyle;
+ if (ww::stiNil == nNewColl)
+ nNewColl = 0;
+ rReader.SetNAktColl( nNewColl );
+
+ // Nun den GrpprlChpx einfach durchnudeln: die Read_xy() Methoden
+ // in WW8PAR6.CXX rufen ganz normal ihr NewAttr() oder GetFmtAttr()
+ // und diese merken am besetzten Reader-ItemSet-Pointer, dass dieser
+ // spezielle ItemSet relevant ist - und nicht ein Stack oder Style!
+ sal_uInt16 nOldFlags1 = rReader.GetToggleAttrFlags();
+ sal_uInt16 nOldFlags2 = rReader.GetToggleBiDiAttrFlags();
+ short nLen = aLVL.nLenGrpprlChpx;
+ sal_uInt8* pSprms1 = &aGrpprlChpx[0];
+ while (0 < nLen)
+ {
+ sal_uInt16 nL1 = rReader.ImportSprm( pSprms1 );
+ nLen = nLen - nL1;
+ pSprms1 += nL1;
+ }
+ // Reader-ItemSet-Pointer und Reader-Style zuruecksetzen
+ rReader.SetAktItemSet( 0 );
+ rReader.SetNAktColl( nOldColl );
+ rReader.SetToggleAttrFlags(nOldFlags1);
+ rReader.SetToggleBiDiAttrFlags(nOldFlags2);
+ }
+ //
+ // 4. den Nummerierungsstring einlesen: ergibt Prefix und Postfix
+ //
+ String sNumString(WW8Read_xstz(rSt, 0, false));
+
+ //
+ // 5. gelesene Werte in Writer Syntax umwandeln
+ //
+ if( 0 <= aLVL.nStartAt )
+ nStartNo = (sal_uInt16)aLVL.nStartAt;
+
+ switch( aLVL.nNFC )
+ {
+ case 0:
+ eType = SVX_NUM_ARABIC;
+ break;
+ case 1:
+ eType = SVX_NUM_ROMAN_UPPER;
+ break;
+ case 2:
+ eType = SVX_NUM_ROMAN_LOWER;
+ break;
+ case 3:
+ eType = SVX_NUM_CHARS_UPPER_LETTER_N;
+ break;
+ case 4:
+ eType = SVX_NUM_CHARS_LOWER_LETTER_N;
+ break;
+ case 5:
+ // eigentlich: ORDINAL
+ eType = SVX_NUM_ARABIC;
+ break;
+ case 23:
+ case 25:
+ eType = SVX_NUM_CHAR_SPECIAL;
+ break;
+ case 255:
+ eType = SVX_NUM_NUMBER_NONE;
+ break;
+ default:
+ // take default
+ eType = SVX_NUM_ARABIC;
+ break;
+ }
+
+ //If a number level is not going to be used, then record this fact
+ if (SVX_NUM_NUMBER_NONE == eType)
+ rNotReallyThere[nLevel] = true;
+
+ /*
+ If a number level was not used (i.e. is in NotReallyThere), and that
+ number level appears at one of the positions in the display string of the
+ list, then it effectively is not there at all. So remove that level entry
+ from a copy of the aOfsNumsXCH.
+ */
+ std::vector<sal_uInt8> aOfsNumsXCH;
+ typedef std::vector<sal_uInt8>::iterator myIter;
+ aOfsNumsXCH.reserve(nMaxLevel);
+
+ for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
+ aOfsNumsXCH.push_back(aLVL.aOfsNumsXCH[nLevelB]);
+
+ for(nLevelB = 0; nLevelB <= nLevel; ++nLevelB)
+ {
+ sal_uInt8 nPos = aOfsNumsXCH[nLevelB];
+ if (nPos && sNumString.GetChar(nPos-1) < nMaxLevel)
+ {
+ if (rNotReallyThere[nLevelB])
+ aOfsNumsXCH[nLevelB] = 0;
+ }
+ }
+ myIter aIter = std::remove(aOfsNumsXCH.begin(), aOfsNumsXCH.end(), 0);
+ myIter aEnd = aOfsNumsXCH.end();
+ // #i60633# - suppress access on <aOfsNumsXCH.end()>
+ if ( aIter != aEnd )
+ {
+ // Somehow the first removed vector element, at which <aIter>
+ // points to, isn't reset to zero.
+ // Investigation is needed to clarify why. It seems that only
+ // special arrays are handled correctly by this code.
+ ++aIter;
+ while (aIter != aEnd)
+ {
+ (*aIter) = 0;
+ ++aIter;
+ }
+ }
+ // <--
+
+ sal_uInt8 nUpperLevel = 0; // akt. Anzeigetiefe fuer den Writer
+ for(nLevelB = 0; nLevelB < nMaxLevel; ++nLevelB)
+ {
+ if (!nUpperLevel && !aOfsNumsXCH[nLevelB])
+ nUpperLevel = nLevelB;
+ }
+
+ // falls kein NULL als Terminierungs-Char kam,
+ // ist die Liste voller Indices, d.h. alle Plaetze sind besetzt,
+ // also sind alle Level anzuzeigen
+ if (!nUpperLevel)
+ nUpperLevel = nMaxLevel;
+
+ if (SVX_NUM_CHAR_SPECIAL == eType)
+ {
+ cBullet = sNumString.Len() ? sNumString.GetChar(0) : 0x2190;
+
+ if (!cBullet) // unsave control code?
+ cBullet = 0x2190;
+ }
+ else
+ {
+ /*
+ #i173#
+ Our aOfsNumsXCH seems generally to be an array that contains the
+ offset into sNumString of locations where the numbers should be
+ filled in, so if the first "fill in a number" slot is greater than
+ 1 there is a "prefix" before the number
+ */
+ //First number appears at
+ sal_uInt8 nOneBasedFirstNoIndex = aOfsNumsXCH[0];
+ xub_StrLen nFirstNoIndex =
+ nOneBasedFirstNoIndex > 0 ? nOneBasedFirstNoIndex -1 : STRING_LEN;
+ lcl_CopyGreaterEight(sPrefix, sNumString, 0, nFirstNoIndex);
+
+ //Next number appears at
+ if (nUpperLevel)
+ {
+ sal_uInt8 nOneBasedNextNoIndex = aOfsNumsXCH[nUpperLevel-1];
+ xub_StrLen nNextNoIndex =
+ nOneBasedNextNoIndex > 0 ? nOneBasedNextNoIndex -1 : STRING_LEN;
+ if (nNextNoIndex != STRING_LEN)
+ ++nNextNoIndex;
+ if (sNumString.Len() > nNextNoIndex)
+ lcl_CopyGreaterEight(sPostfix, sNumString, nNextNoIndex);
+ }
+
+ /*
+ We use lcl_CopyGreaterEight because once if we have removed unused
+ number indexes from the aOfsNumsXCH then placeholders remain in
+ sNumString which must not be copied into the final numbering strings
+ */
+ }
+
+ switch( aLVL.nAlign )
+ {
+ case 0:
+ eAdj = SVX_ADJUST_LEFT;
+ break;
+ case 1:
+ eAdj = SVX_ADJUST_CENTER;
+ break;
+ case 2:
+ eAdj = SVX_ADJUST_RIGHT;
+ break;
+ case 3:
+ // Writer here cannot do block justification
+ eAdj = SVX_ADJUST_LEFT;
+ break;
+ default:
+ // undefied value
+ OSL_ENSURE( !this, "Value of aLVL.nAlign is not supported" );
+ // take default
+ eAdj = SVX_ADJUST_LEFT;
+ break;
+ }
+
+ // 6. entsprechendes NumFmt konfigurieren
+ if( bSetStartNo )
+ rNumFmt.SetStart( nStartNo );
+ rNumFmt.SetNumberingType( static_cast< sal_Int16 >(eType) );
+ rNumFmt.SetNumAdjust( eAdj );
+
+ if( SVX_NUM_CHAR_SPECIAL == eType )
+ {
+ // first character of the Prefix-Text is the Bullet
+ rNumFmt.SetBulletChar(cBullet);
+ // Don't forget: unten, nach dem Bauen eventueller Styles auch noch
+ // SetBulletFont() rufen !!!
+ }
+ else
+ {
+ // reminder: Garnix ist default Prefix
+ if( sPrefix.Len() )
+ rNumFmt.SetPrefix( sPrefix );
+ // reminder: Point is default Postfix
+ rNumFmt.SetSuffix( sPostfix );
+ rNumFmt.SetIncludeUpperLevels( nUpperLevel );
+ }
+
+ // #i89181#
+ if ( rNumFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ if (eAdj == SVX_ADJUST_RIGHT)
+ {
+ rNumFmt.SetAbsLSpace(aLVL.nDxaLeft);
+ rNumFmt.SetFirstLineOffset(-aLVL.nDxaLeft);
+ rNumFmt.SetCharTextDistance(-aLVL.nDxaLeft1);
+ }
+ else
+ {
+ rNumFmt.SetAbsLSpace( aLVL.nDxaLeft );
+ rNumFmt.SetFirstLineOffset(aLVL.nDxaLeft1);
+ }
+ }
+ else
+ {
+ rNumFmt.SetIndentAt( aLVL.nDxaLeft );
+ rNumFmt.SetFirstLineIndent(aLVL.nDxaLeft1);
+ rNumFmt.SetListtabPos( nTabPos );
+ SvxNumberFormat::SvxNumLabelFollowedBy eNumLabelFollowedBy = SvxNumberFormat::LISTTAB;
+ switch ( ixchFollow )
+ {
+ case 0:
+ {
+ eNumLabelFollowedBy = SvxNumberFormat::LISTTAB;
+ }
+ break;
+ case 1:
+ {
+ eNumLabelFollowedBy = SvxNumberFormat::SPACE;
+ }
+ break;
+ case 2:
+ {
+ eNumLabelFollowedBy = SvxNumberFormat::NOTHING;
+ }
+ break;
+ }
+ rNumFmt.SetLabelFollowedBy( eNumLabelFollowedBy );
+ }
+
+ return true;
+}
+
+void WW8ListManager::AdjustLVL( sal_uInt8 nLevel, SwNumRule& rNumRule,
+ WW8aISet& rListItemSet, WW8aCFmt& rCharFmt, bool& bNewCharFmtCreated,
+ String sPrefix )
+{
+ bNewCharFmtCreated = false;
+ SfxItemSet* pThisLevelItemSet;
+ SfxItemSet* pLowerLevelItemSet;
+ sal_uInt8 nIdenticalItemSetLevel;
+ const SfxPoolItem* pItem;
+
+ SwNumFmt aNumFmt = rNumRule.Get( nLevel );
+
+ pThisLevelItemSet = rListItemSet[ nLevel ];
+
+ if( pThisLevelItemSet && pThisLevelItemSet->Count())
+ {
+ nIdenticalItemSetLevel = nMaxLevel;
+ SfxItemIter aIter( *pThisLevelItemSet );
+ for (sal_uInt8 nLowerLevel = 0; nLowerLevel < nLevel; ++nLowerLevel)
+ {
+ pLowerLevelItemSet = rListItemSet[ nLowerLevel ];
+ if( pLowerLevelItemSet
+ && (pLowerLevelItemSet->Count() == pThisLevelItemSet->Count()) )
+ {
+ nIdenticalItemSetLevel = nLowerLevel;
+ sal_uInt16 nWhich = aIter.GetCurItem()->Which();
+ while (true)
+ {
+ if( // ggfs. passenden pItem im pLowerLevelItemSet finden
+ (SFX_ITEM_SET != pLowerLevelItemSet->GetItemState(
+ nWhich, false, &pItem ) )
+ || // virtuellen "!=" Operator anwenden
+ (*pItem != *aIter.GetCurItem() ) )
+ // falls kein Item mit gleicher nWhich gefunden oder Werte
+ // der Items ungleich, Ungleichheit merken und abbrechen!
+ {
+ nIdenticalItemSetLevel = nMaxLevel;
+ break;
+ }
+ if( aIter.IsAtEnd() )
+ break;
+ nWhich = aIter.NextItem()->Which();
+ }
+
+ if( nIdenticalItemSetLevel != nMaxLevel )
+ break;
+ }
+ }
+
+ SwCharFmt* pFmt;
+ if (nMaxLevel == nIdenticalItemSetLevel)
+ {
+ // Style definieren
+ String aName( sPrefix.Len() ? sPrefix : rNumRule.GetName() );
+ (aName += 'z') += String::CreateFromInt32( nLevel );
+
+ // const Wegcasten
+ pFmt = rDoc.MakeCharFmt(aName, (SwCharFmt*)rDoc.GetDfltCharFmt());
+ bNewCharFmtCreated = true;
+ // Attribute reinsetzen
+ pFmt->SetFmtAttr( *pThisLevelItemSet );
+ }
+ else
+ {
+ // passenden Style hier anhaengen
+ pFmt = rCharFmt[ nIdenticalItemSetLevel ];
+ }
+
+ // merken
+ rCharFmt[ nLevel ] = pFmt;
+
+ //
+ // Style an das NumFormat haengen
+ //
+ aNumFmt.SetCharFmt( pFmt );
+ }
+ //
+ // ggfs. Bullet Font an das NumFormat haengen
+ //
+ if( SVX_NUM_CHAR_SPECIAL == aNumFmt.GetNumberingType() )
+ {
+ SwCharFmt* pFmt = aNumFmt.GetCharFmt();
+ Font aFont;
+ if( !pFmt )
+ {
+ aFont = numfunc::GetDefBulletFont();
+ }
+ else
+ {
+ const SvxFontItem& rFontItem = pFmt->GetFont();
+ aFont.SetFamily( rFontItem.GetFamily() );
+ aFont.SetName( rFontItem.GetFamilyName() );
+ aFont.SetStyleName( rFontItem.GetStyleName() );
+ aFont.SetPitch( rFontItem.GetPitch() );
+ aFont.SetCharSet( rFontItem.GetCharSet() );
+ }
+ aNumFmt.SetBulletFont( &aFont );
+ }
+ //
+ // und wieder rein in die NumRule
+ //
+ rNumRule.Set(nLevel, aNumFmt);
+}
+
+SwNumRule* WW8ListManager::CreateNextRule(bool bSimple)
+{
+ // wird erstmal zur Bildung des Style Namens genommen
+ String sPrefix(CREATE_CONST_ASC("WW8Num"));
+ sPrefix += String::CreateFromInt32(nUniqueList++);
+ // #i86652#
+ sal_uInt16 nRul =
+ rDoc.MakeNumRule( rDoc.GetUniqueNumRuleName(&sPrefix), 0, sal_False,
+ SvxNumberFormat::LABEL_ALIGNMENT );
+ // <--
+ SwNumRule* pMyNumRule = rDoc.GetNumRuleTbl()[nRul];
+ pMyNumRule->SetAutoRule(false);
+ pMyNumRule->SetContinusNum(bSimple);
+ return pMyNumRule;
+}
+
+// oeffentliche Methoden /////////////////////////////////////////////////////
+//
+WW8ListManager::WW8ListManager(SvStream& rSt_, SwWW8ImplReader& rReader_)
+ : maSprmParser(rReader_.GetFib().GetFIBVersion()), rReader(rReader_),
+ rDoc(rReader.GetDoc()), rFib(rReader.GetFib()), rSt(rSt_), pLFOInfos(0),
+ nUniqueList(1)
+{
+ // LST und LFO gibts erst ab WW8
+ if( ( 8 > rFib.nVersion )
+ || ( rFib.fcPlcfLst == rFib.fcPlfLfo )
+ || ( !rFib.lcbPlcfLst )
+ || ( !rFib.lcbPlfLfo ) ) return; // offensichtlich keine Listen da
+
+ // Arrays anlegen
+ pLFOInfos = new WW8LFOInfos;
+ bool bLVLOk = true;
+ sal_uInt8 aBits1;
+
+ nLastLFOPosition = USHRT_MAX;
+ long nOriginalPos = rSt.Tell();
+ //
+ // 1. PLCF LST auslesen und die Listen Vorlagen im Writer anlegen
+ //
+ rSt.Seek( rFib.fcPlcfLst );
+ sal_uInt16 nListCount;
+ rSt >> nListCount;
+ bool bOk = 0 < nListCount;
+ if( bOk )
+ {
+ WW8LST aLST;
+ //
+ // 1.1 alle LST einlesen
+ //
+ for (sal_uInt16 nList=0; nList < nListCount; ++nList)
+ {
+ bOk = false;
+ memset(&aLST, 0, sizeof( aLST ));
+ sal_uInt16 nLevel;
+ //
+ // 1.1.1 Daten einlesen
+ //
+ rSt >> aLST.nIdLst;
+ rSt >> aLST.nTplC;
+ for (nLevel = 0; nLevel < nMaxLevel; ++nLevel)
+ rSt >> aLST.aIdSty[ nLevel ];
+
+
+ rSt >> aBits1;
+
+ rSt.SeekRel( 1 );
+
+ if (rSt.GetError())
+ break;
+
+ if( aBits1 & 0x01 )
+ aLST.bSimpleList = true;
+ if( aBits1 & 0x02 )
+ aLST.bRestartHdn = true;
+
+ // 1.1.2 new NumRule inserted in Doc and WW8LSTInfo marked
+
+ /*
+ #i1869#
+ In word 2000 microsoft got rid of creating new "simple lists" with
+ only 1 level, all new lists are created with 9 levels. To hack it
+ so that the list types formerly known as simple lists still have
+ their own tab page to themselves one of the reserved bits is used
+ to show that a given list is to be in the simple list tabpage.
+ This has now nothing to do with the actual number of list level a
+ list has, only how many will be shown in the user interface.
+
+ i.e. create a simple list in 2000 and open it in 97 and 97 will
+ claim (correctly) that it is an outline list. We can set our
+ continous flag in these lists to store this information.
+ */
+ SwNumRule* pMyNumRule = CreateNextRule(
+ aLST.bSimpleList || (aBits1 & 0x10));
+
+ WW8LSTInfo* pLSTInfo = new WW8LSTInfo(pMyNumRule, aLST);
+ maLSTInfos.push_back(pLSTInfo);
+ bOk = true;
+ }
+ }
+
+ if( bOk )
+ {
+ //
+ // 1.2 alle LVL aller aLST einlesen
+ //
+ sal_uInt8 nLevel;
+ sal_uInt16 nLSTInfos = static_cast< sal_uInt16 >(maLSTInfos.size());
+ for (sal_uInt16 nList = 0; nList < nLSTInfos; ++nList)
+ {
+ bOk = false;
+ WW8LSTInfo* pListInfo = maLSTInfos[nList];
+ if( !pListInfo || !pListInfo->pNumRule ) break;
+ SwNumRule& rMyNumRule = *pListInfo->pNumRule;
+ //
+ // 1.2.1 betreffende(n) LVL(s) fuer diese aLST einlesen
+ //
+ sal_uInt16 nLvlCount = static_cast< sal_uInt16 >(pListInfo->bSimpleList ? nMinLevel : nMaxLevel);
+ std::deque<bool> aNotReallyThere;
+ aNotReallyThere.resize(nMaxLevel);
+ pListInfo->maParaSprms.resize(nMaxLevel);
+ for (nLevel = 0; nLevel < nLvlCount; ++nLevel)
+ {
+ SwNumFmt aNumFmt( rMyNumRule.Get( nLevel ) );
+ // LVLF einlesen
+ bLVLOk = ReadLVL( aNumFmt, pListInfo->aItemSet[nLevel],
+ pListInfo->aIdSty[nLevel], true, aNotReallyThere, nLevel,
+ pListInfo->maParaSprms[nLevel]);
+ if( !bLVLOk )
+ break;
+ // und in die rMyNumRule aufnehmen
+ rMyNumRule.Set( nLevel, aNumFmt );
+ }
+ if( !bLVLOk )
+ break;
+ //
+ // 1.2.2 die ItemPools mit den CHPx Einstellungen der verschiedenen
+ // Level miteinander vergleichen und ggfs. Style(s) erzeugen
+ //
+ bool bDummy;
+ for (nLevel = 0; nLevel < nLvlCount; ++nLevel)
+ {
+ AdjustLVL( nLevel, rMyNumRule, pListInfo->aItemSet,
+ pListInfo->aCharFmt, bDummy );
+ }
+ //
+ // 1.2.3 ItemPools leeren und loeschen
+ //
+ for (nLevel = 0; nLevel < nLvlCount; ++nLevel)
+ delete pListInfo->aItemSet[ nLevel ];
+ bOk = true;
+ }
+ }
+ if( !bOk )
+ {
+ // Fehler aufgetreten - LSTInfos abraeumen !!!
+
+ ;
+ }
+
+ //
+ // 2. PLF LFO auslesen und speichern
+ //
+ long nLfoCount(0);
+ if (bOk)
+ {
+ rSt.Seek(rFib.fcPlfLfo);
+ rSt >> nLfoCount;
+ if (0 >= nLfoCount)
+ bOk = false;
+ }
+
+ if(bOk)
+ {
+ WW8LFO aLFO;
+ //
+ // 2.1 alle LFO einlesen
+ //
+ for (sal_uInt16 nLfo = 0; nLfo < nLfoCount; ++nLfo)
+ {
+ bOk = false;
+ memset(&aLFO, 0, sizeof( aLFO ));
+ rSt >> aLFO.nIdLst;
+ rSt.SeekRel( 8 );
+ rSt >> aLFO.nLfoLvl;
+ rSt.SeekRel( 3 );
+ // soviele Overrides existieren
+ if ((nMaxLevel < aLFO.nLfoLvl) || rSt.GetError())
+ break;
+
+ // die Parent NumRule der entsprechenden Liste ermitteln
+ WW8LSTInfo* pParentListInfo = GetLSTByListId(aLFO.nIdLst);
+ if (pParentListInfo)
+ {
+ // hier, im ersten Schritt, erst mal diese NumRule festhalten
+ aLFO.pNumRule = pParentListInfo->pNumRule;
+
+ // hat die Liste mehrere Level ?
+ aLFO.bSimpleList = pParentListInfo->bSimpleList;
+ }
+ // und rein ins Merk-Array mit dem Teil
+ WW8LFOInfo* pLFOInfo = new WW8LFOInfo(aLFO);
+ if (pParentListInfo)
+ {
+ //Copy the basic paragraph properties for each level from the
+ //original list into the list format override levels.
+ int nMaxSize = pParentListInfo->maParaSprms.size();
+ pLFOInfo->maParaSprms.resize(nMaxSize);
+ for (int i = 0; i < nMaxSize; ++i)
+ pLFOInfo->maParaSprms[i] = pParentListInfo->maParaSprms[i];
+ }
+ pLFOInfos->Insert(pLFOInfo, pLFOInfos->Count());
+ bOk = true;
+ }
+ }
+ if( bOk )
+ {
+ //
+ // 2.2 fuer alle LFO die zugehoerigen LFOLVL einlesen
+ //
+ sal_uInt16 nLFOInfos = pLFOInfos ? pLFOInfos->Count() : 0;
+ for (sal_uInt16 nLfo = 0; nLfo < nLFOInfos; ++nLfo)
+ {
+ bOk = false;
+ WW8LFOInfo* pLFOInfo = pLFOInfos->GetObject( nLfo );
+ if (!pLFOInfo)
+ break;
+ // stehen hierfuer ueberhaupt LFOLVL an ?
+ if( pLFOInfo->bOverride )
+ {
+ WW8LSTInfo* pParentListInfo = GetLSTByListId(pLFOInfo->nIdLst);
+ if (!pParentListInfo)
+ break;
+ //
+ // 2.2.1 eine neue NumRule fuer diese Liste anlegen
+ //
+ SwNumRule* pParentNumRule = pLFOInfo->pNumRule;
+ OSL_ENSURE(pParentNumRule, "ww: Impossible lists, please report");
+ if( !pParentNumRule )
+ break;
+ // Nauemsprefix aufbauen: fuer NumRule-Name (eventuell)
+ // und (falls vorhanden) fuer Style-Name (dann auf jeden Fall)
+ String sPrefix(CREATE_CONST_ASC( "WW8NumSt" ));
+ sPrefix += String::CreateFromInt32( nLfo + 1 );
+ // jetzt dem pNumRule seinen RICHTIGEN Wert zuweisen !!!
+ // (bis dahin war hier die Parent NumRule vermerkt )
+ //
+ // Dazu erst mal nachsehen, ob ein Style diesen LFO
+ // referenziert:
+ if( USHRT_MAX > rReader.StyleUsingLFO( nLfo ) )
+ {
+ sal_uInt16 nRul = rDoc.MakeNumRule(
+ rDoc.GetUniqueNumRuleName( &sPrefix ), pParentNumRule);
+ pLFOInfo->pNumRule = rDoc.GetNumRuleTbl()[ nRul ];
+ pLFOInfo->pNumRule->SetAutoRule(false);
+ }
+ else
+ {
+ sal_uInt16 nRul = rDoc.MakeNumRule(
+ rDoc.GetUniqueNumRuleName(), pParentNumRule);
+ pLFOInfo->pNumRule = rDoc.GetNumRuleTbl()[ nRul ];
+ pLFOInfo->pNumRule->SetAutoRule(true); // = default
+ }
+ //
+ // 2.2.2 alle LFOLVL (und ggfs. LVL) fuer die neue NumRule
+ // einlesen
+ //
+ WW8aISet aItemSet; // Zeichenattribute aus GrpprlChpx
+ WW8aCFmt aCharFmt; // Zeichen Style Pointer
+ memset(&aItemSet, 0, sizeof( aItemSet ));
+ memset(&aCharFmt, 0, sizeof( aCharFmt ));
+
+ //2.2.2.0 skip inter-group of override header ?
+ //See #i25438# for why I moved this here, compare
+ //that original bugdoc's binary to what it looks like
+ //when resaved with word, i.e. there is always a
+ //4 byte header, there might be more than one if
+ //that header was 0xFFFFFFFF, e.g. #114412# ?
+ sal_uInt32 nTest;
+ rSt >> nTest;
+ do
+ rSt >> nTest;
+ while (nTest == 0xFFFFFFFF);
+ rSt.SeekRel(-4);
+
+ std::deque<bool> aNotReallyThere(WW8ListManager::nMaxLevel);
+ sal_uInt8 nLevel = 0;
+ for (nLevel = 0; nLevel < pLFOInfo->nLfoLvl; ++nLevel)
+ {
+ WW8LFOLVL aLFOLVL;
+ bLVLOk = false;
+
+ //
+ // 2.2.2.1 den LFOLVL einlesen
+ //
+ rSt >> aLFOLVL.nStartAt;
+ rSt >> aBits1;
+ rSt.SeekRel( 3 );
+ if (rSt.GetError())
+ break;
+
+ // beachte: Die Witzbolde bei MS quetschen die
+ // Override-Level-Nummer in vier Bits hinein, damit sie
+ // wieder einen Grund haben, ihr Dateiformat zu aendern,
+ // falls ihnen einfaellt, dass sie eigentlich doch gerne
+ // bis zu 16 Listen-Level haetten. Wir tun das *nicht*
+ // (siehe Kommentar oben bei "struct
+ // WW8LFOInfo")
+ aLFOLVL.nLevel = aBits1 & 0x0F;
+ if( (0xFF > aBits1) &&
+ (nMaxLevel > aLFOLVL.nLevel) )
+ {
+ if (aBits1 & 0x10)
+ aLFOLVL.bStartAt = true;
+ else
+ aLFOLVL.bStartAt = false;
+ //
+ // 2.2.2.2 eventuell auch den zugehoerigen LVL einlesen
+ //
+ SwNumFmt aNumFmt(
+ pLFOInfo->pNumRule->Get(aLFOLVL.nLevel));
+ if (aBits1 & 0x20)
+ {
+ aLFOLVL.bFormat = true;
+ // falls bStartup true, hier den Startup-Level
+ // durch den im LVL vermerkten ersetzen LVLF
+ // einlesen
+ bLVLOk = ReadLVL(aNumFmt, aItemSet[nLevel],
+ pParentListInfo->aIdSty[nLevel],
+ aLFOLVL.bStartAt, aNotReallyThere, nLevel,
+ pLFOInfo->maParaSprms[nLevel]);
+
+ if (!bLVLOk)
+ break;
+ }
+ else if (aLFOLVL.bStartAt)
+ {
+ aNumFmt.SetStart(
+ writer_cast<sal_uInt16>(aLFOLVL.nStartAt));
+ }
+ //
+ // 2.2.2.3 das NumFmt in die NumRule aufnehmen
+ //
+ pLFOInfo->pNumRule->Set(aLFOLVL.nLevel, aNumFmt);
+ }
+ bLVLOk = true;
+
+ if (nMaxLevel > aLFOLVL.nLevel)
+ pLFOInfo->maOverrides[aLFOLVL.nLevel] = aLFOLVL;
+ }
+ if( !bLVLOk )
+ break;
+ //
+ // 2.2.3 die LVL der neuen NumRule anpassen
+ //
+ sal_uInt16 aFlagsNewCharFmt = 0;
+ bool bNewCharFmtCreated = false;
+ for (nLevel = 0; nLevel < pLFOInfo->nLfoLvl; ++nLevel)
+ {
+ AdjustLVL( nLevel, *pLFOInfo->pNumRule, aItemSet, aCharFmt,
+ bNewCharFmtCreated, sPrefix );
+ if( bNewCharFmtCreated )
+ aFlagsNewCharFmt += (1 << nLevel);
+ }
+ //
+ // 2.2.4 ItemPools leeren und loeschen
+ //
+ for (nLevel = 0; nLevel < pLFOInfo->nLfoLvl; ++nLevel)
+ delete aItemSet[ nLevel ];
+ bOk = true;
+ }
+ }
+ }
+ if( !bOk )
+ {
+ // Fehler aufgetreten - LSTInfos und LFOInfos abraeumen !!!
+ ;
+ }
+ // und schon sind wir fertig!
+ rSt.Seek( nOriginalPos );
+}
+
+WW8ListManager::~WW8ListManager()
+{
+ /*
+ named lists remain in doc!!!
+ unnamed lists are deleted when unused
+ pLFOInfos are in any case destructed
+ */
+ for(std::vector<WW8LSTInfo *>::iterator aIter = maLSTInfos.begin();
+ aIter != maLSTInfos.end(); ++aIter)
+ {
+ if ((*aIter)->pNumRule && !(*aIter)->bUsedInDoc &&
+ (*aIter)->pNumRule->IsAutoRule())
+ {
+ rDoc.DelNumRule((*aIter)->pNumRule->GetName());
+ }
+ delete *aIter;
+ }
+
+ if (pLFOInfos)
+ {
+ for(sal_uInt16 nInfo = pLFOInfos->Count(); nInfo; )
+ {
+ WW8LFOInfo *pActInfo = pLFOInfos->GetObject(--nInfo);
+ if (pActInfo->bOverride && pActInfo->pNumRule
+ && !pActInfo->bUsedInDoc && pActInfo->pNumRule->IsAutoRule())
+ {
+ rDoc.DelNumRule( pActInfo->pNumRule->GetName() );
+ }
+ }
+ delete pLFOInfos;
+ }
+}
+
+bool IsEqualFormatting(const SwNumRule &rOne, const SwNumRule &rTwo)
+{
+ bool bRet =
+ (
+ rOne.GetRuleType() == rTwo.GetRuleType() &&
+ rOne.IsContinusNum() == rTwo.IsContinusNum() &&
+ rOne.IsAbsSpaces() == rTwo.IsAbsSpaces() &&
+ rOne.GetPoolFmtId() == rTwo.GetPoolFmtId() &&
+ rOne.GetPoolHelpId() == rTwo.GetPoolHelpId() &&
+ rTwo.GetPoolHlpFileId() == rTwo.GetPoolHlpFileId()
+ );
+
+ if (bRet)
+ {
+ for (sal_uInt8 n = 0; n < MAXLEVEL; ++n )
+ {
+ //The SvxNumberFormat compare, not the SwNumFmt compare
+ const SvxNumberFormat &rO = rOne.Get(n);
+ const SvxNumberFormat &rT = rTwo.Get(n);
+ if (!(rO == rT))
+ {
+ bRet = false;
+ break;
+ }
+ }
+ }
+ return bRet;
+}
+
+SwNumRule* WW8ListManager::GetNumRuleForActivation(sal_uInt16 nLFOPosition,
+ const sal_uInt8 nLevel, std::vector<sal_uInt8> &rParaSprms, SwTxtNode *pNode)
+{
+ sal_uInt16 nLFOInfos = pLFOInfos ? pLFOInfos->Count() : 0;
+ if( nLFOInfos <= nLFOPosition )
+ return 0;
+
+ WW8LFOInfo* pLFOInfo = pLFOInfos->GetObject( nLFOPosition );
+
+ if( !pLFOInfo )
+ return 0;
+
+ bool bFirstUse = !pLFOInfo->bUsedInDoc;
+ pLFOInfo->bUsedInDoc = true;
+
+ if( !pLFOInfo->pNumRule )
+ return 0;
+
+ // #i25545#
+ // #i100132# - a number format does not have to exist on given list level
+ SwNumFmt pFmt(pLFOInfo->pNumRule->Get(nLevel));
+
+ if (rReader.IsRightToLeft() && nLastLFOPosition != nLFOPosition) {
+ if ( pFmt.GetNumAdjust() == SVX_ADJUST_RIGHT)
+ pFmt.SetNumAdjust(SVX_ADJUST_LEFT);
+ else if ( pFmt.GetNumAdjust() == SVX_ADJUST_LEFT)
+ pFmt.SetNumAdjust(SVX_ADJUST_RIGHT);
+ pLFOInfo->pNumRule->Set(nLevel, pFmt);
+ }
+ nLastLFOPosition = nLFOPosition;
+ /*
+ #i1869#
+ If this list has had its bits set in word 2000 to pretend that it is a
+ simple list from the point of view of the user, then it is almost
+ certainly a simple continous list, and we will try to keep it like that.
+ Otherwise when we save again it will be shown as the true outline list
+ that it is, confusing the user that just wanted what they thought was a
+ simple list. On the otherhand it is possible that some of the other levels
+ were used by the user, in which case we will not pretend anymore that it
+ is a simple list. Something that word 2000 does anyway, that 97 didn't, to
+ my bewilderment.
+ */
+ if (nLevel && pLFOInfo->pNumRule->IsContinusNum())
+ pLFOInfo->pNumRule->SetContinusNum(false);
+
+ if( (!pLFOInfo->bOverride) && (!pLFOInfo->bLSTbUIDSet) )
+ {
+ WW8LSTInfo* pParentListInfo = GetLSTByListId( pLFOInfo->nIdLst );
+ if( pParentListInfo )
+ pParentListInfo->bUsedInDoc = true;
+ pLFOInfo->bLSTbUIDSet = true;
+ }
+
+ if (pLFOInfo->maParaSprms.size() > nLevel)
+ rParaSprms = pLFOInfo->maParaSprms[nLevel];
+
+ SwNumRule *pRet = pLFOInfo->pNumRule;
+
+ bool bRestart(false);
+ sal_uInt16 nStart(0);
+ bool bNewstart(false);
+ /*
+ Note: If you fiddle with this then you have to make sure that #i18322#
+ #i13833#, #i20095# and #112466# continue to work
+
+ Check if there were overrides for this level
+ */
+ if (pLFOInfo->bOverride && nLevel < pLFOInfo->nLfoLvl)
+ {
+ WW8LSTInfo* pParentListInfo = GetLSTByListId(pLFOInfo->nIdLst);
+ OSL_ENSURE(pParentListInfo, "ww: Impossible lists, please report");
+ if (pParentListInfo && pParentListInfo->pNumRule)
+ {
+ const WW8LFOLVL &rOverride = pLFOInfo->maOverrides[nLevel];
+ bool bNoChangeFromParent =
+ IsEqualFormatting(*pRet, *(pParentListInfo->pNumRule));
+
+ //If so then I think word still uses the parent (maybe)
+ if (bNoChangeFromParent)
+ {
+ pRet = pParentListInfo->pNumRule;
+
+ //did it not affect start at value ?
+ if (bFirstUse)
+ {
+ if (rOverride.bStartAt)
+ {
+ const SwNumFmt &rFmt =
+ pParentListInfo->pNumRule->Get(nLevel);
+ if (
+ rFmt.GetStart() ==
+ pLFOInfo->maOverrides[nLevel].nStartAt
+ )
+ {
+ bRestart = true;
+ }
+ else
+ {
+ bNewstart = true;
+ nStart = writer_cast<sal_uInt16>
+ (pLFOInfo->maOverrides[nLevel].nStartAt);
+ }
+ }
+ }
+
+ pParentListInfo->bUsedInDoc = true;
+ }
+ }
+ }
+
+ if (pNode)
+ {
+ pNode->SetAttrListLevel(nLevel);
+
+ if (bRestart || bNewstart)
+ pNode->SetListRestart(true);
+ if (bNewstart)
+ pNode->SetAttrListRestartValue(nStart);
+ }
+ return pRet;
+}
+
+//----------------------------------------------------------------------------
+// SwWW8ImplReader: anhaengen einer Liste an einen Style oder Absatz
+//----------------------------------------------------------------------------
+bool SwWW8ImplReader::SetTxtFmtCollAndListLevel(const SwPaM& rRg,
+ SwWW8StyInf& rStyleInfo)
+{
+ bool bRes = true;
+ if( rStyleInfo.pFmt && rStyleInfo.bColl )
+ {
+ bRes = rDoc.SetTxtFmtColl(rRg, (SwTxtFmtColl*)rStyleInfo.pFmt)
+ ? true : false;
+ SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode();
+ OSL_ENSURE( pTxtNode, "No Text-Node at PaM-Position" );
+ // make code robust
+ if ( !pTxtNode )
+ {
+ return bRes;
+ }
+ // <--
+
+ SwNumRule * pNumRule = pTxtNode->GetNumRule(); // #i27610#
+
+ if( !IsInvalidOrToBeMergedTabCell() &&
+ ! (pNumRule && pNumRule->IsOutlineRule()) ) // #i27610#
+ pTxtNode->ResetAttr( RES_PARATR_NUMRULE );
+
+ if( !rStyleInfo.pOutlineNumrule )
+ {
+ if (
+ (USHRT_MAX > rStyleInfo.nLFOIndex) &&
+ (WW8ListManager::nMaxLevel > rStyleInfo.nListLevel)
+ )
+ {
+ RegisterNumFmtOnTxtNode(rStyleInfo.nLFOIndex,
+ rStyleInfo.nListLevel, false);
+ }
+ }
+ else
+ {
+ // Use outline level set at the style info <rStyleInfo> instead of
+ // the outline level at the text format, because the WW8 document
+ // could contain more than one outline numbering rule and the one
+ // of the text format isn't the one, which a chosen as the Writer
+ // outline rule.
+ pTxtNode->SetAttrListLevel( rStyleInfo.nOutlineLevel );
+ }
+ }
+ return bRes;
+}
+
+void UseListIndent(SwWW8StyInf &rStyle, const SwNumFmt &rFmt)
+{
+ // #i86652#
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ {
+ const long nAbsLSpace = rFmt.GetAbsLSpace();
+ const long nListFirstLineIndent = GetListFirstLineIndent(rFmt);
+ SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*rStyle.pFmt, RES_LR_SPACE));
+ aLR.SetTxtLeft(nAbsLSpace);
+ aLR.SetTxtFirstLineOfst(writer_cast<short>(nListFirstLineIndent));
+ rStyle.pFmt->SetFmtAttr(aLR);
+ rStyle.bListReleventIndentSet = true;
+ }
+ // <--
+}
+
+void SetStyleIndent(SwWW8StyInf &rStyle, const SwNumFmt &rFmt)
+{
+ if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION ) // #i86652#
+ {
+ SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(*rStyle.pFmt, RES_LR_SPACE));
+ if (rStyle.bListReleventIndentSet)
+ {
+
+ SyncIndentWithList( aLR, rFmt, false, false ); // #i103711#, #i105414#
+ }
+ else
+ {
+ aLR.SetTxtLeft(0);
+ aLR.SetTxtFirstLineOfst(0);
+ }
+ rStyle.pFmt->SetFmtAttr(aLR);
+ }
+}
+
+void SwWW8ImplReader::SetStylesList(sal_uInt16 nStyle, sal_uInt16 nActLFO,
+ sal_uInt8 nActLevel)
+{
+ SwWW8StyInf &rStyleInf = pCollA[nStyle];
+ if (rStyleInf.bValid)
+ {
+ OSL_ENSURE(pAktColl, "Cannot be called outside of style import");
+ // Phase 1: Nummerierungsattribute beim Einlesen einer StyleDef
+ if( pAktColl )
+ {
+ // jetzt nur die Parameter vermerken: die tatsaechliche Liste wird
+ // spaeter drangehaengt, wenn die Listendefinitionen gelesen sind...
+ if (
+ (USHRT_MAX > nActLFO) &&
+ (WW8ListManager::nMaxLevel > nActLevel)
+ )
+ {
+ rStyleInf.nLFOIndex = nActLFO;
+ rStyleInf.nListLevel = nActLevel;
+
+ if (
+ (USHRT_MAX > nActLFO) &&
+ (WW8ListManager::nMaxLevel > nActLevel)
+ )
+ {
+ std::vector<sal_uInt8> aParaSprms;
+ SwNumRule *pNmRule =
+ pLstManager->GetNumRuleForActivation(nActLFO,
+ nActLevel, aParaSprms);
+ if (pNmRule)
+ UseListIndent(rStyleInf, pNmRule->Get(nActLevel));
+ }
+ }
+ }
+ }
+}
+
+void SwWW8ImplReader::RegisterNumFmtOnStyle(sal_uInt16 nStyle)
+{
+ SwWW8StyInf &rStyleInf = pCollA[nStyle];
+ if (rStyleInf.bValid && rStyleInf.pFmt)
+ {
+ //Save old pre-list modified indent, which are the word indent values
+ rStyleInf.maWordLR =
+ ItemGet<SvxLRSpaceItem>(*rStyleInf.pFmt, RES_LR_SPACE);
+
+ // Phase 2: aktualisieren der StyleDef nach einlesen aller Listen
+ SwNumRule* pNmRule = 0;
+ sal_uInt16 nLFO = rStyleInf.nLFOIndex;
+ sal_uInt8 nLevel = rStyleInf.nListLevel;
+ if (
+ (USHRT_MAX > nLFO) &&
+ (WW8ListManager::nMaxLevel > nLevel)
+ )
+ {
+ std::vector<sal_uInt8> aParaSprms;
+ pNmRule = pLstManager->GetNumRuleForActivation(nLFO, nLevel,
+ aParaSprms);
+
+ if (pNmRule)
+ {
+ if( MAXLEVEL > rStyleInf.nOutlineLevel )
+ rStyleInf.pOutlineNumrule = pNmRule;
+ else
+ {
+ rStyleInf.pFmt->SetFmtAttr(
+ SwNumRuleItem( pNmRule->GetName() ) );
+ rStyleInf.bHasStyNumRule = true;
+ }
+ }
+ }
+
+ if (pNmRule)
+ SetStyleIndent(rStyleInf, pNmRule->Get(nLevel));
+ }
+}
+
+void SwWW8ImplReader::RegisterNumFmtOnTxtNode(sal_uInt16 nActLFO,
+ sal_uInt8 nActLevel, bool bSetAttr)
+{
+ // beachte: die Methode haengt die NumRule an den Text Node, falls
+ // bSetAttr (dann muessen natuerlich vorher die Listen gelesen sein)
+ // stellt sie NUR den Level ein, im Vertrauen darauf, dass am STYLE eine
+ // NumRule haengt - dies wird NICHT ueberprueft !!!
+
+ if (pLstManager) // sind die Listendeklarationen gelesen?
+ {
+ std::vector<sal_uInt8> aParaSprms;
+ SwTxtNode* pTxtNd = pPaM->GetNode()->GetTxtNode();
+ OSL_ENSURE(pTxtNd, "Kein Text-Node an PaM-Position");
+
+ const SwNumRule* pRule = bSetAttr ?
+ pLstManager->GetNumRuleForActivation( nActLFO, nActLevel,
+ aParaSprms, pTxtNd) : 0;
+
+ if (pRule || !bSetAttr)
+ {
+ //#i24136# old is the same as new, and its the outline numbering,
+ //then we don't set the numrule again, and we just take the num node
+ //(the actual outline numbering gets set in SetOutlineNum)
+ using namespace sw::util;
+ bool bUnchangedOutlineNumbering = false;
+ /*
+ If the node is outline numbered, and the new numbering to apply
+ is the one that was chosen to be the outline numbering then all
+ is unchanged
+ */
+ // correct condition according to the above given comment.
+ if ( pTxtNd->GetNumRule() == rDoc.GetOutlineNumRule() &&
+ pRule == mpChosenOutlineNumRule )
+ // <--
+ {
+ bUnchangedOutlineNumbering = true;
+ }
+ if (!bUnchangedOutlineNumbering)
+ {
+ //If its normal numbering, see if its the same as it already
+ //was, if its not, and we have been asked to set it, then set
+ //it to the new one
+ if (bSetAttr)
+ {
+ const SwNumRule *pNormal = pTxtNd->GetNumRule();
+ if (pNormal != pRule)
+ {
+ pTxtNd->SetAttr
+ (SwNumRuleItem(pRule->GetName()));
+ }
+ }
+ }
+ pTxtNd->SetAttrListLevel(nActLevel);
+
+ // <IsCounted()> state of text node has to be adjusted accordingly.
+ if ( /*nActLevel >= 0 &&*/ nActLevel < MAXLEVEL )
+ {
+ pTxtNd->SetCountedInList( true );
+ }
+ // <--
+
+ // #i99822#
+ // Direct application of the list level formatting no longer
+ // needed for list levels of mode LABEL_ALIGNMENT
+ bool bApplyListLevelIndentDirectlyAtPara( true );
+ if ( pTxtNd->GetNumRule() && nActLevel < MAXLEVEL )
+ {
+ const SwNumFmt& rFmt = pTxtNd->GetNumRule()->Get( nActLevel );
+ if ( rFmt.GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ bApplyListLevelIndentDirectlyAtPara = false;
+ }
+ }
+
+ if ( bApplyListLevelIndentDirectlyAtPara )
+ {
+ SfxItemSet aListIndent(rDoc.GetAttrPool(), RES_LR_SPACE,
+ RES_LR_SPACE);
+ const SvxLRSpaceItem *pItem = (const SvxLRSpaceItem*)(
+ GetFmtAttr(RES_LR_SPACE));
+ OSL_ENSURE(pItem, "impossible");
+ if (pItem)
+ aListIndent.Put(*pItem);
+
+ /*
+ Take the original paragraph sprms attached to this list level
+ formatting and apply them to the paragraph. I'm convinced that
+ this is exactly what word does.
+ */
+ if (short nLen = static_cast< short >(aParaSprms.size()))
+ {
+ SfxItemSet* pOldAktItemSet = pAktItemSet;
+ SetAktItemSet(&aListIndent);
+
+ sal_uInt8* pSprms1 = &aParaSprms[0];
+ while (0 < nLen)
+ {
+ sal_uInt16 nL1 = ImportSprm(pSprms1);
+ nLen = nLen - nL1;
+ pSprms1 += nL1;
+ }
+
+ SetAktItemSet(pOldAktItemSet);
+ }
+
+ const SvxLRSpaceItem *pLR =
+ HasItem<SvxLRSpaceItem>(aListIndent, RES_LR_SPACE);
+ OSL_ENSURE(pLR, "Impossible");
+ if (pLR)
+ {
+ pCtrlStck->NewAttr(*pPaM->GetPoint(), *pLR);
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_LR_SPACE);
+ }
+ }
+ // <--
+ }
+ }
+}
+
+void SwWW8ImplReader::RegisterNumFmt(sal_uInt16 nActLFO, sal_uInt8 nActLevel)
+{
+ // sind wir erst beim Einlesen der StyleDef ?
+ if (pAktColl)
+ SetStylesList( nAktColl , nActLFO, nActLevel);
+ else
+ RegisterNumFmtOnTxtNode(nActLFO, nActLevel);
+}
+
+void SwWW8ImplReader::Read_ListLevel(sal_uInt16, const sal_uInt8* pData,
+ short nLen)
+{
+ if (pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
+ return;
+
+ if( nLen < 0 )
+ {
+ // aktuelle Liste ist hier zu Ende, was ist zu tun ???
+ nListLevel = WW8ListManager::nMaxLevel;
+ if (pStyles && !bVer67)
+ pStyles->nWwNumLevel = 0;
+ }
+ else
+ {
+ // Sicherheitspruefung auf NIL Pointer
+ if( !pData ) return;
+ // die Streamdaten sind hier Null basiert, so wie wir es brauchen
+ nListLevel = *pData;
+
+ if (pStyles && !bVer67)
+ {
+ /*
+ if this is the case, then if the numbering is actually stored in
+ winword 6 format, and its likely that sprmPIlvl has been abused
+ to set the ww6 list level information which we will need when we
+ reach the true ww6 list def. So set it now
+ */
+ pStyles->nWwNumLevel = nListLevel;
+ }
+
+ if (WW8ListManager::nMaxLevel <= nListLevel )
+ nListLevel = WW8ListManager::nMaxLevel;
+ else if
+ (
+ (USHRT_MAX > nLFOPosition) &&
+ (WW8ListManager::nMaxLevel > nListLevel)
+ )
+ {
+ RegisterNumFmt(nLFOPosition, nListLevel);
+ nLFOPosition = USHRT_MAX;
+ nListLevel = WW8ListManager::nMaxLevel;
+ }
+ }
+}
+
+void SwWW8ImplReader::Read_LFOPosition(sal_uInt16, const sal_uInt8* pData,
+ short nLen)
+{
+ if (pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
+ return;
+
+ if( nLen < 0 )
+ {
+ // aktueller Level ist hier zu Ende, was ist zu tun ???
+ nLFOPosition = USHRT_MAX;
+ nListLevel = WW8ListManager::nMaxLevel;
+ }
+ else
+ {
+ // Sicherheitspruefung auf NIL Pointer
+ if( !pData )
+ return;
+ short nData = SVBT16ToShort( pData );
+ if( 0 >= nData )
+ {
+ /*
+ If you have a paragraph in word with left and/or hanging indent
+ and remove its numbering, then the indentation appears to get
+ reset, but not back to the base style, instead its goes to a blank
+ setting.
+ Unless its a broken ww6 list in 97 in which case more hackery is
+ required, some more details about that in
+ ww8par6.cxx#SwWW8ImplReader::Read_LR
+ */
+
+ if (pAktColl)
+ {
+ pAktColl->SetFmtAttr(*GetDfltAttr( RES_PARATR_NUMRULE));
+ pAktColl->SetFmtAttr(SvxLRSpaceItem(RES_LR_SPACE));
+ }
+ else if (SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode())
+ {
+ pTxtNode->ResetAttr( RES_PARATR_NUMRULE ); // #i54393#
+ pTxtNode->SetCountedInList(false);
+
+ /*
+ #i24553#
+ Hmm, I can't remove outline numbering on a per txtnode basis,
+ but I can set some normal numbering, and that overrides outline
+ numbering, and then I can say when I come to say that I want no
+ number on the normal numbering rule, that should all work out
+
+ No special outline number in textnode any more
+ */
+ if (pTxtNode->IsOutline())
+ {
+ // #i54393#
+ // It's not needed to call <SetCounted( false )> again - see above.
+ // #i54393#
+ // Assure that the numbering rule, which is retrieved at
+ // the paragraph is the outline numbering rule, instead of
+ // incorrectly setting the chosen outline rule.
+ // Note: The chosen outline rule doesn't have to correspond
+ // to the outline rule
+ if ( pTxtNode->GetNumRule() != rDoc.GetOutlineNumRule() )
+ {
+ pTxtNode->SetAttr(
+ SwNumRuleItem( rDoc.GetOutlineNumRule()->GetName() ) );
+ }
+ // <--
+ }
+
+ pCtrlStck->NewAttr(*pPaM->GetPoint(), SvxLRSpaceItem(RES_LR_SPACE));
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_LR_SPACE);
+ }
+ nLFOPosition = USHRT_MAX;
+ }
+ else
+ {
+ nLFOPosition = (sal_uInt16)nData-1;
+ /*
+ If we are a ww8+ style with ww7- style lists then there is a
+ bizarre broken word bug where when the list is removed from a para
+ the ww6 list first line indent still affects the first line
+ indentation. Setting this flag will allow us to recover from this
+ braindeadness
+ */
+ if (pAktColl && (nLFOPosition == 2047-1))
+ pCollA[nAktColl].bHasBrokenWW6List = true;
+
+ // die Streamdaten sind hier 1 basiert, wir ziehen EINS ab
+ if (USHRT_MAX > nLFOPosition)
+ {
+ if (nLFOPosition != 2047-1) //Normal ww8+ list behaviour
+ {
+ if (WW8ListManager::nMaxLevel == nListLevel)
+ nListLevel = 0;
+ else if (WW8ListManager::nMaxLevel > nListLevel)
+ {
+ RegisterNumFmt(nLFOPosition, nListLevel);
+ nLFOPosition = USHRT_MAX;
+ nListLevel = WW8ListManager::nMaxLevel;
+ }
+ }
+ else if (pPlcxMan && pPlcxMan->HasParaSprm(0xC63E))
+ {
+ /*
+ #i8114# Horrific backwards compatible ww7- lists in ww8+
+ docs
+ */
+ Read_ANLevelNo(13 /*equiv ww7- sprm no*/, &nListLevel, 1);
+ }
+ }
+ }
+ }
+}
+
+// -------------------------------------------------------------------
+// ------------------------- Reading Controls ------------------------
+// -------------------------------------------------------------------
+
+bool SwWW8ImplReader::ImportFormulaControl(WW8FormulaControl &aFormula,
+ WW8_CP nStart, SwWw8ControlType nWhich )
+{
+ bool bRet=false;
+ /*
+ * Save the reader state and process the sprms for this anchor cp.
+ * Doing so will set the nPicLocFc to the offset to find the hypertext
+ * data in the data stream.
+ */
+ WW8_CP nEndCp = nStart+1; //Only interested in the single 0x01 character
+
+ WW8ReaderSave aSave(this,nStart);
+
+ WW8PLCFManResult aRes;
+ nStart = pPlcxMan->Where();
+ while(nStart <= nEndCp)
+ {
+ if ( pPlcxMan->Get(&aRes)
+ && aRes.pMemPos && aRes.nSprmId )
+ {
+ //only interested in sprms which would set nPicLocFc
+ if ( (68 == aRes.nSprmId) || (0x6A03 == aRes.nSprmId) )
+ {
+ Read_PicLoc( aRes.nSprmId, aRes.pMemPos +
+ mpSprmParser->DistanceToData(aRes.nSprmId), 4);
+ break;
+ }
+ }
+ (*pPlcxMan)++;
+ nStart = pPlcxMan->Where();
+ }
+ sal_uLong nOffset = nPicLocFc;
+ aSave.Restore(this);
+
+ sal_uLong nOldPos = pDataStream->Tell();
+ WW8_PIC aPic;
+ pDataStream->Seek( nOffset);
+ PicRead( pDataStream, &aPic, bVer67);
+
+ if((aPic.lcb > 0x3A) && !pDataStream->GetError() )
+ {
+ aFormula.FormulaRead(nWhich,pDataStream);
+ bRet = true;
+ }
+
+ /*
+ There is a problem with aPic, the WW8_PIC is always used even though it
+ is too big for the WW95 files, it needs to be modified to check the
+ version C.
+ */
+ pDataStream->Seek( nOldPos );
+ return(bRet);
+}
+
+sal_Bool SwMSConvertControls::InsertFormula(WW8FormulaControl &rFormula)
+{
+ sal_Bool bRet = sal_False;
+
+ const uno::Reference< lang::XMultiServiceFactory > & rServiceFactory =
+ GetServiceFactory();
+
+ if(!rServiceFactory.is())
+ return sal_False;
+
+ awt::Size aSz;
+ uno::Reference< form::XFormComponent> xFComp;
+
+ if (sal_True == (bRet = rFormula.Import(rServiceFactory, xFComp, aSz)))
+ {
+ uno::Reference <drawing::XShape> xShapeRef;
+ if (sal_True == (bRet = InsertControl(xFComp, aSz, &xShapeRef, false)))
+ GetShapes()->add(xShapeRef);
+ }
+ return bRet;
+}
+
+void WW8FormulaControl::FormulaRead(SwWw8ControlType nWhich,
+ SvStream *pDataStream)
+{
+ sal_uInt8 nField;
+ sal_uInt8 nHeaderByte;
+
+ int nType=0;
+ *pDataStream >> nHeaderByte;
+ if (nHeaderByte == 0xFF) //Guesswork time, difference between 97 and 95 ?
+ {
+ pDataStream->SeekRel(3);
+ *pDataStream >> nHeaderByte;
+ nType=1;
+ }
+ fUnknown = nHeaderByte & 0x3;
+ fDropdownIndex = (nHeaderByte & 0x7C) >> 2;
+ *pDataStream >> nField;
+ fToolTip = nField & 0x01;
+ fNoMark = (nField & 0x02)>>1;
+ fUseSize = (nField & 0x04)>>2;
+ fNumbersOnly= (nField & 0x08)>>3;
+ fDateOnly = (nField & 0x10)>>4;
+ fUnused = (nField & 0xE0)>>5;
+ *pDataStream >> nSize;
+
+ *pDataStream >> hpsCheckBox;
+ if (nType == 0)
+ pDataStream->SeekRel(2); //Guess
+
+ rtl_TextEncoding eEnc = rRdr.eStructCharSet;
+ sTitle = !nType ? WW8ReadPString(*pDataStream, eEnc, true)
+ : WW8Read_xstz(*pDataStream, 0, true);
+
+ if (nWhich == WW8_CT_CHECKBOX)
+ {
+ *pDataStream >> nDefaultChecked;
+ nChecked = nDefaultChecked;
+
+ sal_uInt8 iRes = (nHeaderByte >> 2) & 0x1F;
+ switch (iRes)
+ {
+ case 1: //checked
+ nChecked = true;
+ break;
+ case 25: //undefined, Undefined checkboxes are treated as unchecked
+ //but it appear that both visually and the value are picked up from the default in that case
+ break;
+ case 0: //unchecked
+ nChecked = false;
+ break;
+ default:
+ OSL_ENSURE(!this, "unknown option, please report to cmc");
+ break;
+ }
+ if ( nDefaultChecked )
+ sDefault = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("1") );
+ else
+ sDefault = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("0") );
+ }
+ else if (nWhich == WW8_CT_DROPDOWN)
+ *pDataStream >> nChecked;
+ else
+ {
+ sDefault = !nType ? WW8ReadPString(*pDataStream, eEnc, true)
+ : WW8Read_xstz(*pDataStream, 0, true);
+ }
+
+ sFormatting = !nType ? WW8ReadPString(*pDataStream, eEnc, true)
+ : WW8Read_xstz(*pDataStream, 0, true);
+
+ sHelp = !nType ? WW8ReadPString(*pDataStream, eEnc, true)
+ : WW8Read_xstz(*pDataStream, 0, true);
+
+ if (nWhich == WW8_CT_DROPDOWN) //is this the case ?
+ fToolTip = true;
+
+ if( fToolTip )
+ {
+ sToolTip = !nType ? WW8ReadPString(*pDataStream, eEnc, true)
+ : WW8Read_xstz(*pDataStream, 0, true);
+ }
+
+ if (nWhich == WW8_CT_DROPDOWN)
+ {
+ bool bAllOk = true;
+ pDataStream->SeekRel(4 * (nType ? 2 : 1));
+ sal_uInt16 nDummy;
+ *pDataStream >> nDummy;
+ sal_uInt32 nNoStrings;
+ if (!nType)
+ {
+ sal_uInt16 nWord95NoStrings;
+ *pDataStream >> nWord95NoStrings;
+ nNoStrings = nWord95NoStrings;
+ *pDataStream >> nWord95NoStrings;
+ if (nNoStrings != nWord95NoStrings)
+ bAllOk = false;
+ nNoStrings = nWord95NoStrings;
+ sal_uInt16 nDummy2;
+ *pDataStream >> nDummy2;
+ if (nDummy2 != 0)
+ bAllOk = false;
+ *pDataStream >> nDummy2;
+ if (nDummy2 != 0xA)
+ bAllOk = false;
+ if (!bAllOk) //Not as expected, don't risk it at all.
+ nNoStrings = 0;
+ for (sal_uInt16 nI = 0; nI < nNoStrings; ++nI)
+ pDataStream->SeekRel(2);
+ }
+ else
+ {
+ if (nDummy != 0xFFFF)
+ bAllOk = false;
+ *pDataStream >> nNoStrings;
+ }
+ OSL_ENSURE(bAllOk,
+ "Unknown formfield dropdown list structure. Report to cmc");
+ if (!bAllOk) //Not as expected, don't risk it at all.
+ nNoStrings = 0;
+ maListEntries.reserve(nNoStrings);
+ for (sal_uInt32 nI = 0; nI < nNoStrings; ++nI)
+ {
+ String sEntry = !nType ? WW8ReadPString(*pDataStream, eEnc, false)
+ : WW8Read_xstz(*pDataStream, 0, false);
+ maListEntries.push_back(sEntry);
+ }
+ }
+}
+
+WW8FormulaListBox::WW8FormulaListBox(SwWW8ImplReader &rR)
+ : WW8FormulaControl( CREATE_CONST_ASC(SL::aListBox), rR)
+{
+}
+
+//Miserable hack to get a hardcoded guesstimate of the size of a list dropdown
+//box's first entry to set as the lists default size
+awt::Size SwWW8ImplReader::MiserableDropDownFormHack(const String &rString,
+ uno::Reference<beans::XPropertySet>& rPropSet)
+{
+ awt::Size aRet;
+ struct CtrlFontMapEntry
+ {
+ sal_uInt16 nWhichId;
+ const sal_Char* pPropNm;
+ };
+ const CtrlFontMapEntry aMapTable[] =
+ {
+ { RES_CHRATR_COLOR, "TextColor" },
+ { RES_CHRATR_FONT, "FontName" },
+ { RES_CHRATR_FONTSIZE, "FontHeight" },
+ { RES_CHRATR_WEIGHT, "FontWeight" },
+ { RES_CHRATR_UNDERLINE, "FontUnderline" },
+ { RES_CHRATR_CROSSEDOUT, "FontStrikeout" },
+ { RES_CHRATR_POSTURE, "FontSlant" },
+ { 0, 0 }
+ };
+
+ Font aFont;
+ uno::Reference< beans::XPropertySetInfo > xPropSetInfo =
+ rPropSet->getPropertySetInfo();
+
+ uno::Any aTmp;
+ for (const CtrlFontMapEntry* pMap = aMapTable; pMap->nWhichId; ++pMap)
+ {
+ bool bSet = true;
+ const SfxPoolItem* pItem = GetFmtAttr( pMap->nWhichId );
+ OSL_ENSURE(pItem, "Impossible");
+ if (!pItem)
+ continue;
+
+ switch ( pMap->nWhichId )
+ {
+ case RES_CHRATR_COLOR:
+ {
+ String pNm;
+ if (xPropSetInfo->hasPropertyByName(pNm = C2U("TextColor")))
+ {
+ aTmp <<= (sal_Int32)((SvxColorItem*)pItem)->GetValue().GetColor();
+ rPropSet->setPropertyValue(pNm, aTmp);
+ }
+ }
+ aFont.SetColor(((SvxColorItem*)pItem)->GetValue());
+ break;
+ case RES_CHRATR_FONT:
+ {
+ const SvxFontItem *pFontItem = (SvxFontItem *)pItem;
+ String pNm;
+ if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontStyleName")))
+ {
+ aTmp <<= rtl::OUString( pFontItem->GetStyleName());
+ rPropSet->setPropertyValue( pNm, aTmp );
+ }
+ if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontFamily")))
+ {
+ aTmp <<= (sal_Int16)pFontItem->GetFamily();
+ rPropSet->setPropertyValue( pNm, aTmp );
+ }
+ if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontCharset")))
+ {
+ aTmp <<= (sal_Int16)pFontItem->GetCharSet();
+ rPropSet->setPropertyValue( pNm, aTmp );
+ }
+ if (xPropSetInfo->hasPropertyByName(pNm = C2U("FontPitch")))
+ {
+ aTmp <<= (sal_Int16)pFontItem->GetPitch();
+ rPropSet->setPropertyValue( pNm, aTmp );
+ }
+
+ aTmp <<= rtl::OUString( pFontItem->GetFamilyName());
+ aFont.SetName( pFontItem->GetFamilyName() );
+ aFont.SetStyleName( pFontItem->GetStyleName() );
+ aFont.SetFamily( pFontItem->GetFamily() );
+ aFont.SetCharSet( pFontItem->GetCharSet() );
+ aFont.SetPitch( pFontItem->GetPitch() );
+ }
+ break;
+
+ case RES_CHRATR_FONTSIZE:
+ {
+ Size aSize( aFont.GetSize().Width(),
+ ((SvxFontHeightItem*)pItem)->GetHeight() );
+ aTmp <<= ((float)aSize.Height()) / 20.0;
+
+ aFont.SetSize(OutputDevice::LogicToLogic(aSize, MAP_TWIP,
+ MAP_100TH_MM));
+ }
+ break;
+
+ case RES_CHRATR_WEIGHT:
+ aTmp <<= (float)VCLUnoHelper::ConvertFontWeight(
+ ((SvxWeightItem*)pItem)->GetWeight() );
+ aFont.SetWeight( ((SvxWeightItem*)pItem)->GetWeight() );
+ break;
+
+ case RES_CHRATR_UNDERLINE:
+ aTmp <<= (sal_Int16)(((SvxUnderlineItem*)pItem)->GetLineStyle());
+ aFont.SetUnderline(((SvxUnderlineItem*)pItem)->GetLineStyle());
+ break;
+
+ case RES_CHRATR_CROSSEDOUT:
+ aTmp <<= (sal_Int16)( ((SvxCrossedOutItem*)pItem)->GetStrikeout() );
+ aFont.SetStrikeout( ((SvxCrossedOutItem*)pItem)->GetStrikeout() );
+ break;
+
+ case RES_CHRATR_POSTURE:
+ aTmp <<= (sal_Int16)( ((SvxPostureItem*)pItem)->GetPosture() );
+ aFont.SetItalic( ((SvxPostureItem*)pItem)->GetPosture() );
+ break;
+
+ default:
+ bSet = false;
+ break;
+ }
+
+ if (bSet && xPropSetInfo->hasPropertyByName(rtl::OUString::createFromAscii(pMap->pPropNm)))
+ rPropSet->setPropertyValue(rtl::OUString::createFromAscii(pMap->pPropNm), aTmp);
+ }
+ // now calculate the size of the control
+ OutputDevice* pOut = Application::GetDefaultDevice();
+ OSL_ENSURE(pOut, "Impossible");
+ if (pOut)
+ {
+ pOut->Push( PUSH_FONT | PUSH_MAPMODE );
+ pOut->SetMapMode( MapMode( MAP_100TH_MM ));
+ pOut->SetFont( aFont );
+ aRet.Width = pOut->GetTextWidth(rString);
+ aRet.Width += 500; //plus size of button, total hack territory
+ aRet.Height = pOut->GetTextHeight();
+ pOut->Pop();
+ }
+ return aRet;
+}
+
+sal_Bool WW8FormulaListBox::Import(const uno::Reference <
+ lang::XMultiServiceFactory> &rServiceFactory,
+ uno::Reference <form::XFormComponent> &rFComp,awt::Size &rSz )
+{
+ uno::Reference<uno::XInterface> xCreate = rServiceFactory->createInstance(
+ C2U("com.sun.star.form.component.ComboBox"));
+ if( !xCreate.is() )
+ return sal_False;
+
+ rFComp = uno::Reference<form::XFormComponent>(xCreate, uno::UNO_QUERY);
+ if( !rFComp.is() )
+ return sal_False;
+
+ uno::Reference<beans::XPropertySet> xPropSet(xCreate, uno::UNO_QUERY);
+
+ uno::Any aTmp;
+ if (sTitle.Len())
+ aTmp <<= rtl::OUString(sTitle);
+ else
+ aTmp <<= rtl::OUString(sName);
+ xPropSet->setPropertyValue(C2U("Name"), aTmp );
+
+ if (sToolTip.Len())
+ {
+ aTmp <<= rtl::OUString(sToolTip);
+ xPropSet->setPropertyValue(C2U("HelpText"), aTmp );
+ }
+
+ sal_Bool bDropDown(sal_True);
+ xPropSet->setPropertyValue(C2U("Dropdown"), cppu::bool2any(bDropDown));
+
+ if (!maListEntries.empty())
+ {
+ sal_uInt32 nLen = maListEntries.size();
+ uno::Sequence< ::rtl::OUString > aListSource(nLen);
+ for (sal_uInt32 nI = 0; nI < nLen; ++nI)
+ aListSource[nI] = rtl::OUString(maListEntries[nI]);
+ aTmp <<= aListSource;
+ xPropSet->setPropertyValue(C2U("StringItemList"), aTmp );
+
+ aTmp <<= aListSource[0];
+ xPropSet->setPropertyValue(C2U("DefaultText"), aTmp );
+
+ rSz = rRdr.MiserableDropDownFormHack(maListEntries[0], xPropSet);
+ }
+ else
+ {
+ static const sal_Unicode aBlank[] =
+ {
+ 0x2002,0x2002,0x2002,0x2002,0x2002
+ };
+ rSz = rRdr.MiserableDropDownFormHack(String(aBlank), xPropSet);
+ }
+
+ return sal_True;
+}
+
+WW8FormulaCheckBox::WW8FormulaCheckBox(SwWW8ImplReader &rR)
+ : WW8FormulaControl( CREATE_CONST_ASC(SL::aCheckBox), rR)
+{
+}
+
+static void lcl_AddToPropertyContainer
+(uno::Reference<beans::XPropertySet> xPropSet,
+ const rtl::OUString & rPropertyName, const rtl::OUString & rValue)
+{
+ uno::Reference<beans::XPropertySetInfo> xPropSetInfo =
+ xPropSet->getPropertySetInfo();
+ if (xPropSetInfo.is() &&
+ ! xPropSetInfo->hasPropertyByName(rPropertyName))
+ {
+ uno::Reference<beans::XPropertyContainer>
+ xPropContainer(xPropSet, uno::UNO_QUERY);
+ uno::Any aAny(C2U(""));
+ xPropContainer->addProperty
+ (rPropertyName,
+ static_cast<sal_Int16>(beans::PropertyAttribute::BOUND ||
+ beans::PropertyAttribute::REMOVABLE),
+ aAny);
+ }
+
+ uno::Any aAnyValue(rValue);
+ xPropSet->setPropertyValue(rPropertyName, aAnyValue );
+}
+
+sal_Bool WW8FormulaCheckBox::Import(const uno::Reference <
+ lang::XMultiServiceFactory> &rServiceFactory,
+ uno::Reference <form::XFormComponent> &rFComp,awt::Size &rSz )
+{
+ uno::Reference< uno::XInterface > xCreate = rServiceFactory->createInstance(
+ C2U("com.sun.star.form.component.CheckBox"));
+ if( !xCreate.is() )
+ return sal_False;
+
+ rFComp = uno::Reference< form::XFormComponent >( xCreate, uno::UNO_QUERY );
+ if( !rFComp.is() )
+ return sal_False;
+
+ uno::Reference< beans::XPropertySet > xPropSet( xCreate, uno::UNO_QUERY );
+
+ rSz.Width = 16 * hpsCheckBox;
+ rSz.Height = 16 * hpsCheckBox;
+
+ uno::Any aTmp;
+ if (sTitle.Len())
+ aTmp <<= rtl::OUString(sTitle);
+ else
+ aTmp <<= rtl::OUString(sName);
+ xPropSet->setPropertyValue(C2U("Name"), aTmp );
+
+ aTmp <<= (sal_Int16)nChecked;
+ xPropSet->setPropertyValue(C2U("DefaultState"), aTmp);
+
+ if( sToolTip.Len() )
+ lcl_AddToPropertyContainer(xPropSet, C2U("HelpText"), sToolTip);
+
+ if( sHelp.Len() )
+ lcl_AddToPropertyContainer(xPropSet, C2U("HelpF1Text"), sHelp);
+
+ return sal_True;
+
+}
+
+WW8FormulaEditBox::WW8FormulaEditBox(SwWW8ImplReader &rR)
+ : WW8FormulaControl( CREATE_CONST_ASC(SL::aTextField) ,rR)
+{
+}
+
+sal_Bool SwMSConvertControls::InsertControl(
+ const uno::Reference< form::XFormComponent > & rFComp,
+ const awt::Size& rSize, uno::Reference< drawing::XShape > *pShape,
+ sal_Bool bFloatingCtrl)
+{
+ const uno::Reference< container::XIndexContainer > &rComps = GetFormComps();
+ uno::Any aTmp( &rFComp, ::getCppuType((const uno::Reference<
+ form::XFormComponent >*)0) );
+ rComps->insertByIndex( rComps->getCount(), aTmp );
+
+ const uno::Reference< lang::XMultiServiceFactory > &rServiceFactory =
+ GetServiceFactory();
+ if( !rServiceFactory.is() )
+ return sal_False;
+
+ uno::Reference< uno::XInterface > xCreate = rServiceFactory->createInstance(
+ C2U("com.sun.star.drawing.ControlShape"));
+ if( !xCreate.is() )
+ return sal_False;
+
+ uno::Reference< drawing::XShape > xShape =
+ uno::Reference< drawing::XShape >(xCreate, uno::UNO_QUERY);
+
+ DBG_ASSERT(xShape.is(), "XShape nicht erhalten");
+ xShape->setSize(rSize);
+
+ uno::Reference< beans::XPropertySet > xShapePropSet(
+ xCreate, uno::UNO_QUERY );
+
+ //I lay a small bet that this will change to
+ //sal_Int16 nTemp=TextContentAnchorType::AS_CHARACTER;
+ sal_Int16 nTemp;
+ if (bFloatingCtrl)
+ nTemp= text::TextContentAnchorType_AT_PARAGRAPH;
+ else
+ nTemp= text::TextContentAnchorType_AS_CHARACTER;
+
+ aTmp <<= nTemp;
+ xShapePropSet->setPropertyValue(C2U("AnchorType"), aTmp );
+
+ nTemp= text::VertOrientation::TOP;
+ aTmp <<= nTemp;
+ xShapePropSet->setPropertyValue(C2U("VertOrient"), aTmp );
+
+ uno::Reference< text::XText > xDummyTxtRef;
+ uno::Reference< text::XTextRange > xTxtRg =
+ new SwXTextRange( *pPaM, xDummyTxtRef );
+
+ aTmp.setValue(&xTxtRg,::getCppuType((
+ uno::Reference< text::XTextRange >*)0));
+ xShapePropSet->setPropertyValue(C2U("TextRange"), aTmp );
+
+ // Das Control-Model am Control-Shape setzen
+ uno::Reference< drawing::XControlShape > xControlShape( xShape,
+ uno::UNO_QUERY );
+ uno::Reference< awt::XControlModel > xControlModel( rFComp,
+ uno::UNO_QUERY );
+ xControlShape->setControl( xControlModel );
+
+ if (pShape)
+ *pShape = xShape;
+
+ return sal_True;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par4.cxx b/sw/source/filter/ww8/ww8par4.cxx
new file mode 100644
index 000000000000..cd91a87d1f08
--- /dev/null
+++ b/sw/source/filter/ww8/ww8par4.cxx
@@ -0,0 +1,572 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <doc.hxx>
+#include "writerhelper.hxx"
+#include <com/sun/star/embed/XClassifiedObject.hpp>
+
+#include <algorithm>
+#include <functional>
+#include <osl/endian.h>
+#include <sot/storage.hxx>
+#include <com/sun/star/drawing/XShape.hpp>
+#include <hintids.hxx>
+#include <svx/svdoole2.hxx>
+#include <filter/msfilter/msdffimp.hxx>
+#include <svx/unoapi.hxx>
+#include <filter/msfilter/msocximex.hxx>
+
+#include <sot/exchange.hxx>
+#include <swtypes.hxx>
+#include <fmtanchr.hxx>
+#include <fmtcntnt.hxx>
+#include <dcontact.hxx>
+#include <frmfmt.hxx>
+#include <pam.hxx>
+#include <ndgrf.hxx>
+#include <docsh.hxx> // fuer Ole-Node
+#include <mdiexp.hxx> // Progress
+#include <redline.hxx>
+#include <fltshell.hxx>
+#include <unodraw.hxx>
+#include <shellio.hxx>
+#include <ndole.hxx>
+
+#include <svtools/filter.hxx>
+
+#include "ww8scan.hxx"
+#include "ww8par.hxx"
+#include "ww8par2.hxx" // WWFlyPara::BoxUpWidth()
+
+struct OLE_MFP
+{
+ sal_Int16 mm; // 0x6 int
+ sal_Int16 xExt; // 0x8 int in 1/100 mm
+ sal_Int16 yExt; // 0xa int in 1/100 mm
+ sal_Int16 hMF; // 0xc int
+};
+
+using namespace ::com::sun::star;
+
+SV_IMPL_OP_PTRARR_SORT(WW8OleMaps, WW8OleMap_Ptr)
+
+static bool SwWw8ReadScaling(long& rX, long& rY, SvStorageRef& rSrc1)
+{
+ // Skalierungsfaktoren holen:
+ // Informationen in PIC-Stream ( durch ausprobieren )
+ // 0x0 (l)cb
+ // 0x08 .. 0x0a Flags ??
+ // 0x08 Inh: 1 / 0
+ // 0x09 Inh: 0,8,0x18
+ // 0x0a Inh: immer 8, MAP_ANISOTROPIC ???
+ // 0x0b Inh: immer 0
+ // 0x0c, 0x10 Originalgroesse x,y in 1/100 mm
+ // 0x14, 0x16 Originalgroesse x,y in tw
+ // 0x2c, 0x30 Skalierung x,y in Promille
+ // 0x34, 0x38, 0x3c, 0x40 Crop Left, Top, Right, Bot in tw
+
+ SvStorageStreamRef xSrc3 = rSrc1->OpenSotStream( CREATE_CONST_ASC( "\3PIC" ),
+ STREAM_STD_READ | STREAM_NOCREATE);
+ SvStorageStream* pS = xSrc3;
+ pS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ pS->Seek( STREAM_SEEK_TO_END );
+
+ OSL_ENSURE( pS->Tell() >= 76, "+OLE-PIC-Stream is shorter than 76 Byte" );
+
+ sal_Int32 nOrgWidth,
+ nOrgHeight,
+ nScaleX,
+ nScaleY,
+ nCropLeft,
+ nCropTop,
+ nCropRight,
+ nCropBottom;
+ pS->Seek( 0x14 );
+ *pS >> nOrgWidth // Original Size in 1/100 mm
+ >> nOrgHeight;
+ pS->Seek( 0x2c );
+ *pS >> nScaleX // Scaling in Promille
+ >> nScaleY
+ >> nCropLeft // Cropping in 1/100 mm
+ >> nCropTop
+ >> nCropRight
+ >> nCropBottom;
+
+ rX = nOrgWidth - nCropLeft - nCropRight;
+ rY = nOrgHeight - nCropTop - nCropBottom;
+ if (10 > nScaleX || 65536 < nScaleX || 10 > nScaleY || 65536 < nScaleY)
+ {
+ OSL_ENSURE( !pS, "+OLE-Scalinginformation in PIC-Stream wrong" );
+ return false;
+ }
+ else
+ {
+ rX = (rX * nScaleX) / 1000;
+ rY = (rY * nScaleY) / 1000;
+ }
+ return true;
+}
+
+static bool SwWw6ReadMetaStream(GDIMetaFile& rWMF, OLE_MFP* pMfp,
+ SvStorageRef& rSrc1)
+{
+ SvStorageStreamRef xSrc2 = rSrc1->OpenSotStream( CREATE_CONST_ASC("\3META"),
+ STREAM_STD_READ | STREAM_NOCREATE);
+ SvStorageStream* pSt = xSrc2;
+ pSt->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ sal_uLong nRead = pSt->Read( pMfp, sizeof(*pMfp ) );
+ // Mini-Placable-Header lesen
+ if (nRead != sizeof(*pMfp))
+ return false;
+
+#if defined OSL_BIGENDIAN
+ pMfp->mm = SWAPSHORT( pMfp->mm );
+ pMfp->xExt = SWAPSHORT( pMfp->xExt );
+ pMfp->yExt = SWAPSHORT( pMfp->yExt );
+#endif // OSL_BIGENDIAN
+
+ if( pMfp->mm == 94 || pMfp->mm == 99 )
+ {
+ OSL_ENSURE( !pSt, "+OLE: Falscher Metafile-Typ" );
+ return false;
+ }
+ if( pMfp->mm != 8 )
+ {
+ OSL_ENSURE( !pSt, "+OLE: Falscher Metafile-Typ ( nicht Anisotropic )" );
+ }
+ if( !pMfp->xExt || !pMfp->yExt )
+ {
+ OSL_ENSURE( !pSt, "+OLE: Groesse von 0 ???" );
+ return false;
+ }
+ bool bOk = ReadWindowMetafile( *pSt, rWMF, NULL ) ? true : false; // WMF lesen
+ // *pSt >> aWMF geht nicht ohne placable Header
+ if (!bOk || pSt->GetError() || rWMF.GetActionCount() == 0)
+ {
+ OSL_ENSURE( !pSt, "+OLE: Konnte Metafile nicht lesen" );
+ return false;
+ }
+
+ rWMF.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
+
+
+ // MetaFile auf neue Groesse skalieren und
+ // neue Groesse am MetaFile setzen
+ Size aOldSiz( rWMF.GetPrefSize() );
+ Size aNewSiz( pMfp->xExt, pMfp->yExt );
+ Fraction aFracX( aNewSiz.Width(), aOldSiz.Width() );
+ Fraction aFracY( aNewSiz.Height(), aOldSiz.Height() );
+
+ rWMF.Scale( aFracX, aFracY );
+ rWMF.SetPrefSize( aNewSiz );
+
+ return true;
+}
+
+static bool SwWw6ReadMacPICTStream(Graphic& rGraph, SvStorageRef& rSrc1)
+{
+ // 03-META-Stream nicht da. Vielleicht ein 03-PICT ?
+ SvStorageStreamRef xSrc4 = rSrc1->OpenSotStream( CREATE_CONST_ASC( "\3PICT" ));
+ SvStorageStream* pStp = xSrc4;
+ pStp->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
+ sal_uInt8 aTestA[10]; // Ist der 01Ole-Stream ueberhaupt vorhanden
+ sal_uLong nReadTst = pStp->Read( aTestA, sizeof( aTestA ) );
+ if (nReadTst != sizeof(aTestA))
+ return false;
+
+ pStp->Seek( STREAM_SEEK_TO_BEGIN );
+
+ // Mac-Pict steht im 03PICT-StorageStream allerdings ohne die ersten 512
+ // Bytes, die bei einem MAC-PICT egal sind ( werden nicht ausgewertet )
+ return SwWW8ImplReader::GetPictGrafFromStream(rGraph, *pStp);
+}
+
+SwFlyFrmFmt* SwWW8ImplReader::InsertOle(SdrOle2Obj &rObject,
+ const SfxItemSet &rFlySet, const SfxItemSet &rGrfSet)
+{
+ SfxObjectShell *pPersist = rDoc.GetPersist();
+ OSL_ENSURE(pPersist, "No persist, cannot insert objects correctly");
+ if (!pPersist)
+ return 0;
+
+ SwFlyFrmFmt *pRet = 0;
+
+ SfxItemSet *pMathFlySet = 0;
+ uno::Reference < embed::XClassifiedObject > xClass( rObject.GetObjRef(), uno::UNO_QUERY );
+ if( xClass.is() )
+ {
+ SvGlobalName aClassName( xClass->getClassID() );
+ if (SotExchange::IsMath(aClassName))
+ {
+ /*
+ StarMath sets it own fixed size, so its counter productive to use the
+ size word says it is. i.e. Don't attempt to override its size.
+ */
+ pMathFlySet = new SfxItemSet(rFlySet);
+ pMathFlySet->ClearItem(RES_FRM_SIZE);
+ }
+ }
+
+ /*
+ Take complete responsibility of the object away from SdrOle2Obj and to
+ me here locally. This utility class now owns the object.
+ */
+
+ // TODO/MBA: is the object inserted multiple times here? Testing!
+ // And is it a problem that we now use the same naming scheme as in the other apps?
+ sw::hack::DrawingOLEAdaptor aOLEObj(rObject, *pPersist);
+ ::rtl::OUString sNewName;
+ bool bSuccess = aOLEObj.TransferToDoc(sNewName);
+
+ OSL_ENSURE(bSuccess, "Insert OLE failed");
+ if (bSuccess)
+ {
+ const SfxItemSet *pFlySet = pMathFlySet ? pMathFlySet : &rFlySet;
+ pRet = rDoc.InsertOLE(*pPaM, sNewName, rObject.GetAspect(), pFlySet, &rGrfSet, 0);
+ }
+ delete pMathFlySet;
+ return pRet;
+}
+
+SwFrmFmt* SwWW8ImplReader::ImportOle(const Graphic* pGrf,
+ const SfxItemSet* pFlySet, const SfxItemSet *pGrfSet, const Rectangle& aVisArea )
+{
+ ::SetProgressState(nProgress, mpDocShell); // Update
+ SwFrmFmt* pFmt = 0;
+
+ GrafikCtor();
+
+ Graphic aGraph;
+ SdrObject* pRet = ImportOleBase(aGraph, pGrf, pFlySet, aVisArea );
+
+ // create flyset
+ SfxItemSet* pTempSet = 0;
+ if( !pFlySet )
+ {
+ pTempSet = new SfxItemSet( rDoc.GetAttrPool(), RES_FRMATR_BEGIN,
+ RES_FRMATR_END-1);
+
+ pFlySet = pTempSet;
+
+ // Abstand/Umrandung raus
+ if (!mbNewDoc)
+ Reader::ResetFrmFmtAttrs( *pTempSet );
+
+ SwFmtAnchor aAnchor( FLY_AS_CHAR );
+ aAnchor.SetAnchor( pPaM->GetPoint() );
+ pTempSet->Put( aAnchor );
+
+ const Size aSizeTwip = OutputDevice::LogicToLogic(
+ aGraph.GetPrefSize(), aGraph.GetPrefMapMode(), MAP_TWIP );
+
+ pTempSet->Put( SwFmtFrmSize( ATT_FIX_SIZE, aSizeTwip.Width(),
+ aSizeTwip.Height() ) );
+ pTempSet->Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
+
+ if( pSFlyPara )
+ {
+ // OLE im Rahmen ? ok, Rahmen auf Bildgroesse vergroessern (
+ // nur wenn Auto-Breite )
+ pSFlyPara->BoxUpWidth( aSizeTwip.Width() );
+ }
+ }
+
+ if (pRet) // Ole-Object wurde eingefuegt
+ {
+ if (pRet->ISA(SdrOle2Obj))
+ {
+ pFmt = InsertOle(*((SdrOle2Obj*)pRet), *pFlySet, *pGrfSet);
+ SdrObject::Free( pRet ); // das brauchen wir nicht mehr
+ }
+ else
+ pFmt = rDoc.Insert(*pPaM, *pRet, pFlySet, NULL);
+ }
+ else if (
+ GRAPHIC_GDIMETAFILE == aGraph.GetType() ||
+ GRAPHIC_BITMAP == aGraph.GetType()
+ )
+ {
+ pFmt = rDoc.Insert(*pPaM, aEmptyStr, aEmptyStr, &aGraph, pFlySet,
+ pGrfSet, NULL);
+ }
+ delete pTempSet;
+ return pFmt;
+}
+
+bool SwWW8ImplReader::ImportOleWMF(SvStorageRef xSrc1,GDIMetaFile &rWMF,
+ long &rX,long &rY)
+{
+ bool bOk = false;
+ OLE_MFP aMfp;
+ if( SwWw6ReadMetaStream( rWMF, &aMfp, xSrc1 ) )
+ {
+ /*
+ take scaling factor as found in PIC and apply it to graphic.
+ */
+ SwWw8ReadScaling( rX, rY, xSrc1 );
+ Size aFinalSize, aOrigSize;
+ aFinalSize.Width() = rX;
+ aFinalSize.Height() = rY;
+ aFinalSize = OutputDevice::LogicToLogic(
+ aFinalSize, MAP_TWIP, rWMF.GetPrefMapMode() );
+ aOrigSize = rWMF.GetPrefSize();
+ Fraction aScaleX(aFinalSize.Width(),aOrigSize.Width());
+ Fraction aScaleY(aFinalSize.Height(),aOrigSize.Height());
+ rWMF.Scale( aScaleX, aScaleY );
+ bOk = true;
+ }
+ return bOk;
+}
+
+SdrObject* SwWW8ImplReader::ImportOleBase( Graphic& rGraph,
+ const Graphic* pGrf, const SfxItemSet* pFlySet, const Rectangle& aVisArea )
+{
+ SdrObject* pRet = 0;
+ OSL_ENSURE( pStg, "ohne storage geht hier fast gar nichts!" );
+
+ ::SetProgressState( nProgress, rDoc.GetDocShell() ); // Update
+
+ long nX=0, nY=0; // nX, nY is graphic size
+ bool bOleOk = true;
+
+ String aSrcStgName = '_';
+ // ergibt Name "_4711"
+ aSrcStgName += String::CreateFromInt32( nObjLocFc );
+
+ SvStorageRef xSrc0 = pStg->OpenSotStorage(CREATE_CONST_ASC(SL::aObjectPool));
+ SvStorageRef xSrc1 = xSrc0->OpenSotStorage( aSrcStgName,
+ STREAM_READWRITE| STREAM_SHARE_DENYALL );
+
+
+ if (pGrf)
+ {
+ rGraph = *pGrf;
+ const Size aSizeTwip = OutputDevice::LogicToLogic(
+ rGraph.GetPrefSize(), rGraph.GetPrefMapMode(), MAP_TWIP );
+ nX = aSizeTwip.Width();
+ nY = aSizeTwip.Height();
+ }
+ else
+ {
+ GDIMetaFile aWMF;
+
+ if (ImportOleWMF(xSrc1,aWMF,nX,nY))
+ rGraph = Graphic( aWMF );
+ else if( SwWw6ReadMacPICTStream( rGraph, xSrc1 ) )
+ {
+ // 03-META-Stream nicht da. Vielleicht ein 03-PICT ?
+ const Size aSizeTwip = OutputDevice::LogicToLogic(
+ rGraph.GetPrefSize(), rGraph.GetPrefMapMode(), MAP_TWIP );
+ nX = aSizeTwip.Width();
+ nY = aSizeTwip.Height();
+ // PICT: kein WMF da -> Grafik statt OLE
+ bOleOk = false;
+ }
+ } // StorageStreams wieder zu
+
+
+ Rectangle aRect(0, 0, nX, nY);
+
+ if (pFlySet)
+ {
+ if (const SwFmtFrmSize* pSize =
+ (const SwFmtFrmSize*)pFlySet->GetItem(RES_FRM_SIZE, false))
+ {
+ aRect.SetSize(pSize->GetSize());
+ }
+ }
+
+ if (!(bIsHeader || bIsFooter))
+ {
+ //Can't put them in headers/footers :-(
+ uno::Reference< drawing::XShape > xRef;
+ OSL_ENSURE(pFormImpl, "Impossible");
+ if (pFormImpl && pFormImpl->ReadOCXStream(xSrc1, &xRef, false))
+ {
+ pRet = GetSdrObjectFromXShape(xRef);
+ OSL_ENSURE(pRet, "Impossible");
+ if (pRet)
+ pRet->SetLogicRect(aRect);
+ return pRet;
+ }
+ }
+
+ if (GRAPHIC_GDIMETAFILE == rGraph.GetType() ||
+ GRAPHIC_BITMAP == rGraph.GetType())
+ {
+ ::SetProgressState(nProgress, mpDocShell); // Update
+
+ if (bOleOk)
+ {
+ sal_uLong nOldPos = pDataStream->Tell();
+ pDataStream->Seek(STREAM_SEEK_TO_END);
+ SvStream *pTmpData = 0;
+ if (nObjLocFc < pDataStream->Tell())
+ {
+ pTmpData = pDataStream;
+ pTmpData->Seek( nObjLocFc );
+ }
+
+ sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
+
+ {
+ SvStorageStreamRef xObjInfoSrc = xSrc1->OpenSotStream( CREATE_CONST_ASC( "\3ObjInfo" ),
+ STREAM_STD_READ | STREAM_NOCREATE );
+ if ( xObjInfoSrc.Is() && !xObjInfoSrc->GetError() )
+ {
+ sal_uInt8 nByte = 0;
+ *xObjInfoSrc >> nByte;
+ if ( ( nByte >> 4 ) & embed::Aspects::MSOLE_ICON )
+ nAspect = embed::Aspects::MSOLE_ICON;
+ }
+ }
+
+ ErrCode nError = ERRCODE_NONE;
+ pRet = SvxMSDffManager::CreateSdrOLEFromStorage(
+ aSrcStgName, xSrc0, mpDocShell->GetStorage(), rGraph, aRect, aVisArea, pTmpData, nError,
+ SwMSDffManager::GetFilterFlags(), nAspect );
+ pDataStream->Seek( nOldPos );
+ }
+ }
+ return pRet;
+}
+
+void SwWW8ImplReader::ReadRevMarkAuthorStrTabl( SvStream& rStrm,
+ sal_Int32 nTblPos, sal_Int32 nTblSiz, SwDoc& rDocOut )
+{
+ ::std::vector<String> aAuthorNames;
+ WW8ReadSTTBF( !bVer67, rStrm, nTblPos, nTblSiz, bVer67 ? 2 : 0,
+ eStructCharSet, aAuthorNames );
+
+ sal_uInt16 nCount = static_cast< sal_uInt16 >(aAuthorNames.size());
+ for( sal_uInt16 nAuthor = 0; nAuthor < nCount; ++nAuthor )
+ {
+ // Store author in doc
+ sal_uInt16 nSWId = rDocOut.InsertRedlineAuthor(aAuthorNames[nAuthor]);
+ // Store matchpair
+ if( !pAuthorInfos )
+ pAuthorInfos = new sw::util::AuthorInfos;
+ sw::util::AuthorInfo* pAutorInfo = new sw::util::AuthorInfo( nAuthor, nSWId );
+ if( 0 == pAuthorInfos->Insert( pAutorInfo ) )
+ delete pAutorInfo;
+ }
+}
+
+/*
+ Revision Marks ( == Redlining )
+*/
+// insert or delete content (change char attributes resp.)
+void SwWW8ImplReader::Read_CRevisionMark(RedlineType_t eType,
+ const sal_uInt8* pData, short nLen )
+{
+ // there *must* be a SprmCIbstRMark[Del] and a SprmCDttmRMark[Del]
+ // pointing to the very same char position as our SprmCFRMark[Del]
+ if (!pPlcxMan)
+ return;
+ const sal_uInt8* pSprmCIbstRMark;
+ const sal_uInt8* pSprmCDttmRMark;
+ if( nsRedlineType_t::REDLINE_FORMAT == eType )
+ {
+ pSprmCIbstRMark = pData+1;
+ pSprmCDttmRMark = pData+3;
+ }
+ else
+ {
+ /*
+ It is possible to have a number of date stamps for the created time
+ of the change, (possibly a word bug) so we must use the "get a full
+ list" varient of HasCharSprm and take the last one as the true one.
+ */
+ std::vector<const sal_uInt8 *> aResult;
+ bool bIns = (nsRedlineType_t::REDLINE_INSERT == eType);
+ if( bVer67 )
+ {
+ pPlcxMan->HasCharSprm(69, aResult);
+ pSprmCIbstRMark = aResult.empty() ? 0 : aResult.back();
+ aResult.clear();
+ pPlcxMan->HasCharSprm(70, aResult);
+ pSprmCDttmRMark = aResult.empty() ? 0 : aResult.back();
+ }
+ else
+ {
+ pPlcxMan->HasCharSprm( bIns ? 0x4804 : 0x4863, aResult);
+ pSprmCIbstRMark = aResult.empty() ? 0 : aResult.back();
+ aResult.clear();
+ pPlcxMan->HasCharSprm( bIns ? 0x6805 : 0x6864, aResult);
+ pSprmCDttmRMark = aResult.empty() ? 0 : aResult.back();
+ }
+ }
+
+ if (nLen < 0)
+ mpRedlineStack->close(*pPaM->GetPoint(), eType, pTableDesc );
+ else
+ {
+ // start of new revision mark, if not there default to first entry
+ sal_uInt16 nWWAutNo = pSprmCIbstRMark ? SVBT16ToShort( pSprmCIbstRMark ) : 0;
+ sw::util::AuthorInfo aEntry(nWWAutNo);
+ sal_uInt16 nPos;
+ if (pAuthorInfos && pAuthorInfos->Seek_Entry(&aEntry, &nPos))
+ {
+ if (const sw::util::AuthorInfo* pAuthor = pAuthorInfos->GetObject(nPos))
+ {
+ sal_uInt32 nWWDate = pSprmCDttmRMark ? SVBT32ToUInt32(pSprmCDttmRMark): 0;
+ DateTime aStamp(sw::ms::DTTM2DateTime(nWWDate));
+ sal_uInt16 nAutorNo = pAuthor->nOurId;
+ SwFltRedline aNewAttr(eType, nAutorNo, aStamp);
+
+ NewAttr(aNewAttr);
+ }
+ }
+ }
+}
+
+// insert new content
+void SwWW8ImplReader::Read_CFRMark(sal_uInt16 , const sal_uInt8* pData, short nLen)
+{
+ Read_CRevisionMark( nsRedlineType_t::REDLINE_INSERT, pData, nLen );
+}
+
+// delete old content
+void SwWW8ImplReader::Read_CFRMarkDel(sal_uInt16 , const sal_uInt8* pData, short nLen)
+{
+ Read_CRevisionMark( nsRedlineType_t::REDLINE_DELETE, pData, nLen );
+}
+
+// change properties of content ( == char formating)
+void SwWW8ImplReader::Read_CPropRMark(sal_uInt16 , const sal_uInt8* pData, short nLen)
+{
+ // complex (len is always 7)
+ // 1 byte - chp.fPropRMark
+ // 2 bytes - chp.ibstPropRMark
+ // 4 bytes - chp.dttmPropRMark;
+ Read_CRevisionMark( nsRedlineType_t::REDLINE_FORMAT, pData, nLen );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par5.cxx b/sw/source/filter/ww8/ww8par5.cxx
new file mode 100644
index 000000000000..e8a1d22f06ce
--- /dev/null
+++ b/sw/source/filter/ww8/ww8par5.cxx
@@ -0,0 +1,3711 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+
+#include <ctype.h> // tolower
+#include <stdio.h> // sscanf()
+
+#include <sal/types.h>
+#include <tools/solar.h>
+
+#include <comphelper/storagehelper.hxx>
+#include <sot/storinfo.hxx>
+#include <com/sun/star/embed/XStorage.hpp>
+#include <com/sun/star/embed/ElementModes.hpp>
+#include <com/sun/star/embed/XTransactedObject.hpp>
+#include <com/sun/star/io/XStream.hpp>
+
+#include <com/sun/star/ucb/XCommandEnvironment.hpp>
+#include <svl/urihelper.hxx>
+#include <svl/zforlist.hxx>
+#include <svl/zformat.hxx>
+#include <sfx2/linkmgr.hxx>
+
+#include <ucbhelper/content.hxx>
+#include <ucbhelper/contentbroker.hxx>
+#include <ucbhelper/commandenvironment.hxx>
+
+#include <com/sun/star/i18n/ScriptType.hdl>
+#include <hintids.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/langitem.hxx>
+#include <fmtfld.hxx>
+#include <fmtanchr.hxx>
+#include <pam.hxx> // fuer SwPam
+#include <doc.hxx>
+#include <charatr.hxx> // class SwFmtFld
+#include <flddat.hxx> // class SwDateTimeField
+#include <docufld.hxx> // class SwPageNumberField
+#include <reffld.hxx> // class SwGetRefField
+#include <IMark.hxx>
+#include <expfld.hxx> // class SwSetExpField
+#include <dbfld.hxx> // class SwDBField
+#include <usrfld.hxx>
+#include <tox.hxx>
+#include <section.hxx> // class SwSection
+#include <ndtxt.hxx>
+#include <fmtinfmt.hxx>
+#include <chpfld.hxx>
+#include <ftnidx.hxx>
+#include <txtftn.hxx>
+#include <viewsh.hxx>
+#include <shellres.hxx>
+#include <fmtruby.hxx>
+#include <charfmt.hxx>
+#include <txtatr.hxx>
+#include <breakit.hxx>
+#include <fmtclds.hxx>
+#include <pagedesc.hxx>
+#include <SwStyleNameMapper.hxx>
+
+#include "ww8scan.hxx" // WW8FieldDesc
+#include "ww8par.hxx"
+#include "ww8par2.hxx"
+#include "writerhelper.hxx"
+#include "fields.hxx"
+#include <unotools/fltrcfg.hxx>
+#include <xmloff/odffields.hxx>
+
+#include <algorithm> // #i24377#
+
+//#define WW_NATIVE_TOC 0
+
+#define MAX_FIELDLEN 64000
+
+#define WW8_TOX_LEVEL_DELIM ':'
+
+using namespace ::com::sun::star;
+using namespace sw::util;
+using namespace sw::mark;
+using namespace std; // #i24377#
+using namespace nsSwDocInfoSubType;
+
+
+class _ReadFieldParams
+{
+private:
+ String aData;
+ xub_StrLen nLen, nFnd, nNext, nSavPtr;
+public:
+ _ReadFieldParams( const String& rData );
+ ~_ReadFieldParams();
+
+ xub_StrLen GoToTokenParam();
+ long SkipToNextToken();
+ xub_StrLen GetTokenSttPtr() const { return nFnd; }
+
+ xub_StrLen FindNextStringPiece( xub_StrLen _nStart = STRING_NOTFOUND );
+ bool GetTokenSttFromTo(xub_StrLen* _pFrom, xub_StrLen* _pTo,
+ xub_StrLen _nMax);
+
+ String GetResult() const;
+};
+
+
+_ReadFieldParams::_ReadFieldParams( const String& _rData )
+ : aData( _rData ), nLen( _rData.Len() ), nNext( 0 )
+{
+ /*
+ erstmal nach einer oeffnenden Klammer oder einer Leerstelle oder einem
+ Anfuehrungszeichen oder einem Backslash suchen, damit der Feldbefehl
+ (also INCLUDEPICTURE bzw EINFUeGENGRAFIK bzw ...) ueberlesen wird
+ */
+ while( (nLen > nNext) && (aData.GetChar( nNext ) == ' ') )
+ ++nNext;
+
+ sal_Unicode c;
+ while( nLen > nNext
+ && (c = aData.GetChar( nNext )) != ' '
+ && c != '"'
+ && c != '\\'
+ && c != 132
+ && c != 0x201c )
+ ++nNext;
+
+ nFnd = nNext;
+ nSavPtr = nNext;
+}
+
+
+_ReadFieldParams::~_ReadFieldParams()
+{
+
+}
+
+
+String _ReadFieldParams::GetResult() const
+{
+ return (STRING_NOTFOUND == nFnd)
+ ? aEmptyStr
+ : aData.Copy( nFnd, (nSavPtr - nFnd) );
+}
+
+
+xub_StrLen _ReadFieldParams::GoToTokenParam()
+{
+ xub_StrLen nOld = nNext;
+ if( -2 == SkipToNextToken() )
+ return GetTokenSttPtr();
+ nNext = nOld;
+ return STRING_NOTFOUND;
+}
+
+// ret: -2: NOT a '\' parameter but normal Text
+long _ReadFieldParams::SkipToNextToken()
+{
+ long nRet = -1; // Ende
+ if (
+ (STRING_NOTFOUND != nNext) && (nLen > nNext) &&
+ STRING_NOTFOUND != (nFnd = FindNextStringPiece(nNext))
+ )
+ {
+ nSavPtr = nNext;
+
+ if ('\\' == aData.GetChar(nFnd) && '\\' != aData.GetChar(nFnd + 1))
+ {
+ nRet = aData.GetChar(++nFnd);
+ nNext = ++nFnd; // und dahinter setzen
+ }
+ else
+ {
+ nRet = -2;
+ if (
+ (STRING_NOTFOUND != nSavPtr ) &&
+ (
+ ('"' == aData.GetChar(nSavPtr - 1)) ||
+ (0x201d == aData.GetChar(nSavPtr - 1))
+ )
+ )
+ {
+ --nSavPtr;
+ }
+ }
+ }
+ return nRet;
+}
+
+// FindNextPara sucht naechsten Backslash-Parameter oder naechste Zeichenkette
+// bis zum Blank oder naechsten "\" oder zum schliessenden Anfuehrungszeichen
+// oder zum String-Ende von pStr.
+//
+// Ausgabe ppNext (falls ppNext != 0) Suchbeginn fuer naechsten Parameter bzw. 0
+//
+// Returnwert: 0 falls String-Ende erreicht,
+// ansonsten Anfang des Paramters bzw. der Zeichenkette
+//
+xub_StrLen _ReadFieldParams::FindNextStringPiece(const xub_StrLen nStart)
+{
+ xub_StrLen n = ( STRING_NOTFOUND == nStart ) ? nFnd : nStart; // Anfang
+ xub_StrLen n2; // Ende
+
+ nNext = STRING_NOTFOUND; // Default fuer nicht gefunden
+
+ while( (nLen > n) && (aData.GetChar( n ) == ' ') )
+ ++n;
+
+ if ( aData.GetChar( n ) == 0x13 )
+ {
+ // Skip the nested field code since it's not supported
+ while ( ( nLen > n ) && ( aData.GetChar( n ) != 0x14 ) )
+ n++;
+ }
+
+ if( nLen == n )
+ return STRING_NOTFOUND; // String End reached!
+
+ if( (aData.GetChar( n ) == '"') // Anfuehrungszeichen vor Para?
+ || (aData.GetChar( n ) == 0x201c)
+ || (aData.GetChar( n ) == 132)
+ || (aData.GetChar( n ) == 0x14) )
+ {
+ n++; // Anfuehrungszeichen ueberlesen
+ n2 = n; // ab hier nach Ende suchen
+ while( (nLen > n2)
+ && (aData.GetChar( n2 ) != '"')
+ && (aData.GetChar( n2 ) != 0x201d)
+ && (aData.GetChar( n2 ) != 147)
+ && (aData.GetChar( n2 ) != 0x15) )
+ n2++; // Ende d. Paras suchen
+ }
+ else // keine Anfuehrungszeichen
+ {
+ n2 = n; // ab hier nach Ende suchen
+ while( (nLen > n2) && (aData.GetChar( n2 ) != ' ') ) // Ende d. Paras suchen
+ {
+ if( aData.GetChar( n2 ) == '\\' )
+ {
+ if( aData.GetChar( n2+1 ) == '\\' )
+ n2 += 2; // Doppel-Backslash -> OK
+ else
+ {
+ if( n2 > n )
+ n2--;
+ break; // einfach-Backslash -> Ende
+ }
+ }
+ else
+ n2++; // kein Backslash -> OK
+ }
+ }
+ if( nLen > n2 )
+ {
+ if(aData.GetChar( n2 ) != ' ') n2++;
+ nNext = n2;
+ }
+ return n;
+}
+
+
+
+// read parameters "1-3" or 1-3 with both values between 1 and nMax
+bool _ReadFieldParams::GetTokenSttFromTo(sal_uInt16* pFrom, sal_uInt16* pTo, sal_uInt16 nMax)
+{
+ sal_uInt16 nStart = 0;
+ sal_uInt16 nEnd = 0;
+ xub_StrLen n = GoToTokenParam();
+ if( STRING_NOTFOUND != n )
+ {
+
+ String sParams( GetResult() );
+
+ xub_StrLen nIndex = 0;
+ String sStart( sParams.GetToken(0, '-', nIndex) );
+ if( STRING_NOTFOUND != nIndex )
+ {
+ nStart = static_cast<sal_uInt16>(sStart.ToInt32());
+ nEnd = static_cast<sal_uInt16>(sParams.Copy(nIndex).ToInt32());
+ }
+ }
+ if( pFrom ) *pFrom = nStart;
+ if( pTo ) *pTo = nEnd;
+
+ return nStart && nEnd && (nMax >= nStart) && (nMax >= nEnd);
+}
+
+//----------------------------------------
+// Bookmarks
+//----------------------------------------
+
+long SwWW8ImplReader::Read_Book(WW8PLCFManResult*)
+{
+ // muesste auch ueber pRes.nCo2OrIdx gehen
+ WW8PLCFx_Book* pB = pPlcxMan->GetBook();
+ if( !pB )
+ {
+ OSL_ENSURE( pB, "WW8PLCFx_Book - Pointer nicht da" );
+ return 0;
+ }
+
+ eBookStatus eB = pB->GetStatus();
+ if (eB & BOOK_IGNORE)
+ return 0; // Bookmark zu ignorieren
+
+ if (pB->GetIsEnd())
+ {
+ pReffedStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_BOOKMARK, true,
+ pB->GetHandle(), (eB & BOOK_FIELD)!=0);
+ return 0;
+ }
+
+ //"_Toc*" and "_Hlt*" are unnecessary
+ const String* pName = pB->GetName();
+#if !defined(WW_NATIVE_TOC)
+ if( !pName || pName->EqualsIgnoreCaseAscii( "_Toc", 0, 4 )
+ || pName->EqualsIgnoreCaseAscii( "_Hlt", 0, 4 ) )
+ return 0;
+#endif
+
+ //ToUpper darf auf keinen Fall gemacht werden, weil der Bookmark- name ein Hyperlink-Ziel sein kann!
+
+ String aVal;
+ if( SwFltGetFlag( nFieldFlags, SwFltControlStack::BOOK_TO_VAR_REF ) )
+ {
+ // Fuer UEbersetzung Bookmark -> Variable setzen
+ long nLen = pB->GetLen();
+ if( nLen > MAX_FIELDLEN )
+ nLen = MAX_FIELDLEN;
+
+ long nOldPos = pStrm->Tell();
+ nLen = pSBase->WW8ReadString( *pStrm, aVal, pB->GetStartPos(), nLen,
+ eStructCharSet );
+ pStrm->Seek( nOldPos );
+
+ // now here the implementation of the old "QuoteString" and
+ // I hope with a better performance as before. It's also only
+ // needed if the filterflags say we will convert bookmarks
+ // to SetExpFields! And this the exception!
+
+ String sHex(CREATE_CONST_ASC( "\\x" ));
+ bool bSetAsHex;
+ bool bAllowCr = SwFltGetFlag(nFieldFlags,
+ SwFltControlStack::ALLOW_FLD_CR) ? true : false;
+
+ sal_Unicode cChar;
+
+ for( xub_StrLen nI = 0;
+ nI < aVal.Len() && aVal.Len() < (MAX_FIELDLEN - 4); ++nI )
+ {
+ switch( cChar = aVal.GetChar( nI ) )
+ {
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ if( bAllowCr )
+ aVal.SetChar( nI, '\n' ), bSetAsHex = false;
+ else
+ bSetAsHex = true;
+ break;
+
+ case 0xFE:
+ case 0xFF:
+ bSetAsHex = true;
+ break;
+
+ default:
+ bSetAsHex = 0x20 > cChar;
+ break;
+ }
+
+ if( bSetAsHex )
+ {
+ //all Hex-Numbers with \x before
+ String sTmp( sHex );
+ if( cChar < 0x10 )
+ sTmp += '0';
+ sTmp += String::CreateFromInt32( cChar, 16 );
+ aVal.Replace( nI, 1 , sTmp );
+ nI += sTmp.Len() - 1;
+ }
+ }
+
+ if( aVal.Len() > (MAX_FIELDLEN - 4))
+ aVal.Erase( MAX_FIELDLEN - 4 );
+ }
+
+ //e.g. inserting bookmark around field result, so we need to put
+ //it around the entire writer field, as we don't have the seperation
+ //of field and field result of word, see #i16941#
+ SwPosition aStart(*pPaM->GetPoint());
+ if (!maFieldStack.empty())
+ {
+ const FieldEntry &rTest = maFieldStack.back();
+ aStart = rTest.maStartPos;
+ }
+
+ pReffedStck->NewAttr(aStart, SwFltBookmark(BookmarkToWriter(*pName), aVal,
+ pB->GetHandle(), 0));
+ return 0;
+}
+
+//----------------------------------------------------------------------
+// allgemeine Hilfsroutinen zum Auseinanderdroeseln der Parameter
+//----------------------------------------------------------------------
+
+// ConvertFFileName uebersetzt FeldParameter-Namen u. ae. in den
+// System-Zeichensatz.
+// Gleichzeitig werden doppelte Backslashes in einzelne uebersetzt.
+void SwWW8ImplReader::ConvertFFileName( String& rName, const String& rOrg )
+{
+ rName = rOrg;
+ rName.SearchAndReplaceAllAscii( "\\\\", String( '\\' ));
+ rName.SearchAndReplaceAllAscii( "%20", String( ' ' ));
+
+ // ggfs. anhaengende Anfuehrungszeichen entfernen
+ if( rName.Len() && '"' == rName.GetChar( rName.Len()-1 ))
+ rName.Erase( rName.Len()-1, 1);
+
+ // Need the more sophisticated url converter. cmc
+ if (rName.Len())
+ rName = URIHelper::SmartRel2Abs(
+ INetURLObject(sBaseURL), rName, Link(), false);
+}
+
+// ConvertUFNneme uebersetzt FeldParameter-Namen u. ae. in den
+// System-Zeichensatz und Upcased sie ( z.B. fuer Ref-Felder )
+namespace
+{
+ void ConvertUFName( String& rName )
+ {
+ GetAppCharClass().toUpper( rName );
+ }
+}
+
+static void lcl_ConvertSequenceName(String& rSequenceName)
+{
+ ConvertUFName(rSequenceName);
+ if ('0' <= rSequenceName.GetChar(0) && '9' >= rSequenceName.GetChar(0))
+ rSequenceName.Insert('_', 0);
+}
+
+// FindParaStart() finds 1st Parameter that follows '\' and cToken
+// and returns start of this parameter or STRING_NOT_FOUND.
+xub_StrLen FindParaStart( const String& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
+{
+ bool bStr = false; // innerhalb String ignorieren
+
+ for( xub_StrLen nBuf=0; nBuf+1 < rStr.Len(); nBuf++ )
+ {
+ if( rStr.GetChar( nBuf ) == '"' )
+ bStr = !bStr;
+
+ if( !bStr
+ && rStr.GetChar( nBuf ) == '\\'
+ && ( rStr.GetChar( nBuf + 1 ) == cToken
+ || rStr.GetChar( nBuf + 1 ) == cToken2 ) )
+ {
+ nBuf += 2;
+ // skip spaces between cToken and it's parameters
+ while( nBuf < rStr.Len()
+ && rStr.GetChar( nBuf ) == ' ' )
+ nBuf++;
+ // return start of parameters
+ return nBuf < rStr.Len() ? nBuf : STRING_NOTFOUND;
+ }
+ }
+ return STRING_NOTFOUND;
+}
+
+// FindPara() findet den ersten Parameter mit '\' und cToken. Es wird
+// ein neuer String allokiert ( der vom Aufrufer deallokiert werden muss )
+// und alles, was zum Parameter gehoert, wird in ihm zurueckgeliefert.
+String FindPara( const String& rStr, sal_Unicode cToken, sal_Unicode cToken2 )
+{
+ xub_StrLen n2; // Ende
+ xub_StrLen n = FindParaStart( rStr, cToken, cToken2 ); // Anfang
+ if( STRING_NOTFOUND == n )
+ return aEmptyStr;
+
+ if( rStr.GetChar( n ) == '"'
+ || rStr.GetChar( n ) == 132 )
+ { // Anfuehrungszeichen vor Para
+ n++; // Anfuehrungszeichen ueberlesen
+ n2 = n; // ab hier nach Ende suchen
+ while( n2 < rStr.Len()
+ && rStr.GetChar( n2 ) != 147
+ && rStr.GetChar( n2 ) != '"' )
+ n2++; // Ende d. Paras suchen
+ }
+ else
+ { // keine Anfuehrungszeichen
+ n2 = n; // ab hier nach Ende suchen
+ while( n2 < rStr.Len()
+ && rStr.GetChar( n2 ) != ' ' )
+ n2++; // Ende d. Paras suchen
+ }
+ return rStr.Copy( n, n2-n );
+}
+
+
+static SvxExtNumType GetNumTypeFromName(const String& rStr,
+ bool bAllowPageDesc = false)
+{
+ SvxExtNumType eTyp = bAllowPageDesc ? SVX_NUM_PAGEDESC : SVX_NUM_ARABIC;
+ if( rStr.EqualsIgnoreCaseAscii( "Arabi", 0, 5 ) ) // Arabisch, Arabic
+ eTyp = SVX_NUM_ARABIC;
+ else if( rStr.EqualsAscii( "misch", 2, 5 ) ) // r"omisch
+ eTyp = SVX_NUM_ROMAN_LOWER;
+ else if( rStr.EqualsAscii( "MISCH", 2, 5 ) ) // R"OMISCH
+ eTyp = SVX_NUM_ROMAN_UPPER;
+ else if( rStr.EqualsIgnoreCaseAscii( "alphabeti", 0, 9 ) )// alphabetisch, alphabetic
+ eTyp = ( rStr.GetChar( 0 ) == 'A' )
+ ? SVX_NUM_CHARS_UPPER_LETTER_N
+ : SVX_NUM_CHARS_LOWER_LETTER_N;
+ else if( rStr.EqualsIgnoreCaseAscii( "roman", 0, 5 ) ) // us
+ eTyp = ( rStr.GetChar( 0 ) == 'R' )
+ ? SVX_NUM_ROMAN_UPPER
+ : SVX_NUM_ROMAN_LOWER;
+ return eTyp;
+}
+
+static SvxExtNumType GetNumberPara(String& rStr, bool bAllowPageDesc = false)
+{
+ String s( FindPara( rStr, '*', '*' ) ); // Ziffernart
+ SvxExtNumType aType = GetNumTypeFromName( s, bAllowPageDesc );
+ return aType;
+}
+
+
+
+
+bool SwWW8ImplReader::ForceFieldLanguage(SwField &rFld, sal_uInt16 nLang)
+{
+ bool bRet(false);
+
+ const SvxLanguageItem *pLang =
+ (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
+ OSL_ENSURE(pLang, "impossible");
+ sal_uInt16 nDefault = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
+
+ if (nLang != nDefault)
+ {
+ rFld.SetAutomaticLanguage(false);
+ rFld.SetLanguage(nLang);
+ bRet = true;
+ }
+
+ return bRet;
+}
+
+String GetWordDefaultDateStringAsUS(SvNumberFormatter* pFormatter, sal_uInt16 nLang)
+{
+ //Get the system date in the correct final language layout, convert to
+ //a known language and modify the 2 digit year part to be 4 digit, and
+ //convert back to the correct language layout.
+ sal_uLong nIndex = pFormatter->GetFormatIndex(NF_DATE_SYSTEM_SHORT, nLang);
+
+ SvNumberformat aFormat = const_cast<SvNumberformat &>
+ (*(pFormatter->GetEntry(nIndex)));
+ aFormat.ConvertLanguage(*pFormatter, nLang, LANGUAGE_ENGLISH_US);
+
+ String sParams(aFormat.GetFormatstring());
+ // #i36594#
+ // Fix provided by mloiseleur@openoffice.org.
+ // A default date can have already 4 year digits, in some case
+ const xub_StrLen pos = sParams.Search( CREATE_CONST_ASC("YYYY") );
+ if ( pos == STRING_NOTFOUND )
+ {
+ sParams.SearchAndReplace(CREATE_CONST_ASC("YY"), CREATE_CONST_ASC("YYYY"));
+ }
+ // <--
+ return sParams;
+}
+
+short SwWW8ImplReader::GetTimeDatePara(String& rStr, sal_uInt32& rFormat,
+ sal_uInt16 &rLang, int nWhichDefault, bool bHijri)
+{
+ bool bRTL = false;
+ if (pPlcxMan && !bVer67)
+ {
+ const sal_uInt8 *pResult = pPlcxMan->HasCharSprm(0x85A);
+ if (pResult && *pResult)
+ bRTL = true;
+ }
+ RES_CHRATR eLang = bRTL ? RES_CHRATR_CTL_LANGUAGE : RES_CHRATR_LANGUAGE;
+ const SvxLanguageItem *pLang = (SvxLanguageItem*)GetFmtAttr( static_cast< sal_uInt16 >(eLang));
+ OSL_ENSURE(pLang, "impossible");
+ rLang = pLang ? pLang->GetValue() : LANGUAGE_ENGLISH_US;
+
+ SvNumberFormatter* pFormatter = rDoc.GetNumberFormatter();
+ String sParams( FindPara( rStr, '@', '@' ) );// Date/Time
+ if (!sParams.Len())
+ {
+ bool bHasTime = false;
+ switch (nWhichDefault)
+ {
+ case ww::ePRINTDATE:
+ case ww::eSAVEDATE:
+ sParams = GetWordDefaultDateStringAsUS(pFormatter, rLang);
+ sParams.APPEND_CONST_ASC(" HH:MM:SS AM/PM");
+ bHasTime = true;
+ break;
+ case ww::eCREATEDATE:
+ sParams.ASSIGN_CONST_ASC("DD/MM/YYYY HH:MM:SS");
+ bHasTime = true;
+ break;
+ default:
+ case ww::eDATE:
+ sParams = GetWordDefaultDateStringAsUS(pFormatter, rLang);
+ break;
+ }
+
+ if (bHijri)
+ sParams.Insert(CREATE_CONST_ASC("[~hijri]"), 0);
+
+ sal_uInt16 nCheckPos = 0;
+ sal_Int16 nType = NUMBERFORMAT_DEFINED;
+ rFormat = 0;
+
+ pFormatter->PutandConvertEntry(sParams, nCheckPos, nType, rFormat,
+ LANGUAGE_ENGLISH_US, rLang);
+
+ return bHasTime ? NUMBERFORMAT_DATETIME : NUMBERFORMAT_DATE;
+ }
+
+ sal_uLong nFmtIdx =
+ sw::ms::MSDateTimeFormatToSwFormat(sParams, pFormatter, rLang, bHijri,
+ GetFib().lid);
+ short nNumFmtType = NUMBERFORMAT_UNDEFINED;
+ if (nFmtIdx)
+ nNumFmtType = pFormatter->GetType(nFmtIdx);
+ rFormat = nFmtIdx;
+
+ return nNumFmtType;
+}
+
+//-----------------------------------------
+// Felder
+//-----------------------------------------
+// Am Ende des Einlesens entsprechende Felder updaten ( z.Zt. die Referenzen )
+void SwWW8ImplReader::UpdateFields()
+{
+ rDoc.SetUpdateExpFldStat(true); // JP: neu fuer alles wichtige
+ rDoc.SetInitDBFields(true); // Datenbank-Felder auch
+}
+
+sal_uInt16 SwWW8ImplReader::End_Field()
+{
+ sal_uInt16 nRet = 0;
+ WW8PLCFx_FLD* pF = pPlcxMan->GetFld();
+ OSL_ENSURE(pF, "WW8PLCFx_FLD - Pointer nicht da");
+ if (!pF || !pF->EndPosIsFieldEnd())
+ return nRet;
+
+ const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
+ sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
+
+ OSL_ENSURE(!maFieldStack.empty(), "Empty field stack\n");
+ if (!maFieldStack.empty())
+ {
+ /*
+ only hyperlinks currently need to be handled like this, for the other
+ cases we have inserted a field not an attribute with an unknown end
+ point
+ */
+ nRet = maFieldStack.back().mnFieldId;
+ switch (nRet)
+ {
+ case 70:
+ if (bUseEnhFields && pPaM!=NULL && pPaM->GetPoint()!=NULL) {
+ SwPosition aEndPos = *pPaM->GetPoint();
+ SwPaM aFldPam( maFieldStack.back().GetPtNode(), maFieldStack.back().GetPtCntnt(), aEndPos.nNode, aEndPos.nContent.GetIndex());
+ IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
+ IFieldmark *pFieldmark = dynamic_cast<IFieldmark*>( pMarksAccess->makeFieldBookmark(
+ aFldPam, maFieldStack.back().GetBookmarkName(), ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_FORMTEXT )) ) );
+ OSL_ENSURE(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
+ if (pFieldmark!=NULL) {
+ const IFieldmark::parameter_map_t& pParametersToAdd = maFieldStack.back().getParameters();
+ pFieldmark->GetParameters()->insert(pParametersToAdd.begin(), pParametersToAdd.end());
+ }
+ }
+ break;
+#if defined(WW_NATIVE_TOC)
+ case 8: // TOX_INDEX
+ case 13: // TOX_CONTENT
+ case 88: // HYPERLINK
+ case 37: // REF
+ if (pPaM!=NULL && pPaM->GetPoint()!=NULL) {
+
+ SwPosition aEndPos = *pPaM->GetPoint();
+ SwPaM aFldPam( maFieldStack.back().GetPtNode(), maFieldStack.back().GetPtCntnt(), aEndPos.nNode, aEndPos.nContent.GetIndex());
+ SwFieldBookmark *pFieldmark=(SwFieldBookmark*)rDoc.makeFieldBookmark(aFldPam, maFieldStack.back().GetBookmarkName(), maFieldStack.back().GetBookmarkType());
+ OSL_ENSURE(pFieldmark!=NULL, "hmmm; why was the bookmark not created?");
+ if (pFieldmark!=NULL) {
+ const IFieldmark::parameter_map_t& pParametersToAdd = maFieldStack.back().getParameters();
+ pFieldmark->GetParameters()->insert(pParameters.begin(), pParameters.end());
+ }
+ }
+ break;
+#else
+ case 88:
+ pCtrlStck->SetAttr(*pPaM->GetPoint(),RES_TXTATR_INETFMT);
+ break;
+#endif
+ case 36:
+ case 68:
+ //Move outside the section associated with this type of field
+ *pPaM->GetPoint() = maFieldStack.back().maStartPos;
+ break;
+ default:
+ rtl::OUString aCode = maFieldStack.back().GetBookmarkCode();
+ if ( aCode.getLength() > 0 )
+ {
+ // Unhandled field with stored code
+ SwPosition aEndPos = *pPaM->GetPoint();
+ SwPaM aFldPam(
+ maFieldStack.back().GetPtNode(), maFieldStack.back().GetPtCntnt(),
+ aEndPos.nNode, aEndPos.nContent.GetIndex());
+
+ IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess( );
+
+ IFieldmark* pFieldmark = pMarksAccess->makeFieldBookmark(
+ aFldPam,
+ maFieldStack.back().GetBookmarkName(),
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_UNHANDLED )) );
+ if ( pFieldmark )
+ {
+ const IFieldmark::parameter_map_t& pParametersToAdd = maFieldStack.back().getParameters();
+ pFieldmark->GetParameters()->insert(pParametersToAdd.begin(), pParametersToAdd.end());
+ rtl::OUString sFieldId = rtl::OUString::valueOf( sal_Int32( maFieldStack.back().mnFieldId ) );
+ pFieldmark->GetParameters()->insert(
+ std::pair< rtl::OUString, uno::Any > (
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_ID_PARAM )),
+ uno::makeAny( sFieldId ) ) );
+ pFieldmark->GetParameters()->insert(
+ std::pair< rtl::OUString, uno::Any > (
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_CODE_PARAM )),
+ uno::makeAny( aCode ) ) );
+
+ if ( maFieldStack.back().mnObjLocFc > 0 )
+ {
+ // Store the OLE object as an internal link
+ String sOleId = '_';
+ sOleId += String::CreateFromInt32( maFieldStack.back().mnObjLocFc );
+
+ SvStorageRef xSrc0 = pStg->OpenSotStorage(CREATE_CONST_ASC(SL::aObjectPool));
+ SvStorageRef xSrc1 = xSrc0->OpenSotStorage( sOleId, STREAM_READ );
+
+ // Store it now!
+ uno::Reference< embed::XStorage > xDocStg = GetDoc().GetDocStorage();
+ uno::Reference< embed::XStorage > xOleStg = xDocStg->openStorageElement(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("OLELinks")), embed::ElementModes::WRITE );
+ SotStorageRef xObjDst = SotStorage::OpenOLEStorage( xOleStg, sOleId );
+
+ if ( xObjDst.Is() )
+ {
+ xSrc1->CopyTo( xObjDst );
+
+ if ( !xObjDst->GetError() )
+ xObjDst->Commit();
+ }
+
+ uno::Reference< embed::XTransactedObject > xTransact( xOleStg, uno::UNO_QUERY );
+ if ( xTransact.is() )
+ xTransact->commit();
+
+ // Store the OLE Id as a parameter
+ pFieldmark->GetParameters()->insert(
+ std::pair< rtl::OUString, uno::Any >(
+ rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( ODF_OLE_PARAM )),
+ uno::makeAny( rtl::OUString( sOleId ) ) ) );
+ }
+
+ }
+ }
+
+ break;
+ }
+ maFieldStack.pop_back();
+ }
+ return nRet;
+}
+
+bool AcceptableNestedField(sal_uInt16 nFieldCode)
+{
+ switch (nFieldCode)
+ {
+#if defined(WW_NATIVE_TOC)
+ case 8: // allow recursive field in TOC...
+ case 13: // allow recursive field in TOC...
+#endif
+ case 36:
+ case 68:
+ case 79:
+ case 88:
+ // Accept AutoTextList field as nested field.
+ // Thus, the field result is imported as plain text.
+ case 89:
+ return true;
+ default:
+ return false;
+ }
+}
+
+FieldEntry::FieldEntry(SwPosition &rPos, sal_uInt16 nFieldId) throw()
+ : maStartPos(rPos), mnFieldId(nFieldId), mnObjLocFc(0)
+{
+}
+
+FieldEntry::FieldEntry(const FieldEntry &rOther) throw()
+ : maStartPos(rOther.maStartPos), mnFieldId(rOther.mnFieldId), mnObjLocFc(rOther.mnObjLocFc)
+{
+}
+
+void FieldEntry::Swap(FieldEntry &rOther) throw()
+{
+ std::swap(maStartPos, rOther.maStartPos);
+ std::swap(mnFieldId, rOther.mnFieldId);
+}
+
+FieldEntry &FieldEntry::operator=(const FieldEntry &rOther) throw()
+{
+ FieldEntry aTemp(rOther);
+ Swap(aTemp);
+ return *this;
+}
+
+::rtl::OUString FieldEntry::GetBookmarkName()
+{
+ return msBookmarkName;
+}
+
+::rtl::OUString FieldEntry::GetBookmarkType()
+{
+ return msMarkType;
+}
+
+::rtl::OUString FieldEntry::GetBookmarkCode()
+{
+ return msMarkCode;
+}
+
+void FieldEntry::SetBookmarkName(::rtl::OUString bookmarkName)
+{
+ msBookmarkName=bookmarkName;
+}
+
+void FieldEntry::SetBookmarkType(::rtl::OUString bookmarkType)
+{
+ msMarkType=bookmarkType;
+}
+
+void FieldEntry::SetBookmarkCode(::rtl::OUString bookmarkCode)
+{
+ msMarkCode = bookmarkCode;
+}
+
+
+::sw::mark::IFieldmark::parameter_map_t& FieldEntry::getParameters() {
+ return maParams;
+}
+
+
+// Read_Field liest ein Feld ein oder, wenn es nicht gelesen werden kann,
+// wird 0 zurueckgegeben, so dass das Feld vom Aufrufer textuell gelesen wird.
+// Returnwert: Gesamtlaenge des Feldes ( zum UEberlesen )
+long SwWW8ImplReader::Read_Field(WW8PLCFManResult* pRes)
+{
+ typedef eF_ResT (SwWW8ImplReader:: *FNReadField)( WW8FieldDesc*, String& );
+ enum Limits {eMax = 96};
+ static FNReadField aWW8FieldTab[eMax+1] =
+ {
+ 0,
+ &SwWW8ImplReader::Read_F_Input,
+ 0,
+ &SwWW8ImplReader::Read_F_Ref, // 3
+ 0,
+ 0,
+ &SwWW8ImplReader::Read_F_Set, // 6
+ 0,
+ &SwWW8ImplReader::Read_F_Tox, // 8
+ 0,
+ 0,
+ 0,
+ &SwWW8ImplReader::Read_F_Seq, // 12
+ &SwWW8ImplReader::Read_F_Tox, // 13
+ &SwWW8ImplReader::Read_F_DocInfo, // 14
+ &SwWW8ImplReader::Read_F_DocInfo, // 15
+ &SwWW8ImplReader::Read_F_DocInfo, // 16
+ &SwWW8ImplReader::Read_F_Author, // 17
+ &SwWW8ImplReader::Read_F_DocInfo, // 18
+ &SwWW8ImplReader::Read_F_DocInfo, // 19
+ &SwWW8ImplReader::Read_F_DocInfo, // 20
+ &SwWW8ImplReader::Read_F_DocInfo, // 21
+ &SwWW8ImplReader::Read_F_DocInfo, // 22
+ &SwWW8ImplReader::Read_F_DocInfo, // 23
+ &SwWW8ImplReader::Read_F_DocInfo, // 24
+ &SwWW8ImplReader::Read_F_DocInfo, // 25
+ &SwWW8ImplReader::Read_F_Anz, // 26
+ &SwWW8ImplReader::Read_F_Anz, // 27
+ &SwWW8ImplReader::Read_F_Anz, // 28
+ &SwWW8ImplReader::Read_F_FileName, // 29
+ &SwWW8ImplReader::Read_F_TemplName, // 30
+ &SwWW8ImplReader::Read_F_DateTime, // 31
+ &SwWW8ImplReader::Read_F_DateTime, // 32
+ &SwWW8ImplReader::Read_F_CurPage, // 33
+ 0,
+ 0,
+ &SwWW8ImplReader::Read_F_IncludeText, // 36
+ &SwWW8ImplReader::Read_F_PgRef, // 37
+ &SwWW8ImplReader::Read_F_InputVar, // 38
+ &SwWW8ImplReader::Read_F_Input, // 39
+ 0,
+ &SwWW8ImplReader::Read_F_DBNext, // 41
+ 0,
+ 0,
+ &SwWW8ImplReader::Read_F_DBNum, // 44
+ 0,
+ 0,
+ 0,
+ 0,
+ &SwWW8ImplReader::Read_F_Equation, // 49
+ 0,
+ &SwWW8ImplReader::Read_F_Macro, // 51
+ &SwWW8ImplReader::Read_F_ANumber, // 52
+ &SwWW8ImplReader::Read_F_ANumber, // 53
+ &SwWW8ImplReader::Read_F_ANumber, // 54
+ 0,
+
+
+ 0, // 56
+
+
+ &SwWW8ImplReader::Read_F_Symbol, // 57
+ &SwWW8ImplReader::Read_F_Embedd, // 58
+ &SwWW8ImplReader::Read_F_DBField, // 59
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ &SwWW8ImplReader::Read_F_IncludePicture, // 67
+ &SwWW8ImplReader::Read_F_IncludeText, // 68
+ 0,
+ &SwWW8ImplReader::Read_F_FormTextBox, // 70
+ &SwWW8ImplReader::Read_F_FormCheckBox, // 71
+ &SwWW8ImplReader::Read_F_NoteReference, // 72
+ 0, /*&SwWW8ImplReader::Read_F_Tox*/
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ &SwWW8ImplReader::Read_F_FormListBox, // 83
+ 0, // 84
+ &SwWW8ImplReader::Read_F_DocInfo, // 85
+ 0, // 86
+ &SwWW8ImplReader::Read_F_OCX, // 87
+ &SwWW8ImplReader::Read_F_Hyperlink, // 88
+ 0, // 89
+ 0, // 90
+ &SwWW8ImplReader::Read_F_HTMLControl, // 91
+ 0, // 92
+ 0, // 93
+ 0, // 94
+ &SwWW8ImplReader::Read_F_Shape, // 95
+ 0 // eMax - Dummy leer Methode
+ };
+ OSL_ENSURE( ( sizeof( aWW8FieldTab ) / sizeof( *aWW8FieldTab ) == eMax+1 ),
+ "FeldFunc-Tabelle stimmt nicht" );
+
+ WW8PLCFx_FLD* pF = pPlcxMan->GetFld();
+ OSL_ENSURE(pF, "WW8PLCFx_FLD - Pointer nicht da");
+
+ if (!pF || !pF->StartPosIsFieldStart())
+ return 0;
+
+ bool bNested = false;
+ if (!maFieldStack.empty())
+ {
+ mycFieldIter aEnd = maFieldStack.end();
+ for(mycFieldIter aIter = maFieldStack.begin(); aIter != aEnd; ++aIter)
+ {
+ bNested = !AcceptableNestedField(aIter->mnFieldId);
+ if (bNested)
+ break;
+ }
+ }
+
+ WW8FieldDesc aF;
+ bool bOk = pF->GetPara(pRes->nCp2OrIdx, aF);
+
+ OSL_ENSURE(bOk, "WW8: Bad Field!\n");
+ if (aF.nId == 33) aF.bCodeNest=false; // do not recurse into nested page fields
+ bool bCodeNest = aF.bCodeNest;
+ if ( aF.nId == 6 ) bCodeNest = false; // We can handle them and loose the inner data
+
+ maFieldStack.push_back(FieldEntry(*pPaM->GetPoint(), aF.nId));
+
+ if (bNested)
+ return 0;
+
+ sal_uInt16 n = ( aF.nId <= eMax ) ? aF.nId : static_cast< sal_uInt16 >(eMax); // alle > 91 werden 92
+ sal_uInt16 nI = n / 32; // # des sal_uInt32
+ sal_uLong nMask = 1 << ( n % 32 ); // Maske fuer Bits
+
+ if( nFieldTagAlways[nI] & nMask ) // Flag: Tag it
+ return Read_F_Tag( &aF ); // Resultat nicht als Text
+
+ if( !bOk || !aF.nId ) // Feld kaputt
+ return aF.nLen; // -> ignorieren
+
+ if( aF.nId > eMax - 1) // WW: Nested Field
+ {
+ if( nFieldTagBad[nI] & nMask ) // Flag: Tag it when bad
+ return Read_F_Tag( &aF ); // Resultat nicht als Text
+ else
+ return aF.nLen;
+ }
+
+ //Only one type of field (hyperlink) in drawing textboxes exists
+ if (aF.nId != 88 && pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
+ return aF.nLen;
+
+ // keine Routine vorhanden
+ if (bNested || !aWW8FieldTab[aF.nId] || bCodeNest)
+ {
+ if( nFieldTagBad[nI] & nMask ) // Flag: Tag it when bad
+ return Read_F_Tag( &aF ); // Resultat nicht als Text
+ // Lese nur Resultat
+ if (aF.bResNest && !AcceptableNestedField(aF.nId))
+ return aF.nLen; // Result nested -> nicht brauchbar
+
+ long nOldPos = pStrm->Tell();
+ String aStr;
+ aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs()+
+ aF.nSCode, aF.nLCode, eTextCharSet );
+ pStrm->Seek( nOldPos );
+
+ // field codes which contain '/' or '.' are not displayed in WinWord
+ xub_StrLen nSpacePos = aStr.Search( ' ', 1 );
+ if ( STRING_NOTFOUND == nSpacePos )
+ nSpacePos = aStr.Len( );
+ xub_StrLen nSearchPos = STRING_NOTFOUND;
+ if ( !( aStr.EqualsAscii( "=", 1, 1 ) ) && (
+ ( ( nSearchPos = aStr.Search('.') ) != STRING_NOTFOUND && nSearchPos < nSpacePos ) ||
+ ( ( nSearchPos = aStr.Search('/') ) != STRING_NOTFOUND && nSearchPos < nSpacePos ) ) )
+ return aF.nLen;
+ else
+ {
+ // Link fields aren't supported, but they are bound to an OLE object
+ // that needs to be roundtripped
+ if ( aF.nId == 56 )
+ bEmbeddObj = true;
+ // Field not supported: store the field code for later use
+ maFieldStack.back().SetBookmarkCode( aStr );
+ return aF.nLen - aF.nLRes - 1; // so viele ueberlesen, das Resultfeld
+ // wird wie Haupttext eingelesen
+ }
+ }
+ else
+ { // Lies Feld
+ long nOldPos = pStrm->Tell();
+ String aStr;
+ if ( aF.nId == 6 && aF.bCodeNest )
+ {
+ // TODO Extract the whole code string using the nested codes
+ aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs() +
+ aF.nSCode, aF.nSRes - aF.nSCode - 1, eTextCharSet );
+ }
+ else
+ {
+ aF.nLCode = pSBase->WW8ReadString( *pStrm, aStr, pPlcxMan->GetCpOfs()+
+ aF.nSCode, aF.nLCode, eTextCharSet );
+ }
+
+ // #i51312# - graphics inside field code not supported by Writer.
+ // Thus, delete character 0x01, which stands for such a graphic.
+ if (aF.nId==51) //#i56768# only do it for the MACROBUTTON field, since DropListFields need the 0x01.
+ {
+ aStr.EraseAllChars( 0x01 );
+ }
+ // <--
+
+ eF_ResT eRes = (this->*aWW8FieldTab[aF.nId])( &aF, aStr );
+ pStrm->Seek( nOldPos );
+
+ switch ( eRes )
+ {
+ case FLD_OK:
+ return aF.nLen; // alles OK
+ case FLD_TAGTXT:
+ if ((nFieldTagBad[nI] & nMask)) // Flag: Tag bad
+ return Read_F_Tag(&aF); // Taggen
+ //fall through...
+ case FLD_TEXT:
+ // so viele ueberlesen, das Resultfeld wird wie Haupttext
+ // eingelesen
+ // attributes can start at char 0x14 so skip one
+ // char more back == "-2"
+ if (aF.nLRes)
+ return aF.nLen - aF.nLRes - 2;
+ else
+ return aF.nLen;
+ case FLD_TAGIGN:
+ if( ( nFieldTagBad[nI] & nMask ) ) // Flag: Tag bad
+ return Read_F_Tag( &aF ); // Taggen
+ return aF.nLen; // oder ignorieren
+ case FLD_READ_FSPA:
+ return aF.nLen - aF.nLRes - 2; // auf Char 1 positionieren
+ default:
+ return aF.nLen; // ignorieren
+ }
+ }
+}
+
+//-----------------------------------------
+// Felder Taggen
+//-----------------------------------------
+
+// MakeTagString() gibt als Returnwert die Position des ersten
+// CR / Zeilenende / Seitenumbruch in pText und wandelt auch nur bis dort
+// Wenn keins dieser Sonderzeichen enthalten ist, wird 0 zurueckgeliefert.
+void SwWW8ImplReader::MakeTagString( String& rStr, const String& rOrg )
+{
+ String sHex( CREATE_CONST_ASC( "\\x" ));
+ bool bAllowCr = SwFltGetFlag( nFieldFlags, SwFltControlStack::TAGS_IN_TEXT )
+ || SwFltGetFlag( nFieldFlags, SwFltControlStack::ALLOW_FLD_CR );
+ sal_Unicode cChar;
+ rStr = rOrg;
+
+ for( xub_StrLen nI = 0;
+ nI < rStr.Len() && rStr.Len() < (MAX_FIELDLEN - 4); ++nI )
+ {
+ bool bSetAsHex = false;
+ switch( cChar = rStr.GetChar( nI ) )
+ {
+ case 132: // Typographische Anfuehrungszeichen
+ case 148: // gegen normale tauschen
+ case 147:
+ rStr.SetChar( nI, '"' );
+ break;
+ case 19:
+ rStr.SetChar( nI, '{' );
+ break; // 19..21 zu {|}
+ case 20:
+ rStr.SetChar( nI, '|' );
+ break;
+ case 21:
+ rStr.SetChar( nI, '}' );
+ break;
+ case '\\': // \{|} per \ Taggen
+ case '{':
+ case '|':
+ case '}':
+ rStr.Insert( nI, '\\' );
+ ++nI;
+ break;
+ case 0x0b:
+ case 0x0c:
+ case 0x0d:
+ if( bAllowCr )
+ rStr.SetChar( nI, '\n' );
+ else
+ bSetAsHex = true;
+ break;
+ case 0xFE:
+ case 0xFF:
+ bSetAsHex = true;
+ break;
+ default:
+ bSetAsHex = 0x20 > cChar;
+ break;
+ }
+
+ if( bSetAsHex )
+ {
+ //all Hex-Numbers with \x before
+ String sTmp( sHex );
+ if( cChar < 0x10 )
+ sTmp += '0';
+ sTmp += String::CreateFromInt32( cChar, 16 );
+ rStr.Replace( nI, 1 , sTmp );
+ nI += sTmp.Len() - 1;
+ }
+ }
+
+ if( rStr.Len() > (MAX_FIELDLEN - 4))
+ rStr.Erase( MAX_FIELDLEN - 4 );
+}
+
+void SwWW8ImplReader::InsertTagField( const sal_uInt16 nId, const String& rTagText )
+{
+ String aName( CREATE_CONST_ASC( "WwFieldTag" ) );
+ if( SwFltGetFlag( nFieldFlags, SwFltControlStack::TAGS_DO_ID ) ) // Nummer?
+ aName += String::CreateFromInt32( nId ); // ausgeben ?
+
+ if( SwFltGetFlag(nFieldFlags, SwFltControlStack::TAGS_IN_TEXT))
+ {
+ aName += rTagText; // als Txt taggen
+ rDoc.InsertString(*pPaM, aName,
+ IDocumentContentOperations::INS_NOHINTEXPAND);
+ }
+ else
+ { // normal tagggen
+
+ SwFieldType* pFT = rDoc.InsertFldType(
+ SwSetExpFieldType( &rDoc, aName, nsSwGetSetExpType::GSE_STRING ) );
+ SwSetExpField aFld( (SwSetExpFieldType*)pFT, rTagText ); // SUB_INVISIBLE
+ sal_uInt16 nSubType = ( SwFltGetFlag( nFieldFlags, SwFltControlStack::TAGS_VISIBLE ) ) ? 0 : nsSwExtendedSubType::SUB_INVISIBLE;
+ aFld.SetSubType(nSubType | nsSwGetSetExpType::GSE_STRING);
+
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ }
+}
+
+long SwWW8ImplReader::Read_F_Tag( WW8FieldDesc* pF )
+{
+ long nOldPos = pStrm->Tell();
+
+ WW8_CP nStart = pF->nSCode - 1; // mit 0x19 am Anfang
+ long nL = pF->nLen; // Gesamtlaenge mit Resultat u. Nest
+ if( nL > MAX_FIELDLEN )
+ nL = MAX_FIELDLEN; // MaxLaenge, durch Quoten
+ // max. 4* so gross
+ String sFTxt;
+ nL = pSBase->WW8ReadString( *pStrm, sFTxt,
+ pPlcxMan->GetCpOfs() + nStart, nL, eStructCharSet);
+
+
+ String aTagText;
+ MakeTagString( aTagText, sFTxt );
+ InsertTagField( pF->nId, aTagText );
+
+ pStrm->Seek( nOldPos );
+ return pF->nLen;
+}
+
+
+//-----------------------------------------
+// normale Felder
+//-----------------------------------------
+
+eF_ResT SwWW8ImplReader::Read_F_Input( WW8FieldDesc* pF, String& rStr )
+{
+ String aDef;
+ String aQ;
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !aQ.Len() )
+ aQ = aReadParam.GetResult();
+ break;
+ case 'd':
+ case 'D':
+ {
+ xub_StrLen n = aReadParam.GoToTokenParam();
+ if( STRING_NOTFOUND != n )
+ aDef = aReadParam.GetResult();
+ }
+ break;
+ }
+ }
+ if( !aDef.Len() )
+ aDef = GetFieldResult( pF );
+
+ if ( pF->nId != 0x01 ) // 0x01 fields have no result
+ {
+ SwInputField aFld( (SwInputFieldType*)rDoc.GetSysFldType( RES_INPUTFLD ),
+ aDef, aQ, INP_TXT, 0 ); // sichtbar ( geht z.Zt. nicht anders )
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ }
+
+ return FLD_OK;
+}
+
+// GetFieldResult alloziert einen String und liest das Feld-Resultat ein
+String SwWW8ImplReader::GetFieldResult( WW8FieldDesc* pF )
+{
+ long nOldPos = pStrm->Tell();
+
+ WW8_CP nStart = pF->nSRes; // Start Resultat
+ long nL = pF->nLRes; // Laenge Resultat
+ if( !nL )
+ return aEmptyStr; // kein Resultat
+
+ if( nL > MAX_FIELDLEN )
+ nL = MAX_FIELDLEN; // MaxLaenge, durch Quoten
+ // max. 4* so gross
+
+ String sRes;
+ nL = pSBase->WW8ReadString( *pStrm, sRes, pPlcxMan->GetCpOfs() + nStart,
+ nL, eStructCharSet );
+
+ pStrm->Seek( nOldPos );
+
+ //replace CR 0x0D with LF 0x0A
+ sRes.SearchAndReplaceAll(0x0D, 0x0A);
+ //replace VT 0x0B with LF 0x0A
+ sRes.SearchAndReplaceAll(0x0B, 0x0A);
+ return sRes;
+}
+
+/*
+Bookmarks can be set with fields SET and ASK, and they can be referenced with
+REF. When set, they behave like variables in writer, otherwise they behave
+like normal bookmarks. We can check whether we should use a show variable
+instead of a normal bookmark ref by converting to "show variable" at the end
+of the document those refs which look for the content of a bookmark but whose
+bookmarks were set with SET or ASK. (See SwWW8FltRefStack)
+
+The other piece of the puzzle is that refs that point to the "location" of the
+bookmark will in word actually point to the last location where the bookmark
+was set with SET or ASK, not the actual bookmark. This is only noticable when
+a document sets the bookmark more than once. This is because word places the
+true bookmark at the location of the last set, but the refs will display the
+position of the first set before the ref.
+
+So what we will do is
+
+1) keep a list of all bookmarks that were set, any bookmark names mentioned
+here that are refed by content will be converted to show variables.
+
+2) create pseudo bookmarks for every position that a bookmark is set with SET
+or ASK but has no existing bookmark. We can then keep a map from the original
+bookmark name to the new one. As we parse the document new pseudo names will
+replace the older ones, so the map always contains the bookmark of the
+location that msword itself would use.
+
+3) word's bookmarks are case insensitive, writers are not. So we need to
+map case different versions together, regardless of whether they are
+variables or not.
+
+4) when a reference is (first) SET or ASK, the bookmark associated with it
+is placed around the 0x14 0x15 result part of the field. We will fiddle
+the placement to be the writer equivalent of directly before and after
+the field, which gives the same effect and meaning, to do so we must
+get any bookmarks in the field range, and begin them immediately before
+the set/ask field, and end them directly afterwards. MapBookmarkVariables
+returns an identifier of the bookmark attribute to close after inserting
+the appropiate set/ask field.
+*/
+long SwWW8ImplReader::MapBookmarkVariables(const WW8FieldDesc* pF,
+ String &rOrigName, const String &rData)
+{
+ OSL_ENSURE(pPlcxMan,"No pPlcxMan");
+ long nNo;
+ /*
+ If there was no bookmark associated with this set field, then we create a
+ pseudo one and insert it in the document.
+ */
+ sal_uInt16 nIndex;
+ pPlcxMan->GetBook()->MapName(rOrigName);
+ String sName = pPlcxMan->GetBook()->GetBookmark(
+ pF->nSCode, pF->nSCode + pF->nLen, nIndex);
+ if (sName.Len())
+ {
+ pPlcxMan->GetBook()->SetStatus(nIndex, BOOK_IGNORE);
+ nNo = nIndex;
+ }
+ else
+ {
+ sName = CREATE_CONST_ASC("WWSetBkmk");
+ nNo = pReffingStck->aFieldVarNames.size()+1;
+ sName += String::CreateFromInt32(nNo);
+ nNo += pPlcxMan->GetBook()->GetIMax();
+ }
+ pReffedStck->NewAttr(*pPaM->GetPoint(),
+ SwFltBookmark(BookmarkToWriter(sName), rData, nNo, 0));
+ pReffingStck->aFieldVarNames[rOrigName] = sName;
+ return nNo;
+}
+
+/*
+Word can set a bookmark with set or with ask, such a bookmark is equivalent to
+our variables, but until the end of a document we cannot be sure if a bookmark
+is a variable or not, at the end we will have a list of reference names which
+were set or asked, all bookmarks using the content of those bookmarks are
+converted to show variables, those that reference the position of the field
+can be left as references, because a bookmark is also inserted at the position
+of a set or ask field, either by word, or in some special cases by the import
+filter itself.
+*/
+SwFltStackEntry *SwWW8FltRefStack::RefToVar(const SwField* pFld,
+ SwFltStackEntry *pEntry)
+{
+ SwFltStackEntry *pRet=0;
+ if (pFld && RES_GETREFFLD == pFld->Which())
+ {
+ //Get the name of the ref field, and see if actually a variable
+ const String &rName = pFld->GetPar1();
+ ::std::map<String,String,SwWW8FltRefStack::ltstr>::const_iterator
+ aResult = aFieldVarNames.find(rName);
+
+ if (aResult != aFieldVarNames.end())
+ {
+ SwGetExpField aFld( (SwGetExpFieldType*)
+ pDoc->GetSysFldType(RES_GETEXPFLD), rName, nsSwGetSetExpType::GSE_STRING, 0);
+ delete pEntry->pAttr;
+ SwFmtFld aTmp(aFld);
+ pEntry->pAttr = aTmp.Clone();
+ pRet = pEntry;
+ }
+ }
+ return pRet;
+}
+
+String SwWW8ImplReader::GetMappedBookmark(const String &rOrigName)
+{
+ String sName(BookmarkToWriter(rOrigName));
+ OSL_ENSURE(pPlcxMan,"no pPlcxMan");
+ pPlcxMan->GetBook()->MapName(sName);
+
+ //See if there has been a variable set with this name, if so get
+ //the pseudo bookmark name that was set with it.
+ ::std::map<String,String,SwWW8FltRefStack::ltstr>::const_iterator aResult =
+ pReffingStck->aFieldVarNames.find(sName);
+
+ const String &rBkmName = (aResult == pReffingStck->aFieldVarNames.end())
+ ? sName : (*aResult).second;
+
+ return rBkmName;
+}
+
+// "ASK"
+eF_ResT SwWW8ImplReader::Read_F_InputVar( WW8FieldDesc* pF, String& rStr )
+{
+ String sOrigName;
+ String aQ;
+ String aDef;
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if (!sOrigName.Len())
+ sOrigName = aReadParam.GetResult();
+ else if( !aQ.Len() )
+ aQ = aReadParam.GetResult();
+ break;
+ case 'd':
+ case 'D':
+ if (STRING_NOTFOUND != aReadParam.GoToTokenParam())
+ aDef = aReadParam.GetResult();
+ break;
+ }
+ }
+
+ if( !sOrigName.Len() )
+ return FLD_TAGIGN; // macht ohne Textmarke keinen Sinn
+
+ String aResult(GetFieldResult(pF));
+
+ //#i24377#, munge Default Text into title as we have only one slot
+ //available for aResult and aDef otherwise
+ if (aDef.Len())
+ {
+ if (aQ.Len())
+ aQ.APPEND_CONST_ASC(" - ");
+ aQ.Append(aDef);
+ }
+
+ long nNo = MapBookmarkVariables(pF, sOrigName, aResult);
+
+ SwSetExpFieldType* pFT = (SwSetExpFieldType*)rDoc.InsertFldType(
+ SwSetExpFieldType(&rDoc, sOrigName, nsSwGetSetExpType::GSE_STRING));
+ SwSetExpField aFld(pFT, aResult);
+ aFld.SetSubType(nsSwExtendedSubType::SUB_INVISIBLE | nsSwGetSetExpType::GSE_STRING);
+ aFld.SetInputFlag(true);
+ aFld.SetPromptText( aQ );
+
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+
+ pReffedStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_BOOKMARK, true, nNo);
+ return FLD_OK;
+}
+
+// "AUTONR"
+eF_ResT SwWW8ImplReader::Read_F_ANumber( WW8FieldDesc*, String& rStr )
+{
+ if( !pNumFldType ){ // 1. Mal
+ SwSetExpFieldType aT( &rDoc, CREATE_CONST_ASC("AutoNr"), nsSwGetSetExpType::GSE_SEQ );
+ pNumFldType = rDoc.InsertFldType( aT );
+ }
+ SwSetExpField aFld( (SwSetExpFieldType*)pNumFldType, aEmptyStr,
+ GetNumberPara( rStr ) );
+ aFld.SetValue( ++nFldNum );
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ return FLD_OK;
+}
+
+// "SEQ"
+eF_ResT SwWW8ImplReader::Read_F_Seq( WW8FieldDesc*, String& rStr )
+{
+ String aSequenceName;
+ String aBook;
+ bool bCountOn = true;
+ String sStart;
+ SvxExtNumType eNumFormat = SVX_NUM_ARABIC;
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !aSequenceName.Len() )
+ aSequenceName = aReadParam.GetResult();
+ else if( !aBook.Len() )
+ aBook = aReadParam.GetResult();
+ break;
+
+ case 'h':
+ break;
+
+ case '*':
+ nRet = aReadParam.SkipToNextToken();
+ if( -2 == nRet )
+ eNumFormat = GetNumTypeFromName( aReadParam.GetResult() );
+ break;
+
+ case 'r':
+ bCountOn = false;
+ nRet = aReadParam.SkipToNextToken();
+ if( -2 == nRet )
+ sStart = aReadParam.GetResult();
+ break;
+
+ case 'c':
+ bCountOn = false;
+ break;
+
+ case 'n':
+ bCountOn = true; // Nummer um eins erhoehen (default)
+ break;
+
+ case 's': // Outline Level
+ //#i19682, what am I to do with this value
+ break;
+ }
+ }
+ if (!aSequenceName.Len() && !aBook.Len())
+ return FLD_TAGIGN;
+
+ SwSetExpFieldType* pFT = (SwSetExpFieldType*)rDoc.InsertFldType(
+ SwSetExpFieldType( &rDoc, aSequenceName, nsSwGetSetExpType::GSE_SEQ ) );
+ SwSetExpField aFld( pFT, aEmptyStr, eNumFormat );
+
+ if (sStart.Len())
+ aFld.SetFormula( ( aSequenceName += '=' ) += sStart );
+ else if (!bCountOn)
+ aFld.SetFormula(aSequenceName);
+
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
+ return FLD_OK;
+}
+
+eF_ResT SwWW8ImplReader::Read_F_DocInfo( WW8FieldDesc* pF, String& rStr )
+{
+ sal_uInt16 nSub=0;
+ // RegInfoFormat, DefaultFormat fuer DocInfoFelder
+ sal_uInt16 nReg = DI_SUB_AUTHOR;
+ bool bDateTime = false;
+
+ if( 85 == pF->nId )
+ {
+ String aDocProperty;
+ _ReadFieldParams aReadParam( rStr );
+ long nRet;
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !aDocProperty.Len() )
+ aDocProperty = aReadParam.GetResult();
+ break;
+ case '*':
+ //Skip over MERGEFORMAT
+ aReadParam.SkipToNextToken();
+ break;
+ }
+ }
+ aDocProperty.EraseAllChars('"');
+
+ /*
+ There are up to 26 fields that may be meant by 'DocumentProperty'.
+ Which of them is to be inserted here ?
+ This Problem can only be solved by implementing a name matching
+ method that compares the given Parameter String with the four
+ possible name sets (english, german, french, spanish)
+ */
+
+ static const sal_Char* aName10 = "\x0F"; // SW field code
+ static const sal_Char* aName11 // German
+ = "TITEL";
+ static const sal_Char* aName12 // French
+ = "TITRE";
+ static const sal_Char* aName13 // English
+ = "TITLE";
+ static const sal_Char* aName14 // Spanish
+ = "TITRO";
+ static const sal_Char* aName20 = "\x15"; // SW filed code
+ static const sal_Char* aName21 // German
+ = "ERSTELLDATUM";
+ static const sal_Char* aName22 // French
+ = "CR\xC9\xC9";
+ static const sal_Char* aName23 // English
+ = "CREATED";
+ static const sal_Char* aName24 // Spanish
+ = "CREADO";
+ static const sal_Char* aName30 = "\x16"; // SW filed code
+ static const sal_Char* aName31 // German
+ = "ZULETZTGESPEICHERTZEIT";
+ static const sal_Char* aName32 // French
+ = "DERNIERENREGISTREMENT";
+ static const sal_Char* aName33 // English
+ = "SAVED";
+ static const sal_Char* aName34 // Spanish
+ = "MODIFICADO";
+ static const sal_Char* aName40 = "\x17"; // SW filed code
+ static const sal_Char* aName41 // German
+ = "ZULETZTGEDRUCKT";
+ static const sal_Char* aName42 // French
+ = "DERNI\xC8" "REIMPRESSION";
+ static const sal_Char* aName43 // English
+ = "LASTPRINTED";
+ static const sal_Char* aName44 // Spanish
+ = "HUPS PUPS";
+ static const sal_Char* aName50 = "\x18"; // SW filed code
+ static const sal_Char* aName51 // German
+ = "\xDC" "BERARBEITUNGSNUMMER";
+ static const sal_Char* aName52 // French
+ = "NUM\xC9" "RODEREVISION";
+ static const sal_Char* aName53 // English
+ = "REVISIONNUMBER";
+ static const sal_Char* aName54 // Spanish
+ = "SNUBBEL BUBBEL";
+ static const sal_uInt16 nFldCnt = 5;
+
+ // additional fields are to be coded soon! :-)
+
+ static const sal_uInt16 nLangCnt = 4;
+ static const sal_Char *aNameSet_26[nFldCnt][nLangCnt+1] =
+ {
+ {aName10, aName11, aName12, aName13, aName14},
+ {aName20, aName21, aName22, aName23, aName24},
+ {aName30, aName31, aName32, aName33, aName34},
+ {aName40, aName41, aName42, aName43, aName44},
+ {aName50, aName51, aName52, aName53, aName54}
+ };
+
+ bool bFldFound= false;
+ sal_uInt16 nFIdx;
+ for(sal_uInt16 nLIdx=1; !bFldFound && (nLangCnt > nLIdx); ++nLIdx)
+ {
+ for(nFIdx = 0; !bFldFound && (nFldCnt > nFIdx); ++nFIdx)
+ {
+ if( aDocProperty.Equals( String( aNameSet_26[nFIdx][nLIdx],
+ RTL_TEXTENCODING_MS_1252 ) ) )
+ {
+ bFldFound = true;
+ pF->nId = aNameSet_26[nFIdx][0][0];
+ }
+ }
+ }
+
+ if( !bFldFound )
+ {
+ SwDocInfoField aFld( (SwDocInfoFieldType*)
+ rDoc.GetSysFldType( RES_DOCINFOFLD ), DI_CUSTOM|nReg, aDocProperty, GetFieldResult( pF ) );
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
+
+ return FLD_OK;
+ }
+ }
+
+ switch( pF->nId )
+ {
+ case 14:
+ /* kann alle INFO-Vars!! */
+ nSub = DI_KEYS;
+ break;
+ case 15:
+ nSub = DI_TITEL;
+ break;
+ case 16:
+ nSub = DI_THEMA;
+ break;
+ case 18:
+ nSub = DI_KEYS;
+ break;
+ case 19:
+ nSub = DI_COMMENT;
+ break;
+ case 20:
+ nSub = DI_CHANGE;
+ nReg = DI_SUB_AUTHOR;
+ break;
+ case 21:
+ nSub = DI_CREATE;
+ nReg = DI_SUB_DATE;
+ bDateTime = true;
+ break;
+ case 23:
+ nSub = DI_PRINT;
+ nReg = DI_SUB_DATE;
+ bDateTime = true;
+ break;
+ case 24:
+ nSub = DI_DOCNO;
+ break;
+ case 22:
+ nSub = DI_CHANGE;
+ nReg = DI_SUB_DATE;
+ bDateTime = true;
+ break;
+ case 25:
+ nSub = DI_CHANGE;
+ nReg = DI_SUB_TIME;
+ bDateTime = true;
+ break;
+ }
+
+ sal_uInt32 nFormat = 0;
+
+ sal_uInt16 nLang(0);
+ if (bDateTime)
+ {
+ short nDT = GetTimeDatePara(rStr, nFormat, nLang, pF->nId);
+ switch (nDT)
+ {
+ case NUMBERFORMAT_DATE:
+ nReg = DI_SUB_DATE;
+ break;
+ case NUMBERFORMAT_TIME:
+ nReg = DI_SUB_TIME;
+ break;
+ case NUMBERFORMAT_DATETIME:
+ nReg = DI_SUB_DATE;
+ break;
+ default:
+ nReg = DI_SUB_DATE;
+ break;
+ }
+ }
+
+ SwDocInfoField aFld( (SwDocInfoFieldType*)
+ rDoc.GetSysFldType( RES_DOCINFOFLD ), nSub|nReg, String(), nFormat );
+ if (bDateTime)
+ ForceFieldLanguage(aFld, nLang);
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
+
+ return FLD_OK;
+}
+
+eF_ResT SwWW8ImplReader::Read_F_Author( WW8FieldDesc*, String& )
+{
+ // SH: Das SwAuthorField bezeichnet nicht den urspruenglichen
+ // Autor, sondern den aktuellen Benutzer, also besser ueber DocInfo
+ SwDocInfoField aFld( (SwDocInfoFieldType*)
+ rDoc.GetSysFldType( RES_DOCINFOFLD ),
+ DI_CREATE|DI_SUB_AUTHOR, String() );
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ return FLD_OK;
+}
+
+eF_ResT SwWW8ImplReader::Read_F_TemplName( WW8FieldDesc*, String& )
+{
+ SwTemplNameField aFld( (SwTemplNameFieldType*)
+ rDoc.GetSysFldType( RES_TEMPLNAMEFLD ), FF_NAME );
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ return FLD_OK;
+}
+
+// Sowohl das Datum- wie auch das Uhrzeit-Feld kann fuer Datum, fuer Uhrzeit
+// oder fuer beides benutzt werden.
+eF_ResT SwWW8ImplReader::Read_F_DateTime( WW8FieldDesc*pF, String& rStr )
+{
+ bool bHijri = false;
+ _ReadFieldParams aReadParam(rStr);
+ long nTok;
+ while (-1 != (nTok = aReadParam.SkipToNextToken()))
+ {
+ switch (nTok)
+ {
+ default:
+ case 'l':
+ case -2:
+ break;
+ case 'h':
+ bHijri = true;
+ break;
+ case 's':
+ //Saka Calendar, should we do something with this ?
+ break;
+ }
+ }
+
+ sal_uInt32 nFormat = 0;
+
+ sal_uInt16 nLang(0);
+ short nDT = GetTimeDatePara(rStr, nFormat, nLang, ww::eDATE, bHijri);
+
+ if( NUMBERFORMAT_UNDEFINED == nDT ) // no D/T-Formatstring
+ {
+ if (32 == pF->nId)
+ {
+ nDT = NUMBERFORMAT_TIME;
+ nFormat = rDoc.GetNumberFormatter()->GetFormatIndex(
+ NF_TIME_START, LANGUAGE_SYSTEM );
+ }
+ else
+ {
+ nDT = NUMBERFORMAT_DATE;
+ nFormat = rDoc.GetNumberFormatter()->GetFormatIndex(
+ NF_DATE_START, LANGUAGE_SYSTEM );
+ }
+ }
+
+ if (nDT & NUMBERFORMAT_DATE)
+ {
+ SwDateTimeField aFld((SwDateTimeFieldType*)
+ rDoc.GetSysFldType(RES_DATETIMEFLD ), DATEFLD, nFormat);
+ ForceFieldLanguage(aFld, nLang);
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ }
+ else if (nDT == NUMBERFORMAT_TIME)
+ {
+ SwDateTimeField aFld((SwDateTimeFieldType*)
+ rDoc.GetSysFldType(RES_DATETIMEFLD), TIMEFLD, nFormat);
+ ForceFieldLanguage(aFld, nLang);
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ }
+
+ return FLD_OK;
+}
+
+eF_ResT SwWW8ImplReader::Read_F_FileName(WW8FieldDesc*, String &rStr)
+{
+ SwFileNameFormat eType = FF_NAME;
+ long nRet;
+ _ReadFieldParams aReadParam(rStr);
+ while (-1 != (nRet = aReadParam.SkipToNextToken()))
+ {
+ switch (nRet)
+ {
+ case 'p':
+ eType = FF_PATHNAME;
+ break;
+ case '*':
+ //Skip over MERGEFORMAT
+ aReadParam.SkipToNextToken();
+ break;
+ default:
+ OSL_ENSURE(!this, "unknown option in FileName field");
+ break;
+ }
+ }
+
+ SwFileNameField aFld(
+ (SwFileNameFieldType*)rDoc.GetSysFldType(RES_FILENAMEFLD), eType);
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
+ return FLD_OK;
+}
+
+eF_ResT SwWW8ImplReader::Read_F_Anz( WW8FieldDesc* pF, String& rStr )
+{ // SeitenZahl - Feld
+ sal_uInt16 nSub = DS_PAGE;
+ switch ( pF->nId ){
+ case 27: nSub = DS_WORD; break; // Wordzahl
+ case 28: nSub = DS_CHAR; break; // Zeichenzahl
+ }
+ SwDocStatField aFld( (SwDocStatFieldType*)
+ rDoc.GetSysFldType( RES_DOCSTATFLD ), nSub,
+ GetNumberPara( rStr ) );
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ return FLD_OK;
+}
+
+eF_ResT SwWW8ImplReader::Read_F_CurPage( WW8FieldDesc*, String& rStr )
+{
+ // zusaetzlich mit Kapitelnummer?
+ if( bPgChpLevel )
+ {
+ SwChapterField aFld( (SwChapterFieldType*)
+ rDoc.GetSysFldType( RES_CHAPTERFLD ), CF_NUMBER );
+ aFld.SetLevel( nPgChpLevel );
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+
+ static const sal_Char aDelim[] = "-.:\x97\x96";
+ sal_uInt8 nDelim = nPgChpDelim;
+ if( nDelim > 4 )
+ nDelim = 0;
+
+ sal_Unicode c = ByteString::ConvertToUnicode( aDelim[ nDelim ],
+ RTL_TEXTENCODING_MS_1252 );
+ if( '-' == c )
+ {
+ rDoc.InsertString( *pPaM, CHAR_HARDHYPHEN );
+ }
+ else
+ {
+ rDoc.InsertString( *pPaM, c ); // maybe insert ZWNBSP?
+ }
+ }
+
+ // Seitennummer
+ SwPageNumberField aFld( (SwPageNumberFieldType*)
+ rDoc.GetSysFldType( RES_PAGENUMBERFLD ), PG_RANDOM,
+ GetNumberPara(rStr, true));
+
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ return FLD_OK;
+}
+
+eF_ResT SwWW8ImplReader::Read_F_Symbol( WW8FieldDesc*, String& rStr )
+{
+ //e.g. #i20118#
+ String aQ;
+ String aName;
+ sal_Int32 nSize = 0;
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !aQ.Len() )
+ aQ = aReadParam.GetResult();
+ break;
+ case 'f':
+ case 'F':
+ {
+ xub_StrLen n = aReadParam.GoToTokenParam();
+ if( STRING_NOTFOUND != n )
+ aName = aReadParam.GetResult();
+ }
+ break;
+ case 's':
+ case 'S':
+ {
+ String aSiz;
+ xub_StrLen n = aReadParam.GoToTokenParam();
+ if (STRING_NOTFOUND != n)
+ aSiz = aReadParam.GetResult();
+ if (aSiz.Len())
+ nSize = aSiz.ToInt32() * 20; // pT -> twip
+ }
+ break;
+ }
+ }
+ if( !aQ.Len() )
+ return FLD_TAGIGN; // -> kein 0-Zeichen in Text
+
+ if (sal_Unicode cChar = static_cast<sal_Unicode>(aQ.ToInt32()))
+ {
+ if (aName.Len()) // Font Name set ?
+ {
+ SvxFontItem aFont(FAMILY_DONTKNOW, aName, aEmptyStr,
+ PITCH_DONTKNOW, RTL_TEXTENCODING_SYMBOL, RES_CHRATR_FONT);
+ NewAttr(aFont); // new Font
+ }
+
+ if (nSize > 0) //#i20118#
+ {
+ SvxFontHeightItem aSz(nSize, 100, RES_CHRATR_FONTSIZE);
+ NewAttr(aSz);
+ }
+
+ rDoc.InsertString(*pPaM, cChar);
+
+ if (nSize > 0)
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_FONTSIZE);
+ if (aName.Len())
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_FONT);
+ }
+ else
+ {
+ rDoc.InsertString(*pPaM, CREATE_CONST_ASC("###"));
+ }
+
+ return FLD_OK;
+}
+
+// "EINBETTEN"
+eF_ResT SwWW8ImplReader::Read_F_Embedd( WW8FieldDesc*, String& rStr )
+{
+ String sHost;
+
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ sHost = aReadParam.GetResult();
+ break;
+
+ case 's':
+ // use ObjectSize
+ break;
+ }
+ }
+
+ if( bObj && nPicLocFc )
+ nObjLocFc = nPicLocFc;
+ bEmbeddObj = true;
+ return FLD_TEXT;
+}
+
+
+// "SET"
+eF_ResT SwWW8ImplReader::Read_F_Set( WW8FieldDesc* pF, String& rStr )
+{
+ String sOrigName;
+ String sVal;
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !sOrigName.Len() )
+ sOrigName = aReadParam.GetResult();
+ else if( !sVal.Len() )
+ sVal = aReadParam.GetResult();
+ break;
+ }
+ }
+
+ long nNo = MapBookmarkVariables(pF,sOrigName,sVal);
+
+ SwFieldType* pFT = rDoc.InsertFldType( SwSetExpFieldType( &rDoc, sOrigName,
+ nsSwGetSetExpType::GSE_STRING ) );
+ SwSetExpField aFld( (SwSetExpFieldType*)pFT, sVal, ULONG_MAX );
+ aFld.SetSubType(nsSwExtendedSubType::SUB_INVISIBLE | nsSwGetSetExpType::GSE_STRING);
+
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+
+ pReffedStck->SetAttr(*pPaM->GetPoint(), RES_FLTR_BOOKMARK, true, nNo);
+
+ return FLD_OK;
+}
+
+// "REF"
+eF_ResT SwWW8ImplReader::Read_F_Ref( WW8FieldDesc*, String& rStr )
+{ // Reference - Field
+ String sOrigBkmName;
+ bool bChapterNr = false;
+ bool bAboveBelow = false;
+
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !sOrigBkmName.Len() ) // get name of bookmark
+ sOrigBkmName = aReadParam.GetResult();
+ break;
+ case 'n':
+ case 'r':
+ case 'w':
+ bChapterNr = true; // activate flag 'Chapter Number'
+ break;
+
+ case 'p':
+ bAboveBelow = true;
+ break;
+ case 'h':
+ break;
+ default:
+ // unimplemented switch: just do 'nix nought nothing' :-)
+ break;
+ }
+ }
+
+ String sBkmName(GetMappedBookmark(sOrigBkmName));
+
+ if (!bAboveBelow || bChapterNr)
+ {
+ if (bChapterNr)
+ {
+ SwGetRefField aFld(
+ (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ),
+ sBkmName,REF_BOOKMARK,0,REF_CHAPTER);
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ }
+ else
+ {
+ /*
+ If we are just inserting the contents of the bookmark, then it
+ is possible that the bookmark is actually a variable, so we
+ must store it until the end of the document to see if it was,
+ in which case we'll turn it into a show variable
+ */
+ SwGetRefField aFld(
+ (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ),
+ sBkmName,REF_BOOKMARK,0,REF_CONTENT);
+ pReffingStck->NewAttr( *pPaM->GetPoint(), SwFmtFld(aFld) );
+ pReffingStck->SetAttr( *pPaM->GetPoint(), RES_TXTATR_FIELD);
+ }
+ }
+
+ if( bAboveBelow )
+ {
+ SwGetRefField aFld( (SwGetRefFieldType*)
+ rDoc.GetSysFldType( RES_GETREFFLD ), sBkmName, REF_BOOKMARK, 0,
+ REF_UPDOWN );
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
+ }
+ return FLD_OK;
+}
+
+// Note Reference - Field
+eF_ResT SwWW8ImplReader::Read_F_NoteReference( WW8FieldDesc*, String& rStr )
+{
+ String aBkmName;
+ bool bAboveBelow = false;
+
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !aBkmName.Len() ) // get name of foot/endnote
+ aBkmName = aReadParam.GetResult();
+ break;
+ case 'r':
+ // activate flag 'Chapter Number'
+ break;
+ case 'p':
+ bAboveBelow = true;
+ break;
+ case 'h':
+ break;
+ default:
+ // unimplemented switch: just do 'nix nought nothing' :-)
+ break;
+ }
+ }
+
+ // set Sequence No of corresponding Foot-/Endnote to Zero
+ // (will be corrected in
+ SwGetRefField aFld( (SwGetRefFieldType*)
+ rDoc.GetSysFldType( RES_GETREFFLD ), aBkmName, REF_FOOTNOTE, 0,
+ REF_ONLYNUMBER );
+ pReffingStck->NewAttr(*pPaM->GetPoint(), SwFmtFld(aFld));
+ pReffingStck->SetAttr(*pPaM->GetPoint(), RES_TXTATR_FIELD);
+ if (bAboveBelow)
+ {
+ SwGetRefField aFld2( (SwGetRefFieldType*)
+ rDoc.GetSysFldType( RES_GETREFFLD ),aBkmName, REF_FOOTNOTE, 0,
+ REF_UPDOWN );
+ pReffingStck->NewAttr(*pPaM->GetPoint(), SwFmtFld(aFld2));
+ pReffingStck->SetAttr(*pPaM->GetPoint(), RES_TXTATR_FIELD);
+ }
+ return FLD_OK;
+}
+
+// "SEITENREF"
+eF_ResT SwWW8ImplReader::Read_F_PgRef( WW8FieldDesc*, String& rStr )
+{
+ String sOrigName;
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !sOrigName.Len() )
+ sOrigName = aReadParam.GetResult();
+ break;
+ }
+ }
+
+ String sName(GetMappedBookmark(sOrigName));
+
+#if defined(WW_NATIVE_TOC)
+ if (1) {
+ ::rtl::OUString aBookmarkName=(RTL_CONSTASCII_USTRINGPARAM("_REF"));
+ maFieldStack.back().SetBookmarkName(aBookmarkName);
+ maFieldStack.back().SetBookmarkType(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_PAGEREF)));
+ maFieldStack.back().AddParam(rtl::OUString(), sName);
+ return FLD_TEXT;
+ }
+#endif
+
+
+ SwGetRefField aFld(
+ (SwGetRefFieldType*)rDoc.GetSysFldType( RES_GETREFFLD ), sName,
+ REF_BOOKMARK, 0, REF_PAGE );
+
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ return FLD_OK;
+}
+
+// "MACROSCHALTFL"ACHE"
+eF_ResT SwWW8ImplReader::Read_F_Macro( WW8FieldDesc*, String& rStr)
+{
+ String aName;
+ String aVText;
+ long nRet;
+ bool bNewVText = true;
+ bool bBracket = false;
+ _ReadFieldParams aReadParam( rStr );
+
+ xub_StrLen nOffset = 0;
+
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !aName.Len() )
+ aName = aReadParam.GetResult();
+ else if( !aVText.Len() || bBracket )
+ {
+ nOffset = aReadParam.GetTokenSttPtr() + 1;
+
+ if( bBracket )
+ aVText += ' ';
+ aVText += aReadParam.GetResult();
+ if (bNewVText)
+ {
+ bBracket = aVText.EqualsIgnoreCaseAscii('[', 1, 0)
+ ? true : false;
+ bNewVText = false;
+ }
+ else if( aVText.GetChar( aVText.Len()-1 ) == ']' )
+ bBracket = false;
+ }
+ break;
+ }
+ }
+ if( !aName.Len() )
+ return FLD_TAGIGN; // makes no sense without Makro-Name
+
+ aName.InsertAscii( "StarOffice.Standard.Modul1.", 0 );
+
+ SwMacroField aFld( (SwMacroFieldType*)
+ rDoc.GetSysFldType( RES_MACROFLD ), aName, aVText );
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+
+
+ WW8_CP nOldCp = pPlcxMan->Where();
+ WW8_CP nCp = nOldCp + nOffset;
+
+ SwPaM aPaM(*pPaM);
+ aPaM.SetMark();
+ aPaM.Move(fnMoveBackward);
+ aPaM.Exchange();
+
+ mpPostProcessAttrsInfo = new WW8PostProcessAttrsInfo(nCp, nCp, aPaM);
+
+ return FLD_OK;
+}
+
+WW8PostProcessAttrsInfo::WW8PostProcessAttrsInfo(WW8_CP nCpStart, WW8_CP nCpEnd,
+ SwPaM & rPaM)
+: mbCopy(false),
+ mnCpStart(nCpStart),
+ mnCpEnd(nCpEnd),
+ mPaM(*rPaM.GetPoint(), *rPaM.GetMark()),
+ mItemSet(rPaM.GetDoc()->GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END - 1)
+{
+}
+
+bool CanUseRemoteLink(const String &rGrfName)
+{
+ bool bUseRemote = false;
+ try
+ {
+ ::ucbhelper::Content aCnt(rGrfName,
+ uno::Reference<
+ ucb::XCommandEnvironment >() );
+ rtl::OUString aTitle;
+
+ aCnt.getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Title")))
+ >>= aTitle;
+ bUseRemote = (aTitle.getLength() > 0);
+ }
+ catch ( ... )
+ {
+ // this file did not exist, so we will not set this as graphiclink
+ bUseRemote = false;
+ }
+ return bUseRemote;
+}
+
+// "EINF"UGENGRAFIK"
+eF_ResT SwWW8ImplReader::Read_F_IncludePicture( WW8FieldDesc*, String& rStr )
+{
+ String aGrfName;
+ bool bEmbedded = true;
+
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if (!aGrfName.Len())
+ ConvertFFileName(aGrfName, aReadParam.GetResult());
+ break;
+
+ case 'd':
+ bEmbedded = false; // Embedded-Flag deaktivieren
+ break;
+
+ case 'c':// den Converter-Namen ueberlesen
+ aReadParam.FindNextStringPiece();
+ break;
+ }
+ }
+
+ if (!bEmbedded)
+ bEmbedded = !CanUseRemoteLink(aGrfName);
+
+ if (!bEmbedded)
+ {
+ /*
+ Besonderheit:
+
+ Wir setzen jetzt den Link ins Doc und merken uns den SwFlyFrmFmt.
+ Da wir ja unten auf jjeden Fall mit Return-Wert FLD_READ_FSPA enden,
+ wird der Skip-Wert so bemessen, dass das folgende Char-1 eingelesen
+ wird.
+ Wenn wir dann in SwWW8ImplReader::ImportGraf() reinlaufen, wird
+ erkannt, dass wir soeben einen Grafik-Link inserted haben und
+ das passende SwAttrSet wird ins Frame-Format eingesetzt.
+ */
+ SfxItemSet aFlySet( rDoc.GetAttrPool(), RES_FRMATR_BEGIN,
+ RES_FRMATR_END-1 );
+ aFlySet.Put( SwFmtAnchor( FLY_AS_CHAR ) );
+ aFlySet.Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
+ pFlyFmtOfJustInsertedGraphic = rDoc.Insert( *pPaM,
+ aGrfName,
+ aEmptyStr,
+ 0, // Graphic*
+ &aFlySet,
+ 0, 0); // SwFrmFmt*
+ maGrfNameGenerator.SetUniqueGraphName(pFlyFmtOfJustInsertedGraphic,
+ INetURLObject(aGrfName).GetBase());
+ }
+ return FLD_READ_FSPA;
+}
+
+
+String wwSectionNamer::UniqueName()
+{
+ String aName(msFileLinkSeed);
+ aName += String::CreateFromInt32(++mnFileSectionNo);
+ return mrDoc.GetUniqueSectionName(&aName);
+}
+
+// "EINFUEGENTEXT"
+eF_ResT SwWW8ImplReader::Read_F_IncludeText( WW8FieldDesc* /*pF*/, String& rStr )
+{
+ String aPara;
+ String aBook;
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !aPara.Len() )
+ aPara = aReadParam.GetResult();
+ else if( !aBook.Len() )
+ aBook = aReadParam.GetResult();
+ break;
+ case '*':
+ //Skip over MERGEFORMAT
+ aReadParam.SkipToNextToken();
+ break;
+ }
+ }
+ ConvertFFileName(aPara, aPara);
+
+ if (aBook.Len() && aBook.GetChar( 0 ) != '\\')
+ {
+ // Bereich aus Quelle ( kein Switch ) ?
+ ConvertUFName(aBook);
+ aPara += sfx2::cTokenSeperator;
+ aPara += sfx2::cTokenSeperator;
+ aPara += aBook;
+ }
+
+ /*
+ ##509##
+ What we will do is insert a section to be linked to a file, but just in
+ case the file is not available we will fill in the section with the stored
+ content of this winword field as a fallback.
+ */
+ SwPosition aTmpPos(*pPaM->GetPoint());
+
+ SwSectionData aSection(FILE_LINK_SECTION,
+ maSectionNameGenerator.UniqueName());
+ aSection.SetLinkFileName( aPara );
+ aSection.SetProtectFlag(true);
+
+ SwSection *const pSection =
+ rDoc.InsertSwSection(*pPaM, aSection, 0, 0, false);
+ OSL_ENSURE(pSection, "no section inserted");
+ if (!pSection)
+ return FLD_TEXT;
+ const SwSectionNode* pSectionNode = pSection->GetFmt()->GetSectionNode();
+ OSL_ENSURE(pSectionNode, "no section node!");
+ if (!pSectionNode)
+ return FLD_TEXT;
+
+ pPaM->GetPoint()->nNode = pSectionNode->GetIndex()+1;
+ pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(), 0 );
+
+ //we have inserted a section before this point, so adjust pos
+ //for future page/section segment insertion
+ maSectionManager.PrependedInlineNode(aTmpPos, *pPaM->GetNode());
+
+ return FLD_TEXT;
+}
+
+// "SERIENDRUCKFELD"
+eF_ResT SwWW8ImplReader::Read_F_DBField( WW8FieldDesc* pF, String& rStr )
+{
+ String aName;
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if( !aName.Len() )
+ aName = aReadParam.GetResult();
+ break;
+ }
+ }
+ SwDBFieldType aD( &rDoc, aName, SwDBData() ); // Datenbank: Nichts
+
+ SwFieldType* pFT = rDoc.InsertFldType( aD );
+ SwDBField aFld( (SwDBFieldType*)pFT );
+ aFld.SetFieldCode( rStr );
+
+ String aResult;
+ pSBase->WW8ReadString( *pStrm, aResult, pPlcxMan->GetCpOfs()+
+ pF->nSRes, pF->nLRes, eTextCharSet );
+
+ aFld.InitContent(aResult);
+
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld( aFld ), 0);
+
+ return FLD_OK;
+}
+
+// "N"ACHSTER"
+eF_ResT SwWW8ImplReader::Read_F_DBNext( WW8FieldDesc*, String& )
+{
+ SwDBNextSetFieldType aN;
+ SwFieldType* pFT = rDoc.InsertFldType( aN );
+ SwDBNextSetField aFld( (SwDBNextSetFieldType*)pFT, aEmptyStr, aEmptyStr,
+ SwDBData() ); // Datenbank: Nichts
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ return FLD_OK;
+}
+
+// "DATENSATZ"
+eF_ResT SwWW8ImplReader::Read_F_DBNum( WW8FieldDesc*, String& )
+{
+ SwDBSetNumberFieldType aN;
+ SwFieldType* pFT = rDoc.InsertFldType( aN );
+ SwDBSetNumberField aFld( (SwDBSetNumberFieldType*)pFT,
+ SwDBData() ); // Datenbank: Nichts
+ rDoc.InsertPoolItem( *pPaM, SwFmtFld( aFld ), 0 );
+ return FLD_OK;
+}
+
+/*
+ EQ , only the usage for
+ a. Combined Characters supported, must be exactly in the form that word
+ only accepts as combined charactersm, i.e.
+ eq \o(\s\up Y(XXX),\s\do Y(XXX))
+ b. Ruby Text supported, must be in the form that word recognizes as being
+ ruby text
+ ...
+*/
+eF_ResT SwWW8ImplReader::Read_F_Equation( WW8FieldDesc*, String& rStr )
+{
+ _ReadFieldParams aReadParam( rStr );
+ long cChar = aReadParam.SkipToNextToken();
+ if ('o' == cChar)
+ Read_SubF_Combined(aReadParam);
+ else if ('*' == cChar)
+ Read_SubF_Ruby(aReadParam);
+ return FLD_OK;
+}
+
+void SwWW8ImplReader::Read_SubF_Combined( _ReadFieldParams& rReadParam)
+{
+ String sCombinedCharacters;
+ if ((-2 == rReadParam.SkipToNextToken()) &&
+ rReadParam.GetResult().EqualsIgnoreCaseAscii('(', 1, 0))
+ {
+ for (int i=0;i<2;i++)
+ {
+ if ('s' == rReadParam.SkipToNextToken())
+ {
+ long cChar = rReadParam.SkipToNextToken();
+ if (-2 != rReadParam.SkipToNextToken())
+ break;
+ String sF = rReadParam.GetResult();
+ if ((('u' == cChar) && sF.EqualsIgnoreCaseAscii('p', 1, 0))
+ || (('d' == cChar) && sF.EqualsIgnoreCaseAscii('o', 1, 0)))
+ {
+ if (-2 == rReadParam.SkipToNextToken())
+ {
+ String sPart = rReadParam.GetResult();
+ xub_StrLen nBegin = sPart.Search('(');
+
+ //Word disallows brackets in this field, which
+ //aids figuring out the case of an end of )) vs )
+ xub_StrLen nEnd = sPart.Search(')');
+
+ if ((nBegin != STRING_NOTFOUND) &&
+ (nEnd != STRING_NOTFOUND))
+ {
+ sCombinedCharacters +=
+ sPart.Copy(nBegin+1,nEnd-nBegin-1);
+ }
+ }
+ }
+ }
+ }
+ }
+ if (sCombinedCharacters.Len())
+ {
+ SwCombinedCharField aFld((SwCombinedCharFieldType*)
+ rDoc.GetSysFldType(RES_COMBINED_CHARS),sCombinedCharacters);
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
+ }
+}
+
+void SwWW8ImplReader::Read_SubF_Ruby( _ReadFieldParams& rReadParam)
+{
+ sal_uInt16 nJustificationCode=0;
+ String sFontName;
+ sal_uInt32 nFontSize=0;
+ String sRuby;
+ String sText;
+ long nRet;
+ while( -1 != ( nRet = rReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ {
+ String sTemp = rReadParam.GetResult();
+ if( sTemp.EqualsIgnoreCaseAscii( "jc", 0, 2 ) )
+ {
+ sTemp.Erase(0,2);
+ nJustificationCode = static_cast<sal_uInt16>(sTemp.ToInt32());
+ }
+ else if( sTemp.EqualsIgnoreCaseAscii( "hps", 0, 3 ) )
+ {
+ sTemp.Erase(0,3);
+ nFontSize= static_cast<sal_uInt32>(sTemp.ToInt32());
+ }
+ else if( sTemp.EqualsIgnoreCaseAscii( "Font:", 0, 5 ) )
+ {
+ sTemp.Erase(0,5);
+ sFontName = sTemp;
+ }
+ }
+ break;
+ case '*':
+ break;
+ case 'o':
+ while( -1 != ( nRet = rReadParam.SkipToNextToken() ))
+ {
+ if ('u' == nRet)
+ {
+ if (-2 == rReadParam.SkipToNextToken() &&
+ (rReadParam.GetResult().EqualsIgnoreCaseAscii('p', 1, 0)))
+ {
+ if (-2 == rReadParam.SkipToNextToken())
+ {
+ String sPart = rReadParam.GetResult();
+ xub_StrLen nBegin = sPart.Search('(');
+
+ //Word disallows brackets in this field,
+ xub_StrLen nEnd = sPart.Search(')');
+
+ if ((nBegin != STRING_NOTFOUND) &&
+ (nEnd != STRING_NOTFOUND))
+ {
+ sRuby = sPart.Copy(nBegin+1,nEnd-nBegin-1);
+ }
+ if (STRING_NOTFOUND ==
+ (nBegin = sPart.Search(',',nEnd)))
+ {
+ nBegin = sPart.Search(';',nEnd);
+ }
+ nEnd = sPart.SearchBackward(')');
+ if ((nBegin != STRING_NOTFOUND) &&
+ (nEnd != STRING_NOTFOUND))
+ {
+ sText = sPart.Copy(nBegin+1,nEnd-nBegin-1);
+ }
+ }
+ }
+ }
+
+ }
+ break;
+ }
+ }
+
+ //Translate and apply
+ if (sRuby.Len() && sText.Len() && sFontName.Len() && nFontSize)
+ {
+ switch (nJustificationCode)
+ {
+ case 0:
+ nJustificationCode=1;
+ break;
+ case 1:
+ nJustificationCode=3;
+ break;
+ case 2:
+ nJustificationCode=4;
+ break;
+ default:
+ case 3:
+ nJustificationCode=0;
+ break;
+ case 4:
+ nJustificationCode=2;
+ break;
+ }
+
+ SwFmtRuby aRuby(sRuby);
+ const SwCharFmt *pCharFmt=0;
+ //Make a guess at which of asian of western we should be setting
+ sal_uInt16 nScript;
+ if (pBreakIt->GetBreakIter().is())
+ nScript = pBreakIt->GetBreakIter()->getScriptType(sRuby, 0);
+ else
+ nScript = i18n::ScriptType::ASIAN;
+
+ //Check to see if we already have a ruby charstyle that this fits
+ std::vector<const SwCharFmt*>::const_iterator aEnd =
+ aRubyCharFmts.end();
+ for(std::vector<const SwCharFmt*>::const_iterator aIter
+ = aRubyCharFmts.begin(); aIter != aEnd; ++aIter)
+ {
+ const SvxFontHeightItem &rFH =
+ ItemGet<SvxFontHeightItem>(*(*aIter),
+ GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript));
+ if (rFH.GetHeight() == nFontSize*10)
+ {
+ const SvxFontItem &rF = ItemGet<SvxFontItem>(*(*aIter),
+ GetWhichOfScript(RES_CHRATR_FONT,nScript));
+ if (rF.GetFamilyName().Equals(sFontName))
+ {
+ pCharFmt=*aIter;
+ break;
+ }
+ }
+ }
+
+ //Create a new char style if necessary
+ if (!pCharFmt)
+ {
+ SwCharFmt *pFmt=0;
+ String aNm;
+ //Take this as the base name
+ SwStyleNameMapper::FillUIName(RES_POOLCHR_RUBYTEXT,aNm);
+ aNm+=String::CreateFromInt32(aRubyCharFmts.size()+1);
+ pFmt = rDoc.MakeCharFmt(aNm,(SwCharFmt*)rDoc.GetDfltCharFmt());
+ SvxFontHeightItem aHeightItem(nFontSize*10, 100, RES_CHRATR_FONTSIZE);
+ SvxFontItem aFontItem(FAMILY_DONTKNOW,sFontName,
+ aEmptyStr,PITCH_DONTKNOW,RTL_TEXTENCODING_DONTKNOW, RES_CHRATR_FONT);
+ aHeightItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONTSIZE,nScript));
+ aFontItem.SetWhich(GetWhichOfScript(RES_CHRATR_FONT,nScript));
+ pFmt->SetFmtAttr(aHeightItem);
+ pFmt->SetFmtAttr(aFontItem);
+ aRubyCharFmts.push_back(pFmt);
+ pCharFmt = pFmt;
+ }
+
+ //Set the charstyle and justification
+ aRuby.SetCharFmtName(pCharFmt->GetName());
+ aRuby.SetCharFmtId(pCharFmt->GetPoolFmtId());
+ aRuby.SetAdjustment(nJustificationCode);
+
+ NewAttr(aRuby);
+ rDoc.InsertString( *pPaM, sText );
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_TXTATR_CJK_RUBY );
+ }
+}
+
+//-----------------------------------------
+// Verzeichnis-Felder
+//-----------------------------------------
+
+void lcl_toxMatchACSwitch( SwWW8ImplReader& /*rReader*/,
+ SwDoc& rDoc,
+ SwTOXBase& rBase,
+ _ReadFieldParams& rParam,
+ SwCaptionDisplay eCaptionType)
+{
+ xub_StrLen n = rParam.GoToTokenParam();
+ if( STRING_NOTFOUND != n )
+ {
+ SwTOXType* pType = (SwTOXType*)rDoc.GetTOXType( TOX_ILLUSTRATIONS, 0);
+ rBase.RegisterToTOXType( *pType );
+ rBase.SetCaptionDisplay( eCaptionType );
+ // Read Sequence Name and store in TOXBase
+ String sSeqName( rParam.GetResult() );
+ lcl_ConvertSequenceName( sSeqName );
+ rBase.SetSequenceName( sSeqName );
+ }
+}
+
+//For all outline styles that are not in the outline numbering add them here as
+//custom extra styles
+bool SwWW8ImplReader::AddExtraOutlinesAsExtraStyles(SwTOXBase& rBase)
+{
+ bool bExtras = false;
+ //This is the case if the winword outline numbering is set while the
+ //writer one is not
+ for (sal_uInt16 nI = 0; nI < nColls; ++nI)
+ {
+ SwWW8StyInf& rSI = pCollA[nI];
+ if (rSI.IsOutline())
+ {
+ const SwTxtFmtColl *pFmt = (const SwTxtFmtColl*)(rSI.pFmt);
+ sal_uInt16 nStyleLevel = rSI.nOutlineLevel;
+ sal_uInt16 nMaxLevel = rBase.GetLevel();
+ if (
+ nStyleLevel != (pFmt->GetAttrOutlineLevel()-1) && //<-end,zhaojianwei
+ nStyleLevel < nMaxLevel
+ )
+ {
+ String sStyles(rBase.GetStyleNames(rSI.nOutlineLevel));
+ if( sStyles.Len())
+ sStyles += TOX_STYLE_DELIMITER;
+ sStyles += pFmt->GetName();
+ rBase.SetStyleNames(sStyles, rSI.nOutlineLevel);
+ bExtras = true;
+ }
+ }
+ }
+ return bExtras;
+}
+
+static void EnsureMaxLevelForTemplates(SwTOXBase& rBase)
+{
+ //If the TOC contains Template entries at levels > the evaluation level
+ //that was initially taken from the max normal outline level of the word TOC
+ //then we cannot use that for the evaluation level because writer cuts off
+ //all styles above that level, while word just cuts off the "standard"
+ //outline styles, we have no option but to expand to the highest level
+ //Word included.
+ if ((rBase.GetLevel() != MAXLEVEL) && (nsSwTOXElement::TOX_TEMPLATE & rBase.GetCreateType()))
+ {
+ for (sal_uInt16 nI = MAXLEVEL; nI > 0; --nI)
+ {
+ String sStyles(rBase.GetStyleNames(nI-1));
+ if (rBase.GetStyleNames(nI-1).Len())
+ {
+ rBase.SetLevel(nI);
+ break;
+ }
+ }
+ }
+}
+
+void lcl_toxMatchTSwitch(SwWW8ImplReader& rReader, SwTOXBase& rBase,
+ _ReadFieldParams& rParam)
+{
+ xub_StrLen n = rParam.GoToTokenParam();
+ if( STRING_NOTFOUND != n )
+ {
+ String sParams( rParam.GetResult() );
+ if( sParams.Len() )
+ {
+ xub_StrLen nIndex = 0;
+
+ // Delimiters between styles and style levels appears to allow both ; and ,
+
+ String sTemplate( sParams.GetToken(0, ';', nIndex) );
+ if( STRING_NOTFOUND == nIndex )
+ {
+ nIndex=0;
+ sTemplate = sParams.GetToken(0, ',', nIndex);
+ }
+ if( STRING_NOTFOUND == nIndex )
+ {
+ const SwFmt* pStyle = rReader.GetStyleWithOrgWWName(sTemplate);
+ if( pStyle )
+ sTemplate = pStyle->GetName();
+ // Store Style for Level 0 into TOXBase
+ rBase.SetStyleNames( sTemplate, 0 );
+ }
+ else while( STRING_NOTFOUND != nIndex )
+ {
+ xub_StrLen nOldIndex=nIndex;
+ sal_uInt16 nLevel = static_cast<sal_uInt16>(
+ sParams.GetToken(0, ';', nIndex).ToInt32());
+ if( STRING_NOTFOUND == nIndex )
+ {
+ nIndex = nOldIndex;
+ nLevel = static_cast<sal_uInt16>(
+ sParams.GetToken(0, ',', nIndex).ToInt32());
+ }
+
+ if( (0 < nLevel) && (MAXLEVEL >= nLevel) )
+ {
+ nLevel--;
+ // Store Style and Level into TOXBase
+ const SwFmt* pStyle
+ = rReader.GetStyleWithOrgWWName( sTemplate );
+
+ if( pStyle )
+ sTemplate = pStyle->GetName();
+
+ String sStyles( rBase.GetStyleNames( nLevel ) );
+ if( sStyles.Len() )
+ sStyles += TOX_STYLE_DELIMITER;
+ sStyles += sTemplate;
+ rBase.SetStyleNames( sStyles, nLevel );
+ }
+ // read next style name...
+ nOldIndex = nIndex;
+ sTemplate = sParams.GetToken(0, ';', nIndex);
+ if( STRING_NOTFOUND == nIndex )
+ {
+ nIndex=nOldIndex;
+ sTemplate = sParams.GetToken(0, ',', nIndex);
+ }
+ }
+ }
+ }
+}
+
+sal_uInt16 wwSectionManager::CurrentSectionColCount() const
+{
+ sal_uInt16 nIndexCols = 1;
+ if (!maSegments.empty())
+ nIndexCols = maSegments.back().maSep.ccolM1 + 1;
+ return nIndexCols;
+}
+
+//Will there be a new pagebreak at this position (don't know what type
+//until later)
+bool wwSectionManager::WillHavePageDescHere(SwNodeIndex aIdx) const
+{
+ bool bRet = false;
+ if (!maSegments.empty())
+ {
+ if (!maSegments.back().IsContinous() &&
+ maSegments.back().maStart == aIdx)
+ {
+ bRet = true;
+ }
+ }
+ return bRet;
+}
+
+sal_uInt16 lcl_GetMaxValidWordTOCLevel(const SwForm &rForm)
+{
+ // GetFormMax() returns level + 1, hence the -1
+ sal_uInt16 nRet = rForm.GetFormMax()-1;
+
+ // If the max of this type of TOC is greater than the max of a word
+ // possible toc, then clip to the word max
+ if (nRet > WW8ListManager::nMaxLevel)
+ nRet = WW8ListManager::nMaxLevel;
+
+ return nRet;
+}
+
+eF_ResT SwWW8ImplReader::Read_F_Tox( WW8FieldDesc* pF, String& rStr )
+{
+#if defined(WW_NATIVE_TOC)
+ if (1) {
+ ::rtl::OUString aBookmarkName=(RTL_CONSTASCII_USTRINGPARAM("_TOC"));
+ maFieldStack.back().SetBookmarkName(aBookmarkName);
+ maFieldStack.back().SetBookmarkType(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_TOC)));
+ return FLD_TEXT;
+ }
+#endif
+
+ if (pF->nLRes < 3)
+ return FLD_TEXT; // ignore (#i25440#)
+
+ TOXTypes eTox; // Baue ToxBase zusammen
+ switch( pF->nId )
+ {
+ case 8:
+ eTox = TOX_INDEX;
+ break;
+ case 13:
+ eTox = TOX_CONTENT;
+ break;
+ default:
+ eTox = TOX_USER;
+ break;
+ }
+
+ sal_uInt16 nCreateOf = (eTox == TOX_CONTENT) ? nsSwTOXElement::TOX_OUTLINELEVEL : nsSwTOXElement::TOX_MARK;
+
+ sal_uInt16 nIndexCols = 1;
+
+ const SwTOXType* pType = rDoc.GetTOXType( eTox, 0 );
+ SwForm aOrigForm(eTox);
+ SwTOXBase* pBase = new SwTOXBase( pType, aOrigForm, nCreateOf, aEmptyStr );
+ pBase->SetProtected(maSectionManager.CurrentSectionIsProtected());
+ switch( eTox ){
+ case TOX_INDEX:
+ {
+ sal_uInt16 eOptions = nsSwTOIOptions::TOI_SAME_ENTRY | nsSwTOIOptions::TOI_CASE_SENSITIVE;
+
+ // TOX_OUTLINELEVEL setzen wir genau dann, wenn
+ // die Parameter \o in 1 bis 9 liegen
+ // oder der Parameter \f existiert
+ // oder GARKEINE Switches Parameter angegeben sind.
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case 'c':
+ {
+ xub_StrLen n = aReadParam.GoToTokenParam();
+ if( STRING_NOTFOUND != n )
+ {
+ String sParams( aReadParam.GetResult() );
+ // if NO String just ignore the \c
+ if( sParams.Len() )
+ {
+ nIndexCols =
+ static_cast<sal_uInt16>(sParams.ToInt32());
+ }
+ }
+ }
+ break;
+ case 'e':
+ {
+ xub_StrLen n = aReadParam.GoToTokenParam();
+ if( STRING_NOTFOUND != n ) // if NO String just ignore the \e
+ {
+ String sDelimiter( aReadParam.GetResult() );
+ SwForm aForm( pBase->GetTOXForm() );
+
+ // Attention: if TOX_CONTENT brave
+ // GetFormMax() returns MAXLEVEL + 1 !!
+ sal_uInt16 nEnd = aForm.GetFormMax()-1;
+
+ for(sal_uInt16 nLevel = 1;
+ nLevel <= nEnd;
+ ++nLevel)
+ {
+ // Levels count from 1
+ // Level 0 is reserved for CAPTION
+
+ // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
+ // falls es eine Seitenzahl gibt:
+ FormTokenType ePrevType = TOKEN_END;
+ FormTokenType eType;
+ // -> #i21237#
+ SwFormTokens aPattern =
+ aForm.GetPattern(nLevel);
+ SwFormTokens::iterator aIt = aPattern.begin();
+ do
+ {
+ eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
+
+ if (eType == TOKEN_PAGE_NUMS)
+ {
+ if (TOKEN_TAB_STOP == ePrevType)
+ {
+ --aIt;
+
+ if(0x09 == sDelimiter.GetChar(0))
+ aIt->eTabAlign = SVX_TAB_ADJUST_END;
+ else
+ {
+ SwFormToken aToken(TOKEN_TEXT);
+ aToken.sText = sDelimiter;
+ *aIt = aToken;
+ }
+ aForm.SetPattern(nLevel, aPattern);
+ }
+
+ eType = TOKEN_END;
+ }
+
+ ePrevType = eType;
+ }
+ while (TOKEN_END != eType);
+ // <- #i21237#
+ }
+ pBase->SetTOXForm( aForm );
+ }
+ }
+ break;
+ case 'h':
+ {
+ eOptions |= nsSwTOIOptions::TOI_ALPHA_DELIMITTER;
+ }
+ break;
+ }
+ }
+ pBase->SetOptions( eOptions );
+ }
+ break;
+
+ case TOX_CONTENT:
+ {
+ bool bIsHyperlink = false;
+ // TOX_OUTLINELEVEL setzen wir genau dann, wenn
+ // die Parameter \o in 1 bis 9 liegen
+ // oder der Parameter \f existiert
+ // oder GARKEINE Switches Parameter angegeben sind.
+ sal_uInt16 eCreateFrom = 0;
+ sal_uInt16 nMaxLevel = 0;
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case 'h':
+ bIsHyperlink = true;
+ break;
+ case 'a':
+ case 'c':
+ lcl_toxMatchACSwitch(*this, rDoc, *pBase, aReadParam,
+ ('c' == nRet)
+ ? CAPTION_COMPLETE
+ : CAPTION_TEXT );
+ break;
+ case 'o':
+ {
+ sal_uInt16 nVal;
+ if( !aReadParam.GetTokenSttFromTo(0, &nVal, WW8ListManager::nMaxLevel) )
+ nVal = lcl_GetMaxValidWordTOCLevel(aOrigForm);
+ if( nMaxLevel < nVal )
+ nMaxLevel = nVal;
+ eCreateFrom |= nsSwTOXElement::TOX_OUTLINELEVEL;
+ }
+ break;
+ case 'f':
+ eCreateFrom |= nsSwTOXElement::TOX_MARK;
+ break;
+ case 'l':
+ {
+ sal_uInt16 nVal;
+ if( aReadParam.GetTokenSttFromTo(0, &nVal, WW8ListManager::nMaxLevel) )
+ {
+ if( nMaxLevel < nVal )
+ nMaxLevel = nVal;
+ eCreateFrom |= nsSwTOXElement::TOX_MARK;
+ }
+ }
+ break;
+ case 't': // paragraphs using special styles shall
+ // provide the TOX's content
+ lcl_toxMatchTSwitch(*this, *pBase, aReadParam);
+ eCreateFrom |= nsSwTOXElement::TOX_TEMPLATE;
+ break;
+ case 'p':
+ {
+ xub_StrLen n = aReadParam.GoToTokenParam();
+ if( STRING_NOTFOUND != n ) // if NO String just ignore the \p
+ {
+ String sDelimiter( aReadParam.GetResult() );
+ SwForm aForm( pBase->GetTOXForm() );
+
+ // Attention: if TOX_CONTENT brave
+ // GetFormMax() returns MAXLEVEL + 1 !!
+ sal_uInt16 nEnd = aForm.GetFormMax()-1;
+
+ for(sal_uInt16 nLevel = 1;
+ nLevel <= nEnd;
+ ++nLevel)
+ {
+ // Levels count from 1
+ // Level 0 is reserved for CAPTION
+
+ // Delimiter statt Tabstop vor der Seitenzahl einsetzen,
+ // falls es eine Seitenzahl gibt:
+ FormTokenType ePrevType = TOKEN_END;
+ FormTokenType eType;
+
+ // -> #i21237#
+ SwFormTokens aPattern = aForm.GetPattern(nLevel);
+ SwFormTokens::iterator aIt = aPattern.begin();
+ do
+ {
+ eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
+
+ if (eType == TOKEN_PAGE_NUMS)
+ {
+ if (TOKEN_TAB_STOP == ePrevType)
+ {
+ --aIt;
+
+ SwFormToken aToken(TOKEN_TEXT);
+ aToken.sText = sDelimiter;
+
+ *aIt = aToken;
+ aForm.SetPattern(nLevel,
+ aPattern);
+ }
+ eType = TOKEN_END;
+ }
+ ePrevType = eType;
+ }
+ while( TOKEN_END != eType );
+ // <- #i21237#
+ }
+ pBase->SetTOXForm( aForm );
+ }
+ }
+ break;
+ case 'n': // don't print page numbers
+ {
+ // read START and END param
+ sal_uInt16 nStart, nEnd;
+ if( !aReadParam.GetTokenSttFromTo( &nStart, &nEnd,
+ WW8ListManager::nMaxLevel ) )
+ {
+ nStart = 1;
+ nEnd = aOrigForm.GetFormMax()-1;
+ }
+ // remove page numbers from this levels
+ SwForm aForm( pBase->GetTOXForm() );
+ if (aForm.GetFormMax() <= nEnd)
+ nEnd = aForm.GetFormMax()-1;
+ for (
+ sal_uInt16 nLevel = nStart; nLevel <= nEnd;
+ ++nLevel
+ )
+ {
+ // Levels count from 1
+ // Level 0 is reserved for CAPTION
+
+ // Seitenzahl und ggfs. davorstehenden Tabstop
+ // entfernen:
+ FormTokenType eType;
+ // -> #i21237#
+ SwFormTokens aPattern = aForm.GetPattern(nLevel);
+ SwFormTokens::iterator aIt = aPattern.begin();
+ do
+ {
+ eType = ++aIt == aPattern.end() ? TOKEN_END : aIt->eTokenType;
+
+ if (eType == TOKEN_PAGE_NUMS)
+ {
+ aIt = aPattern.erase(aIt);
+ --aIt;
+ if (
+ TOKEN_TAB_STOP ==
+ aIt->eTokenType
+ )
+ {
+ aPattern.erase(aIt);
+ aForm.SetPattern(nLevel, aPattern);
+ }
+ eType = TOKEN_END;
+ }
+ }
+ while (TOKEN_END != eType);
+ // <- #i21237#
+ }
+ pBase->SetTOXForm( aForm );
+ }
+ break;
+
+ /*
+ // the following switches are not (yet) supported
+ // by good old StarWriter:
+ case 'b':
+ case 's':
+ case 'd':
+ break;
+ */
+ }
+ }
+
+ if (bIsHyperlink)
+ {
+ SwForm aForm(pBase->GetTOXForm());
+ sal_uInt16 nEnd = aForm.GetFormMax()-1;
+ SwFormToken aLinkStart(TOKEN_LINK_START);
+ SwFormToken aLinkEnd(TOKEN_LINK_END);
+
+ // -> #i21237#
+ for(sal_uInt16 nLevel = 1; nLevel <= nEnd; ++nLevel)
+ {
+ SwFormTokens aPattern = aForm.GetPattern(nLevel);
+
+ aPattern.insert(aPattern.begin(), aLinkStart);
+ aPattern.push_back(aLinkEnd);
+
+ aForm.SetPattern(nLevel, aPattern);
+
+ }
+ // <- #i21237#
+ pBase->SetTOXForm(aForm);
+ }
+
+ if (!nMaxLevel)
+ nMaxLevel = WW8ListManager::nMaxLevel;
+ pBase->SetLevel(nMaxLevel);
+
+ const TOXTypes eType = pBase->GetTOXType()->GetType();
+ switch( eType )
+ {
+ case TOX_CONTENT:
+ {
+ //If we would be created from outlines, either explictly or by default
+ //then see if we need extra styles added to the outlines
+ sal_uInt16 eEffectivelyFrom = eCreateFrom ? eCreateFrom : nsSwTOXElement::TOX_OUTLINELEVEL;
+ if (eEffectivelyFrom & nsSwTOXElement::TOX_OUTLINELEVEL)
+ {
+ if (AddExtraOutlinesAsExtraStyles(*pBase))
+ eCreateFrom |= (nsSwTOXElement::TOX_TEMPLATE | nsSwTOXElement::TOX_OUTLINELEVEL);
+
+ // #i19683# Insert a text token " " between the number and entry token.
+ // In an ideal world we could handle the tab stop between the number and
+ // the entry correctly, but I currently have no clue how to obtain
+ // the tab stop position. It is _not_ set at the paragraph style.
+ SwForm* pForm = 0;
+ for (sal_uInt16 nI = 0; nI < nColls; ++nI)
+ {
+ const SwWW8StyInf& rSI = pCollA[nI];
+ if (rSI.IsOutlineNumbered())
+ {
+ sal_uInt16 nStyleLevel = rSI.nOutlineLevel;
+ const SwNumFmt& rFmt = rSI.GetOutlineNumrule()->Get( nStyleLevel );
+ if ( SVX_NUM_NUMBER_NONE != rFmt.GetNumberingType() )
+ {
+ ++nStyleLevel;
+
+ if ( !pForm )
+ pForm = new SwForm( pBase->GetTOXForm() );
+
+ SwFormTokens aPattern = pForm->GetPattern(nStyleLevel);
+ SwFormTokens::iterator aIt =
+ find_if(aPattern.begin(), aPattern.end(),
+ SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO));
+
+ if ( aIt != aPattern.end() )
+ {
+ SwFormToken aNumberEntrySeparator( TOKEN_TEXT );
+ aNumberEntrySeparator.sText = String::CreateFromAscii(" ");
+ aPattern.insert( ++aIt, aNumberEntrySeparator );
+ pForm->SetPattern( nStyleLevel, aPattern );
+ }
+ }
+ }
+ }
+ if ( pForm )
+ pBase->SetTOXForm( *pForm );
+ // <--
+ }
+
+ if (eCreateFrom)
+ pBase->SetCreate(eCreateFrom);
+ EnsureMaxLevelForTemplates(*pBase);
+ }
+ break;
+ case TOX_ILLUSTRATIONS:
+ {
+ if( !eCreateFrom )
+ eCreateFrom = nsSwTOXElement::TOX_SEQUENCE;
+ pBase->SetCreate( eCreateFrom );
+
+ /*
+ We don't know until here if we are an illustration
+ or not, and so have being used a TOX_CONTENT so far
+ which has 10 levels, while TOX has only two, this
+ level is set only in the constructor of SwForm, so
+ create a new one and copy over anything that could
+ be set in the old one, and remove entries from the
+ pattern which do not apply to illustration indices
+ */
+ SwForm aOldForm( pBase->GetTOXForm() );
+ SwForm aForm( eType );
+ sal_uInt16 nEnd = aForm.GetFormMax()-1;
+
+ // #i21237#
+ for(sal_uInt16 nLevel = 1; nLevel <= nEnd; ++nLevel)
+ {
+ SwFormTokens aPattern = aOldForm.GetPattern(nLevel);
+
+ SwFormTokens::iterator new_end=remove_if(aPattern.begin(), aPattern.end(),
+ SwFormTokenEqualToFormTokenType(TOKEN_ENTRY_NO));
+
+ // table index imported with wrong page number format
+ aPattern.erase (new_end, aPattern.end() );
+
+ aForm.SetPattern(nLevel, aPattern);
+
+ aForm.SetTemplate( nLevel,
+ aOldForm.GetTemplate(nLevel));
+ }
+ // <--
+
+ pBase->SetTOXForm( aForm );
+ }
+ break;
+ default:
+ OSL_ENSURE(!this, "Unhandled toc options!");
+ break;
+ }
+ }
+ break;
+ case TOX_USER:
+ break;
+ default:
+ OSL_ENSURE(!this, "Unhandled toc options!");
+ break;
+ } // ToxBase fertig
+
+ // Update fuer TOX anstossen
+ rDoc.SetUpdateTOX(true);
+
+ // #i21237# - propagate tab stops from paragraph styles
+ // used in TOX to patterns of the TOX
+
+ pBase->AdjustTabStops(rDoc, sal_True);
+
+ // #i10028# - inserting a toc implicltly acts like a parabreak in word and writer
+ if (pPaM->GetPoint()->nContent.GetIndex())
+ AppendTxtNode(*pPaM->GetPoint());
+
+ const SwPosition* pPos = pPaM->GetPoint();
+
+ SwFltTOX aFltTOX( pBase, nIndexCols );
+
+ // test if there is already a break item on this node
+ if(SwCntntNode* pNd = pPos->nNode.GetNode().GetCntntNode())
+ {
+ const SfxItemSet* pSet = pNd->GetpSwAttrSet();
+ if( pSet )
+ {
+ if (SFX_ITEM_SET == pSet->GetItemState(RES_BREAK, false))
+ aFltTOX.SetHadBreakItem(true);
+ if (SFX_ITEM_SET == pSet->GetItemState(RES_PAGEDESC, false))
+ aFltTOX.SetHadPageDescItem(true);
+ }
+ }
+
+ //Will there be a new pagebreak at this position (don't know what type
+ //until later)
+ if (maSectionManager.WillHavePageDescHere(pPos->nNode))
+ aFltTOX.SetHadPageDescItem(true);
+
+ // Setze Anfang in Stack
+ pReffedStck->NewAttr( *pPos, aFltTOX );
+
+ rDoc.InsertTableOf(*pPaM->GetPoint(), *aFltTOX.GetBase());
+
+ //inserting a toc inserts a section before this point, so adjust pos
+ //for future page/section segment insertion
+ SwPaM aRegion(*pPaM);
+ aRegion.Move(fnMoveBackward);
+ OSL_ENSURE(rDoc.GetCurTOX(*aRegion.GetPoint()), "Misunderstood how toc works");
+ if (SwTOXBase* pBase2 = (SwTOXBase*)rDoc.GetCurTOX(*aRegion.GetPoint()))
+ {
+ if(nIndexCols>1)
+ {
+ // Set the column number for index
+ SfxItemSet aSet( rDoc.GetAttrPool(), RES_COL, RES_COL );
+ SwFmtCol aCol;
+ aCol.Init( nIndexCols, 708, USHRT_MAX );
+ aSet.Put( aCol );
+ pBase2->SetAttrSet( aSet );
+ }
+
+ maSectionManager.PrependedInlineNode(*pPaM->GetPoint(),
+ *aRegion.GetNode());
+ }
+
+ // Setze Ende in Stack
+ pReffedStck->SetAttr( *pPos, RES_FLTR_TOX );
+
+ if (!maApos.back()) //a para end in apo doesn't count
+ bWasParaEnd = true;
+ return FLD_OK;
+}
+
+eF_ResT SwWW8ImplReader::Read_F_Shape(WW8FieldDesc* /*pF*/, String& /*rStr*/)
+{
+ /*
+ #i3958# 0x8 followed by 0x1 where the shape is the 0x8 and its anchoring
+ to be ignored followed by a 0x1 with an empty drawing. Detect in inserting
+ the drawing that we are in the Shape field and respond accordingly
+ */
+ return FLD_TEXT;
+ }
+
+eF_ResT SwWW8ImplReader::Read_F_Hyperlink( WW8FieldDesc* /*pF*/, String& rStr )
+{
+#if defined(WW_NATIVE_TOC)
+ if (1) {
+ ::rtl::OUString aBookmarkName=(RTL_CONSTASCII_USTRINGPARAM("_HYPERLINK"));
+ maFieldStack.back().SetBookmarkName(aBookmarkName);
+ maFieldStack.back().SetBookmarkType(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(ODF_HYPERLINK)));
+ return FLD_TEXT;
+ }
+#endif
+
+ String sURL, sTarget, sMark;
+ bool bDataImport = false;
+ //HYPERLINk "filename" [switches]
+ bool bOptions=false;
+
+ rStr.EraseTrailingChars( 1 );
+
+ if (!bDataImport)
+ {
+ long nRet;
+ _ReadFieldParams aReadParam( rStr );
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ {
+ switch( nRet )
+ {
+ case -2:
+ if (!sURL.Len() & !bOptions)
+ ConvertFFileName(sURL, aReadParam.GetResult());
+ break;
+
+ case 'n':
+ sTarget.ASSIGN_CONST_ASC( "_blank" );
+ bOptions = true;
+ break;
+
+ case 'l':
+ nRet = aReadParam.SkipToNextToken();
+ bOptions = true;
+ if( -2 == nRet )
+ {
+ sMark = aReadParam.GetResult();
+ if( sMark.Len() && '"' == sMark.GetChar( sMark.Len()-1 ))
+ sMark.Erase( sMark.Len() - 1 );
+
+ }
+ break;
+ case 't':
+ nRet = aReadParam.SkipToNextToken();
+ bOptions = true;
+ if (-2 == nRet)
+ sTarget = aReadParam.GetResult();
+ break;
+ case 'h':
+ case 'm':
+ OSL_ENSURE( !this, "Auswertung fehlt noch - Daten unbekannt" );
+ case 's': //worthless fake anchor option
+ bOptions = true;
+ break;
+ }
+ }
+ }
+
+ // das Resultat uebernehmen
+ OSL_ENSURE((sURL.Len() || sMark.Len()), "WW8: Empty URL");
+
+ if( sMark.Len() )
+ ( sURL += INET_MARK_TOKEN ) += sMark;
+
+ SwFmtINetFmt aURL( sURL, sTarget );
+
+ //As an attribute this needs to be closed, and that'll happen from
+ //EndExtSprm in conjunction with the maFieldStack If there are are flyfrms
+ //between the start and begin, their hyperlinks will be set at that time
+ //as well.
+ pCtrlStck->NewAttr( *pPaM->GetPoint(), aURL );
+ return FLD_TEXT;
+}
+
+void lcl_ImportTox(SwDoc &rDoc, SwPaM &rPaM, const String &rStr, bool bIdx)
+{
+ TOXTypes eTox = ( !bIdx ) ? TOX_CONTENT : TOX_INDEX; // Default
+
+ sal_uInt16 nLevel = 1;
+
+ xub_StrLen n;
+ String sFldTxt;
+ long nRet;
+ _ReadFieldParams aReadParam(rStr);
+ while( -1 != ( nRet = aReadParam.SkipToNextToken() ))
+ switch( nRet )
+ {
+ case -2:
+ if( !sFldTxt.Len() )
+ {
+ // PrimaryKey ohne ":", 2nd dahinter
+ sFldTxt = aReadParam.GetResult();
+ }
+ break;
+
+ case 'f':
+ n = aReadParam.GoToTokenParam();
+ if( STRING_NOTFOUND != n )
+ {
+ String sParams( aReadParam.GetResult() );
+ if( 'C' != sParams.GetChar(0) && 'c' != sParams.GetChar(0) )
+ eTox = TOX_USER;
+ }
+ break;
+
+ case 'l':
+ n = aReadParam.GoToTokenParam();
+ if( STRING_NOTFOUND != n )
+ {
+ String sParams( aReadParam.GetResult() );
+ if( sParams.Len() // if NO String just ignore the \l
+ && sParams.GetChar( 0 ) > '0'
+ && sParams.GetChar( 0 ) <= '9' )
+ {
+ nLevel = (sal_uInt16)sParams.ToInt32();
+ }
+ }
+ break;
+ }
+
+ OSL_ENSURE( rDoc.GetTOXTypeCount( eTox ), "Doc.GetTOXTypeCount() == 0 :-(" );
+
+ const SwTOXType* pT = rDoc.GetTOXType( eTox, 0 );
+ SwTOXMark aM( pT );
+
+ if( eTox != TOX_INDEX )
+ aM.SetLevel( nLevel );
+ else
+ {
+ xub_StrLen nFnd = sFldTxt.Search( WW8_TOX_LEVEL_DELIM );
+ if( STRING_NOTFOUND != nFnd ) // it exist levels
+ {
+ aM.SetPrimaryKey( sFldTxt.Copy( 0, nFnd ) );
+ xub_StrLen nScndFnd =
+ sFldTxt.Search( WW8_TOX_LEVEL_DELIM, nFnd+1 );
+ if( STRING_NOTFOUND != nScndFnd )
+ {
+ aM.SetSecondaryKey( sFldTxt.Copy( nFnd+1, nScndFnd - nFnd - 1 ));
+ nFnd = nScndFnd;
+ }
+ sFldTxt.Erase( 0, nFnd+1 );
+ }
+ }
+
+ if (sFldTxt.Len())
+ {
+ aM.SetAlternativeText( sFldTxt );
+ rDoc.InsertPoolItem( rPaM, aM, 0 );
+ }
+}
+
+void sw::ms::ImportXE(SwDoc &rDoc, SwPaM &rPaM, const String &rStr)
+{
+ lcl_ImportTox(rDoc, rPaM, rStr, true);
+}
+
+void SwWW8ImplReader::ImportTox( int nFldId, String aStr )
+{
+ bool bIdx = (nFldId != 9);
+ lcl_ImportTox(rDoc, *pPaM, aStr, bIdx);
+}
+
+void SwWW8ImplReader::Read_FldVanish( sal_uInt16, const sal_uInt8*, short nLen )
+{
+ //Meaningless in a style
+ if (pAktColl || !pPlcxMan)
+ return;
+
+ const int nChunk = 64; //number of characters to read at one time
+
+ // Vorsicht: Bei Feldnamen mit Umlauten geht das MEMICMP nicht!
+ const static sal_Char *aFldNames[] = { "\x06""INHALT", "\x02""XE", // dt.
+ "\x02""TC" }; // us
+ const static sal_uInt8 aFldId[] = { 9, 4, 9 };
+
+ if( nLen < 0 )
+ {
+ bIgnoreText = false;
+ return;
+ }
+
+ // our methode was called from
+ // ''Skip attributes of field contents'' loop within ReadTextAttr()
+ if( bIgnoreText )
+ return;
+
+ bIgnoreText = true;
+ long nOldPos = pStrm->Tell();
+
+ WW8_CP nStartCp = pPlcxMan->Where() + pPlcxMan->GetCpOfs();
+
+ String sFieldName;
+ sal_uInt16 nFieldLen = pSBase->WW8ReadString( *pStrm, sFieldName, nStartCp,
+ nChunk, eStructCharSet );
+ nStartCp+=nFieldLen;
+
+ xub_StrLen nC = 0;
+ //If the first chunk did not start with a field start then
+ //reset the stream position and give up
+ if( !nFieldLen || (0x13 != sFieldName.GetChar( nC ))) // Field Start Mark
+ {
+ // If Field End Mark found
+ if( nFieldLen && (0x15 == sFieldName.GetChar( nC )))
+ bIgnoreText = false;
+ pStrm->Seek( nOldPos );
+ return; // kein Feld zu finden
+ }
+
+ xub_StrLen nFnd;
+ //If this chunk does not contain a field end, keep reading chunks
+ //until we find one, or we run out of text,
+ while (STRING_NOTFOUND == (nFnd = sFieldName.Search(0x15)))
+ {
+ String sTemp;
+ nFieldLen = pSBase->WW8ReadString( *pStrm, sTemp,
+ nStartCp, nChunk, eStructCharSet );
+ sFieldName+=sTemp;
+ nStartCp+=nFieldLen;
+ if (!nFieldLen)
+ break;
+ }
+
+ pStrm->Seek( nOldPos );
+
+ //if we have no 0x15 give up, otherwise erase everything from the 0x15
+ //onwards
+ if (STRING_NOTFOUND == nFnd)
+ return;
+ else
+ sFieldName.Erase(nFnd);
+
+ nC++;
+ while( ' ' == sFieldName.GetChar( nC ))
+ nC++;
+
+ for( int i = 0; i < 3; i++ )
+ {
+ const sal_Char* pName = aFldNames[i];
+ sal_uInt16 nNameLen = *pName++;
+ if( sFieldName.EqualsIgnoreCaseAscii( pName, nC, nNameLen ) )
+ {
+ ImportTox( aFldId[i], sFieldName.Copy( nC + nNameLen ) );
+ break; // keine Mehrfachnennungen moeglich
+ }
+ }
+ bIgnoreText = true;
+ pStrm->Seek( nOldPos );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8par6.cxx b/sw/source/filter/ww8/ww8par6.cxx
new file mode 100644
index 000000000000..8f6ad9f2f439
--- /dev/null
+++ b/sw/source/filter/ww8/ww8par6.cxx
@@ -0,0 +1,6149 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include <stdlib.h>
+#include <svl/itemiter.hxx>
+#include <rtl/tencinfo.h>
+
+
+#include <hintids.hxx>
+#include <editeng/lspcitem.hxx>
+#include <editeng/wrlmitem.hxx>
+#include <editeng/udlnitem.hxx>
+#include <editeng/kernitem.hxx>
+#include <editeng/langitem.hxx>
+#include <editeng/cmapitem.hxx>
+#include <editeng/shdditem.hxx>
+#include <editeng/cntritem.hxx>
+#include <editeng/crsditem.hxx>
+#include <editeng/postitem.hxx>
+#include <editeng/wghtitem.hxx>
+#include <editeng/colritem.hxx>
+#include <editeng/brshitem.hxx>
+#include <editeng/spltitem.hxx>
+#include <editeng/keepitem.hxx>
+#include <editeng/orphitem.hxx>
+#include <editeng/widwitem.hxx>
+#include <editeng/adjitem.hxx>
+#include <editeng/escpitem.hxx>
+#include <editeng/fhgtitem.hxx>
+#include <editeng/fontitem.hxx>
+#include <editeng/shaditem.hxx>
+#include <editeng/boxitem.hxx>
+#include <editeng/ulspitem.hxx>
+#include <editeng/lrspitem.hxx>
+#include <editeng/tstpitem.hxx>
+#include <editeng/akrnitem.hxx>
+#include <editeng/paperinf.hxx>
+#include <editeng/emphitem.hxx>
+#include <editeng/forbiddenruleitem.hxx>
+#include <editeng/twolinesitem.hxx>
+#include <editeng/scriptspaceitem.hxx>
+#include <editeng/hngpnctitem.hxx>
+#include <editeng/pbinitem.hxx>
+#include <editeng/charscaleitem.hxx>
+#include <editeng/charrotateitem.hxx>
+#include <editeng/charreliefitem.hxx>
+#include <editeng/blnkitem.hxx>
+#include <editeng/hyznitem.hxx>
+#include <editeng/paravertalignitem.hxx>
+#include <editeng/pgrditem.hxx>
+#include <editeng/frmdiritem.hxx>
+#include <editeng/charhiddenitem.hxx>
+#include <fmtpdsc.hxx>
+#include <node.hxx>
+#include <ndtxt.hxx> // SwTxtNode, siehe unten: JoinNode()
+#include <pam.hxx> // fuer SwPam
+#include <doc.hxx>
+#include <pagedesc.hxx> // class SwPageDesc
+#include <fmtanchr.hxx>
+#include <fmtcntnt.hxx>
+#include <fchrfmt.hxx>
+#include <fmthdft.hxx>
+#include <fmtclds.hxx>
+#include <fmtftntx.hxx>
+#include <frmatr.hxx>
+#include <section.hxx>
+#include <lineinfo.hxx>
+#include <fmtline.hxx>
+#include <txatbase.hxx>
+#include <fmtflcnt.hxx>
+#include <fmtclbl.hxx>
+#include <tgrditem.hxx>
+#include <hfspacingitem.hxx>
+#include <swtable.hxx>
+#include <fltini.hxx> //For CalculateFlySize
+#include "writerhelper.hxx"
+#include "writerwordglue.hxx"
+#include "ww8scan.hxx"
+#include "ww8par2.hxx" // class WW8RStyle, class WwAnchorPara
+#include "ww8graf.hxx"
+
+// #i27767#
+#include <fmtwrapinfluenceonobjpos.hxx>
+
+using namespace sw::util;
+using namespace sw::types;
+using namespace ::com::sun::star;
+using namespace nsHdFtFlags;
+
+//-----------------------------------------
+// diverses
+//-----------------------------------------
+
+#define MM_250 1417 // WW-Default fuer Hor. Seitenraender: 2.5 cm
+#define MM_200 1134 // WW-Default fuer u.Seitenrand: 2.0 cm
+
+
+sal_uInt8 lcl_ReadBorders(bool bVer67, WW8_BRC* brc, WW8PLCFx_Cp_FKP* pPap,
+ const WW8RStyle* pSty = 0, const WW8PLCFx_SEPX* pSep = 0);
+
+
+ColorData SwWW8ImplReader::GetCol(sal_uInt8 nIco)
+{
+ static const ColorData eSwWW8ColA[] =
+ {
+ COL_AUTO, COL_BLACK, COL_LIGHTBLUE, COL_LIGHTCYAN, COL_LIGHTGREEN,
+ COL_LIGHTMAGENTA, COL_LIGHTRED, COL_YELLOW, COL_WHITE, COL_BLUE,
+ COL_CYAN, COL_GREEN, COL_MAGENTA, COL_RED, COL_BROWN, COL_GRAY,
+ COL_LIGHTGRAY
+ };
+
+ return eSwWW8ColA[nIco];
+}
+
+inline sal_uInt32 MSRoundTweak(sal_uInt32 x)
+{
+ return x;
+}
+
+/***************************************************************************
+# Seiten - Attribute, die nicht ueber die Attribut-Verwaltung, sondern
+# ueber ...->HasSprm abgearbeitet werden
+# ( ausser OLST, dass weiterhin ein normales Attribut ist )
+#**************************************************************************/
+
+static short ReadSprm( const WW8PLCFx_SEPX* pSep, sal_uInt16 nId, short nDefaultVal )
+{
+ const sal_uInt8* pS = pSep->HasSprm( nId ); // sprm da ?
+ short nVal = ( pS ) ? SVBT16ToShort( pS ) : nDefaultVal;
+ return nVal;
+}
+
+static sal_uInt16 ReadUSprm( const WW8PLCFx_SEPX* pSep, sal_uInt16 nId, short nDefaultVal )
+{
+ const sal_uInt8* pS = pSep->HasSprm( nId ); // sprm da ?
+ sal_uInt16 nVal = ( pS ) ? SVBT16ToShort( pS ) : nDefaultVal;
+ return nVal;
+}
+
+static sal_uInt8 ReadBSprm( const WW8PLCFx_SEPX* pSep, sal_uInt16 nId, sal_uInt8 nDefaultVal )
+{
+ const sal_uInt8* pS = pSep->HasSprm( nId ); // sprm da ?
+ sal_uInt8 nVal = ( pS ) ? SVBT8ToByte( pS ) : nDefaultVal;
+ return nVal;
+}
+
+void wwSection::SetDirection()
+{
+ //sprmSTextFlow
+ switch (maSep.wTextFlow)
+ {
+ default:
+ OSL_ENSURE(!this, "Unknown layout type");
+ case 0:
+ meDir=FRMDIR_HORI_LEFT_TOP;
+ break;
+ case 1:
+ meDir=FRMDIR_VERT_TOP_RIGHT;
+ break;
+ case 2:
+ //asian letters are not rotated, western are. We can't import
+ //bottom to top going left to right, we can't do this in
+ //pages, (in drawboxes we could partly hack it with a rotated
+ //drawing box, though not frame)
+ meDir=FRMDIR_VERT_TOP_RIGHT;
+ break;
+ case 3:
+ //asian letters are not rotated, western are. We can't import
+ meDir=FRMDIR_VERT_TOP_RIGHT;
+ break;
+ case 4:
+ //asian letters are rotated, western not. We can't import
+ meDir=FRMDIR_HORI_LEFT_TOP;
+ break;
+ }
+
+ sal_uInt8 nRTLPgn = maSep.fBiDi;
+ if ((meDir == FRMDIR_HORI_LEFT_TOP) && nRTLPgn)
+ meDir = FRMDIR_HORI_RIGHT_TOP;
+}
+
+bool wwSection::IsVertical() const
+{
+ if (meDir == FRMDIR_VERT_TOP_RIGHT || meDir == FRMDIR_VERT_TOP_LEFT)
+ return true;
+ return false;
+}
+
+/*
+ This is something of festering mapping, I'm open to better ways of doing it,
+ but primarily the grid in writer is different to that in word. In writer the
+ grid elements are squares with ruby rows inbetween. While in word there is no
+ ruby stuff, and the elements are rectangles. By misusing the ruby row I can
+ handle distortions in one direction, but its all a bit of a mess:
+*/
+void SwWW8ImplReader::SetDocumentGrid(SwFrmFmt &rFmt, const wwSection &rSection)
+{
+ if (bVer67)
+ return;
+
+ rFmt.SetFmtAttr(SvxFrameDirectionItem(rSection.meDir, RES_FRAMEDIR));
+
+ SwTwips nTextareaHeight = rFmt.GetFrmSize().GetHeight();
+ const SvxULSpaceItem &rUL = ItemGet<SvxULSpaceItem>(rFmt, RES_UL_SPACE);
+ nTextareaHeight -= rUL.GetUpper();
+ nTextareaHeight -= rUL.GetLower();
+
+ SwTwips nTextareaWidth = rFmt.GetFrmSize().GetWidth();
+ const SvxLRSpaceItem &rLR = ItemGet<SvxLRSpaceItem>(rFmt, RES_LR_SPACE);
+ nTextareaWidth -= rLR.GetLeft();
+ nTextareaWidth -= rLR.GetRight();
+
+ if (rSection.IsVertical())
+ std::swap(nTextareaHeight, nTextareaWidth);
+
+ SwTextGridItem aGrid;
+ aGrid.SetDisplayGrid(false);
+ aGrid.SetPrintGrid(false);
+ SwTextGrid eType=GRID_NONE;
+
+ switch (rSection.maSep.clm)
+ {
+ case 0:
+ eType = GRID_NONE;
+ break;
+ default:
+ OSL_ENSURE(!this, "Unknown grid type");
+ case 3:
+ eType = GRID_LINES_CHARS;
+ aGrid.SetSnapToChars(sal_True);
+ break;
+ case 1:
+ eType = GRID_LINES_CHARS;
+ aGrid.SetSnapToChars(sal_False);
+ break;
+ case 2:
+ eType = GRID_LINES_ONLY;
+ break;
+ }
+
+ aGrid.SetGridType(eType);
+
+ // seem to not add external leading in word, or the character would run across
+ // two line in some cases.
+ if (eType != GRID_NONE)
+ rDoc.set(IDocumentSettingAccess::ADD_EXT_LEADING, false);
+
+ //force to set document as standard page mode
+ sal_Bool bSquaredMode = sal_False;
+ rDoc.SetDefaultPageMode( bSquaredMode );
+ aGrid.SetSquaredMode( bSquaredMode );
+
+ //sep.dyaLinePitch
+ sal_Int32 nLinePitch = rSection.maSep.dyaLinePitch;
+
+ //Get the size of word's default styles font
+ sal_uInt32 nCharWidth=240;
+ for (sal_uInt16 nI = 0; nI < pStyles->GetCount(); ++nI)
+ {
+ if (pCollA[nI].bValid && pCollA[nI].pFmt &&
+ pCollA[nI].GetWWStyleId() == 0)
+ {
+ nCharWidth = ItemGet<SvxFontHeightItem>(*(pCollA[nI].pFmt),
+ RES_CHRATR_CJK_FONTSIZE).GetHeight();
+ break;
+ }
+ }
+
+ //dxtCharSpace
+ if (rSection.maSep.dxtCharSpace)
+ {
+ sal_uInt32 nCharSpace = rSection.maSep.dxtCharSpace;
+ //main lives in top 20 bits, and is signed.
+ sal_Int32 nMain = (nCharSpace & 0xFFFFF000);
+ nMain/=0x1000;
+ nCharWidth += nMain*20;
+
+ int nFraction = (nCharSpace & 0x00000FFF);
+ nFraction = (nFraction*20)/0xFFF;
+ nCharWidth += nFraction;
+ }
+
+ aGrid.SetBaseWidth( writer_cast<sal_uInt16>(nCharWidth));
+ aGrid.SetLines(writer_cast<sal_uInt16>(nTextareaHeight/nLinePitch));
+ aGrid.SetBaseHeight(writer_cast<sal_uInt16>(nLinePitch));
+
+ sal_Int32 nRubyHeight = 0;
+ aGrid.SetRubyHeight(writer_cast<sal_uInt16>(nRubyHeight));
+
+ rFmt.SetFmtAttr(aGrid);
+}
+
+void SwWW8ImplReader::Read_ParaBiDi(sal_uInt16, const sal_uInt8* pData, short nLen)
+{
+ if( nLen < 0 )
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_FRAMEDIR);
+ else
+ {
+ SvxFrameDirection eDir =
+ *pData ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP;
+ NewAttr(SvxFrameDirectionItem(eDir, RES_FRAMEDIR));
+ }
+}
+
+bool wwSectionManager::SetCols(SwFrmFmt &rFmt, const wwSection &rSection,
+ sal_uInt32 nNettoWidth) const
+{
+ //sprmSCcolumns - Anzahl der Spalten - 1
+ sal_Int16 nCols = rSection.NoCols();
+
+ if (nCols < 2)
+ return false; // keine oder bloedsinnige Spalten
+
+ SwFmtCol aCol; // Erzeuge SwFmtCol
+
+ //sprmSDxaColumns - Default-Abstand 1.25 cm
+ sal_Int32 nColSpace = rSection.StandardColSeperation();
+
+ // sprmSLBetween
+ if (rSection.maSep.fLBetween)
+ {
+ aCol.SetLineAdj(COLADJ_TOP); // Line
+ aCol.SetLineHeight(100);
+ aCol.SetLineColor(Color(COL_BLACK));
+ aCol.SetLineWidth(1);
+ }
+
+ aCol.Init(nCols, writer_cast<sal_uInt16>(nColSpace),
+ writer_cast<sal_uInt16>(nNettoWidth));
+
+ // sprmSFEvenlySpaced
+ if (!rSection.maSep.fEvenlySpaced)
+ {
+ aCol._SetOrtho(false);
+ int nIdx = 1;
+ for (sal_uInt16 i = 0; i < nCols; i++ )
+ {
+ SwColumn* pCol = aCol.GetColumns()[i];
+ sal_Int32 nLeft = rSection.maSep.rgdxaColumnWidthSpacing[nIdx-1]/2;
+ sal_Int32 nRight = rSection.maSep.rgdxaColumnWidthSpacing[nIdx+1]/2;
+ sal_Int32 nWishWidth = rSection.maSep.rgdxaColumnWidthSpacing[nIdx]
+ + nLeft + nRight;
+ pCol->SetWishWidth(writer_cast<sal_uInt16>(nWishWidth));
+ pCol->SetLeft(writer_cast<sal_uInt16>(nLeft));
+ pCol->SetRight(writer_cast<sal_uInt16>(nRight));
+ nIdx += 2;
+ }
+ aCol.SetWishWidth(writer_cast<sal_uInt16>(nNettoWidth));
+ }
+ rFmt.SetFmtAttr(aCol);
+ return true;
+}
+
+void wwSectionManager::SetLeftRight(wwSection &rSection)
+{
+ // 3. LR-Raender
+ sal_uInt32 nWWLe = MSRoundTweak(rSection.maSep.dxaLeft);
+ sal_uInt32 nWWRi = MSRoundTweak(rSection.maSep.dxaRight);
+ sal_uInt32 nWWGu = rSection.maSep.dzaGutter;
+
+ /*
+ fRTLGutter is set if the gutter is on the right, the gutter is otherwise
+ placed on the left unless the global dop options are to put it on top, that
+ case is handled in GetPageULData.
+ */
+ if (rSection.maSep.fRTLGutter)
+ nWWRi += nWWGu;
+ else if (!mrReader.pWDop->iGutterPos)
+ nWWLe += nWWGu;
+
+ // Left / Right
+ if ((rSection.nPgWidth - nWWLe - nWWRi) < MINLAY)
+ {
+ /*
+ There are some label templates which are "broken", they specify
+ margins which make no sense e.g. Left 16.10cm, Right 16.10cm. So the
+ space left between the margins is less than 0 In word the left margin
+ is honoured and if the right margin would be past the left margin is
+ left at the left margin position.
+
+ Now this will work fine for importing, layout and exporting, *but* the
+ page layout dialog has a hardcoded minimum page width of 0.5cm so it
+ will report a different value than what is actually being used. i.e.
+ it will add up the values to give a wider page than is actually being
+ used.
+ */
+ nWWRi = rSection.nPgWidth - nWWLe - MINLAY;
+ }
+
+ rSection.nPgLeft = nWWLe;
+ rSection.nPgRight = nWWRi;
+}
+
+void wwSectionManager::SetPage(SwPageDesc &rInPageDesc, SwFrmFmt &rFmt,
+ const wwSection &rSection, bool bIgnoreCols) const
+{
+ // 1. Orientierung
+ rInPageDesc.SetLandscape(rSection.IsLandScape());
+
+ // 2. Papiergroesse
+ SwFmtFrmSize aSz( rFmt.GetFrmSize() );
+ aSz.SetWidth(rSection.GetPageWidth());
+ aSz.SetHeight(SvxPaperInfo::GetSloppyPaperDimension(rSection.GetPageHeight()));
+ rFmt.SetFmtAttr(aSz);
+
+ rFmt.SetFmtAttr(
+ SvxLRSpaceItem(rSection.GetPageLeft(), rSection.GetPageRight(), 0, 0, RES_LR_SPACE));
+
+ if (!bIgnoreCols)
+ SetCols(rFmt, rSection, rSection.GetTextAreaWidth());
+}
+
+sal_uInt16 lcl_MakeSafeNegativeSpacing(sal_uInt16 nIn)
+{
+ if (nIn > SHRT_MAX)
+ nIn = 0;
+ return nIn;
+}
+
+void SwWW8ImplReader::SetPageBorder(SwFrmFmt &rFmt, const wwSection &rSection) const
+{
+ if (!IsBorder(rSection.brc))
+ return;
+
+ SfxItemSet aSet(rFmt.GetAttrSet());
+ short aSizeArray[5]={0};
+ SetFlyBordersShadow(aSet, rSection.brc, &aSizeArray[0]);
+ SvxLRSpaceItem aLR(ItemGet<SvxLRSpaceItem>(aSet, RES_LR_SPACE));
+ SvxULSpaceItem aUL(ItemGet<SvxULSpaceItem>(aSet, RES_UL_SPACE));
+
+ SvxBoxItem aBox(ItemGet<SvxBoxItem>(aSet, RES_BOX));
+ short aOriginalBottomMargin = aBox.GetDistance(BOX_LINE_BOTTOM);
+
+ if (rSection.maSep.pgbOffsetFrom == 1)
+ {
+ sal_uInt16 nDist;
+ if (aBox.GetLeft())
+ {
+ nDist = aBox.GetDistance(BOX_LINE_LEFT);
+ aBox.SetDistance(lcl_MakeSafeNegativeSpacing(static_cast<sal_uInt16>(aLR.GetLeft() - nDist)), BOX_LINE_LEFT);
+ aSizeArray[WW8_LEFT] =
+ aSizeArray[WW8_LEFT] - nDist + aBox.GetDistance(BOX_LINE_LEFT);
+ }
+
+ if (aBox.GetRight())
+ {
+ nDist = aBox.GetDistance(BOX_LINE_RIGHT);
+ aBox.SetDistance(lcl_MakeSafeNegativeSpacing(static_cast<sal_uInt16>(aLR.GetRight() - nDist)), BOX_LINE_RIGHT);
+ aSizeArray[WW8_RIGHT] =
+ aSizeArray[WW8_RIGHT] - nDist + aBox.GetDistance(BOX_LINE_RIGHT);
+ }
+
+ if (aBox.GetTop())
+ {
+ nDist = aBox.GetDistance(BOX_LINE_TOP);
+ aBox.SetDistance(lcl_MakeSafeNegativeSpacing(static_cast<sal_uInt16>(aUL.GetUpper() - nDist)), BOX_LINE_TOP);
+ aSizeArray[WW8_TOP] =
+ aSizeArray[WW8_TOP] - nDist + aBox.GetDistance(BOX_LINE_TOP);
+ }
+
+ if (aBox.GetBottom())
+ {
+ nDist = aBox.GetDistance(BOX_LINE_BOTTOM);
+ aBox.SetDistance(lcl_MakeSafeNegativeSpacing(static_cast<sal_uInt16>(aUL.GetLower() - nDist)), BOX_LINE_BOTTOM);
+ aSizeArray[WW8_BOT] =
+ aSizeArray[WW8_BOT] - nDist + aBox.GetDistance(BOX_LINE_BOTTOM);
+ }
+
+ aSet.Put(aBox);
+ }
+
+ if (aBox.GetLeft())
+ aLR.SetLeft(lcl_MakeSafeNegativeSpacing(static_cast<sal_uInt16>(aLR.GetLeft() - aSizeArray[WW8_LEFT])));
+ if (aBox.GetRight())
+ aLR.SetRight(lcl_MakeSafeNegativeSpacing(static_cast<sal_uInt16>(aLR.GetRight() - aSizeArray[WW8_RIGHT])));
+ if (aBox.GetTop())
+ aUL.SetUpper(lcl_MakeSafeNegativeSpacing(static_cast<sal_uInt16>(aUL.GetUpper() - aSizeArray[WW8_TOP])));
+ if (aBox.GetBottom())
+ {
+ //#i30088# and #i30074# - do a final sanity check on
+ //bottom value. Do not allow a resulting zero if bottom
+ //Border margin value was not originally zero.
+ if(aUL.GetLower() != 0)
+ aUL.SetLower(lcl_MakeSafeNegativeSpacing(static_cast<sal_uInt16>(aUL.GetLower() - aSizeArray[WW8_BOT])));
+ else
+ aUL.SetLower(lcl_MakeSafeNegativeSpacing(static_cast<sal_uInt16>(aOriginalBottomMargin - aSizeArray[WW8_BOT])));
+ }
+
+ aSet.Put(aLR);
+ aSet.Put(aUL);
+ rFmt.SetFmtAttr(aSet);
+}
+
+void wwSectionManager::GetPageULData(const wwSection &rSection, bool bFirst,
+ wwSectionManager::wwULSpaceData& rData) const
+{
+ sal_Int32 nWWUp = rSection.maSep.dyaTop;
+ sal_Int32 nWWLo = rSection.maSep.dyaBottom;
+ sal_uInt32 nWWHTop = rSection.maSep.dyaHdrTop;
+ sal_uInt32 nWWFBot = rSection.maSep.dyaHdrBottom;
+
+ /*
+ If there is gutter in 97+ and the dop says put it on top then get the
+ gutter distance and set it to the top margin. When we are "two pages
+ in one" the gutter is put at the top of odd pages, and bottom of
+ even pages, something we cannot do. So we will put it on top of all
+ pages, that way the pages are at least the right size.
+ */
+ if (
+ (!mrReader.bVer67 && mrReader.pWDop->iGutterPos &&
+ rSection.maSep.fRTLGutter)
+ )
+ {
+ nWWUp += rSection.maSep.dzaGutter;
+ }
+
+ if( bFirst )
+ rData.bHasHeader = (rSection.maSep.grpfIhdt & WW8_HEADER_FIRST) !=0;
+ else
+ {
+ rData.bHasHeader = (rSection.maSep.grpfIhdt &
+ (WW8_HEADER_EVEN | WW8_HEADER_ODD)) != 0;
+ }
+
+ if( rData.bHasHeader )
+ {
+ rData.nSwUp = nWWHTop; // Header -> umrechnen
+ // #i19922# - correction:
+ // consider that <nWWUp> can be negative, compare only if it's positive
+ if ( nWWUp > 0 &&
+ static_cast<sal_uInt32>(abs(nWWUp)) >= nWWHTop )
+ rData.nSwHLo = nWWUp - nWWHTop;
+ else
+ rData.nSwHLo = 0;
+
+ // #i19922# - minimum page header height is now 1mm
+ // use new constant <cMinHdFtHeight>
+ if (rData.nSwHLo < sal::static_int_cast< sal_uInt32 >(cMinHdFtHeight))
+ rData.nSwHLo = sal::static_int_cast< sal_uInt32 >(cMinHdFtHeight);
+ }
+ else // kein Header -> Up einfach uebernehmen
+ rData.nSwUp = Abs(nWWUp);
+
+ if( bFirst )
+ rData.bHasFooter = (rSection.maSep.grpfIhdt & WW8_FOOTER_FIRST) !=0;
+ else
+ {
+ rData.bHasFooter = (rSection.maSep.grpfIhdt &
+ (WW8_FOOTER_EVEN | WW8_FOOTER_ODD)) != 0;
+ }
+
+ if( rData.bHasFooter )
+ {
+ rData.nSwLo = nWWFBot; // Footer -> Umrechnen
+ // #i19922# - correction: consider that <nWWLo> can be negative, compare only if it's positive
+ if ( nWWLo > 0 &&
+ static_cast<sal_uInt32>(abs(nWWLo)) >= nWWFBot )
+ rData.nSwFUp = nWWLo - nWWFBot;
+ else
+ rData.nSwFUp = 0;
+
+ // #i19922# - minimum page header height is now 1mm
+ // use new constant <cMinHdFtHeight>
+ if (rData.nSwFUp < sal::static_int_cast< sal_uInt32 >(cMinHdFtHeight))
+ rData.nSwFUp = sal::static_int_cast< sal_uInt32 >(cMinHdFtHeight);
+ }
+ else // kein Footer -> Lo einfach uebernehmen
+ rData.nSwLo = Abs(nWWLo);
+}
+
+void wwSectionManager::SetPageULSpaceItems(SwFrmFmt &rFmt,
+ wwSectionManager::wwULSpaceData& rData, const wwSection &rSection) const
+{
+ if (rData.bHasHeader) // ... und Header-Lower setzen
+ {
+ //Kopfzeilenhoehe minimal sezten
+ if (SwFrmFmt* pHdFmt = (SwFrmFmt*)rFmt.GetHeader().GetHeaderFmt())
+ {
+ SvxULSpaceItem aHdUL(pHdFmt->GetULSpace());
+ if (!rSection.IsFixedHeightHeader()) //normal
+ {
+ pHdFmt->SetFmtAttr(SwFmtFrmSize(ATT_MIN_SIZE, 0, rData.nSwHLo));
+ // #i19922# - minimum page header height is now 1mm
+ // use new constant <cMinHdFtHeight>
+ aHdUL.SetLower( writer_cast<sal_uInt16>(rData.nSwHLo - cMinHdFtHeight) );
+ pHdFmt->SetFmtAttr(SwHeaderAndFooterEatSpacingItem(
+ RES_HEADER_FOOTER_EAT_SPACING, true));
+ }
+ else
+ {
+ // #i48832# - set correct spacing between header and body.
+ const SwTwips nHdLowerSpace( Abs(rSection.maSep.dyaTop) - rData.nSwUp - rData.nSwHLo );
+ pHdFmt->SetFmtAttr(SwFmtFrmSize(ATT_FIX_SIZE, 0, rData.nSwHLo + nHdLowerSpace));
+ aHdUL.SetLower( static_cast< sal_uInt16 >(nHdLowerSpace) );
+ // <--
+ pHdFmt->SetFmtAttr(SwHeaderAndFooterEatSpacingItem(
+ RES_HEADER_FOOTER_EAT_SPACING, false));
+ }
+ pHdFmt->SetFmtAttr(aHdUL);
+ }
+ }
+
+ if (rData.bHasFooter) // ... und Footer-Upper setzen
+ {
+ if (SwFrmFmt* pFtFmt = (SwFrmFmt*)rFmt.GetFooter().GetFooterFmt())
+ {
+ SvxULSpaceItem aFtUL(pFtFmt->GetULSpace());
+ if (!rSection.IsFixedHeightFooter()) //normal
+ {
+ pFtFmt->SetFmtAttr(SwFmtFrmSize(ATT_MIN_SIZE, 0, rData.nSwFUp));
+ // #i19922# - minimum page header height is now 1mm
+ // use new constant <cMinHdFtHeight>
+ aFtUL.SetUpper( writer_cast<sal_uInt16>(rData.nSwFUp - cMinHdFtHeight) );
+ pFtFmt->SetFmtAttr(SwHeaderAndFooterEatSpacingItem(
+ RES_HEADER_FOOTER_EAT_SPACING, true));
+ }
+ else
+ {
+ // #i48832# - set correct spacing between footer and body.
+ const SwTwips nFtUpperSpace( Abs(rSection.maSep.dyaBottom) - rData.nSwLo - rData.nSwFUp );
+ pFtFmt->SetFmtAttr(SwFmtFrmSize(ATT_FIX_SIZE, 0, rData.nSwFUp + nFtUpperSpace));
+ aFtUL.SetUpper( static_cast< sal_uInt16 >(nFtUpperSpace) );
+ // <--
+ pFtFmt->SetFmtAttr(SwHeaderAndFooterEatSpacingItem(
+ RES_HEADER_FOOTER_EAT_SPACING, false));
+ }
+ pFtFmt->SetFmtAttr(aFtUL);
+ }
+ }
+
+ SvxULSpaceItem aUL(writer_cast<sal_uInt16>(rData.nSwUp),
+ writer_cast<sal_uInt16>(rData.nSwLo), RES_UL_SPACE);
+ rFmt.SetFmtAttr(aUL);
+}
+
+SwSectionFmt *wwSectionManager::InsertSection(
+ SwPaM& rMyPaM, wwSection &rSection)
+{
+ SwSectionData aSection( CONTENT_SECTION,
+ mrReader.rDoc.GetUniqueSectionName() );
+
+ SfxItemSet aSet( mrReader.rDoc.GetAttrPool(), aFrmFmtSetRange );
+
+ sal_uInt8 nRTLPgn = maSegments.empty() ? 0 : maSegments.back().IsBiDi();
+ aSet.Put(SvxFrameDirectionItem(
+ nRTLPgn ? FRMDIR_HORI_RIGHT_TOP : FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR));
+
+ if (2 == mrReader.pWDop->fpc)
+ aSet.Put( SwFmtFtnAtTxtEnd(FTNEND_ATTXTEND));
+ if (0 == mrReader.pWDop->epc)
+ aSet.Put( SwFmtEndAtTxtEnd(FTNEND_ATTXTEND));
+
+ aSection.SetProtectFlag(SectionIsProtected(rSection));
+
+ rSection.mpSection =
+ mrReader.rDoc.InsertSwSection( rMyPaM, aSection, 0, & aSet );
+ OSL_ENSURE(rSection.mpSection, "section not inserted!");
+ if (!rSection.mpSection)
+ return 0;
+
+ SwPageDesc *pPage = 0;
+ mySegrIter aEnd = maSegments.rend();
+ for (mySegrIter aIter = maSegments.rbegin(); aIter != aEnd; ++aIter)
+ {
+ if (0 != (pPage = aIter->mpPage))
+ break;
+ }
+
+ OSL_ENSURE(pPage, "no page outside this section!");
+
+ if (!pPage)
+ pPage = &mrReader.rDoc._GetPageDesc(0);
+
+ if (!pPage)
+ return 0;
+
+ SwSectionFmt *pFmt = rSection.mpSection->GetFmt();
+ OSL_ENSURE(pFmt, "impossible");
+ if (!pFmt)
+ return 0;
+
+ SwFrmFmt& rFmt = pPage->GetMaster();
+ const SvxLRSpaceItem& rLR = rFmt.GetLRSpace();
+ long nPageLeft = rLR.GetLeft();
+ long nPageRight = rLR.GetRight();
+ long nSectionLeft = rSection.GetPageLeft() - nPageLeft;
+ long nSectionRight = rSection.GetPageRight() - nPageRight;
+ if ((nSectionLeft != 0) || (nSectionRight != 0))
+ {
+ SvxLRSpaceItem aLR(nSectionLeft, nSectionRight, 0, 0, RES_LR_SPACE);
+ pFmt->SetFmtAttr(aLR);
+ }
+
+ SetCols(*pFmt, rSection, rSection.GetTextAreaWidth());
+ return pFmt;
+}
+
+void SwWW8ImplReader::HandleLineNumbering(const wwSection &rSection)
+{
+ // check if Line Numbering must be activated or resetted
+ if (mbNewDoc && rSection.maSep.nLnnMod)
+ {
+ // restart-numbering-mode: 0 per page, 1 per section, 2 never restart
+ bool bRestartLnNumPerSection = (1 == rSection.maSep.lnc);
+
+ if (bNoLnNumYet)
+ {
+ SwLineNumberInfo aInfo( rDoc.GetLineNumberInfo() );
+
+ aInfo.SetPaintLineNumbers(true);
+
+ aInfo.SetRestartEachPage(rSection.maSep.lnc == 0);
+
+ aInfo.SetPosFromLeft(writer_cast<sal_uInt16>(rSection.maSep.dxaLnn));
+
+ //Paint only for every n line
+ aInfo.SetCountBy(rSection.maSep.nLnnMod);
+
+ // to be defaulted features ( HARDCODED in MS Word 6,7,8,9 )
+ aInfo.SetCountBlankLines(true);
+ aInfo.SetCountInFlys(false);
+ aInfo.SetPos( LINENUMBER_POS_LEFT );
+ SvxNumberType aNumType; // this sets SVX_NUM_ARABIC per default
+ aInfo.SetNumType( aNumType );
+
+ rDoc.SetLineNumberInfo( aInfo );
+ bNoLnNumYet = false;
+ }
+
+ if (
+ (0 < rSection.maSep.lnnMin) ||
+ (bRestartLnNumPerSection && !bNoLnNumYet)
+ )
+ {
+ SwFmtLineNumber aLN;
+ if (const SwFmtLineNumber* pLN
+ = (const SwFmtLineNumber*)GetFmtAttr(RES_LINENUMBER))
+ {
+ aLN.SetCountLines( pLN->IsCount() );
+ }
+ aLN.SetStartValue(1 + rSection.maSep.lnnMin);
+ NewAttr(aLN);
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_LINENUMBER);
+ }
+ bNoLnNumYet = false;
+ }
+}
+
+wwSection::wwSection(const SwPosition &rPos) : maStart(rPos.nNode),
+ mpSection(0), mpTitlePage(0), mpPage(0), meDir(FRMDIR_HORI_LEFT_TOP),
+ nPgWidth(SvxPaperInfo::GetPaperSize(PAPER_A4).Width()),
+ nPgLeft(MM_250), nPgRight(MM_250), mnBorders(0), mbHasFootnote(false)
+{
+}
+
+void wwSectionManager::SetNumberingType(const wwSection &rNewSection,
+ SwPageDesc &rPageDesc) const
+{
+ // Seitennummernformat speichern
+ static const SvxExtNumType aNumTyp[5] =
+ {
+ SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,
+ SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N
+ };
+
+ SvxNumberType aType;
+ aType.SetNumberingType( static_cast< sal_Int16 >(aNumTyp[rNewSection.maSep.nfcPgn]) );
+ rPageDesc.SetNumType(aType);
+}
+
+// Bei jedem Abschnittswechsel ( auch am Anfang eines Dokuments ) wird
+// CreateSep gerufen, dass dann den / die Pagedesc(s) erzeugt und
+// mit Attributen un KF-Texten fuellt.
+// Dieses Vorgehen ist noetig geworden, da die UEbersetzung der verschiedenen
+// Seiten-Attribute zu stark verflochten ist.
+void wwSectionManager::CreateSep(const long nTxtPos, bool /*bMustHaveBreak*/)
+{
+ /*
+ #i1909# section/page breaks should not occur in tables or subpage
+ elements like frames. Word itself ignores them in this case. The bug is
+ more likely that this filter created such documents in the past!
+ */
+ if (mrReader.nInTable || mrReader.bTxbxFlySection || mrReader.InLocalApo())
+ return;
+
+ WW8PLCFx_SEPX* pSep = mrReader.pPlcxMan->GetSepPLCF();
+ OSL_ENSURE(pSep, "impossible!");
+ if (!pSep)
+ return;
+
+ ww::WordVersion eVer = mrReader.GetFib().GetFIBVersion();
+
+ // M.M. Create a linked section if the WkbPLCF
+ // has an entry for one at this cp
+ WW8PLCFspecial* pWkb = mrReader.pPlcxMan->GetWkbPLCF();
+ if (pWkb && pWkb->SeekPosExact(nTxtPos) &&
+ pWkb->Where() == nTxtPos)
+ {
+ void* pData;
+ WW8_CP nTest;
+ pWkb->Get(nTest, pData);
+ String sSectionName = mrReader.aLinkStringMap[SVBT16ToShort( ((WW8_WKB*)pData)->nLinkId) ];
+ mrReader.ConvertFFileName(sSectionName, sSectionName);
+ SwSectionData aSection(FILE_LINK_SECTION, sSectionName);
+ aSection.SetLinkFileName( sSectionName );
+ aSection.SetProtectFlag(true);
+ // #i19922# - improvement: return value of method <Insert> not used.
+ mrReader.rDoc.InsertSwSection(*mrReader.pPaM, aSection, 0, 0, false);
+ }
+
+ wwSection aLastSection(*mrReader.pPaM->GetPoint());
+ if (!maSegments.empty())
+ aLastSection = maSegments.back();
+
+ //Here
+ sal_uInt16 nLIdx = ( ( mrReader.pWwFib->lid & 0xff ) == 0x9 ) ? 1 : 0;
+
+ //BEGIN read section values
+ wwSection aNewSection(*mrReader.pPaM->GetPoint());
+
+ static const sal_uInt16 aVer2Ids0[] =
+ {
+ /*sprmSBkc*/ 117,
+ /*sprmSFTitlePage*/ 118,
+ /*sprmSNfcPgn*/ 122,
+ /*sprmSCcolumns*/ 119,
+ /*sprmSDxaColumns*/ 120,
+ /*sprmSLBetween*/ 133
+ };
+
+ static const sal_uInt16 aVer67Ids0[] =
+ {
+ /*sprmSBkc*/ 142,
+ /*sprmSFTitlePage*/ 143,
+ /*sprmSNfcPgn*/ 147,
+ /*sprmSCcolumns*/ 144,
+ /*sprmSDxaColumns*/ 145,
+ /*sprmSLBetween*/ 158
+ };
+
+ static const sal_uInt16 aVer8Ids0[] =
+ {
+ /*sprmSBkc*/ 0x3009,
+ /*sprmSFTitlePage*/ 0x300A,
+ /*sprmSNfcPgn*/ 0x300E,
+ /*sprmSCcolumns*/ 0x500B,
+ /*sprmSDxaColumns*/ 0x900C,
+ /*sprmSLBetween*/ 0x3019
+ };
+
+ const sal_uInt16* pIds = eVer <= ww::eWW2 ? aVer2Ids0 : eVer <= ww::eWW7 ? aVer67Ids0 : aVer8Ids0;
+
+ if (!maSegments.empty())
+ {
+ // Type of break: break codes are:
+ // 0 No break
+ // 1 New column
+ // 2 New page
+ // 3 Even page
+ // 4 Odd page
+ if (const sal_uInt8* pSprmBkc = pSep->HasSprm(pIds[0]))
+ aNewSection.maSep.bkc = *pSprmBkc;
+ }
+
+ // Has a table page
+ aNewSection.maSep.fTitlePage =
+ (0 != ReadBSprm( pSep, pIds[1], 0 ));
+
+ // sprmSNfcPgn
+ aNewSection.maSep.nfcPgn = ReadBSprm( pSep, pIds[2], 0 );
+ if (aNewSection.maSep.nfcPgn > 4)
+ aNewSection.maSep.nfcPgn = 0;
+
+ aNewSection.maSep.fUnlocked = eVer > ww::eWW2 ? ReadBSprm(pSep, (eVer <= ww::eWW7 ? 139 : 0x3006), 0 ) : 0;
+
+ // sprmSFBiDi
+ aNewSection.maSep.fBiDi = eVer >= ww::eWW8 ? ReadBSprm(pSep, 0x3228, 0) : 0;
+
+ aNewSection.maSep.ccolM1 = ReadSprm(pSep, pIds[3], 0 );
+
+ //sprmSDxaColumns - Default-Abstand 1.25 cm
+ aNewSection.maSep.dxaColumns = ReadUSprm( pSep, pIds[4], 708 );
+
+ // sprmSLBetween
+ aNewSection.maSep.fLBetween = ReadBSprm(pSep, pIds[5], 0 );
+
+ if (eVer >= ww::eWW6)
+ {
+ // sprmSFEvenlySpaced
+ aNewSection.maSep.fEvenlySpaced =
+ ReadBSprm(pSep, (eVer <= ww::eWW7 ? 138 : 0x3005), 1) ? true : false;
+
+ if (aNewSection.maSep.ccolM1 > 0 && !aNewSection.maSep.fEvenlySpaced)
+ {
+ aNewSection.maSep.rgdxaColumnWidthSpacing[0] = 0;
+ int nCols = aNewSection.maSep.ccolM1 + 1;
+ int nIdx = 0;
+ for (int i = 0; i < nCols; ++i)
+ {
+ //sprmSDxaColWidth
+ const sal_uInt8* pSW = pSep->HasSprm( (eVer <= ww::eWW7 ? 136 : 0xF203), sal_uInt8( i ) );
+
+ OSL_ENSURE( pSW, "+Sprm 136 (bzw. 0xF203) (ColWidth) fehlt" );
+ sal_uInt16 nWidth = pSW ? SVBT16ToShort(pSW + 1) : 1440;
+
+ aNewSection.maSep.rgdxaColumnWidthSpacing[++nIdx] = nWidth;
+
+ if (i < nCols-1)
+ {
+ //sprmSDxaColSpacing
+ const sal_uInt8* pSD = pSep->HasSprm( (eVer <= ww::eWW7 ? 137 : 0xF204), sal_uInt8( i ) );
+
+ OSL_ENSURE( pSD, "+Sprm 137 (bzw. 0xF204) (Colspacing) fehlt" );
+ if( pSD )
+ {
+ nWidth = SVBT16ToShort(pSD + 1);
+ aNewSection.maSep.rgdxaColumnWidthSpacing[++nIdx] = nWidth;
+ }
+ }
+ }
+ }
+ }
+
+ static const sal_uInt16 aVer2Ids1[] =
+ {
+ /*sprmSBOrientation*/ 137,
+ /*sprmSXaPage*/ 139,
+ /*sprmSYaPage*/ 140,
+ /*sprmSDxaLeft*/ 141,
+ /*sprmSDxaRight*/ 142,
+ /*sprmSDzaGutter*/ 145,
+ /*sprmSFPgnRestart*/ 125,
+ /*sprmSPgnStart*/ 136,
+ /*sprmSDmBinFirst*/ 115,
+ /*sprmSDmBinOther*/ 116
+ };
+
+ static const sal_uInt16 aVer67Ids1[] =
+ {
+ /*sprmSBOrientation*/ 162,
+ /*sprmSXaPage*/ 164,
+ /*sprmSYaPage*/ 165,
+ /*sprmSDxaLeft*/ 166,
+ /*sprmSDxaRight*/ 167,
+ /*sprmSDzaGutter*/ 170,
+ /*sprmSFPgnRestart*/ 150,
+ /*sprmSPgnStart*/ 161,
+ /*sprmSDmBinFirst*/ 140,
+ /*sprmSDmBinOther*/ 141
+ };
+
+ static const sal_uInt16 aVer8Ids1[] =
+ {
+ /*sprmSBOrientation*/ 0x301d,
+ /*sprmSXaPage*/ 0xB01F,
+ /*sprmSYaPage*/ 0xB020,
+ /*sprmSDxaLeft*/ 0xB021,
+ /*sprmSDxaRight*/ 0xB022,
+ /*sprmSDzaGutter*/ 0xB025,
+ /*sprmSFPgnRestart*/ 0x3011,
+ /*sprmSPgnStart*/ 0x501C,
+ /*sprmSDmBinFirst*/ 0x5007,
+ /*sprmSDmBinOther*/ 0x5008
+ };
+
+ pIds = eVer <= ww::eWW2 ? aVer2Ids1 : eVer <= ww::eWW7 ? aVer67Ids1 : aVer8Ids1;
+
+ // 1. Orientierung
+ aNewSection.maSep.dmOrientPage = ReadBSprm(pSep, pIds[0], 0);
+
+ // 2. Papiergroesse
+ aNewSection.maSep.xaPage = ReadUSprm(pSep, pIds[1], lLetterWidth);
+ aNewSection.nPgWidth = SvxPaperInfo::GetSloppyPaperDimension(aNewSection.maSep.xaPage);
+
+ aNewSection.maSep.yaPage = ReadUSprm(pSep, pIds[2], lLetterHeight);
+
+ // 3. LR-Raender
+ static const sal_uInt16 nLef[] = { MM_250, 1800 };
+ static const sal_uInt16 nRig[] = { MM_250, 1800 };
+
+ aNewSection.maSep.dxaLeft = ReadUSprm( pSep, pIds[3], nLef[nLIdx]);
+ aNewSection.maSep.dxaRight = ReadUSprm( pSep, pIds[4], nRig[nLIdx]);
+
+ // 2pages in 1sheet hackery ?
+ // #i31806# but only swap if 2page in 1sheet is enabled.
+ // its not clear if dmOrientPage is the correct member to
+ // decide on this but I am not about to 2nd guess cmc.
+ if(mrReader.pWDop->doptypography.f2on1 &&
+ aNewSection.maSep.dmOrientPage == 2)
+ std::swap(aNewSection.maSep.dxaLeft, aNewSection.maSep.dxaRight);
+
+ aNewSection.maSep.dzaGutter = ReadUSprm( pSep, pIds[5], 0);
+
+ aNewSection.maSep.fRTLGutter = static_cast< sal_uInt8 >(eVer >= ww::eWW8 ? ReadUSprm( pSep, 0x322A, 0 ) : 0);
+
+ // Page Number Restarts - sprmSFPgnRestart
+ aNewSection.maSep.fPgnRestart = ReadBSprm(pSep, pIds[6], 0);
+
+ aNewSection.maSep.pgnStart = ReadBSprm( pSep, pIds[7], 0 );
+
+ if (eVer >= ww::eWW6)
+ {
+ if (const sal_uInt8* p = pSep->HasSprm( (eVer <= ww::eWW7 ? 132 : 0x3001) ))
+ aNewSection.maSep.iHeadingPgn = *p;
+
+ if (const sal_uInt8* p = pSep->HasSprm( (eVer <= ww::eWW7 ? 131 : 0x3000) ))
+ aNewSection.maSep.cnsPgn = *p;
+ }
+
+ if(const sal_uInt8* pSprmSDmBinFirst = pSep->HasSprm( pIds[8] ))
+ aNewSection.maSep.dmBinFirst = *pSprmSDmBinFirst;
+
+ if (const sal_uInt8* pSprmSDmBinOther = pSep->HasSprm( pIds[9] ))
+ aNewSection.maSep.dmBinOther = *pSprmSDmBinOther;
+
+ static const sal_uInt16 nTop[] = { MM_250, 1440 };
+ static const sal_uInt16 nBot[] = { MM_200, 1440 };
+
+ static const sal_uInt16 aVer2Ids2[] =
+ {
+ /*sprmSDyaTop*/ 143,
+ /*sprmSDyaBottom*/ 144,
+ /*sprmSDyaHdrTop*/ 131,
+ /*sprmSDyaHdrBottom*/ 132,
+ /*sprmSNLnnMod*/ 129,
+ /*sprmSLnc*/ 127,
+ /*sprmSDxaLnn*/ 130,
+ /*sprmSLnnMin*/ 135
+ };
+
+ static const sal_uInt16 aVer67Ids2[] =
+ {
+ /*sprmSDyaTop*/ 168,
+ /*sprmSDyaBottom*/ 169,
+ /*sprmSDyaHdrTop*/ 156,
+ /*sprmSDyaHdrBottom*/ 157,
+ /*sprmSNLnnMod*/ 154,
+ /*sprmSLnc*/ 152,
+ /*sprmSDxaLnn*/ 155,
+ /*sprmSLnnMin*/ 160
+ };
+ static const sal_uInt16 aVer8Ids2[] =
+ {
+ /*sprmSDyaTop*/ 0x9023,
+ /*sprmSDyaBottom*/ 0x9024,
+ /*sprmSDyaHdrTop*/ 0xB017,
+ /*sprmSDyaHdrBottom*/ 0xB018,
+ /*sprmSNLnnMod*/ 0x5015,
+ /*sprmSLnc*/ 0x3013,
+ /*sprmSDxaLnn*/ 0x9016,
+ /*sprmSLnnMin*/ 0x501B
+ };
+
+ pIds = eVer <= ww::eWW2 ? aVer2Ids2 : eVer <= ww::eWW7 ? aVer67Ids2 : aVer8Ids2;
+
+ aNewSection.maSep.dyaTop = ReadSprm( pSep, pIds[0], nTop[nLIdx] );
+ aNewSection.maSep.dyaBottom = ReadSprm( pSep, pIds[1], nBot[nLIdx] );
+ aNewSection.maSep.dyaHdrTop = ReadUSprm( pSep, pIds[2], 720 );
+ aNewSection.maSep.dyaHdrBottom = ReadUSprm( pSep, pIds[3], 720 );
+
+ if (eVer >= ww::eWW8)
+ {
+ aNewSection.maSep.wTextFlow = ReadUSprm(pSep, 0x5033, 0);
+ aNewSection.maSep.clm = ReadUSprm( pSep, 0x5032, 0 );
+ aNewSection.maSep.dyaLinePitch = ReadUSprm(pSep, 0x9031, 360);
+ if (const sal_uInt8* pS = pSep->HasSprm(0x7030))
+ aNewSection.maSep.dxtCharSpace = SVBT32ToUInt32(pS);
+
+ //sprmSPgbProp
+ sal_uInt16 pgbProp = ReadSprm( pSep, 0x522F, 0 );
+ aNewSection.maSep.pgbApplyTo = pgbProp & 0x0007;
+ aNewSection.maSep.pgbPageDepth = (pgbProp & 0x0018) >> 3;
+ aNewSection.maSep.pgbOffsetFrom = (pgbProp & 0x00E0) >> 5;
+
+ aNewSection.mnBorders =
+ ::lcl_ReadBorders(eVer <= ww::eWW7, aNewSection.brc, 0, 0, pSep);
+ }
+
+ // check if Line Numbering must be activated or resetted
+ if (const sal_uInt8* pSprmSNLnnMod = pSep->HasSprm( pIds[4] ))
+ aNewSection.maSep.nLnnMod = *pSprmSNLnnMod;
+
+ if (const sal_uInt8* pSprmSLnc = pSep->HasSprm( pIds[5] ))
+ aNewSection.maSep.lnc = *pSprmSLnc;
+
+ if (const sal_uInt8* pSprmSDxaLnn = pSep->HasSprm( pIds[6] ))
+ aNewSection.maSep.dxaLnn = SVBT16ToShort( pSprmSDxaLnn );
+
+ if (const sal_uInt8* pSprmSLnnMin = pSep->HasSprm( pIds[7] ))
+ aNewSection.maSep.lnnMin = *pSprmSLnnMin;
+
+ if (eVer <= ww::eWW7)
+ aNewSection.maSep.grpfIhdt = ReadBSprm(pSep, eVer <= ww::eWW2 ? 128 : 153, 0);
+ else if (mrReader.pHdFt)
+ {
+ aNewSection.maSep.grpfIhdt = WW8_HEADER_ODD | WW8_FOOTER_ODD;
+
+ if (aNewSection.HasTitlePage())
+ aNewSection.maSep.grpfIhdt |= WW8_HEADER_FIRST | WW8_FOOTER_FIRST;
+
+ if (mrReader.pWDop->fFacingPages)
+ aNewSection.maSep.grpfIhdt |= WW8_HEADER_EVEN | WW8_FOOTER_EVEN;
+
+ //See if we have a header or footer for each enabled possibility
+ //if we do not then we inherit the previous sections header/footer,
+ for (int nI = 0, nMask = 1; nI < 6; ++nI, nMask <<= 1)
+ {
+ if (aNewSection.maSep.grpfIhdt & nMask)
+ {
+ WW8_CP nStart;
+ long nLen;
+ mrReader.pHdFt->GetTextPosExact( static_cast< short >(nI + ( maSegments.size() + 1) * 6), nStart, nLen);
+ //No header or footer, inherit pervious one, or set to zero
+ //if no previous one
+ if (!nLen)
+ {
+ if (
+ maSegments.empty() ||
+ !(maSegments.back().maSep.grpfIhdt & nMask)
+ )
+ {
+ aNewSection.maSep.grpfIhdt &= ~nMask;
+ }
+ }
+ }
+ }
+ }
+
+ SetLeftRight(aNewSection);
+ //END read section values
+
+ if (eVer >= ww::eWW8)
+ aNewSection.SetDirection();
+
+ mrReader.HandleLineNumbering(aNewSection);
+ maSegments.push_back(aNewSection);
+}
+
+void SwWW8ImplReader::CopyPageDescHdFt(const SwPageDesc* pOrgPageDesc,
+ SwPageDesc* pNewPageDesc, sal_uInt8 nCode )
+{
+ // copy first header content section
+ if (nCode & WW8_HEADER_FIRST)
+ rDoc.CopyHeader(pOrgPageDesc->GetMaster(), pNewPageDesc->GetMaster());
+
+ // copy first footer content section
+ if( nCode & WW8_FOOTER_FIRST )
+ rDoc.CopyFooter(pOrgPageDesc->GetMaster(), pNewPageDesc->GetMaster());
+
+ if( nCode & ( WW8_HEADER_ODD | WW8_FOOTER_ODD
+ | WW8_HEADER_EVEN | WW8_FOOTER_EVEN ) )
+ {
+ // copy odd header content section
+ if( nCode & WW8_HEADER_ODD )
+ {
+ rDoc.CopyHeader(pOrgPageDesc->GetMaster(),
+ pNewPageDesc->GetMaster() );
+ }
+ // copy odd footer content section
+ if( nCode & WW8_FOOTER_ODD )
+ {
+ rDoc.CopyFooter(pOrgPageDesc->GetMaster(),
+ pNewPageDesc->GetMaster());
+ }
+ // copy even header content section
+ if( nCode & WW8_HEADER_EVEN )
+ {
+ rDoc.CopyHeader(pOrgPageDesc->GetLeft(),
+ pNewPageDesc->GetLeft());
+ }
+ // copy even footer content section
+ if( nCode & WW8_FOOTER_EVEN )
+ {
+ rDoc.CopyFooter(pOrgPageDesc->GetLeft(),
+ pNewPageDesc->GetLeft());
+ }
+ }
+}
+
+//------------------------------------------------------
+// Hilfsroutinen fuer Grafiken und Apos und Tabellen
+//------------------------------------------------------
+
+static bool _SetWW8_BRC(bool bVer67, WW8_BRC& rVar, const sal_uInt8* pS)
+{
+ if( pS )
+ {
+ if( bVer67 )
+ memcpy( rVar.aBits1, pS, sizeof( SVBT16 ) );
+ else
+ rVar = *((WW8_BRC*)pS);
+ }
+
+ return 0 != pS;
+}
+
+sal_uInt8 lcl_ReadBorders(bool bVer67, WW8_BRC* brc, WW8PLCFx_Cp_FKP* pPap,
+ const WW8RStyle* pSty, const WW8PLCFx_SEPX* pSep)
+{
+
+//returns a sal_uInt8 filled with a bit for each position that had a sprm
+//setting that border
+
+ sal_uInt8 nBorder = false;
+ if( pSep )
+ {
+ if( !bVer67 )
+ {
+ sal_uInt8* pSprm[4];
+
+ // sprmSBrcTop, sprmSBrcLeft, sprmSBrcBottom, sprmSBrcRight
+ if( pSep->Find4Sprms( 0x702B, 0x702C, 0x702D, 0x702E,
+ pSprm[0], pSprm[1], pSprm[2], pSprm[3] ) )
+ {
+ for( int i = 0; i < 4; ++i )
+ nBorder |= (_SetWW8_BRC( bVer67, brc[ i ], pSprm[ i ] ))<<i;
+ }
+ }
+ }
+ else
+ {
+
+ static const sal_uInt16 aVer67Ids[5] = { 38, 39, 40, 41, 42 };
+
+ static const sal_uInt16 aVer8Ids[5] =
+ { 0x6424, 0x6425, 0x6426, 0x6427, 0x6428 };
+
+ const sal_uInt16* pIds = bVer67 ? aVer67Ids : aVer8Ids;
+
+ if( pPap )
+ {
+ for( int i = 0; i < 5; ++i, ++pIds )
+ nBorder |= (_SetWW8_BRC( bVer67, brc[ i ], pPap->HasSprm( *pIds )))<<i;
+ }
+ else if( pSty )
+ {
+ for( int i = 0; i < 5; ++i, ++pIds )
+ nBorder |= (_SetWW8_BRC( bVer67, brc[ i ], pSty->HasParaSprm( *pIds )))<<i;
+ }
+ else {
+ OSL_ENSURE( pSty || pPap, "WW8PLCFx_Cp_FKP and WW8RStyle "
+ "and WW8PLCFx_SEPX is 0" );
+ }
+ }
+
+ return nBorder;
+}
+
+void GetLineIndex(SvxBoxItem &rBox, short nLineThickness, short nSpace, sal_uInt8 nCol, short nIdx,
+ sal_uInt16 nOOIndex, sal_uInt16 nWWIndex, short *pSize=0)
+{
+ ::editeng::SvxBorderStyle eStyle = ::editeng::SOLID;
+ switch (nIdx)
+ {
+ // First the single lines
+ case 1:
+ case 5:
+ // and the unsupported special cases which we map to a single line
+ case 8:
+ case 9:
+ case 20:
+ case 22:
+ eStyle = ::editeng::SOLID;
+ break;
+ case 2:
+ {
+ eStyle = ::editeng::SOLID;
+ nLineThickness *= 2;
+ }
+ break;
+ case 6:
+ eStyle = ::editeng::DOTTED;
+ break;
+ case 7:
+ eStyle = ::editeng::DASHED;
+ break;
+ // then the shading beams which we represent by a double line
+ case 23:
+ eStyle = ::editeng::DOUBLE;
+ break;
+ // then the double lines, for which we have good matches
+ case 3:
+ case 10: //Don't have tripple so use double
+ case 21: //Don't have double wave: use double instead
+ eStyle = ::editeng::DOUBLE;
+ break;
+ case 11:
+ eStyle = ::editeng::THINTHICK_SMALLGAP;
+ break;
+ case 12:
+ case 13: //Don't have thin thick thin, so use thick thin
+ eStyle = ::editeng::THICKTHIN_SMALLGAP;
+ break;
+ case 14:
+ eStyle = ::editeng::THINTHICK_MEDIUMGAP;
+ break;
+ case 15:
+ case 16: //Don't have thin thick thin, so use thick thin
+ eStyle = ::editeng::THICKTHIN_MEDIUMGAP;
+ break;
+ case 17:
+ eStyle = ::editeng::THINTHICK_LARGEGAP;
+ break;
+ case 18:
+ case 19: //Don't have thin thick thin, so use thick thin
+ eStyle = ::editeng::THICKTHIN_LARGEGAP;
+ break;
+ case 24:
+ eStyle = ::editeng::EMBOSSED;
+ break;
+ case 25:
+ eStyle = ::editeng::ENGRAVED;
+ break;
+ case 26:
+ eStyle = ::editeng::OUTSET;
+ break;
+ case 27:
+ eStyle = ::editeng::INSET;
+ break;
+ default:
+ eStyle = ::editeng::NO_STYLE;
+ break;
+ }
+
+ ::editeng::SvxBorderLine aLine;
+ aLine.SetStyle( eStyle );
+ aLine.SetWidth( nLineThickness );
+
+ //No AUTO for borders as yet, so if AUTO, use BLACK
+ if (nCol == 0)
+ nCol = 1;
+
+ aLine.SetColor(SwWW8ImplReader::GetCol(nCol));
+
+ if (pSize)
+ pSize[nWWIndex] = nLineThickness+nSpace;
+
+ rBox.SetLine(&aLine, nOOIndex);
+ rBox.SetDistance(nSpace, nOOIndex);
+
+}
+
+void Set1Border(bool bVer67, SvxBoxItem &rBox, const WW8_BRC& rBor,
+ sal_uInt16 nOOIndex, sal_uInt16 nWWIndex, short *pSize=0)
+{
+ sal_uInt8 nCol;
+ short nSpace, nIdx;
+ short nLineThickness = rBor.DetermineBorderProperties(bVer67,&nSpace,&nCol,
+ &nIdx);
+
+ GetLineIndex(rBox, nLineThickness, nSpace, nCol, nIdx, nOOIndex, nWWIndex, pSize );
+
+}
+
+bool lcl_IsBorder(bool bVer67, const WW8_BRC* pbrc, bool bChkBtwn = false)
+{
+ if( bVer67 )
+ return ( pbrc[WW8_TOP ].aBits1[0] & 0x18 ) || // brcType != 0
+ ( pbrc[WW8_LEFT ].aBits1[0] & 0x18 ) ||
+ ( pbrc[WW8_BOT ].aBits1[0] & 0x18 ) ||
+ ( pbrc[WW8_RIGHT].aBits1[0] & 0x18 ) ||
+ ( bChkBtwn && ( pbrc[WW8_BETW ].aBits1[0] )) ||
+ //can have dotted and dashed with a brcType of 0
+ ( (pbrc[WW8_TOP ].aBits1[0] & 0x07)+1 > 6) ||
+ ( (pbrc[WW8_LEFT ].aBits1[0] & 0x07)+1 > 6) ||
+ ( (pbrc[WW8_BOT ].aBits1[0] & 0x07)+1 > 6) ||
+ ( (pbrc[WW8_RIGHT].aBits1[0] & 0x07)+1 > 6) ||
+ ( bChkBtwn && ( (pbrc[WW8_BETW ].aBits1[0] & 0x07)+1 > 6))
+ ;
+ // Abfrage auf 0x1f statt 0x18 ist noetig, da zumindest einige
+ // WW-Versionen ( 6.0 US ) bei dotted brcType auf 0 setzen
+ else
+ return pbrc[WW8_TOP ].aBits1[1] || // brcType != 0
+ pbrc[WW8_LEFT ].aBits1[1] ||
+ pbrc[WW8_BOT ].aBits1[1] ||
+ pbrc[WW8_RIGHT].aBits1[1] ||
+ (bChkBtwn && pbrc[WW8_BETW ].aBits1[1]);
+}
+
+bool SwWW8ImplReader::IsBorder(const WW8_BRC* pbrc, bool bChkBtwn) const
+{
+ return lcl_IsBorder(bVer67, pbrc, bChkBtwn);
+}
+
+bool WW8_BRC::IsEmpty(bool bVer67) const
+{
+ return (IsBlank() || IsZeroed(bVer67));
+}
+
+bool WW8_BRC::IsBlank() const
+{
+ return (aBits1[0] == 0xff && aBits1[1] == 0xff);
+}
+
+bool WW8_BRC::IsZeroed(bool bVer67) const
+{
+ return (!(bVer67 ? (aBits1[0] & 0x001f) : aBits1[1]));
+}
+
+bool SwWW8ImplReader::SetBorder(SvxBoxItem& rBox, const WW8_BRC* pbrc,
+ short *pSizeArray, sal_uInt8 nSetBorders) const
+{
+ bool bChange = false;
+ static const sal_uInt16 aIdArr[ 10 ] =
+ {
+ WW8_TOP, BOX_LINE_TOP,
+ WW8_LEFT, BOX_LINE_LEFT,
+ WW8_RIGHT, BOX_LINE_RIGHT,
+ WW8_BOT, BOX_LINE_BOTTOM,
+ WW8_BETW, BOX_LINE_BOTTOM
+ };
+
+ for( int i = 0, nEnd = 8; i < nEnd; i += 2 )
+ {
+ // ungueltige Borders ausfiltern
+ const WW8_BRC& rB = pbrc[ aIdArr[ i ] ];
+ if( !rB.IsEmpty(bVer67))
+ {
+ Set1Border(bVer67, rBox, rB, aIdArr[i+1], aIdArr[i], pSizeArray);
+ bChange = true;
+ }
+ else if ( nSetBorders & (1 << aIdArr[i]) )
+ {
+ /*
+ ##826##, ##653##
+
+ If a style has borders set,and the para attributes attempt remove
+ the borders, then this is perfectably acceptable, so we shouldn't
+ ignore this blank entry
+
+ nSetBorders has a bit set for each location that a sprm set a
+ border, so with a sprm set, but no border, then disable the
+ appropiate border
+ */
+ rBox.SetLine( 0, aIdArr[ i+1 ] );
+ }
+ }
+ return bChange;
+}
+
+
+bool SwWW8ImplReader::SetShadow(SvxShadowItem& rShadow, const short *pSizeArray,
+ const WW8_BRC *pbrc) const
+{
+ bool bRet = (
+ ( bVer67 ? (pbrc[WW8_RIGHT].aBits1[ 0 ] & 0x20 )
+ : (pbrc[WW8_RIGHT].aBits2[ 1 ] & 0x20 ) )
+ && (pSizeArray && pSizeArray[WW8_RIGHT])
+ );
+ if (bRet)
+ {
+ rShadow.SetColor(Color(COL_BLACK));
+ short nVal = pSizeArray[WW8_RIGHT];
+ if (nVal < 0x10)
+ nVal = 0x10;
+ rShadow.SetWidth(nVal);
+ rShadow.SetLocation(SVX_SHADOW_BOTTOMRIGHT);
+ bRet = true;
+ }
+ return bRet;
+}
+
+void SwWW8ImplReader::GetBorderDistance(const WW8_BRC* pbrc,
+ Rectangle& rInnerDist) const
+{
+ // 'dptSpace' is stored in 3 bits of 'Border Code (BRC)'
+ if (bVer67)
+ {
+ rInnerDist = Rectangle(((pbrc[ 1 ].aBits1[1] >> 3) & 0x1f) * 20,
+ ((pbrc[ 0 ].aBits1[1] >> 3) & 0x1f) * 20,
+ ((pbrc[ 3 ].aBits1[1] >> 3) & 0x1f) * 20,
+ ((pbrc[ 2 ].aBits1[1] >> 3) & 0x1f) * 20 );
+ }
+ else
+ {
+ rInnerDist = Rectangle( (pbrc[ 1 ].aBits2[1] & 0x1f) * 20,
+ (pbrc[ 0 ].aBits2[1] & 0x1f) * 20,
+ (pbrc[ 3 ].aBits2[1] & 0x1f) * 20,
+ (pbrc[ 2 ].aBits2[1] & 0x1f) * 20 );
+ }
+}
+
+
+bool SwWW8ImplReader::SetFlyBordersShadow(SfxItemSet& rFlySet,
+ const WW8_BRC *pbrc, short *pSizeArray) const
+{
+ bool bShadowed = false;
+ if (IsBorder(pbrc))
+ {
+ SvxBoxItem aBox( RES_BOX );
+ SetBorder(aBox, pbrc, pSizeArray);
+
+ rFlySet.Put( aBox );
+
+ // fShadow
+ SvxShadowItem aShadow( RES_SHADOW );
+ if( SetShadow( aShadow, pSizeArray, pbrc ))
+ {
+ bShadowed = true;
+ rFlySet.Put( aShadow );
+ }
+ }
+ return bShadowed;
+}
+
+//-----------------------------------------
+// APOs
+//-----------------------------------------
+ // fuer Berechnung der minimalen FrameSize
+#define MAX_BORDER_SIZE 210 // so breit ist max. der Border
+#define MAX_EMPTY_BORDER 10 // fuer +-1-Fehler, mindestens 1
+
+static void FlySecur1(short& rSize, const bool bBorder)
+{
+ short nMin = MINFLY +
+ bBorder ? MAX_BORDER_SIZE : MAX_EMPTY_BORDER;
+
+ if ( rSize < nMin )
+ rSize = nMin;
+}
+
+inline bool SetValSprm( sal_Int16* pVar, WW8PLCFx_Cp_FKP* pPap, sal_uInt16 nId )
+{
+ const sal_uInt8* pS = pPap->HasSprm( nId );
+ if( pS )
+ *pVar = (sal_Int16)SVBT16ToShort( pS );
+ return ( pS != 0 );
+}
+
+inline bool SetValSprm( sal_Int16* pVar, const WW8RStyle* pStyle, sal_uInt16 nId )
+{
+ const sal_uInt8* pS = pStyle->HasParaSprm( nId );
+ if( pS )
+ *pVar = (sal_Int16)SVBT16ToShort( pS );
+ return ( pS != 0 );
+}
+
+/*
+#i1930 revealed that sprm 0x360D as used in tables can affect the frame
+around the table. Its full structure is not fully understood as yet.
+*/
+void WW8FlyPara::ApplyTabPos(const WW8_TablePos *pTabPos)
+{
+ if (pTabPos)
+ {
+ nSp26 = pTabPos->nSp26;
+ nSp27 = pTabPos->nSp27;
+ nSp29 = pTabPos->nSp29;
+ nLeMgn = pTabPos->nLeMgn;
+ nRiMgn = pTabPos->nRiMgn;
+ nUpMgn = pTabPos->nUpMgn;
+ nLoMgn = pTabPos->nLoMgn;
+ nSp37 = pTabPos->nSp37;
+ }
+}
+
+WW8FlyPara::WW8FlyPara(bool bIsVer67, const WW8FlyPara* pSrc /* = 0 */)
+{
+ if ( pSrc )
+ memcpy( this, pSrc, sizeof( WW8FlyPara ) ); // Copy-Ctor
+ else
+ {
+ memset( this, 0, sizeof( WW8FlyPara ) ); // Default-Ctor
+ nSp37 = 2; // Default: Umfluss
+ }
+ bVer67 = bIsVer67;
+}
+
+bool WW8FlyPara::operator==(const WW8FlyPara& rSrc) const
+{
+ /*
+ Compare the parts that word seems to compare for equivalence.
+ Interestingly being autoheight or absolute height (the & 0x7fff) doesn't
+ matter to word
+ */
+ return
+ (
+ (nSp26 == rSrc.nSp26) &&
+ (nSp27 == rSrc.nSp27) &&
+ ((nSp45 & 0x7fff) == (rSrc.nSp45 & 0x7fff)) &&
+ (nSp28 == rSrc.nSp28) &&
+ (nLeMgn == rSrc.nLeMgn) &&
+ (nRiMgn == rSrc.nRiMgn) &&
+ (nUpMgn == rSrc.nUpMgn) &&
+ (nLoMgn == rSrc.nLoMgn) &&
+ (nSp29 == rSrc.nSp29) &&
+ (nSp37 == rSrc.nSp37)
+ );
+}
+
+// Read fuer normalen Text
+void WW8FlyPara::Read(const sal_uInt8* pSprm29, WW8PLCFx_Cp_FKP* pPap)
+{
+ if (pSprm29)
+ nOrigSp29 = *pSprm29; // PPC ( Bindung )
+
+ const sal_uInt8* pS = 0;
+ if( bVer67 )
+ {
+ SetValSprm( &nSp26, pPap, 26 ); // X-Position //sprmPDxaAbs
+ //set in me or in parent style
+ mbVertSet |= SetValSprm( &nSp27, pPap, 27 ); // Y-Position //sprmPDyaAbs
+ SetValSprm( &nSp45, pPap, 45 ); // Hoehe //sprmPWHeightAbs
+ SetValSprm( &nSp28, pPap, 28 ); // Breite //sprmPDxaWidth
+ SetValSprm( &nLeMgn, pPap, 49 ); // L-Raender //sprmPDxaFromText
+ SetValSprm( &nRiMgn, pPap, 49 ); // R-Raender //sprmPDxaFromText
+ SetValSprm( &nUpMgn, pPap, 48 ); // U-Raender //sprmPDyaFromText
+ SetValSprm( &nLoMgn, pPap, 48 ); // D-Raender //sprmPDyaFromText
+
+ pS = pPap->HasSprm( 37 ); //sprmPWr
+ if( pS )
+ nSp37 = *pS;
+ }
+ else
+ {
+ SetValSprm( &nSp26, pPap, 0x8418 ); // X-Position
+ //set in me or in parent style
+ mbVertSet |= SetValSprm( &nSp27, pPap, 0x8419 ); // Y-Position
+ SetValSprm( &nSp45, pPap, 0x442B ); // Hoehe
+ SetValSprm( &nSp28, pPap, 0x841A ); // Breite
+ SetValSprm( &nLeMgn, pPap, 0x842F ); // L-Raender
+ SetValSprm( &nRiMgn, pPap, 0x842F ); // R-Raender
+ SetValSprm( &nUpMgn, pPap, 0x842E ); // U-Raender
+ SetValSprm( &nLoMgn, pPap, 0x842E ); // D-Raender
+
+ pS = pPap->HasSprm( 0x2423 ); // Umfluss
+ if( pS )
+ nSp37 = *pS;
+ }
+
+ if( ::lcl_ReadBorders( bVer67, brc, pPap )) // Umrandung
+ bBorderLines = ::lcl_IsBorder( bVer67, brc );
+
+ /*
+ #i8798#
+ Appears that with no dyaAbs set then the actual vert anchoring set is
+ ignored and we remain relative to text, so if that is the case we are 0
+ from para anchor, so we update the frame to have explicitly this type of
+ anchoring
+ */
+ if (!mbVertSet)
+ nSp29 = (nOrigSp29 & 0xCF) | 0x20;
+ else
+ nSp29 = nOrigSp29;
+}
+
+void WW8FlyPara::ReadFull(const sal_uInt8* pSprm29, SwWW8ImplReader* pIo)
+{
+ WW8PLCFMan* pPlcxMan = pIo->pPlcxMan;
+ WW8PLCFx_Cp_FKP* pPap = pPlcxMan->GetPapPLCF();
+
+ Read(pSprm29, pPap); // Lies Apo-Parameter
+
+ do{ // Block zum rausspringen
+ if( nSp45 != 0 /* || nSp28 != 0 */ )
+ break; // bGrafApo nur bei Hoehe automatisch
+ if( pIo->pWwFib->fComplex )
+ break; // (*pPap)++ geht bei FastSave schief
+ // -> bei FastSave kein Test auf Grafik-APO
+ SvStream* pIoStrm = pIo->pStrm;
+ sal_uLong nPos = pIoStrm->Tell();
+ WW8PLCFxSave1 aSave;
+ pPlcxMan->GetPap()->Save( aSave );
+ bGrafApo = false;
+
+ do{ // Block zum rausspringen
+
+ sal_uInt8 nTxt[2];
+
+ pIoStrm->Read( nTxt, 2 ); // lies Text
+ if( nTxt[0] != 0x01 || nTxt[1] != 0x0d )// nur Grafik + CR ?
+ break; // Nein
+
+ (*pPap)++; // Naechste Zeile
+
+ // In APO ?
+ //sprmPPc
+ const sal_uInt8* pS = pPap->HasSprm( bVer67 ? 29 : 0x261B );
+
+ // Nein -> Grafik-Apo
+ if( !pS ){
+ bGrafApo = true;
+ break; // Ende des APO
+ }
+
+ ww::WordVersion eVer = pIo->GetFib().GetFIBVersion();
+ WW8FlyPara *pNowStyleApo=0;
+ sal_uInt16 nColl = pPap->GetIstd();
+ ww::sti eSti = eVer < ww::eWW6 ? ww::GetCanonicalStiFromStc( static_cast< sal_uInt8 >(nColl) ) : static_cast<ww::sti>(nColl);
+ while (eSti != ww::stiNil && 0 == (pNowStyleApo = pIo->pCollA[nColl].pWWFly))
+ {
+ nColl = pIo->pCollA[nColl].nBase;
+ eSti = eVer < ww::eWW6 ? ww::GetCanonicalStiFromStc( static_cast< sal_uInt8 >(nColl) ) : static_cast<ww::sti>(nColl);
+ }
+
+ WW8FlyPara aF(bVer67, pNowStyleApo);
+ // Neuer FlaPara zum Vergleich
+ aF.Read( pS, pPap ); // WWPara fuer neuen Para
+ if( !( aF == *this ) ) // selber APO ? ( oder neuer ? )
+ bGrafApo = true; // nein -> 1-zeiliger APO
+ // -> Grafik-APO
+ }
+ while( 0 ); // Block zum rausspringen
+
+ pPlcxMan->GetPap()->Restore( aSave );
+ pIoStrm->Seek( nPos );
+ }while( 0 ); // Block zum rausspringen
+}
+
+
+// Read fuer Apo-Defs in Styledefs
+void WW8FlyPara::Read(const sal_uInt8* pSprm29, WW8RStyle* pStyle)
+{
+ if (pSprm29)
+ nOrigSp29 = *pSprm29; // PPC ( Bindung )
+
+ const sal_uInt8* pS = 0;
+ if (bVer67)
+ {
+ SetValSprm( &nSp26, pStyle, 26 ); // X-Position
+ //set in me or in parent style
+ mbVertSet |= SetValSprm(&nSp27, pStyle, 27); // Y-Position
+ SetValSprm( &nSp45, pStyle, 45 ); // Hoehe
+ SetValSprm( &nSp28, pStyle, 28 ); // Breite
+ SetValSprm( &nLeMgn, pStyle, 49 ); // L-Raender
+ SetValSprm( &nRiMgn, pStyle, 49 ); // R-Raender
+ SetValSprm( &nUpMgn, pStyle, 48 ); // U-Raender
+ SetValSprm( &nLoMgn, pStyle, 48 ); // D-Raender
+
+ pS = pStyle->HasParaSprm( 37 ); // Umfluss
+ if( pS )
+ nSp37 = *pS;
+ }
+ else
+ {
+ SetValSprm( &nSp26, pStyle, 0x8418 ); // X-Position
+ //set in me or in parent style
+ mbVertSet |= SetValSprm(&nSp27, pStyle, 0x8419); // Y-Position
+ SetValSprm( &nSp45, pStyle, 0x442B ); // Hoehe
+ SetValSprm( &nSp28, pStyle, 0x841A ); // Breite
+ SetValSprm( &nLeMgn, pStyle, 0x842F ); // L-Raender
+ SetValSprm( &nRiMgn, pStyle, 0x842F ); // R-Raender
+ SetValSprm( &nUpMgn, pStyle, 0x842E ); // U-Raender
+ SetValSprm( &nLoMgn, pStyle, 0x842E ); // D-Raender
+
+ pS = pStyle->HasParaSprm( 0x2423 ); // Umfluss
+ if( pS )
+ nSp37 = *pS;
+ }
+
+ if (::lcl_ReadBorders(bVer67, brc, 0, pStyle)) // Umrandung
+ bBorderLines = ::lcl_IsBorder(bVer67, brc);
+
+ /*
+ #i8798#
+ Appears that with no dyaAbs set then the actual vert anchoring set is
+ ignored and we remain relative to text, so if that is the case we are 0
+ from para anchor, so we update the frame to have explicitly this type of
+ anchoring
+ */
+ if (!mbVertSet)
+ nSp29 = (nOrigSp29 & 0xCF) | 0x20;
+ else
+ nSp29 = nOrigSp29;
+}
+
+bool WW8FlyPara::IsEmpty() const
+{
+ WW8FlyPara aEmpty(bVer67);
+ /*
+ wr of 0 like 2 appears to me to be equivalent for checking here. See
+ #107103# if wrong, so given that the empty is 2, if we are 0 then set
+ empty to 0 to make 0 equiv to 2 for empty checking
+ */
+ OSL_ENSURE(aEmpty.nSp37 == 2, "this is not what we expect for nSp37");
+ if (this->nSp37 == 0)
+ aEmpty.nSp37 = 0;
+ if (aEmpty == *this)
+ return true;
+ return false;
+}
+
+// #i18732# - changes made on behalf of CMC
+WW8SwFlyPara::WW8SwFlyPara( SwPaM& rPaM,
+ SwWW8ImplReader& rIo,
+ WW8FlyPara& rWW,
+ const sal_uInt32 nWWPgTop,
+ const sal_uInt32 nPgLeft,
+ const sal_uInt32 nPgWidth,
+ const sal_Int32 nIniFlyDx,
+ const sal_Int32 nIniFlyDy )
+{
+ (void) rPaM;
+ (void) nPgLeft;
+
+ memset( this, 0, sizeof( WW8SwFlyPara ) ); // Initialisieren
+ nNewNettoWidth = MINFLY; // Minimum
+
+ eSurround = ( rWW.nSp37 > 1 ) ? SURROUND_IDEAL : SURROUND_NONE;
+
+ /*
+ #95905#, #83307# seems to have gone away now, so reenable parallel
+ wrapping support for frames in headers/footers. I don't know if we truly
+ have an explictly specified behaviour for these circumstances.
+ */
+
+ nHeight = rWW.nSp45;
+ if( nHeight & 0x8000 )
+ {
+ nHeight &= 0x7fff;
+ eHeightFix = ATT_MIN_SIZE;
+ }
+ else
+ eHeightFix = ATT_FIX_SIZE;
+
+ if( nHeight <= MINFLY )
+ { // keine Angabe oder Stuss
+ eHeightFix = ATT_MIN_SIZE;
+ nHeight = MINFLY;
+ }
+
+ nWidth = nNettoWidth = rWW.nSp28;
+ if( nWidth <= 10 ) // Auto-Breite
+ {
+ bAutoWidth = true;
+ rIo.maTracer.Log(sw::log::eAutoWidthFrame);
+ nWidth = nNettoWidth =
+ msword_cast<sal_Int16>((nPgWidth ? nPgWidth : 2268)); // 4 cm
+ }
+ if( nWidth <= MINFLY )
+ nWidth = nNettoWidth = MINFLY; // Minimale Breite
+
+ eVAlign = text::VertOrientation::NONE; // Defaults
+ eHAlign = text::HoriOrientation::NONE;
+ nYPos = 0;
+ nXPos = 0;
+
+ nRiMgn = rWW.nRiMgn;
+ nLeMgn = rWW.nLeMgn;
+ nLoMgn = rWW.nLoMgn;
+ nUpMgn = rWW.nUpMgn;
+
+ /*
+ See issue #i9178# for the 9 anchoring options, and make sure they stay
+ working if you modify the anchoring logic here.
+ */
+
+ // Wenn der Fly links, rechts, oben oder unten aligned ist,
+ // wird der aeussere Textabstand ignoriert, da sonst
+ // der Fly an falscher Position landen wuerde
+ // Problematisch wird es nur bei Innen/Aussen
+
+ // Bindung
+ nYBind = (( rWW.nSp29 & 0x30 ) >> 4);
+ //#i53725# - absolute positioned objects have to be
+ // anchored at-paragraph to assure its correct anchor position.
+ eAnchor = FLY_AT_PARA;
+
+ switch (nYBind)
+ {
+ case 0: //relative to margin
+ eVRel = text::RelOrientation::PAGE_PRINT_AREA;
+ break;
+ case 1: //relative to page
+ eVRel = text::RelOrientation::PAGE_FRAME;
+ break;
+ default: //relative to text
+ eVRel = text::RelOrientation::FRAME;
+ break;
+ }
+
+// #i18732#
+ switch( rWW.nSp27 ) // besondere Y-Positionen ?
+ {
+ case -4:
+ eVAlign = text::VertOrientation::TOP;
+ if (nYBind < 2)
+ nUpMgn = 0;
+ break; // oben
+ case -8:
+ eVAlign = text::VertOrientation::CENTER;
+ break; // zentriert
+ case -12:
+ eVAlign = text::VertOrientation::BOTTOM;
+ if (nYBind < 2)
+ nLoMgn = 0;
+ break; // unten
+ default:
+ nYPos = rWW.nSp27 + (short)nIniFlyDy;
+ break; // Korrekturen per Ini-Datei
+ }
+
+ switch( rWW.nSp26 ) // besondere X-Positionen ?
+ {
+ case 0:
+ eHAlign = text::HoriOrientation::LEFT;
+ nLeMgn = 0;
+ break; // links
+ case -4:
+ eHAlign = text::HoriOrientation::CENTER;
+ break; // zentriert
+ case -8:
+ eHAlign = text::HoriOrientation::RIGHT;
+ nRiMgn = 0;
+ break; // rechts
+ case -12:
+ eHAlign = text::HoriOrientation::LEFT;
+ bToggelPos = true;
+ break; // innen
+ case -16:
+ eHAlign = text::HoriOrientation::RIGHT;
+ bToggelPos = true;
+ break; // aussen
+ default:
+ nXPos = rWW.nSp26 + (short)nIniFlyDx;
+ break; // Korrekturen per Ini-Datei
+ }
+
+ nXBind = ( rWW.nSp29 & 0xc0 ) >> 6;
+// #i18732#
+ switch (nXBind) // X - Bindung -> Koordinatentransformation
+ {
+ case 0: //relative to column
+ eHRel = text::RelOrientation::FRAME;
+ break;
+ case 1: //relative to margin
+ eHRel = text::RelOrientation::PAGE_PRINT_AREA;
+ break;
+ default: //relative to page
+ eHRel = text::RelOrientation::PAGE_FRAME;
+ break;
+ }
+
+ // #i36649# - adjustments for certain horizontal alignments
+ // Note: These special adjustments found by an investigation of documents
+ // containing frames with different left/right border distances and
+ // distances to text. The outcome is some how strange.
+ // Note: These adjustments causes wrong horizontal positions for frames,
+ // which are aligned inside|outside to page|margin on even pages,
+ // the left and right border distances are different.
+ // no adjustments possible, if frame has automatic width.
+ // determine left border distance
+ sal_Int16 nLeBorderMgn( 0L );
+ if ( !bAutoWidth )
+ {
+ sal_Int16 nTemp = rWW.brc[WW8_LEFT].DetermineBorderProperties(rWW.bVer67,
+ &nLeBorderMgn);
+ nLeBorderMgn = nLeBorderMgn + nTemp;
+ }
+ // determine right border distance
+ sal_Int16 nRiBorderMgn( 0L );
+ if ( !bAutoWidth )
+ {
+ sal_Int16 nTemp = rWW.brc[WW8_RIGHT].DetermineBorderProperties(rWW.bVer67,
+ &nRiBorderMgn);
+ nRiBorderMgn = nRiBorderMgn + nTemp;
+ }
+ if ( !bAutoWidth && eHAlign == text::HoriOrientation::LEFT && eHRel == text::RelOrientation::PAGE_FRAME )
+ {
+ // convert 'left to page' to
+ // 'from left -<width>-<2*left border distance>-<right wrap distance>
+ // to page text area'
+ eHAlign = text::HoriOrientation::NONE;
+ eHRel = text::RelOrientation::PAGE_PRINT_AREA;
+ nXPos = -nWidth - (2*nLeBorderMgn) - rWW.nRiMgn;
+ // re-set left wrap distance
+ nLeMgn = rWW.nLeMgn;
+ }
+ else if ( !bAutoWidth && eHAlign == text::HoriOrientation::RIGHT && eHRel == text::RelOrientation::PAGE_FRAME )
+ {
+ // convert 'right to page' to
+ // 'from left <right border distance-left border distance>+<left wrap distance>
+ // to right page border'
+ eHAlign = text::HoriOrientation::NONE;
+ eHRel = text::RelOrientation::PAGE_RIGHT;
+ nXPos = ( nRiBorderMgn - nLeBorderMgn ) + rWW.nLeMgn;
+ // re-set right wrap distance
+ nRiMgn = rWW.nRiMgn;
+ }
+ else if ( !bAutoWidth && eHAlign == text::HoriOrientation::LEFT && eHRel == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ // convert 'left to margin' to
+ // 'from left -<left border distance> to page text area'
+ eHAlign = text::HoriOrientation::NONE;
+ eHRel = text::RelOrientation::PAGE_PRINT_AREA;
+ nXPos = -nLeBorderMgn;
+ // re-set left wrap distance
+ nLeMgn = rWW.nLeMgn;
+ }
+ else if ( !bAutoWidth && eHAlign == text::HoriOrientation::RIGHT && eHRel == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ // convert 'right to margin' to
+ // 'from left -<width>-<left border distance> to right page border'
+ eHAlign = text::HoriOrientation::NONE;
+ eHRel = text::RelOrientation::PAGE_RIGHT;
+ nXPos = -nWidth - nLeBorderMgn;
+ // re-set right wrap distance
+ nRiMgn = rWW.nRiMgn;
+ }
+ else if (rWW.bBorderLines)
+ // <--
+ {
+ /*
+ #i582#
+ Word has a curious bug where the offset stored do not take into
+ account the internal distance from the corner both
+ */
+ sal_Int16 nLeLMgn = 0;
+ sal_Int16 nTemp = rWW.brc[WW8_LEFT].DetermineBorderProperties(rWW.bVer67,
+ &nLeLMgn);
+ nLeLMgn = nLeLMgn + nTemp;
+
+ if (nLeLMgn)
+ {
+ if (eHAlign == text::HoriOrientation::LEFT)
+ eHAlign = text::HoriOrientation::NONE;
+ nXPos = nXPos - nLeLMgn;
+ }
+ }
+
+ // adjustments for certain vertical alignments
+ if ( eVAlign == text::VertOrientation::NONE && eVRel == text::RelOrientation::PAGE_PRINT_AREA )
+ {
+ // convert "<X> from top page text area" to
+ // "<X + page top margin> from page"
+ eVRel = text::RelOrientation::PAGE_FRAME;
+ nYPos = static_cast< sal_Int16 >( nYPos + nWWPgTop );
+ }
+
+ FlySecur1( nWidth, rWW.bBorderLines ); // passen Raender ?
+ FlySecur1( nHeight, rWW.bBorderLines );
+
+}
+
+// hat ein Fly in WW eine automatische Breite, dann muss das durch
+// nachtraegliches Anpassen der ( im SW festen ) Fly-Breite simuliert werden.
+// Dabei kann die Fly-Breite groesser oder kleiner werden, da der Default-Wert
+// ohne Wissen ueber den Inhalt eingesetzt wird.
+void WW8SwFlyPara::BoxUpWidth( long nInWidth )
+{
+ if( bAutoWidth && nInWidth > nNewNettoWidth )
+ nNewNettoWidth = nInWidth;
+};
+
+// Die Klasse WW8FlySet ist von SfxItemSet abgeleitet und stellt auch
+// im Prizip nicht mehr zur Verfuegung, ist aber fuer mich besser
+// zu handeln
+// WW8FlySet-ctor fuer Apos und Graf-Apos
+WW8FlySet::WW8FlySet(SwWW8ImplReader& rReader, const WW8FlyPara* pFW,
+ const WW8SwFlyPara* pFS, bool bGraf)
+ : SfxItemSet(rReader.rDoc.GetAttrPool(),RES_FRMATR_BEGIN,RES_FRMATR_END-1)
+{
+ if (!rReader.mbNewDoc)
+ Reader::ResetFrmFmtAttrs(*this); // Abstand/Umrandung raus
+ // Position
+ Put(SvxFrameDirectionItem(FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR));
+
+/*Below can all go when we have from left in rtl mode*/
+ SwTwips nXPos = pFS->nXPos;
+ sal_Int16 eHRel = pFS->eHRel;
+ rReader.MiserableRTLGraphicsHack(nXPos, pFS->nWidth, pFS->eHAlign, eHRel);
+/*Above can all go when we have from left in rtl mode*/
+ Put( SwFmtHoriOrient(nXPos, pFS->eHAlign, pFS->eHRel, pFS->bToggelPos ));
+ Put( SwFmtVertOrient( pFS->nYPos, pFS->eVAlign, pFS->eVRel ) );
+
+ if (pFS->nLeMgn || pFS->nRiMgn) // Raender setzen
+ Put(SvxLRSpaceItem(pFS->nLeMgn, pFS->nRiMgn, 0, 0, RES_LR_SPACE));
+
+ if (pFS->nUpMgn || pFS->nLoMgn)
+ Put(SvxULSpaceItem(pFS->nUpMgn, pFS->nLoMgn, RES_UL_SPACE));
+
+ //we no longer need to hack around the header/footer problems
+ SwFmtSurround aSurround(pFS->eSurround);
+ if ( pFS->eSurround == SURROUND_IDEAL )
+ aSurround.SetAnchorOnly( sal_True );
+ Put( aSurround );
+
+ short aSizeArray[5]={0};
+ rReader.SetFlyBordersShadow(*this,(const WW8_BRC*)pFW->brc,&aSizeArray[0]);
+
+ // der 5. Parameter ist immer 0, daher geht beim Cast nix verloren
+
+ // #i27767#
+ // #i35017# - constant name has changed
+ Put( SwFmtWrapInfluenceOnObjPos(
+ text::WrapInfluenceOnPosition::ONCE_SUCCESSIVE ) );
+
+ if( !bGraf )
+ {
+ Put( SwFmtAnchor(pFS->eAnchor) );
+ // Groesse einstellen
+
+ //Ordinarily with frames, the border width and spacing is
+ //placed outside the frame, making it larger. With these
+ //types of frames, the left right thickness and space makes
+ //it wider, but the top bottom spacing and border thickness
+ //is placed inside.
+ Put( SwFmtFrmSize( pFS->eHeightFix, pFS->nWidth +
+ aSizeArray[WW8_LEFT] + aSizeArray[WW8_RIGHT],
+ pFS->nHeight));
+ }
+}
+
+// WW8FlySet-ctor fuer zeichengebundene Grafiken
+WW8FlySet::WW8FlySet( SwWW8ImplReader& rReader, const SwPaM* pPaM,
+ const WW8_PIC& rPic, long nWidth, long nHeight )
+ : SfxItemSet(rReader.rDoc.GetAttrPool(),RES_FRMATR_BEGIN,RES_FRMATR_END-1)
+{
+ Init(rReader, pPaM);
+
+ Put(SvxFrameDirectionItem(FRMDIR_HORI_LEFT_TOP, RES_FRAMEDIR));
+
+ short aSizeArray[5]={0};
+ /*
+ If we have set borders then in word the graphic is displaced from the left
+ and top the width of the borders of those sides, and then the shadow
+ itself is drawn to the bottom and right of the displaced graphic. In word
+ the total size is that of the graphic plus the borders, plus the total
+ shadow around all edges, for this translation the top and left shadow
+ region is translated spacing around the graphic to those sides, and the
+ bottom and right shadow size is added to the graphic size.
+ */
+ if (rReader.SetFlyBordersShadow( *this, rPic.rgbrc, &aSizeArray[0]))
+ {
+ Put(SvxLRSpaceItem( aSizeArray[WW8_LEFT], 0, 0, 0, RES_LR_SPACE ) );
+ Put(SvxULSpaceItem( aSizeArray[WW8_TOP], 0, RES_UL_SPACE ));
+ aSizeArray[WW8_RIGHT]*=2;
+ aSizeArray[WW8_BOT]*=2;
+ }
+
+ Put( SwFmtFrmSize( ATT_FIX_SIZE, nWidth+aSizeArray[WW8_LEFT]+
+ aSizeArray[WW8_RIGHT], nHeight+aSizeArray[WW8_TOP]
+ + aSizeArray[WW8_BOT]) );
+}
+
+void WW8FlySet::Init(const SwWW8ImplReader& rReader, const SwPaM* pPaM)
+{
+ if (!rReader.mbNewDoc)
+ Reader::ResetFrmFmtAttrs(*this); // Abstand/Umrandung raus
+
+ Put(SvxLRSpaceItem(RES_LR_SPACE)); //inline writer ole2 objects start with 0.2cm l/r
+ SwFmtAnchor aAnchor(FLY_AS_CHAR);
+
+ aAnchor.SetAnchor(pPaM->GetPoint());
+ Put(aAnchor);
+
+ //The horizontal default is on the baseline, the vertical is centered
+ //around the character center it appears
+ if (rReader.maSectionManager.CurrentSectionIsVertical())
+ Put(SwFmtVertOrient(0, text::VertOrientation::CHAR_CENTER,text::RelOrientation::CHAR));
+ else
+ Put(SwFmtVertOrient(0, text::VertOrientation::TOP, text::RelOrientation::FRAME));
+}
+
+WW8DupProperties::WW8DupProperties(SwDoc &rDoc, SwWW8FltControlStack *pStk)
+ : pCtrlStck(pStk),
+ aChrSet(rDoc.GetAttrPool(), RES_CHRATR_BEGIN, RES_CHRATR_END - 1 ),
+ aParSet(rDoc.GetAttrPool(), RES_PARATR_BEGIN, RES_PARATR_END - 1 )
+{
+ //Close any open character properties and duplicate them inside the
+ //first table cell
+ sal_uInt16 nCnt = static_cast< sal_uInt16 >(pCtrlStck->Count());
+ for (sal_uInt16 i=0; i < nCnt; i++)
+ {
+ const SwFltStackEntry* pEntry = (*pCtrlStck)[ i ];
+ if(pEntry->bLocked)
+ {
+ if (isCHRATR(pEntry->pAttr->Which()))
+ {
+ aChrSet.Put( *pEntry->pAttr );
+
+ }
+ else if (isPARATR(pEntry->pAttr->Which()))
+ {
+ aParSet.Put( *pEntry->pAttr );
+ }
+ }
+ }
+}
+
+void WW8DupProperties::Insert(const SwPosition &rPos)
+{
+ const SfxItemSet *pSet=&aChrSet;
+ for(int i=0;i<2;i++)
+ {
+ if (i==1)
+ pSet = &aParSet;
+
+ if( pSet->Count() )
+ {
+ SfxItemIter aIter( *pSet );
+ const SfxPoolItem* pItem = aIter.GetCurItem();
+ do
+ {
+ pCtrlStck->NewAttr(rPos, *pItem);
+ }while( !aIter.IsAtEnd() && 0 != ( pItem = aIter.NextItem() ) );
+ }
+ }
+}
+
+void SwWW8ImplReader::MoveInsideFly(const SwFrmFmt *pFlyFmt)
+{
+ WW8DupProperties aDup(rDoc,pCtrlStck);
+
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), 0, false);
+
+ // Setze Pam in den FlyFrame
+ const SwFmtCntnt& rCntnt = pFlyFmt->GetCntnt();
+ OSL_ENSURE( rCntnt.GetCntntIdx(), "Kein Inhalt vorbereitet." );
+ pPaM->GetPoint()->nNode = rCntnt.GetCntntIdx()->GetIndex() + 1;
+ pPaM->GetPoint()->nContent.Assign( pPaM->GetCntntNode(), 0 );
+
+ aDup.Insert(*pPaM->GetPoint());
+}
+
+SwTwips SwWW8ImplReader::MoveOutsideFly(SwFrmFmt *pFlyFmt,
+ const SwPosition &rPos, bool bTableJoin)
+{
+ SwTwips nRetWidth = 0;
+ // Alle Attribute schliessen, da sonst Attribute entstehen koennen,
+ // die aus Flys rausragen
+ WW8DupProperties aDup(rDoc,pCtrlStck);
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), 0, false);
+
+ /*
+ #i1291
+ If this fly frame consists entirely of one table inside a frame
+ followed by an empty paragraph then we want to delete the empty
+ paragraph so as to get the frame to autoshrink to the size of the
+ table to emulate words behaviour closer.
+ */
+ if (bTableJoin)
+ {
+ const SwNodeIndex* pNodeIndex = pFlyFmt->GetCntnt().
+ GetCntntIdx();
+ if (pNodeIndex)
+ {
+ SwNodeIndex aIdx( *pNodeIndex, 1 ),
+ aEnd( *pNodeIndex->GetNode().EndOfSectionNode() );
+
+ if (aIdx < aEnd)
+ {
+ if(aIdx.GetNode().IsTableNode())
+ {
+ SwTableNode *pTable = aIdx.GetNode().GetTableNode();
+ aIdx = *aIdx.GetNode().EndOfSectionNode();
+ aIdx++;
+ if ( (aIdx < aEnd) && aIdx.GetNode().IsTxtNode() )
+ {
+ SwTxtNode *pNd = aIdx.GetNode().GetTxtNode();
+ aIdx++;
+ if (aIdx == aEnd && pNd && !pNd->GetTxt().Len())
+ {
+ rDoc.DelFullPara( *pPaM );
+
+ SwTable& rTable = pTable->GetTable();
+ SwFrmFmt* pTblFmt = rTable.GetFrmFmt();
+
+ if (pTblFmt)
+ {
+ SwFmtFrmSize aSize = pTblFmt->GetFrmSize();
+ aSize.SetHeightSizeType(ATT_MIN_SIZE);
+ aSize.SetHeight(MINLAY);
+ pFlyFmt->SetFmtAttr(aSize);
+ pTblFmt->SetFmtAttr(SwFmtHoriOrient(0,text::HoriOrientation::FULL));
+ nRetWidth = aSize.GetWidth();
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ *pPaM->GetPoint() = rPos;
+ aDup.Insert(*pPaM->GetPoint());
+ return nRetWidth;
+}
+
+WW8FlyPara *SwWW8ImplReader::ConstructApo(const ApoTestResults &rApo,
+ const WW8_TablePos *pTabPos)
+{
+ WW8FlyPara *pRet = 0;
+ OSL_ENSURE(rApo.HasFrame() || pTabPos,
+ "If no frame found, *MUST* be in a table");
+
+ pRet = new WW8FlyPara(bVer67, rApo.mpStyleApo);
+
+ // APO-Parameter ermitteln und Test auf bGrafApo
+ if (rApo.HasFrame())
+ pRet->ReadFull(rApo.mpSprm29, this);
+
+ pRet->ApplyTabPos(pTabPos);
+
+ if (pRet->IsEmpty())
+ delete pRet, pRet = 0;
+ return pRet;
+}
+
+bool SwWW8ImplReader::IsDropCap()
+{
+ // Find the DCS (Drop Cap Specifier) for the paragraph
+ // if does not exist or if the first three bits are 0
+ // then there is no dropcap on the paragraph
+ WW8PLCFx_Cp_FKP *pPap = pPlcxMan ? pPlcxMan->GetPapPLCF() : 0;
+ if (pPap)
+ {
+ const sal_uInt8 *pDCS;
+ if (bVer67)
+ pDCS = pPap->HasSprm(46);
+ else
+ pDCS = pPlcxMan->GetPapPLCF()->HasSprm(0x442C);
+ if(pDCS)
+ {
+ short nDCS = SVBT16ToShort( pDCS );
+ if((nDCS | 7) != 0)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool SwWW8ImplReader::StartApo(const ApoTestResults &rApo,
+ const WW8_TablePos *pTabPos)
+{
+ if (0 == (pWFlyPara = ConstructApo(rApo, pTabPos)))
+ return false;
+
+ // <WW8SwFlyPara> constructor has changed - new 4th parameter
+ // containing WW8 page top margin.
+ pSFlyPara = new WW8SwFlyPara( *pPaM, *this, *pWFlyPara,
+ maSectionManager.GetWWPageTopMargin(),
+ maSectionManager.GetPageLeft(),
+ maSectionManager.GetTextAreaWidth(),
+ nIniFlyDx, nIniFlyDy);
+
+ // If this paragraph is a Dropcap set the flag and we will deal with it later
+ if (IsDropCap())
+ {
+ bDropCap = true;
+ pAktItemSet = new SfxItemSet( rDoc.GetAttrPool(), RES_CHRATR_BEGIN, RES_PARATR_END - 1 );
+ return false;
+ }
+
+ if( !pWFlyPara->bGrafApo )
+ {
+
+ // Innerhalb des GrafApo muessen Textattribute ignoriert werden, da
+ // sie sonst auf den folgenden Zeilen landen. Der Rahmen wird nur
+ // eingefuegt, wenn er *nicht* nur zum Positionieren einer einzelnen
+ // Grafik dient. Ist es ein Grafik-Rahmen, dann werden pWFlyPara und
+ // pSFlyPara behalten und die
+ // daraus resultierenden Attribute beim Einfuegen der Grafik auf die
+ // Grafik angewendet.
+
+ WW8FlySet aFlySet(*this, pWFlyPara, pSFlyPara, false);
+
+ pSFlyPara->pFlyFmt = rDoc.MakeFlySection( pSFlyPara->eAnchor,
+ pPaM->GetPoint(), &aFlySet );
+ OSL_ENSURE(pSFlyPara->pFlyFmt->GetAnchor().GetAnchorId() ==
+ pSFlyPara->eAnchor, "Not the anchor type requested!");
+
+ if (pSFlyPara->pFlyFmt)
+ {
+ if (!pDrawModel)
+ GrafikCtor();
+
+ SdrObject* pOurNewObject = CreateContactObject(pSFlyPara->pFlyFmt);
+ pWWZOrder->InsertTextLayerObject(pOurNewObject);
+ }
+
+ if (FLY_AS_CHAR != pSFlyPara->eAnchor)
+ {
+ pAnchorStck->AddAnchor(*pPaM->GetPoint(),pSFlyPara->pFlyFmt);
+ }
+
+ // merke Pos im Haupttext
+ pSFlyPara->pMainTextPos = new SwPosition( *pPaM->GetPoint() );
+
+ //remove fltanchors, otherwise they will be closed inside the
+ //frame, which makes no sense, restore them after the frame is
+ //closed
+ pSFlyPara->pOldAnchorStck = pAnchorStck;
+ pAnchorStck = new SwWW8FltAnchorStack(&rDoc, nFieldFlags);
+
+ MoveInsideFly(pSFlyPara->pFlyFmt);
+
+ // 1) ReadText() wird nicht wie beim W4W-Reader rekursiv aufgerufen,
+ // da die Laenge des Apo zu diesen Zeitpunkt noch nicht feststeht,
+ // ReadText() diese Angabe aber braucht.
+ // 2) Der CtrlStck wird nicht neu erzeugt.
+ // die Char-Attribute laufen weiter ( AErger mit SW-Attributen )
+ // Paraattribute muessten am Ende jeden Absatzes zurueckgesetzt
+ // sein, d.h. es duerften am Absatzende keine Paraattribute
+ // auf dem Stack liegen
+ }
+ return true;
+}
+
+void wwSectionManager::JoinNode(const SwPosition &rPos, const SwNode &rNode)
+{
+ if ((!maSegments.empty()) && (maSegments.back().maStart == rPos.nNode))
+ maSegments.back().maStart = SwNodeIndex(rNode);
+}
+
+bool SwWW8ImplReader::JoinNode(SwPaM &rPam, bool bStealAttr)
+{
+ bool bRet = false;
+ rPam.GetPoint()->nContent = 0; // an den Anfang der Zeile gehen
+
+ SwNodeIndex aPref(rPam.GetPoint()->nNode, -1);
+
+ if (SwTxtNode* pNode = aPref.GetNode().GetTxtNode())
+ {
+ maSectionManager.JoinNode(*rPam.GetPoint(), aPref.GetNode());
+ rPam.GetPoint()->nNode = aPref;
+ rPam.GetPoint()->nContent.Assign(pNode, pNode->GetTxt().Len());
+ if (bStealAttr)
+ pCtrlStck->StealAttr(rPam.GetPoint());
+
+ pNode->JoinNext();
+
+ bRet = true;
+ }
+ return bRet;
+}
+
+void SwWW8ImplReader::StopApo()
+{
+ OSL_ENSURE(pWFlyPara, "no pWFlyPara to close");
+ if (!pWFlyPara)
+ return;
+ if (pWFlyPara->bGrafApo)
+ {
+ // Grafik-Rahmen, der *nicht* eingefuegt wurde leeren Absatz incl.
+ // Attributen entfernen
+ JoinNode(*pPaM, true);
+
+ }
+ else
+ {
+ if (!pSFlyPara->pMainTextPos || !pWFlyPara)
+ {
+ OSL_ENSURE( pSFlyPara->pMainTextPos, "StopApo: pMainTextPos ist 0" );
+ OSL_ENSURE( pWFlyPara, "StopApo: pWFlyPara ist 0" );
+ return;
+ }
+
+ /*
+ What we are doing with this temporary nodeindex is as follows: The
+ stack of attributes normally only places them into the document when
+ the current insertion point has passed them by. Otherwise the end
+ point of the attribute gets pushed along with the insertion point. The
+ insertion point is moved and the properties commited during
+ MoveOutsideFly. We also may want to remove the final paragraph in the
+ frame, but we need to wait until the properties for that frame text
+ have been commited otherwise they will be lost. So we first get a
+ handle to the last the filter inserted. After the attributes are
+ commited, if that paragraph exists we join it with the para after it
+ that comes with the frame by default so that as normal we don't end up
+ with one more paragraph than we wanted.
+ */
+ SwNodeIndex aPref(pPaM->GetPoint()->nNode, -1);
+
+ SwTwips nNewWidth =
+ MoveOutsideFly(pSFlyPara->pFlyFmt, *pSFlyPara->pMainTextPos);
+ if (nNewWidth)
+ pSFlyPara->BoxUpWidth(nNewWidth);
+
+ Color aBg(0xFE, 0xFF, 0xFF, 0xFF); //Transparent by default
+
+ if (SwTxtNode* pNd = aPref.GetNode().GetTxtNode())
+ {
+ /*
+ #i582#
+ Take the last paragraph background colour and fill the frame with
+ it. Otherwise, make it transparent, this appears to be how MSWord
+ works
+ */
+ const SfxPoolItem &rItm = pNd->SwCntntNode::GetAttr(RES_BACKGROUND);
+ const SvxBrushItem &rBrush = (const SvxBrushItem&)(rItm);
+ if (rBrush.GetColor().GetColor() != COL_AUTO)
+ aBg = rBrush.GetColor();
+
+ //Get rid of extra empty paragraph
+ pNd->JoinNext();
+ }
+
+ pSFlyPara->pFlyFmt->SetFmtAttr(SvxBrushItem(aBg, RES_BACKGROUND));
+
+ DeleteAnchorStk();
+ pAnchorStck = pSFlyPara->pOldAnchorStck;
+
+ // Ist die Fly-Breite durch eine innenliegende Grafik vergroessert
+ // worden ( bei automatischer Breite des Flys ), dann muss die Breite
+ // des SW-Flys entsprechend umgesetzt werden, da der SW keine
+ // automatische Breite kennt.
+ if( pSFlyPara->nNewNettoWidth > MINFLY ) // BoxUpWidth ?
+ {
+ long nW = pSFlyPara->nNewNettoWidth;
+ nW += pSFlyPara->nWidth - pSFlyPara->nNettoWidth; // Rand dazu
+ pSFlyPara->pFlyFmt->SetFmtAttr(
+ SwFmtFrmSize( pSFlyPara->eHeightFix, nW, pSFlyPara->nHeight ) );
+ }
+ /*
+ Word set *no* width meaning its an automatic width. The
+ SwFlyPara reader will have already set a fallback width of the
+ printable regions width, so we should reuse it. Despite the related
+ problems with layout addressed with a hack in WW8FlyPara's constructor
+ #i27204# Added AutoWidth setting. Left the old CalculateFlySize in place
+ so that if the user unselects autowidth, the width doesn't max out
+ */
+ else if( !pWFlyPara->nSp28 )
+ {
+ using namespace sw::util;
+ SfxItemSet aFlySet( pSFlyPara->pFlyFmt->GetAttrSet() );
+
+ SwFmtFrmSize aSize(ItemGet<SwFmtFrmSize>(aFlySet, RES_FRM_SIZE));
+
+ aFlySet.ClearItem(RES_FRM_SIZE);
+
+ CalculateFlySize(aFlySet, pSFlyPara->pMainTextPos->nNode,
+ pSFlyPara->nWidth);
+
+ nNewWidth = ItemGet<SwFmtFrmSize>(aFlySet, RES_FRM_SIZE).GetWidth();
+
+ aSize.SetWidth(nNewWidth);
+ aSize.SetWidthSizeType(ATT_VAR_SIZE);
+
+ pSFlyPara->pFlyFmt->SetFmtAttr(aSize);
+ }
+
+ delete pSFlyPara->pMainTextPos, pSFlyPara->pMainTextPos = 0;
+
+// Damit die Frames bei Einfuegen in existierendes Doc erzeugt werden,
+// wird in fltshell.cxx beim Setzen des FltAnchor-Attributes
+// pFlyFrm->MakeFrms() gerufen
+
+ }
+
+ //#i8062#
+ if (pSFlyPara && pSFlyPara->pFlyFmt)
+ pFmtOfJustInsertedApo = pSFlyPara->pFlyFmt;
+
+ DELETEZ( pSFlyPara );
+ DELETEZ( pWFlyPara );
+}
+
+// TestSameApo() beantwortet die Frage, ob es dasselbe APO oder ein neues ist
+bool SwWW8ImplReader::TestSameApo(const ApoTestResults &rApo,
+ const WW8_TablePos *pTabPos)
+{
+ if( !pWFlyPara )
+ {
+ OSL_ENSURE( pWFlyPara, " Wo ist mein pWFlyPara ? " );
+ return true;
+ }
+
+ // Es muss ein kompletter Vergleich ( ausser Borders ) stattfinden, um
+ // alle Kombinationen Style / Hart richtig einzuordnen. Deshalb wird ein
+ // temporaerer WW8FlyPara angelegt ( abh. ob Style oder nicht ), darauf
+ // die harten Attrs angewendet, und dann verglichen
+
+ // Zum Vergleich
+ WW8FlyPara aF(bVer67, rApo.mpStyleApo);
+ // WWPara fuer akt. Para
+ if (rApo.HasFrame())
+ aF.Read(rApo.mpSprm29, pPlcxMan->GetPapPLCF());
+ aF.ApplyTabPos(pTabPos);
+
+ return aF == *pWFlyPara;
+}
+
+/***************************************************************************
+# Attribut - Verwaltung
+#**************************************************************************/
+
+void SwWW8ImplReader::NewAttr( const SfxPoolItem& rAttr,
+ const bool bFirstLineOfStSet,
+ const bool bLeftIndentSet )
+{
+ if( !bNoAttrImport ) // zum Ignorieren von Styles beim Doc-Einfuegen
+ {
+ if (pAktColl)
+ {
+ OSL_ENSURE(rAttr.Which() != RES_FLTR_REDLINE, "redline in style!");
+ pAktColl->SetFmtAttr(rAttr);
+ }
+ else if (pAktItemSet)
+ {
+ pAktItemSet->Put(rAttr);
+ }
+ else if (rAttr.Which() == RES_FLTR_REDLINE)
+ {
+ mpRedlineStack->open(*pPaM->GetPoint(), rAttr);
+ }
+ else
+ {
+ pCtrlStck->NewAttr(*pPaM->GetPoint(), rAttr);
+ // #i103711#
+ if ( bFirstLineOfStSet )
+ {
+ const SwNode* pNd = &(pPaM->GetPoint()->nNode.GetNode());
+ maTxtNodesHavingFirstLineOfstSet.insert( pNd );
+ }
+ // <--
+ // #i105414#
+ if ( bLeftIndentSet )
+ {
+ const SwNode* pNd = &(pPaM->GetPoint()->nNode.GetNode());
+ maTxtNodesHavingLeftIndentSet.insert( pNd );
+ }
+ // <--
+ }
+
+ if (mpPostProcessAttrsInfo && mpPostProcessAttrsInfo->mbCopy)
+ mpPostProcessAttrsInfo->mItemSet.Put(rAttr);
+ }
+}
+
+// holt Attribut aus der FmtColl / Stack / Doc
+const SfxPoolItem* SwWW8ImplReader::GetFmtAttr( sal_uInt16 nWhich )
+{
+ const SfxPoolItem* pRet = 0;
+ if (pAktColl)
+ pRet = &(pAktColl->GetFmtAttr(nWhich));
+ else if (pAktItemSet)
+ {
+ pRet = pAktItemSet->GetItem(nWhich);
+ if (!pRet)
+ pRet = pStandardFmtColl ? &(pStandardFmtColl->GetFmtAttr(nWhich)) : 0;
+ if (!pRet)
+ pRet = &rDoc.GetAttrPool().GetDefaultItem(nWhich);
+ }
+ else if (pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
+ {
+ pRet = pCtrlStck->GetStackAttr(*pPaM->GetPoint(), nWhich);
+ if (!pRet)
+ {
+ if (nAktColl < nColls && pCollA[nAktColl].pFmt &&
+ pCollA[nAktColl].bColl)
+ {
+ pRet = &(pCollA[nAktColl].pFmt->GetFmtAttr(nWhich));
+ }
+ }
+ if (!pRet)
+ pRet = pStandardFmtColl ? &(pStandardFmtColl->GetFmtAttr(nWhich)) : 0;
+ if (!pRet)
+ pRet = &rDoc.GetAttrPool().GetDefaultItem(nWhich);
+ }
+ else
+ pRet = pCtrlStck->GetFmtAttr(*pPaM->GetPoint(), nWhich);
+ return pRet;
+}
+
+/***************************************************************************
+# eigentliche Attribute
+#
+# Die Methoden erhalten die Token-Id und die Laenge der noch folgenden
+# Parameter gemaess Tabelle in WWScan.cxx als Parameter
+#**************************************************************************/
+
+/***************************************************************************
+# Spezial WW - Attribute
+#**************************************************************************/
+
+void SwWW8ImplReader::Read_Special(sal_uInt16, const sal_uInt8* pData, short nLen)
+{
+ if( nLen < 0 )
+ {
+ bSpec = false;
+ return;
+ }
+ bSpec = ( *pData != 0 );
+}
+
+// Read_Obj wird fuer fObj und fuer fOle2 benutzt !
+void SwWW8ImplReader::Read_Obj(sal_uInt16 , const sal_uInt8* pData, short nLen)
+{
+ if( nLen < 0 )
+ bObj = false;
+ else
+ {
+ bObj = 0 != *pData;
+
+ if( bObj && nPicLocFc && bEmbeddObj )
+ {
+ if ( maFieldStack.back().mnFieldId == 56 ) {
+ // For LINK fields, store the nObjLocFc value in the field entry
+ maFieldStack.back().mnObjLocFc = nPicLocFc;
+ } else {
+ nObjLocFc = nPicLocFc;
+ }
+ }
+ }
+}
+
+void SwWW8ImplReader::Read_PicLoc(sal_uInt16 , const sal_uInt8* pData, short nLen )
+{
+ if( nLen < 0 )
+ {
+ nPicLocFc = 0;
+ bSpec = false; // Stimmt das immer ?
+ }
+ else
+ {
+ nPicLocFc = SVBT32ToUInt32( pData );
+ bSpec = true;
+
+ if( bObj && nPicLocFc && bEmbeddObj )
+ nObjLocFc = nPicLocFc;
+ }
+}
+
+void SwWW8ImplReader::Read_POutLvl(sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if (pAktColl && (0 < nLen))
+ {
+ if (SwWW8StyInf* pSI = GetStyle(nAktColl))
+ {
+ pSI->nOutlineLevel = static_cast< sal_uInt8 >(
+ ( (1 <= pSI->GetWWStyleId()) && (9 >= pSI->GetWWStyleId()) )
+ ? pSI->GetWWStyleId()-1
+ : (pData ? *pData : 0) );
+ }
+ }
+}
+
+void SwWW8ImplReader::Read_Symbol(sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( !bIgnoreText )
+ {
+ if( nLen < 0 )
+ {
+ //otherwise disable after we print the char
+ if (pPlcxMan && pPlcxMan->GetDoingDrawTextBox())
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_FONT );
+ bSymbol = false;
+ }
+ else
+ {
+ // Make new Font-Atribut
+ // (will be closed in SwWW8ImplReader::ReadChars() )
+
+ //Will not be added to the charencoding stack, for styles the real
+ //font setting will be put in as the styles charset, and for plain
+ //text encoding for symbols is moot. Drawing boxes will check bSymbol
+ //themselves so they don't need to add it to the stack either.
+ if (SetNewFontAttr(SVBT16ToShort( pData ), false, RES_CHRATR_FONT))
+ {
+ if( bVer67 )
+ {
+ cSymbol = ByteString::ConvertToUnicode(
+ *(sal_Char*)(pData+2), RTL_TEXTENCODING_MS_1252 );
+ }
+ else
+ cSymbol = SVBT16ToShort( pData+2 );
+ bSymbol = true;
+ }
+ }
+ }
+}
+
+SwWW8StyInf *SwWW8ImplReader::GetStyle(sal_uInt16 nColl) const
+{
+ return nColl < nColls ? &pCollA[nColl] : 0;
+}
+
+/***************************************************************************
+# Zeichen - Attribute
+#**************************************************************************/
+
+// Read_BoldUsw fuer Italic, Bold, Kapitaelchen, Versalien, durchgestrichen,
+// Contour und Shadow
+void SwWW8ImplReader::Read_BoldUsw( sal_uInt16 nId, const sal_uInt8* pData, short nLen )
+{
+ const int nContigiousWestern = 8;
+ const int nWestern = nContigiousWestern + 1;
+ const int nEastern = 2;
+ const int nCTL = 2;
+ const int nIds = nWestern + nEastern + nCTL;
+ static const sal_uInt16 nEndIds[ nIds ] =
+ {
+ RES_CHRATR_WEIGHT, RES_CHRATR_POSTURE,
+ RES_CHRATR_CROSSEDOUT, RES_CHRATR_CONTOUR,
+ RES_CHRATR_SHADOWED, RES_CHRATR_CASEMAP,
+ RES_CHRATR_CASEMAP, RES_CHRATR_HIDDEN,
+
+ RES_CHRATR_CROSSEDOUT,
+
+ RES_CHRATR_CJK_WEIGHT, RES_CHRATR_CJK_POSTURE,
+
+ RES_CHRATR_CTL_WEIGHT, RES_CHRATR_CTL_POSTURE
+ };
+
+ ww::WordVersion eVersion = pWwFib->GetFIBVersion();
+
+ sal_uInt8 nI;
+ // die Attribut-Nr fuer "doppelt durchgestrichen" tanzt aus der Reihe
+ if (0x2A53 == nId)
+ nI = nContigiousWestern; // The out of sequence western id
+ else
+ {
+ // The contigious western ids
+ if (eVersion <= ww::eWW2)
+ nI = static_cast< sal_uInt8 >(nId - 60);
+ else if (eVersion < ww::eWW8)
+ nI = static_cast< sal_uInt8 >(nId - 85);
+ else
+ nI = static_cast< sal_uInt8 >(nId - 0x0835);
+ }
+
+ sal_uInt16 nMask = 1 << nI;
+
+ if (nLen < 0)
+ {
+ if (nI < 2)
+ {
+ if (eVersion <= ww::eWW6)
+ {
+ // reset the CTL Weight and Posture, because they are the same as their
+ // western equivalents in ww6
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), nEndIds[ nWestern + nEastern + nI ] );
+ }
+ // reset the CJK Weight and Posture, because they are the same as their
+ // western equivalents in word
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), nEndIds[ nWestern + nI ] );
+ }
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), nEndIds[ nI ] );
+ pCtrlStck->SetToggleAttr(nI, false);
+ return;
+ }
+ // Wert: 0 = Aus, 1 = An, 128 = Wie Style, 129 entgegen Style
+ bool bOn = *pData & 1;
+ SwWW8StyInf* pSI = GetStyle(nAktColl);
+ if (pPlcxMan && eVersion > ww::eWW2)
+ {
+ const sal_uInt8 *pCharIstd =
+ pPlcxMan->GetChpPLCF()->HasSprm(bVer67 ? 80 : 0x4A30);
+ if (pCharIstd)
+ pSI = GetStyle(SVBT16ToShort(pCharIstd));
+ }
+
+ if( pAktColl ) // StyleDef -> Flags merken
+ {
+ if (pSI)
+ {
+ // The style based on has Bit 7 set ?
+ if (
+ pSI->nBase < nColls && (*pData & 0x80) &&
+ (pCollA[pSI->nBase].n81Flags & nMask)
+ )
+ {
+ bOn = !bOn; // umdrehen
+ }
+
+ if (bOn)
+ pSI->n81Flags |= nMask; // Flag setzen
+ else
+ pSI->n81Flags &= ~nMask; // Flag loeschen
+ }
+ }
+ else
+ {
+
+ // im Text -> Flags abfragen
+ if( *pData & 0x80 ) // Bit 7 gesetzt ?
+ {
+ if (pSI && pSI->n81Flags & nMask) // und in StyleDef an ?
+ bOn = !bOn; // dann invertieren
+ // am Stack vermerken, das dieses ein Toggle-Attribut ist
+ pCtrlStck->SetToggleAttr(nI, true);
+ }
+ }
+
+ SetToggleAttr( nI, bOn );
+}
+
+void SwWW8ImplReader::Read_Bidi(sal_uInt16, const sal_uInt8*, short nLen)
+{
+ if (nLen > 0)
+ bBidi = true;
+ else
+ bBidi = false;
+}
+
+// Read_BoldUsw for BiDi Italic, Bold
+void SwWW8ImplReader::Read_BoldBiDiUsw(sal_uInt16 nId, const sal_uInt8* pData,
+ short nLen)
+{
+ static const sal_uInt16 nEndIds[2] =
+ {
+ RES_CHRATR_CTL_WEIGHT, RES_CHRATR_CTL_POSTURE,
+ };
+
+ sal_uInt8 nI;
+ ww::WordVersion eVersion = pWwFib->GetFIBVersion();
+ if (eVersion <= ww::eWW2)
+ nI = static_cast< sal_uInt8 >(nId - 80);
+ else if (eVersion < ww::eWW8)
+ nI = static_cast< sal_uInt8 >(nId - 111);
+ else
+ nI = static_cast< sal_uInt8 >(nId - 0x085C);
+
+ OSL_ENSURE(nI <= 1, "not happening");
+ if (nI > 1)
+ return;
+
+ sal_uInt16 nMask = 1 << nI;
+
+ if( nLen < 0 )
+ {
+ pCtrlStck->SetAttr(*pPaM->GetPoint(),nEndIds[nI]);
+ pCtrlStck->SetToggleBiDiAttr(nI, false);
+ return;
+ }
+ bool bOn = *pData & 1;
+ SwWW8StyInf* pSI = GetStyle(nAktColl);
+ if (pPlcxMan)
+ {
+ const sal_uInt8 *pCharIstd =
+ pPlcxMan->GetChpPLCF()->HasSprm(bVer67 ? 80 : 0x4A30);
+ if (pCharIstd)
+ pSI = GetStyle(SVBT16ToShort(pCharIstd));
+ }
+
+ if (pAktColl && eVersion > ww::eWW2) // StyleDef -> Flags merken
+ {
+ if (pSI)
+ {
+ if( pSI->nBase < nColls // Style Based on
+ && ( *pData & 0x80 ) // Bit 7 gesetzt ?
+ && ( pCollA[pSI->nBase].n81BiDiFlags & nMask ) ) // BasisMaske ?
+ bOn = !bOn; // umdrehen
+
+ if( bOn )
+ pSI->n81BiDiFlags |= nMask; // Flag setzen
+ else
+ pSI->n81BiDiFlags &= ~nMask; // Flag loeschen
+ }
+ }
+ else
+ {
+
+ // im Text -> Flags abfragen
+ if (*pData & 0x80) // Bit 7 gesetzt ?
+ {
+ if (pSI && pSI->n81BiDiFlags & nMask) // und in StyleDef an ?
+ bOn = !bOn; // dann invertieren
+ // am Stack vermerken, das dieses ein Toggle-Attribut ist
+ pCtrlStck->SetToggleBiDiAttr(nI, true);
+ }
+ }
+
+ SetToggleBiDiAttr(nI, bOn);
+}
+
+void SwWW8ImplReader::SetToggleBiDiAttr(sal_uInt8 nAttrId, bool bOn)
+{
+ switch (nAttrId)
+ {
+ case 0:
+ {
+ SvxWeightItem aAttr( bOn ? WEIGHT_BOLD : WEIGHT_NORMAL, RES_CHRATR_WEIGHT );
+ aAttr.SetWhich( RES_CHRATR_CTL_WEIGHT );
+ NewAttr( aAttr );
+ }
+ break;
+ case 1:
+ {
+ SvxPostureItem aAttr( bOn ? ITALIC_NORMAL : ITALIC_NONE, RES_CHRATR_POSTURE );
+ aAttr.SetWhich( RES_CHRATR_CTL_POSTURE );
+ NewAttr( aAttr );
+ }
+ break;
+ default:
+ OSL_ENSURE(!this, "Unhandled unknown bidi toggle attribute");
+ break;
+
+ }
+}
+
+void SwWW8ImplReader::SetToggleAttr(sal_uInt8 nAttrId, bool bOn)
+{
+ ww::WordVersion eVersion = pWwFib->GetFIBVersion();
+
+ switch (nAttrId)
+ {
+ case 0:
+ {
+ SvxWeightItem aAttr( bOn ? WEIGHT_BOLD : WEIGHT_NORMAL, RES_CHRATR_WEIGHT );
+ NewAttr( aAttr );
+ aAttr.SetWhich( RES_CHRATR_CJK_WEIGHT );
+ NewAttr( aAttr );
+ if (eVersion <= ww::eWW6)
+ {
+ aAttr.SetWhich( RES_CHRATR_CTL_WEIGHT );
+ NewAttr( aAttr );
+ }
+ }
+ break;
+ case 1:
+ {
+ SvxPostureItem aAttr( bOn ? ITALIC_NORMAL : ITALIC_NONE, RES_CHRATR_POSTURE );
+ NewAttr( aAttr );
+ aAttr.SetWhich( RES_CHRATR_CJK_POSTURE );
+ NewAttr( aAttr );
+ if (eVersion <= ww::eWW6)
+ {
+ aAttr.SetWhich( RES_CHRATR_CTL_POSTURE );
+ NewAttr( aAttr );
+ }
+ }
+ break;
+ case 2:
+ NewAttr(SvxCrossedOutItem(bOn ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, RES_CHRATR_CROSSEDOUT));
+ break;
+ case 3:
+ NewAttr( SvxContourItem( bOn, RES_CHRATR_CONTOUR ) );
+ break;
+ case 4:
+ NewAttr( SvxShadowedItem( bOn, RES_CHRATR_SHADOWED ) );
+ break;
+ case 5:
+ NewAttr( SvxCaseMapItem( bOn ? SVX_CASEMAP_KAPITAELCHEN
+ : SVX_CASEMAP_NOT_MAPPED, RES_CHRATR_CASEMAP ) );
+ break;
+ case 6:
+ NewAttr( SvxCaseMapItem( bOn ? SVX_CASEMAP_VERSALIEN
+ : SVX_CASEMAP_NOT_MAPPED, RES_CHRATR_CASEMAP ) );
+ break;
+ case 7:
+ NewAttr(SvxCharHiddenItem(bOn, RES_CHRATR_HIDDEN));
+ break;
+ case 8:
+ NewAttr( SvxCrossedOutItem( bOn ? STRIKEOUT_DOUBLE
+ : STRIKEOUT_NONE, RES_CHRATR_CROSSEDOUT ) );
+ break;
+ default:
+ OSL_ENSURE(!this, "Unhandled unknown toggle attribute");
+ break;
+ }
+}
+
+void SwWW8ImplReader::_ChkToggleAttr( sal_uInt16 nOldStyle81Mask,
+ sal_uInt16 nNewStyle81Mask )
+{
+ sal_uInt16 i = 1, nToggleAttrFlags = pCtrlStck->GetToggleAttrFlags();
+ for (sal_uInt8 n = 0; n < 7; ++n, i <<= 1)
+ {
+ if (
+ (i & nToggleAttrFlags) &&
+ ((i & nOldStyle81Mask) != (i & nNewStyle81Mask))
+ )
+ {
+ SetToggleAttr(n, (i & nOldStyle81Mask));
+ }
+ }
+}
+
+void SwWW8ImplReader::_ChkToggleBiDiAttr( sal_uInt16 nOldStyle81Mask,
+ sal_uInt16 nNewStyle81Mask )
+{
+ sal_uInt16 i = 1, nToggleAttrFlags = pCtrlStck->GetToggleBiDiAttrFlags();
+ for (sal_uInt8 n = 0; n < 7; ++n, i <<= 1)
+ {
+ if (
+ (i & nToggleAttrFlags) &&
+ ((i & nOldStyle81Mask) != (i & nNewStyle81Mask))
+ )
+ {
+ SetToggleBiDiAttr(n, (i & nOldStyle81Mask));
+ }
+ }
+}
+
+void SwWW8ImplReader::Read_SubSuper( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen < 0 ){
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_ESCAPEMENT );
+ return;
+ }
+
+ short nEs;
+ sal_uInt8 nProp;
+ switch( *pData )
+ {
+ case 1:
+ nEs = DFLT_ESC_AUTO_SUPER;
+ nProp = DFLT_ESC_PROP;
+ break;
+ case 2:
+ nEs = DFLT_ESC_AUTO_SUB;
+ nProp = DFLT_ESC_PROP;
+ break;
+ default:
+ nEs = 0;
+ nProp = 100;
+ break;
+ }
+ NewAttr( SvxEscapementItem( nEs, nProp, RES_CHRATR_ESCAPEMENT ) );
+}
+
+SwFrmFmt *SwWW8ImplReader::ContainsSingleInlineGraphic(const SwPaM &rRegion)
+{
+ /*
+ For inline graphics and objects word has a hacked in feature to use
+ subscripting to force the graphic into a centered position on the line, so
+ we must check when applying sub/super to see if it the subscript range
+ contains only a single graphic, and if that graphic is anchored as
+ FLY_AS_CHAR and then we can change its anchoring to centered in the line.
+ */
+ SwFrmFmt *pRet=0;
+ SwNodeIndex aBegin(rRegion.Start()->nNode);
+ xub_StrLen nBegin(rRegion.Start()->nContent.GetIndex());
+ SwNodeIndex aEnd(rRegion.End()->nNode);
+ xub_StrLen nEnd(rRegion.End()->nContent.GetIndex());
+ const SwTxtNode* pTNd;
+ const SwTxtAttr* pTFlyAttr;
+ if (
+ aBegin == aEnd && nBegin == nEnd - 1 &&
+ 0 != (pTNd = aBegin.GetNode().GetTxtNode()) &&
+ 0 != (pTFlyAttr = pTNd->GetTxtAttrForCharAt(nBegin, RES_TXTATR_FLYCNT))
+ )
+ {
+ const SwFmtFlyCnt& rFly = pTFlyAttr->GetFlyCnt();
+ SwFrmFmt *pFlyFmt = rFly.GetFrmFmt();
+ if (pFlyFmt &&
+ (FLY_AS_CHAR == pFlyFmt->GetAnchor().GetAnchorId()))
+ {
+ pRet = pFlyFmt;
+ }
+ }
+ return pRet;
+}
+
+bool SwWW8ImplReader::ConvertSubToGraphicPlacement()
+{
+ /*
+ For inline graphics and objects word has a hacked in feature to use
+ subscripting to force the graphic into a centered position on the line, so
+ we must check when applying sub/super to see if it the subscript range
+ contains only a single graphic, and if that graphic is anchored as
+ FLY_AS_CHAR and then we can change its anchoring to centered in the line.
+ */
+ bool bIsGraphicPlacementHack = false;
+ sal_uInt16 nPos;
+ if (pCtrlStck->GetFmtStackAttr(RES_CHRATR_ESCAPEMENT, &nPos))
+ {
+ SwPaM aRegion(*pPaM->GetPoint());
+
+ SwFltStackEntry aEntry = *((*pCtrlStck)[nPos]);
+ aEntry.SetEndPos(*pPaM->GetPoint());
+
+ SwFrmFmt *pFlyFmt = 0;
+ if (
+ aEntry.MakeRegion(&rDoc,aRegion,false) &&
+ 0 != (pFlyFmt = ContainsSingleInlineGraphic(aRegion))
+ )
+ {
+ pCtrlStck->DeleteAndDestroy(nPos);
+ pFlyFmt->SetFmtAttr(SwFmtVertOrient(0, text::VertOrientation::CHAR_CENTER, text::RelOrientation::CHAR));
+ bIsGraphicPlacementHack = true;
+ }
+ }
+ return bIsGraphicPlacementHack;
+}
+
+void SwWW8ImplReader::Read_SubSuperProp( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen < 0 )
+ {
+ if (!ConvertSubToGraphicPlacement())
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_ESCAPEMENT );
+ return;
+ }
+
+ ww::WordVersion eVersion = pWwFib->GetFIBVersion();
+
+ // Font-Position in HalfPoints
+ short nPos = eVersion <= ww::eWW2 ? static_cast< sal_Int8 >( *pData ) : SVBT16ToShort( pData );
+ sal_Int32 nPos2 = nPos * ( 10 * 100 ); // HalfPoints in 100 * tw
+ const SvxFontHeightItem* pF
+ = (const SvxFontHeightItem*)GetFmtAttr(RES_CHRATR_FONTSIZE);
+ OSL_ENSURE(pF, "Expected to have the fontheight available here");
+
+ // #i59022: Check ensure nHeight != 0. Div by zero otherwise.
+ sal_Int32 nHeight = 240;
+ if (pF != NULL && pF->GetHeight() != 0)
+ nHeight = pF->GetHeight();
+ nPos2 /= nHeight; // ... nun in % ( gerundet )
+ if( nPos2 > 100 ) // zur Sicherheit
+ nPos2 = 100;
+ if( nPos2 < -100 )
+ nPos2 = -100;
+ SvxEscapementItem aEs( (short)nPos2, 100, RES_CHRATR_ESCAPEMENT );
+ NewAttr( aEs );
+}
+
+void SwWW8ImplReader::Read_Underline( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ FontUnderline eUnderline = UNDERLINE_NONE;
+ bool bWordLine = false;
+ if( pData )
+ {
+ // Parameter: 0 = none, 1 = single, 2 = by Word,
+ // 3 = double, 4 = dotted, 5 = hidden
+ // 6 = thick, 7 = dash, 8 = dot(not used)
+ // 9 = dotdash 10 = dotdotdash 11 = wave
+
+
+ // pruefe auf Sonderfall "fett+unterstrichen"
+ bool bAlsoBold = /*( 6 == b )*/ false;
+ // erst mal ggfs. *bold* einschalten!
+ if( bAlsoBold )
+ {
+ sal_uInt8 nOn = 1;
+ Read_BoldUsw( 0x0835, &nOn, nLen );
+ eUnderline = UNDERLINE_SINGLE;
+ }
+ else
+ {
+ switch( *pData )
+ {
+ case 2: bWordLine = true; // no break;
+ case 1: eUnderline = (FontUnderline)UNDERLINE_SINGLE; break;
+ case 3: eUnderline = (FontUnderline)UNDERLINE_DOUBLE; break;
+ case 4: eUnderline = (FontUnderline)UNDERLINE_DOTTED; break;
+ case 7: eUnderline = (FontUnderline)UNDERLINE_DASH; break;
+ case 9: eUnderline = (FontUnderline)UNDERLINE_DASHDOT; break;
+ case 10:eUnderline = (FontUnderline)UNDERLINE_DASHDOTDOT; break;
+ case 6: eUnderline = (FontUnderline)UNDERLINE_BOLD; break;
+ case 11:eUnderline = (FontUnderline)UNDERLINE_WAVE; break;
+ case 20:eUnderline = (FontUnderline)UNDERLINE_BOLDDOTTED; break;
+ case 23:eUnderline = (FontUnderline)UNDERLINE_BOLDDASH; break;
+ case 39:eUnderline = (FontUnderline)UNDERLINE_LONGDASH; break;
+ case 55:eUnderline = (FontUnderline)UNDERLINE_BOLDLONGDASH; break;
+ case 25:eUnderline = (FontUnderline)UNDERLINE_BOLDDASHDOT; break;
+ case 26:eUnderline = (FontUnderline)UNDERLINE_BOLDDASHDOTDOT;break;
+ case 27:eUnderline = (FontUnderline)UNDERLINE_BOLDWAVE; break;
+ case 43:eUnderline = (FontUnderline)UNDERLINE_DOUBLEWAVE; break;
+ }
+ }
+ }
+
+ // dann Stack ggfs. verwursteln und exit!
+ if( nLen < 0 )
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_UNDERLINE );
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_WORDLINEMODE );
+ }
+ else
+ {
+ NewAttr( SvxUnderlineItem( eUnderline, RES_CHRATR_UNDERLINE ));
+ if( bWordLine )
+ NewAttr(SvxWordLineModeItem(true, RES_CHRATR_WORDLINEMODE));
+ }
+}
+
+/*
+//The last three vary, measurements, rotation ? ?
+NoBracket 78 CA 06 - 02 00 00 02 34 52
+() 78 CA 06 - 02 01 00 02 34 52
+[] 78 CA 06 - 02 02 00 02 34 52
+<> 78 CA 06 - 02 03 00 02 34 52
+{} 78 CA 06 - 02 04 00 02 34 52
+*/
+void SwWW8ImplReader::Read_DoubleLine_Rotate( sal_uInt16, const sal_uInt8* pData,
+ short nLen )
+{
+ if( nLen < 0 ) // close the tag
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_TWO_LINES );
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_ROTATE );
+ }
+ else if( pData && 6 == nLen )
+ {
+ switch( *pData )
+ {
+ case 2: // double line
+ {
+ sal_Unicode cStt = 0, cEnd = 0;
+ switch( SVBT16ToShort( pData+1 ) )
+ {
+ case 1: cStt = '(', cEnd = ')'; break;
+ case 2: cStt = '[', cEnd = ']'; break;
+ case 3: cStt = '<', cEnd = '>'; break;
+ case 4: cStt = '{', cEnd = '}'; break;
+ }
+ NewAttr( SvxTwoLinesItem( sal_True, cStt, cEnd, RES_CHRATR_TWO_LINES ));
+ }
+ break;
+
+ case 1: // rotated characters
+ {
+ bool bFitToLine = 0 != *(pData+1);
+ NewAttr( SvxCharRotateItem( 900, bFitToLine, RES_CHRATR_ROTATE ));
+ }
+ break;
+ }
+ }
+}
+
+void SwWW8ImplReader::Read_TxtColor( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ //Has newer colour varient, ignore this old varient
+ if (!bVer67 && pPlcxMan && pPlcxMan->GetChpPLCF()->HasSprm(0x6870))
+ return;
+
+ if( nLen < 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_COLOR );
+ else
+ {
+ sal_uInt8 b = *pData; // Parameter: 0 = Auto, 1..16 Farben
+
+ if( b > 16 ) // unbekannt -> Black
+ b = 0;
+
+ NewAttr( SvxColorItem(Color(GetCol(b)), RES_CHRATR_COLOR));
+ if (pAktColl && pStyles)
+ pStyles->bTxtColChanged = true;
+ }
+}
+
+sal_uInt32 wwUtility::BGRToRGB(sal_uInt32 nColor)
+{
+ sal_uInt8
+ r(static_cast<sal_uInt8>(nColor&0xFF)),
+ g(static_cast<sal_uInt8>(((nColor)>>8)&0xFF)),
+ b(static_cast<sal_uInt8>((nColor>>16)&0xFF)),
+ t(static_cast<sal_uInt8>((nColor>>24)&0xFF));
+ nColor = (t<<24) + (r<<16) + (g<<8) + b;
+ return nColor;
+}
+
+void SwWW8ImplReader::Read_TxtForeColor(sal_uInt16, const sal_uInt8* pData, short nLen)
+{
+ if( nLen < 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_COLOR );
+ else
+ {
+ Color aColor(wwUtility::BGRToRGB(SVBT32ToUInt32(pData)));
+ NewAttr(SvxColorItem(aColor, RES_CHRATR_COLOR));
+ if (pAktColl && pStyles)
+ pStyles->bTxtColChanged = true;
+ }
+}
+
+bool SwWW8ImplReader::GetFontParams( sal_uInt16 nFCode, FontFamily& reFamily,
+ String& rName, FontPitch& rePitch, CharSet& reCharSet )
+{
+ // Die Defines, aus denen diese Tabellen erzeugt werden, stehen in windows.h
+ static const FontPitch ePitchA[] =
+ {
+ PITCH_DONTKNOW, PITCH_FIXED, PITCH_VARIABLE, PITCH_DONTKNOW
+ };
+
+ static const FontFamily eFamilyA[] =
+ {
+ FAMILY_DONTKNOW, FAMILY_ROMAN, FAMILY_SWISS, FAMILY_MODERN,
+ FAMILY_SCRIPT, FAMILY_DECORATIVE
+ };
+
+ const WW8_FFN* pF = pFonts->GetFont( nFCode ); // Info dazu
+ if( !pF ) // FontNummer unbekannt ?
+ return false; // dann ignorieren
+
+ rName = String( pF->sFontname );
+
+ // pF->prg : Pitch
+ rePitch = ePitchA[pF->prg];
+
+ // pF->chs: Charset
+ if( 77 == pF->chs ) // Mac-Font im Mac-Charset oder
+ reCharSet = eTextCharSet; // auf ANSI-Charset uebersetzt
+ else
+ { // patch from cmc for #i52786#
+ // #i52786#, for word 67 we'll assume that ANSI is basically invalid,
+ // might be true for (above) mac as well, but would need a mac example
+ // that exercises this to be sure
+ if (bVer67 && pF->chs == 0)
+ reCharSet = RTL_TEXTENCODING_DONTKNOW;
+ else
+ reCharSet = rtl_getTextEncodingFromWindowsCharset( pF->chs );
+ }
+
+ // pF->ff : Family
+ sal_uInt8 b = pF->ff;
+
+ // make sure Font Family Code is set correctly
+ // at least for the most important fonts
+ // ( might be set wrong when Doc was not created by
+ // Winword but by third party program like Applixware... )
+ /*
+ 0: FAMILY_DONTKNOW
+ 1: FAMILY_ROMAN
+ 2: FAMILY_SWISS
+ 3: FAMILY_MODERN
+ 4: FAMILY_SCRIPT
+ 5: FAMILY_DECORATIVE
+ */
+#define FONTNAMETAB_SZ 14
+#define MAX_FONTNAME_ROMAN 6
+ static const sal_Char
+ // first comes ROMAN
+ sFontName0[] = "\x07""Tms Rmn",
+ sFontName1[] = "\x07""Timmons",
+ sFontName2[] = "\x08""CG Times",
+ sFontName3[] = "\x08""MS Serif",
+ sFontName4[] = "\x08""Garamond",
+ sFontName5[] = "\x11""Times Roman",
+ sFontName6[] = "\x15""Times New Roman",
+ // from here SWISS --> see above: #define MAX_FONTNAME_ROMAN 6
+ sFontName7[] = "\x04""Helv",
+ sFontName8[] = "\x05""Arial",
+ sFontName9[] = "\x07""Univers",
+ sFontName10[]= "\x11""LinePrinter",
+ sFontName11[]= "\x11""Lucida Sans",
+ sFontName12[]= "\x11""Small Fonts",
+ sFontName13[]= "\x13""MS Sans Serif";
+ static const sal_Char* const aFontNameTab[ FONTNAMETAB_SZ ] =
+ {
+ sFontName0, sFontName1, sFontName2, sFontName3,
+ sFontName4, sFontName5, sFontName6, sFontName7,
+ sFontName8, sFontName9, sFontName10, sFontName11,
+ sFontName12, sFontName13
+ };
+
+ for( sal_uInt16 n = 0; n < FONTNAMETAB_SZ; n++ )
+ {
+ const sal_Char* pCmp = aFontNameTab[ n ];
+ xub_StrLen nLen = *pCmp++;
+ if( rName.EqualsIgnoreCaseAscii(pCmp, 0, nLen) )
+ {
+ b = n <= MAX_FONTNAME_ROMAN ? 1 : 2;
+ break;
+ }
+ }
+ if( b < sizeof( eFamilyA ) )
+ reFamily = eFamilyA[b];
+ else
+ reFamily = FAMILY_DONTKNOW;
+
+ return true;
+}
+
+bool SwWW8ImplReader::SetNewFontAttr(sal_uInt16 nFCode, bool bSetEnums,
+ sal_uInt16 nWhich)
+{
+ FontFamily eFamily;
+ String aName;
+ FontPitch ePitch;
+ CharSet eSrcCharSet;
+
+ if( !GetFontParams( nFCode, eFamily, aName, ePitch, eSrcCharSet ) )
+ {
+ //If we fail (and are not doing a style) then put something into the
+ //character encodings stack anyway so that the property end that pops
+ //off the stack will keep in sync
+ if (!pAktColl && IsListOrDropcap())
+ {
+ if (nWhich == RES_CHRATR_CJK_FONT)
+ {
+ if (!maFontSrcCJKCharSets.empty())
+ {
+ eSrcCharSet = maFontSrcCJKCharSets.top();
+ }
+ else
+ {
+ eSrcCharSet = RTL_TEXTENCODING_DONTKNOW;
+ }
+
+ maFontSrcCJKCharSets.push(eSrcCharSet);
+ }
+ else
+ {
+ if (!maFontSrcCharSets.empty())
+ {
+ eSrcCharSet = maFontSrcCharSets.top();
+ }
+ else
+ {
+ eSrcCharSet = RTL_TEXTENCODING_DONTKNOW;
+ }
+
+ maFontSrcCharSets.push(eSrcCharSet);
+ }
+ }
+ return false;
+ }
+
+ CharSet eDstCharSet = eSrcCharSet;
+
+ SvxFontItem aFont( eFamily, aName, aEmptyStr, ePitch, eDstCharSet, nWhich);
+
+ if( bSetEnums )
+ {
+ if( pAktColl ) // StyleDef
+ {
+ switch(nWhich)
+ {
+ default:
+ case RES_CHRATR_FONT:
+ pCollA[nAktColl].eLTRFontSrcCharSet = eSrcCharSet;
+ break;
+ case RES_CHRATR_CTL_FONT:
+ pCollA[nAktColl].eRTLFontSrcCharSet = eSrcCharSet;
+ break;
+ case RES_CHRATR_CJK_FONT:
+ pCollA[nAktColl].eCJKFontSrcCharSet = eSrcCharSet;
+ break;
+ }
+ }
+ else if (IsListOrDropcap())
+ {
+ //Add character text encoding to stack
+ if (nWhich == RES_CHRATR_CJK_FONT)
+ maFontSrcCJKCharSets.push(eSrcCharSet);
+ else
+ maFontSrcCharSets.push(eSrcCharSet);
+ }
+ }
+
+ NewAttr( aFont ); // ...und 'reinsetzen
+
+ return true;
+}
+
+void SwWW8ImplReader::ResetCharSetVars()
+{
+ OSL_ENSURE(!maFontSrcCharSets.empty(),"no charset to remove");
+ if (!maFontSrcCharSets.empty())
+ maFontSrcCharSets.pop();
+}
+
+void SwWW8ImplReader::ResetCJKCharSetVars()
+{
+ OSL_ENSURE(!maFontSrcCJKCharSets.empty(),"no charset to remove");
+ if (!maFontSrcCJKCharSets.empty())
+ maFontSrcCJKCharSets.pop();
+}
+
+void SwWW8ImplReader::openFont(sal_uInt16 nFCode, sal_uInt16 nId)
+{
+ if (SetNewFontAttr(nFCode, true, nId) && pAktColl && pStyles)
+ {
+ // merken zur Simulation Default-Font
+ if (RES_CHRATR_CJK_FONT == nId)
+ pStyles->bCJKFontChanged = true;
+ else if (RES_CHRATR_CTL_FONT == nId)
+ pStyles->bCTLFontChanged = true;
+ else
+ pStyles->bFontChanged = true;
+ }
+}
+
+void SwWW8ImplReader::closeFont(sal_uInt16 nId)
+{
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), nId );
+ if (nId == RES_CHRATR_CJK_FONT)
+ ResetCJKCharSetVars();
+ else
+ ResetCharSetVars();
+}
+
+/*
+ Font ein oder ausschalten:
+*/
+void SwWW8ImplReader::Read_FontCode( sal_uInt16 nId, const sal_uInt8* pData, short nLen )
+{
+ if (!bSymbol) // falls bSymbol, gilt der am Symbol
+ { // (siehe sprmCSymbol) gesetzte Font !
+ switch( nId )
+ {
+ case 113: //WW7
+ case 0x4A51: //"Other" font, override with BiDi if it exists
+ case 0x4A5E: //BiDi Font
+ nId = RES_CHRATR_CTL_FONT;
+ break;
+ case 93: //WW6
+ case 111: //WW7
+ case 0x4A4f:
+ nId = RES_CHRATR_FONT;
+ break;
+ case 112: //WW7
+ case 0x4A50:
+ nId = RES_CHRATR_CJK_FONT;
+ break;
+ default:
+ return ;
+ }
+
+ ww::WordVersion eVersion = pWwFib->GetFIBVersion();
+
+ if( nLen < 0 ) // Ende des Attributes
+ {
+ if (eVersion <= ww::eWW6)
+ {
+ closeFont(RES_CHRATR_CTL_FONT);
+ closeFont(RES_CHRATR_CJK_FONT);
+ }
+ closeFont(nId);
+ }
+ else
+ {
+ sal_uInt16 nFCode = SVBT16ToShort( pData ); // Font-Nummer
+ openFont(nFCode, nId);
+ if (eVersion <= ww::eWW6)
+ {
+ openFont(nFCode, RES_CHRATR_CJK_FONT);
+ openFont(nFCode, RES_CHRATR_CTL_FONT);
+ }
+ }
+ }
+}
+
+void SwWW8ImplReader::Read_FontSize( sal_uInt16 nId, const sal_uInt8* pData, short nLen )
+{
+ switch( nId )
+ {
+ case 74:
+ case 99:
+ case 0x4a43:
+ nId = RES_CHRATR_FONTSIZE;
+ break;
+ case 85: //WW2
+ case 116: //WW7
+ case 0x4a61:
+ nId = RES_CHRATR_CTL_FONTSIZE;
+ break;
+ default:
+ return ;
+ }
+
+ ww::WordVersion eVersion = pWwFib->GetFIBVersion();
+
+ if( nLen < 0 ) // Ende des Attributes
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), nId );
+ if (eVersion <= ww::eWW6) // reset additionally the CTL size
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_CTL_FONTSIZE );
+ if (RES_CHRATR_FONTSIZE == nId) // reset additionally the CJK size
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_CJK_FONTSIZE );
+ }
+ else
+ {
+ // Font-Size in half points e.g. 10 = 1440 / ( 72 * 2 )
+ sal_uInt16 nFSize = eVersion <= ww::eWW2 ? *pData : SVBT16ToShort(pData);
+ nFSize*= 10;
+
+ SvxFontHeightItem aSz( nFSize, 100, nId );
+ NewAttr( aSz );
+ if (RES_CHRATR_FONTSIZE == nId) // set additionally the CJK size
+ {
+ aSz.SetWhich( RES_CHRATR_CJK_FONTSIZE );
+ NewAttr( aSz );
+ }
+ if (eVersion <= ww::eWW6) // set additionally the CTL size
+ {
+ aSz.SetWhich( RES_CHRATR_CTL_FONTSIZE );
+ NewAttr( aSz );
+ }
+ if (pAktColl && pStyles) // Style-Def ?
+ {
+ // merken zur Simulation Default-FontSize
+ if (nId == RES_CHRATR_CTL_FONTSIZE)
+ pStyles->bFCTLSizeChanged = true;
+ else
+ {
+ pStyles->bFSizeChanged = true;
+ if (eVersion <= ww::eWW6)
+ pStyles->bFCTLSizeChanged= true;
+ }
+ }
+ }
+}
+
+
+
+void SwWW8ImplReader::Read_CharSet(sal_uInt16 , const sal_uInt8* pData, short nLen)
+{
+ if( nLen < 0 )
+ { // Ende des Attributes
+ eHardCharSet = RTL_TEXTENCODING_DONTKNOW;
+ return;
+ }
+ sal_uInt8 nfChsDiff = SVBT8ToByte( pData );
+
+ if( nfChsDiff )
+ eHardCharSet = rtl_getTextEncodingFromWindowsCharset( *(pData + 1) );
+ else
+ eHardCharSet = RTL_TEXTENCODING_DONTKNOW;
+}
+
+void SwWW8ImplReader::Read_Language( sal_uInt16 nId, const sal_uInt8* pData, short nLen )
+{
+ switch( nId )
+ {
+ case 97:
+ case 0x486D: //sprmCRgLid0_80
+ case 0x4873: //Methinks, uncertain
+ nId = RES_CHRATR_LANGUAGE;
+ break;
+ case 0x486E: //sprmCRgLid1_80
+ case 0x4874: //Methinks, uncertain
+ nId = RES_CHRATR_CJK_LANGUAGE;
+ break;
+ case 83:
+ case 114:
+ case 0x485F:
+ nId = RES_CHRATR_CTL_LANGUAGE;
+ break;
+ default:
+ return;
+ }
+
+ if( nLen < 0 ) // Ende des Attributes
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), nId );
+ else
+ {
+ sal_uInt16 nLang = SVBT16ToShort( pData ); // Language-Id
+ NewAttr(SvxLanguageItem((const LanguageType)nLang, nId));
+ }
+}
+
+/*
+ Einschalten des Zeichen-Styles:
+*/
+void SwWW8ImplReader::Read_CColl( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen < 0 ){ // Ende des Attributes
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_TXTATR_CHARFMT );
+ nCharFmt = -1;
+ return;
+ }
+ sal_uInt16 nId = SVBT16ToShort( pData ); // Style-Id (NICHT Sprm-Id!)
+
+ if( nId >= nColls || !pCollA[nId].pFmt // ungueltige Id ?
+ || pCollA[nId].bColl ) // oder Para-Style ?
+ return; // dann ignorieren
+
+ NewAttr( SwFmtCharFmt( (SwCharFmt*)pCollA[nId].pFmt ) );
+ nCharFmt = (short) nId;
+}
+
+
+/*
+ enger oder weiter als normal:
+*/
+void SwWW8ImplReader::Read_Kern( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen < 0 ){ // Ende des Attributes
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_KERNING );
+ return;
+ }
+ sal_Int16 nKern = SVBT16ToShort( pData ); // Kerning in Twips
+ NewAttr( SvxKerningItem( nKern, RES_CHRATR_KERNING ) );
+}
+
+void SwWW8ImplReader::Read_FontKern( sal_uInt16, const sal_uInt8* , short nLen )
+{
+ if( nLen < 0 ) // Ende des Attributes
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_AUTOKERN );
+ else
+ NewAttr(SvxAutoKernItem(true, RES_CHRATR_AUTOKERN));
+}
+
+void SwWW8ImplReader::Read_CharShadow( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ //Has newer colour varient, ignore this old varient
+ if (!bVer67 && pPlcxMan && pPlcxMan->GetChpPLCF()->HasSprm(0xCA71))
+ return;
+
+ if( nLen <= 0 )
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_BACKGROUND );
+ if( bCharShdTxtCol )
+ {
+ // Zeichenfarbe auch
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_COLOR );
+ bCharShdTxtCol = false;
+ }
+ }
+ else
+ {
+ WW8_SHD aSHD;
+ aSHD.SetWWValue( *(SVBT16*)pData );
+ SwWW8Shade aSh( bVer67, aSHD );
+
+ NewAttr( SvxBrushItem( aSh.aColor, RES_CHRATR_BACKGROUND ));
+ }
+}
+
+void SwWW8ImplReader::Read_TxtBackColor(sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen <= 0 )
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_BACKGROUND );
+ if( bCharShdTxtCol )
+ {
+ // Zeichenfarbe auch
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_COLOR );
+ bCharShdTxtCol = false;
+ }
+ }
+ else
+ {
+ OSL_ENSURE(nLen == 10, "Len of para back colour not 10!");
+ if (nLen != 10)
+ return;
+ Color aColour(ExtractColour(pData, bVer67));
+ NewAttr(SvxBrushItem(aColour, RES_CHRATR_BACKGROUND));
+ }
+}
+
+void SwWW8ImplReader::Read_CharHighlight(sal_uInt16, const sal_uInt8* pData, short nLen)
+{
+ if( nLen <= 0 )
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_BACKGROUND );
+ if( bCharShdTxtCol )
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_COLOR ); // Zeichenfarbe auch
+ bCharShdTxtCol = false;
+ }
+ }
+ else
+ {
+ sal_uInt8 b = *pData; // Parameter: 0 = Auto, 1..16 Farben
+
+ if( b > 16 ) // unbekannt -> Black
+ b = 0; // Auto -> Black
+
+ Color aCol(GetCol(b));
+ NewAttr( SvxBrushItem( aCol , RES_CHRATR_BACKGROUND ));
+ }
+}
+
+
+/***************************************************************************
+# Absatz - Attribute
+#**************************************************************************/
+
+void SwWW8ImplReader::Read_NoLineNumb(sal_uInt16 , const sal_uInt8* pData, short nLen)
+{
+ if( nLen < 0 ) // Ende des Attributes
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_LINENUMBER );
+ return;
+ }
+ SwFmtLineNumber aLN;
+ if (const SwFmtLineNumber* pLN
+ = (const SwFmtLineNumber*)GetFmtAttr(RES_LINENUMBER))
+ {
+ aLN.SetStartValue( pLN->GetStartValue() );
+ }
+
+ aLN.SetCountLines( pData && (0 == *pData) );
+ NewAttr( aLN );
+}
+
+// Sprm 16, 17
+void SwWW8ImplReader::Read_LR( sal_uInt16 nId, const sal_uInt8* pData, short nLen )
+{
+ if (nLen < 0) // End of the Attributes
+ {
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_LR_SPACE);
+ return;
+ }
+
+ short nPara = SVBT16ToShort( pData );
+
+ SvxLRSpaceItem aLR( RES_LR_SPACE );
+ const SfxPoolItem* pLR = GetFmtAttr(RES_LR_SPACE);
+ if( pLR )
+ aLR = *(const SvxLRSpaceItem*)pLR;
+
+ // Fix the regression issue: #i99822#: Discussion?
+ // Since the list lever formatting doesn't apply into paragraph style
+ // for list levels of mode LABEL_ALIGNMENT.(see ww8par3.cxx
+ // W8ImplReader::RegisterNumFmtOnTxtNode).
+ // Need to apply the list format to the paragraph here.
+ SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode();
+ if( pTxtNode && pTxtNode->AreListLevelIndentsApplicable() )
+ {
+ SwNumRule * pNumRule = pTxtNode->GetNumRule();
+ if( pNumRule )
+ {
+ sal_uInt8 nLvl = static_cast< sal_uInt8 >(pTxtNode->GetActualListLevel());
+ const SwNumFmt* pFmt = pNumRule->GetNumFmt( nLvl );
+ if ( pFmt && pFmt->GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
+ {
+ aLR.SetTxtLeft( pFmt->GetIndentAt() );
+ aLR.SetTxtFirstLineOfst( static_cast<short>(pFmt->GetFirstLineIndent()) );
+ // make paragraph have hard-set indent attributes
+ pTxtNode->SetAttr( aLR );
+ }
+ }
+ }
+
+ /*
+ The older word sprms mean left/right, while the new ones mean before/after.
+ Writer now also works with before after, so when we see old left/right and
+ we're RTL. We swap them
+ */
+ if (IsRightToLeft())
+ {
+ switch (nId)
+ {
+ //Left becomes after;
+ case 17:
+ nId = 16;
+ break;
+ case 0x840F:
+ nId = 0x840E;
+ break;
+ //Right becomes before;
+ case 16:
+ nId = 17;
+ break;
+ case 0x840E:
+ nId = 0x840F;
+ break;
+ }
+ }
+
+ bool bFirstLinOfstSet( false ); // #i103711#
+ bool bLeftIndentSet( false ); // #i105414#
+
+ switch (nId)
+ {
+ //sprmPDxaLeft
+ case 17:
+ case 0x840F:
+ case 0x845E:
+ aLR.SetTxtLeft( nPara );
+ if (pAktColl)
+ {
+ pCollA[nAktColl].bListReleventIndentSet = true;
+ }
+ bLeftIndentSet = true; // #i105414#
+ break;
+ //sprmPDxaLeft1
+ case 19:
+ case 0x8411:
+ case 0x8460:
+ /*
+ As part of an attempt to break my spirit ww 8+ formats can contain
+ ww 7- lists. If they do and the list is part of the style, then
+ when removing the list from a paragraph of that style there
+ appears to be a bug where the hanging indent value which the list
+ set is still factored into the left indent of the paragraph. Its
+ not listed in the winword dialogs, but it is clearly there. So if
+ our style has a broken ww 7- list and we know that the list has
+ been removed then we will factor the original list applied hanging
+ into our calculation.
+ */
+ if (pPlcxMan && pCollA[nAktColl].bHasBrokenWW6List)
+ {
+ const sal_uInt8 *pIsZeroed = pPlcxMan->GetPapPLCF()->HasSprm(0x460B);
+ if (pIsZeroed && *pIsZeroed == 0)
+ {
+ const SvxLRSpaceItem &rLR =
+ ItemGet<SvxLRSpaceItem>(*(pCollA[nAktColl].pFmt),
+ RES_LR_SPACE);
+ nPara = nPara - rLR.GetTxtFirstLineOfst();
+ }
+ }
+
+ aLR.SetTxtFirstLineOfst(nPara);
+ if (pAktColl)
+ {
+ pCollA[nAktColl].bListReleventIndentSet = true;
+ }
+ bFirstLinOfstSet = true; // #i103711#
+ break;
+ //sprmPDxaRight
+ case 16:
+ case 0x840E:
+ case 0x845D:
+ aLR.SetRight( nPara );
+ break;
+ default:
+ return;
+ }
+
+ NewAttr( aLR, bFirstLinOfstSet, bLeftIndentSet ); // #i103711#, #i105414#
+}
+
+// Sprm 20
+void SwWW8ImplReader::Read_LineSpace( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+// Kommentear siehe Read_UL()
+ if (bStyNormal && bWWBugNormal)
+ return;
+
+ if( nLen < 0 ){
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_PARATR_LINESPACING );
+ if( !( nIniFlags & WW8FL_NO_IMPLPASP ) )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_UL_SPACE );
+ return;
+ }
+
+ short nSpace = SVBT16ToShort( pData );
+ ww::WordVersion eVersion = pWwFib->GetFIBVersion();
+ short nMulti = (eVersion <= ww::eWW2) ? 1 : SVBT16ToShort( pData + 2 );
+
+ SvxLineSpace eLnSpc;
+ if( 0 > nSpace )
+ {
+ nSpace = -nSpace;
+ eLnSpc = SVX_LINE_SPACE_FIX;
+ }
+ else
+ eLnSpc = SVX_LINE_SPACE_MIN;
+
+// WW hat einen impliziten zusaetzlichen Absatzabstand abhaengig vom
+// Zeilenabstand. Er betraegt bei "genau", 0.8*Zeilenabstand "vor" und
+// 0.2*Zeilenabstand "nach".
+// Bei "Mindestens" sind es 1*Zeilenabstand "vor" und 0*Zeilenabstand "nach".
+// Bei Mehrfach sind es 0 "vor" und min( 0cm, FontSize*(nFach-1) ) "nach".
+//
+// SW hat auch einen impliziten Zeilenabstand. er betraegt bei "mindestens"
+// 1*Zeilenabstand "vor" und 0 "nach"
+// bei proportional betraegt er min( 0cm, FontSize*(nFach-1) ) sowohl "vor"
+// wie auch "nach"
+
+ sal_uInt16 nSpaceTw = 0;
+
+ SvxLineSpacingItem aLSpc( LINE_SPACE_DEFAULT_HEIGHT, RES_PARATR_LINESPACING );
+
+ if( 1 == nMulti ) // MultilineSpace ( proportional )
+ {
+ long n = nSpace * 10 / 24; // WW: 240 = 100%, SW: 100 = 100%
+
+// nach Absprache mit AMA ist die Begrenzung unsinnig
+ if( n>200 ) n = 200; // SW_UI-Maximum
+ aLSpc.SetPropLineSpace( (const sal_uInt8)n );
+ const SvxFontHeightItem* pH = (const SvxFontHeightItem*)
+ GetFmtAttr( RES_CHRATR_FONTSIZE );
+ nSpaceTw = (sal_uInt16)( n * pH->GetHeight() / 100 );
+ }
+ else // Fixed / Minimum
+ {
+ // bei negativen Space ist der Abstand exakt, sonst minimum
+ nSpaceTw = (sal_uInt16)nSpace;
+ aLSpc.SetLineHeight( nSpaceTw );
+ aLSpc.GetLineSpaceRule() = eLnSpc;
+ }
+ NewAttr( aLSpc );
+ if( pSFlyPara )
+ pSFlyPara->nLineSpace = nSpaceTw; // LineSpace fuer Graf-Apos
+}
+
+//#i18519# AutoSpace value depends on Dop fDontUseHTMLAutoSpacing setting
+sal_uInt16 SwWW8ImplReader::GetParagraphAutoSpace(bool fDontUseHTMLAutoSpacing)
+{
+ if (fDontUseHTMLAutoSpacing)
+ return 100; //Seems to be always 5points in this case
+ else
+ return 280; //Seems to be always 14points in this case
+}
+
+void SwWW8ImplReader::Read_DontAddEqual(sal_uInt16, const sal_uInt8 *pData, short nLen)
+{
+ if (nLen < 0)
+ return;
+
+ if (*pData)
+ maTracer.Log(sw::log::eDontAddSpaceForEqualStyles);
+}
+
+void SwWW8ImplReader::Read_ParaAutoBefore(sal_uInt16, const sal_uInt8 *pData, short nLen)
+{
+ if (nLen < 0)
+ {
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_UL_SPACE);
+ return;
+ }
+
+ if (*pData)
+ {
+ SvxULSpaceItem aUL(*(const SvxULSpaceItem*)GetFmtAttr(RES_UL_SPACE));
+ aUL.SetUpper(GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
+ NewAttr(aUL);
+ if (pAktColl)
+ pCollA[nAktColl].bParaAutoBefore = true;
+ else
+ bParaAutoBefore = true;
+ }
+ else
+ {
+ if (pAktColl)
+ pCollA[nAktColl].bParaAutoBefore = false;
+ else
+ bParaAutoBefore = false;
+ }
+}
+
+void SwWW8ImplReader::Read_ParaAutoAfter(sal_uInt16, const sal_uInt8 *pData, short nLen)
+{
+ if (nLen < 0)
+ {
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_UL_SPACE);
+ return;
+ }
+
+ if (*pData)
+ {
+ SvxULSpaceItem aUL(*(const SvxULSpaceItem*)GetFmtAttr(RES_UL_SPACE));
+ aUL.SetLower(GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
+ NewAttr(aUL);
+ if (pAktColl)
+ pCollA[nAktColl].bParaAutoAfter = true;
+ else
+ bParaAutoAfter = true;
+ }
+ else
+ {
+ if (pAktColl)
+ pCollA[nAktColl].bParaAutoAfter = false;
+ else
+ bParaAutoAfter = false;
+ }
+}
+
+// Sprm 21, 22
+void SwWW8ImplReader::Read_UL( sal_uInt16 nId, const sal_uInt8* pData, short nLen )
+{
+// Nun eine Umpopelung eines WW-Fehlers: Bei nProduct == 0c03d wird
+// faelschlicherweise ein DyaAfter 240 ( delta y abstand after, amn.d.?b.)
+// im Style "Normal" eingefuegt, der
+// gar nicht da ist. Ueber das IniFlag WW8FL_NO_STY_DYA laesst sich dieses
+// Verhalten auch fuer andere WW-Versionen erzwingen
+// OSL_ENSURE( !bStyNormal || bWWBugNormal, "+Dieses Doc deutet evtl. auf einen
+// Fehler in der benutzten WW-Version hin. Wenn sich die Styles <Standard> bzw.
+// <Normal> zwischen WW und SW im Absatz- oder Zeilenabstand unterscheiden,
+// dann bitte dieses Doc SH zukommen lassen." );
+// bWWBugNormal ist kein hinreichendes Kriterium dafuer, dass der
+// angegebene Abstand falsch ist
+
+ if( nLen < 0 )
+ {
+ // Ende des Attributes
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_UL_SPACE );
+ return;
+ }
+ short nPara = SVBT16ToShort( pData );
+ if( nPara < 0 )
+ nPara = -nPara;
+
+ SvxULSpaceItem aUL( *(const SvxULSpaceItem*)GetFmtAttr( RES_UL_SPACE ));
+
+ switch( nId )
+ {
+ //sprmPDyaBefore
+ case 21:
+ case 0xA413:
+ aUL.SetUpper( nPara );
+ break;
+ //sprmPDyaAfter
+ case 22:
+ case 0xA414:
+ aUL.SetLower( nPara );
+ break;
+ default:
+ return;
+ };
+
+ NewAttr( aUL );
+}
+
+void SwWW8ImplReader::Read_IdctHint( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if (nLen < 0)
+ nIdctHint = 0;
+ else
+ nIdctHint = *pData;
+}
+
+void SwWW8ImplReader::Read_Justify( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen < 0 )
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_PARATR_ADJUST );
+ return;
+ }
+
+ SvxAdjust eAdjust(SVX_ADJUST_LEFT);
+ bool bDistributed = false;
+ switch (*pData)
+ {
+ default:
+ case 0:
+ break;
+ case 1:
+ eAdjust = SVX_ADJUST_CENTER;
+ break;
+ case 2:
+ eAdjust = SVX_ADJUST_RIGHT;
+ break;
+ case 3:
+ eAdjust = SVX_ADJUST_BLOCK;
+ break;
+ case 4:
+ eAdjust = SVX_ADJUST_BLOCK;
+ bDistributed = true;
+ break;
+ }
+ SvxAdjustItem aAdjust(eAdjust, RES_PARATR_ADJUST);
+ if (bDistributed)
+ aAdjust.SetLastBlock(SVX_ADJUST_BLOCK);
+
+ NewAttr(aAdjust);
+}
+
+bool SwWW8ImplReader::IsRightToLeft()
+{
+ bool bRTL = false;
+ const sal_uInt8 *pDir =
+ pPlcxMan ? pPlcxMan->GetPapPLCF()->HasSprm(0x2441) : 0;
+ if (pDir)
+ bRTL = *pDir ? true : false;
+ else
+ {
+ const SvxFrameDirectionItem* pItem=
+ (const SvxFrameDirectionItem*)GetFmtAttr(RES_FRAMEDIR);
+ if (pItem && (pItem->GetValue() == FRMDIR_HORI_RIGHT_TOP))
+ bRTL = true;
+ }
+ return bRTL;
+}
+
+void SwWW8ImplReader::Read_RTLJustify( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen < 0 )
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_PARATR_ADJUST );
+ return;
+ }
+
+ //If we are in a ltr paragraph this is the same as normal Justify,
+ //If we are in a rtl paragraph the meaning is reversed.
+ if (!IsRightToLeft())
+ Read_Justify(0x2403 /*dummy*/, pData, nLen);
+ else
+ {
+ SvxAdjust eAdjust(SVX_ADJUST_RIGHT);
+ bool bDistributed = false;
+ switch (*pData)
+ {
+ default:
+ case 0:
+ break;
+ case 1:
+ eAdjust = SVX_ADJUST_CENTER;
+ break;
+ case 2:
+ eAdjust = SVX_ADJUST_LEFT;
+ break;
+ case 3:
+ eAdjust = SVX_ADJUST_BLOCK;
+ break;
+ case 4:
+ eAdjust = SVX_ADJUST_BLOCK;
+ bDistributed = true;
+ break;
+ }
+ SvxAdjustItem aAdjust(eAdjust, RES_PARATR_ADJUST);
+ if (bDistributed)
+ aAdjust.SetLastBlock(SVX_ADJUST_BLOCK);
+
+ NewAttr(aAdjust);
+ }
+}
+
+void SwWW8ImplReader::Read_BoolItem( sal_uInt16 nId, const sal_uInt8* pData, short nLen )
+{
+ switch( nId )
+ {
+ case 0x2433:
+ nId = RES_PARATR_FORBIDDEN_RULES;
+ break;
+ case 0x2435:
+ nId = RES_PARATR_HANGINGPUNCTUATION;
+ break;
+ case 0x2437:
+ nId = RES_PARATR_SCRIPTSPACE;
+ break;
+ default:
+ OSL_ENSURE( !this, "wrong Id" );
+ return ;
+ }
+
+ if( nLen < 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), nId );
+ else
+ {
+ SfxBoolItem* pI = (SfxBoolItem*)GetDfltAttr( nId )->Clone();
+ pI->SetValue( 0 != *pData );
+ NewAttr( *pI );
+ delete pI;
+ }
+}
+
+void SwWW8ImplReader::Read_Emphasis( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen < 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_EMPHASIS_MARK );
+ else
+ {
+ LanguageType nLang;
+ //Check to see if there is an up and coming cjk language property. If
+ //there is use it, if there is not fall back to the currently set one.
+ //Only the cjk language setting seems to matter to word, the western
+ //one is ignored
+ const sal_uInt8 *pLang =
+ pPlcxMan ? pPlcxMan->GetChpPLCF()->HasSprm(0x486E) : 0;
+
+ if (pLang)
+ nLang = SVBT16ToShort( pLang );
+ else
+ {
+ nLang = ((const SvxLanguageItem *)
+ GetFmtAttr(RES_CHRATR_CJK_LANGUAGE))->GetLanguage();
+ }
+
+ sal_uInt16 nVal;
+ switch( *pData )
+ {
+ case 0:
+ nVal = EMPHASISMARK_NONE;
+ break;
+ case 2:
+ if ((nLang == LANGUAGE_CHINESE_HONGKONG) ||
+ (nLang == LANGUAGE_CHINESE_MACAU) ||
+ (nLang == LANGUAGE_CHINESE_TRADITIONAL) ||
+ (nLang == LANGUAGE_KOREAN))
+ nVal = EMPHASISMARK_CIRCLE_ABOVE;
+ else if (nLang == LANGUAGE_JAPANESE)
+ nVal = EMPHASISMARK_SIDE_DOTS;
+ else
+ nVal = EMPHASISMARK_DOTS_BELOW;
+ break;
+ case 3:
+ nVal = EMPHASISMARK_CIRCLE_ABOVE;
+ break;
+ case 4:
+ nVal = EMPHASISMARK_DOTS_BELOW;
+ break;
+ case 1:
+ if ((nLang == LANGUAGE_CHINESE_SIMPLIFIED) ||
+ (nLang == LANGUAGE_CHINESE_SINGAPORE))
+ nVal = EMPHASISMARK_DOTS_BELOW;
+ else
+ nVal = EMPHASISMARK_DOTS_ABOVE;
+ break;
+ default:
+ nVal = EMPHASISMARK_DOTS_ABOVE;
+ break;
+ }
+
+ NewAttr( SvxEmphasisMarkItem( nVal, RES_CHRATR_EMPHASIS_MARK ) );
+ }
+}
+
+void SwWW8ImplReader::Read_ScaleWidth( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen < 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_SCALEW );
+ else
+ {
+ sal_uInt16 nVal = SVBT16ToShort( pData );
+ //The number must be between 1 and 600
+ if (nVal < 1 || nVal > 600)
+ nVal = 100;
+ NewAttr( SvxCharScaleWidthItem( nVal, RES_CHRATR_SCALEW ) );
+ }
+}
+
+void SwWW8ImplReader::Read_Relief( sal_uInt16 nId, const sal_uInt8* pData, short nLen )
+{
+ if( nLen < 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_RELIEF );
+ else
+ {
+ if( *pData )
+ {
+// not so eays because this is also a toggle attribute!
+// 2 x emboss on -> no emboss !!!
+// the actual value must be searched over the stack / template
+
+ const SvxCharReliefItem* pOld = (const SvxCharReliefItem*)
+ GetFmtAttr( RES_CHRATR_RELIEF );
+ FontRelief nNewValue = 0x854 == nId ? RELIEF_ENGRAVED
+ : ( 0x858 == nId ? RELIEF_EMBOSSED
+ : RELIEF_NONE );
+ if( pOld->GetValue() == nNewValue )
+ {
+ if( RELIEF_NONE != nNewValue )
+ nNewValue = RELIEF_NONE;
+ }
+ NewAttr( SvxCharReliefItem( nNewValue, RES_CHRATR_RELIEF ));
+ }
+ }
+}
+
+void SwWW8ImplReader::Read_TxtAnim(sal_uInt16 /*nId*/, const sal_uInt8* pData, short nLen)
+{
+ if (nLen < 0)
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_BLINK);
+ else
+ {
+ if (*pData)
+ {
+ bool bBlink;
+
+ // The 7 animated text effects available in word all get
+ // mapped to a blinking text effect in StarOffice
+ // 0 no animation 1 Las Vegas lights
+ // 2 background blink 3 sparkle text
+ // 4 marching ants 5 marchine red ants
+ // 6 shimmer
+ if (*pData > 0 && *pData < 7 )
+ bBlink = true;
+ else
+ bBlink = false;
+
+ NewAttr(SvxBlinkItem(bBlink, RES_CHRATR_BLINK));
+ }
+ }
+}
+
+SwWW8Shade::SwWW8Shade(bool bVer67, const WW8_SHD& rSHD)
+{
+ sal_uInt8 b = rSHD.GetFore();
+ OSL_ENSURE(b < 17, "ww8: colour out of range");
+ if (b >= 17)
+ b = 0;
+
+ ColorData nFore(SwWW8ImplReader::GetCol(b));
+
+ b = rSHD.GetBack();
+ OSL_ENSURE(b < 17, "ww8: colour out of range");
+ if( b >= 17 )
+ b = 0;
+
+ ColorData nBack(SwWW8ImplReader::GetCol(b));
+
+ b = rSHD.GetStyle(bVer67);
+
+ SetShade(nFore, nBack, b);
+}
+
+void SwWW8Shade::SetShade(ColorData nFore, ColorData nBack, sal_uInt16 nIndex)
+{
+ static const sal_uLong eMSGrayScale[] =
+ {
+ // Nul-Brush
+ 0, // 0
+ // Solid-Brush
+ 1000, // 1
+ // promillemaessig abgestufte Schattierungen
+ 50, // 2
+ 100, // 3
+ 200, // 4
+ 250, // 5
+ 300, // 6
+ 400, // 7
+ 500, // 8
+ 600, // 9
+ 700, // 10
+ 750, // 11
+ 800, // 12
+ 900, // 13
+ 333, // 14 Dark Horizontal
+ 333, // 15 Dark Vertical
+ 333, // 16 Dark Forward Diagonal
+ 333, // 17 Dark Backward Diagonal
+ 333, // 18 Dark Cross
+ 333, // 19 Dark Diagonal Cross
+ 333, // 20 Horizontal
+ 333, // 21 Vertical
+ 333, // 22 Forward Diagonal
+ 333, // 23 Backward Diagonal
+ 333, // 24 Cross
+ 333, // 25 Diagonal Cross
+ // neun Nummern ohne Bedeutung in Ver8
+ 500, // 26
+ 500, // 27
+ 500, // 28
+ 500, // 29
+ 500, // 30
+ 500, // 31
+ 500, // 32
+ 500, // 33
+ 500, // 34
+ // und weiter gehts mit tollen Schattierungen ;-)
+ 25, // 35
+ 75, // 36
+ 125, // 37
+ 150, // 38
+ 175, // 39
+ 225, // 40
+ 275, // 41
+ 325, // 42
+ 350, // 43
+ 375, // 44
+ 425, // 45
+ 450, // 46
+ 475, // 47
+ 525, // 48
+ 550, // 49
+ 575, // 50
+ 625, // 51
+ 650, // 52
+ 675, // 53
+ 725, // 54
+ 775, // 55
+ 825, // 56
+ 850, // 57
+ 875, // 58
+ 925, // 59
+ 950, // 60
+ 975, // 61
+ // und zu guter Letzt:
+ 970
+ };// 62
+
+
+ //NO auto for shading so Foreground: Auto = Black
+ if (nFore == COL_AUTO)
+ nFore = COL_BLACK;
+
+ //NO auto for shading so background: Auto = Weiss
+ ColorData nUseBack = nBack;
+ if (nUseBack == COL_AUTO)
+ nUseBack = COL_WHITE;
+
+
+ if( nIndex >= SAL_N_ELEMENTS(eMSGrayScale))
+ nIndex = 0;
+
+ sal_uLong nWW8BrushStyle = eMSGrayScale[nIndex];
+
+ switch (nWW8BrushStyle)
+ {
+ case 0: // Null-Brush
+ aColor.SetColor( nBack );
+ break;
+ default:
+ {
+ Color aForeColor(nFore);
+ Color aBackColor(nUseBack);
+
+ sal_uInt32 nRed = aForeColor.GetRed() * nWW8BrushStyle;
+ sal_uInt32 nGreen = aForeColor.GetGreen() * nWW8BrushStyle;
+ sal_uInt32 nBlue = aForeColor.GetBlue() * nWW8BrushStyle;
+ nRed += aBackColor.GetRed() * (1000L - nWW8BrushStyle);
+ nGreen += aBackColor.GetGreen()* (1000L - nWW8BrushStyle);
+ nBlue += aBackColor.GetBlue() * (1000L - nWW8BrushStyle);
+
+ aColor.SetColor( RGB_COLORDATA( nRed/1000, nGreen/1000,
+ nBlue/1000 ) );
+ }
+ break;
+ }
+}
+
+void SwWW8ImplReader::Read_Shade( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if (!bVer67 && pPlcxMan && pPlcxMan->GetPapPLCF()->HasSprm(0xC64D))
+ return;
+
+ if (nLen <= 0)
+ {
+ // Ende des Attributes
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_BACKGROUND );
+ if (bShdTxtCol)
+ {
+ // Zeichenfarbe auch
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_COLOR );
+ bShdTxtCol = false;
+ }
+ }
+ else
+ {
+ WW8_SHD aSHD;
+ aSHD.SetWWValue( *(SVBT16*)pData );
+ SwWW8Shade aSh( bVer67, aSHD );
+
+ NewAttr(SvxBrushItem(aSh.aColor, RES_BACKGROUND));
+ }
+}
+
+void SwWW8ImplReader::Read_ParaBackColor(sal_uInt16, const sal_uInt8* pData, short nLen)
+{
+ if (nLen <= 0)
+ {
+ // Ende des Attributes
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_BACKGROUND );
+ if (bShdTxtCol)
+ {
+ // Zeichenfarbe auch
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_COLOR );
+ bShdTxtCol = false;
+ }
+ }
+ else
+ {
+ OSL_ENSURE(nLen == 10, "Len of para back colour not 10!");
+ if (nLen != 10)
+ return;
+ NewAttr(SvxBrushItem(Color(ExtractColour(pData, bVer67)), RES_BACKGROUND));
+ }
+}
+
+sal_uInt32 SwWW8ImplReader::ExtractColour(const sal_uInt8* &rpData,
+ bool
+#if OSL_DEBUG_LEVEL > 1
+ bVer67
+#endif
+ )
+{
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE(bVer67 == false, "Impossible");
+#endif
+ sal_uInt32 nFore = wwUtility::BGRToRGB(SVBT32ToUInt32(rpData));
+ rpData+=4;
+ sal_uInt32 nBack = wwUtility::BGRToRGB(SVBT32ToUInt32(rpData));
+ rpData+=4;
+ sal_uInt16 nIndex = SVBT16ToShort(rpData);
+ rpData+=2;
+ //Being a transparent background colour doesn't actually show the page
+ //background through, it merely acts like white
+ if (nBack == 0xFF000000)
+ nBack = COL_AUTO;
+ OSL_ENSURE(nBack == COL_AUTO || !(nBack & 0xFF000000),
+ "ww8: don't know what to do with such a transparent bg colour, report");
+ SwWW8Shade aShade(nFore, nBack, nIndex);
+ return aShade.aColor.GetColor();
+}
+
+void SwWW8ImplReader::Read_Border(sal_uInt16 , const sal_uInt8* , short nLen)
+{
+ if( nLen < 0 )
+ {
+ if( bHasBorder )
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_BOX );
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_SHADOW );
+ bHasBorder = false;
+ }
+ }
+ else if( !bHasBorder )
+ {
+ // die Borders auf allen 4 Seiten werden gebuendelt. dieses
+ // vereinfacht die Verwaltung, d.h. die Box muss nicht 4 mal auf den
+ // CtrlStack und wieder runter
+ bHasBorder = true;
+
+ WW8_BRC5 aBrcs; // Top, Left, Bottom, Right, Between
+ sal_uInt8 nBorder;
+
+ if( pAktColl )
+ nBorder = ::lcl_ReadBorders(bVer67, aBrcs, 0, pStyles);
+ else
+ nBorder = ::lcl_ReadBorders(bVer67, aBrcs, pPlcxMan->GetPapPLCF());
+
+ if( nBorder ) // Border
+ {
+ bool bIsB = IsBorder(aBrcs, true);
+ if (!InLocalApo() || !bIsB ||
+ (pWFlyPara && !pWFlyPara->bBorderLines ))
+ {
+ // in Apo keine Umrandungen *ein*-schalten, da ich
+ // sonst die Flyumrandungen doppelt bekomme
+ // aber nur wenn am Fly ein gesetzt ist, keine
+ // uebernehmen. Sonst wird gar keine gesetzt!
+
+ // auch wenn kein Rand gesetzt ist, muss das Attribut gesetzt
+ // werden, sonst ist kein hartes Ausschalten von Style-Attrs
+ // moeglich
+ const SvxBoxItem* pBox
+ = (const SvxBoxItem*)GetFmtAttr( RES_BOX );
+ SvxBoxItem aBox(RES_BOX);
+ if (pBox)
+ aBox = *pBox;
+ short aSizeArray[5]={0};
+
+ SetBorder(aBox, aBrcs, &aSizeArray[0], nBorder);
+
+ Rectangle aInnerDist;
+ GetBorderDistance( aBrcs, aInnerDist );
+
+ maTracer.Log(sw::log::eBorderDistOutside);
+
+ if ((nBorder & WW8_LEFT)==WW8_LEFT) {
+ aBox.SetDistance( (sal_uInt16)aInnerDist.Left(), BOX_LINE_LEFT );
+ }
+ if ((nBorder & WW8_TOP)==WW8_TOP) {
+ aBox.SetDistance( (sal_uInt16)aInnerDist.Top(), BOX_LINE_TOP );
+ }
+ if ((nBorder & WW8_RIGHT)==WW8_RIGHT) {
+ aBox.SetDistance( (sal_uInt16)aInnerDist.Right(), BOX_LINE_RIGHT );
+ }
+
+ if ((nBorder & WW8_BOT)==WW8_BOT) {
+ aBox.SetDistance( (sal_uInt16)aInnerDist.Bottom(), BOX_LINE_BOTTOM );
+ }
+
+ NewAttr( aBox );
+
+ SvxShadowItem aS(RES_SHADOW);
+ if( SetShadow( aS, &aSizeArray[0], aBrcs ) )
+ NewAttr( aS );
+ }
+ }
+ }
+}
+
+void SwWW8ImplReader::Read_Hyphenation( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ // set Hyphenation flag
+ if( nLen <= 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_PARATR_HYPHENZONE );
+ else
+ {
+ SvxHyphenZoneItem aAttr(
+ *(const SvxHyphenZoneItem*)GetFmtAttr( RES_PARATR_HYPHENZONE ) );
+
+ aAttr.SetHyphen( 0 == *pData ); // sic !
+
+ if( !*pData )
+ {
+ aAttr.GetMinLead() = 2;
+ aAttr.GetMinTrail() = 2;
+ aAttr.GetMaxHyphens() = 0;
+ }
+
+ NewAttr( aAttr );
+ }
+}
+
+void SwWW8ImplReader::Read_WidowControl( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen <= 0 )
+ {
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_PARATR_WIDOWS );
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_PARATR_ORPHANS );
+ }
+ else
+ {
+ sal_uInt8 nL = ( *pData & 1 ) ? 2 : 0;
+
+ NewAttr( SvxWidowsItem( nL, RES_PARATR_WIDOWS ) ); // Aus -> nLines = 0
+ NewAttr( SvxOrphansItem( nL, RES_PARATR_ORPHANS ) );
+
+ if( pAktColl && pStyles ) // Style-Def ?
+ pStyles->bWidowsChanged = true; // merken zur Simulation
+ // Default-Widows
+ }
+}
+
+void SwWW8ImplReader::Read_UsePgsuSettings(sal_uInt16,const sal_uInt8* pData,short nLen)
+{
+ if( nLen <= 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_PARATR_SNAPTOGRID);
+ else
+ {
+ if(nInTable)
+ NewAttr( SvxParaGridItem(false, RES_PARATR_SNAPTOGRID) );
+ else
+ NewAttr( SvxParaGridItem(*pData, RES_PARATR_SNAPTOGRID) );
+ }
+}
+
+void SwWW8ImplReader::Read_AlignFont( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen <= 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_PARATR_VERTALIGN);
+ else
+ {
+ sal_uInt16 nVal = SVBT16ToShort( pData );
+ switch (nVal)
+ {
+ case 0:
+ nVal = SvxParaVertAlignItem::TOP;
+ break;
+ case 1:
+ nVal = SvxParaVertAlignItem::CENTER;
+ break;
+ case 2:
+ nVal = SvxParaVertAlignItem::BASELINE;
+ break;
+ case 3:
+ nVal = SvxParaVertAlignItem::BOTTOM;
+ break;
+ case 4:
+ nVal = SvxParaVertAlignItem::AUTOMATIC;
+ break;
+ default:
+ nVal = SvxParaVertAlignItem::AUTOMATIC;
+ OSL_ENSURE(!this,"Unknown paragraph vertical align");
+ break;
+ }
+ NewAttr( SvxParaVertAlignItem( nVal, RES_PARATR_VERTALIGN ) );
+ }
+}
+
+void SwWW8ImplReader::Read_KeepLines( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen <= 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_PARATR_SPLIT );
+ else
+ NewAttr( SvxFmtSplitItem( ( *pData & 1 ) == 0, RES_PARATR_SPLIT ) );
+}
+
+void SwWW8ImplReader::Read_KeepParas( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen <= 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_KEEP );
+ else
+ NewAttr( SvxFmtKeepItem( ( *pData & 1 ) != 0 , RES_KEEP) );
+}
+
+void SwWW8ImplReader::Read_BreakBefore( sal_uInt16, const sal_uInt8* pData, short nLen )
+{
+ if( nLen <= 0 )
+ pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_BREAK );
+ else
+ NewAttr( SvxFmtBreakItem(
+ ( *pData & 1 ) ? SVX_BREAK_PAGE_BEFORE : SVX_BREAK_NONE, RES_BREAK ) );
+}
+
+void SwWW8ImplReader::Read_ApoPPC( sal_uInt16, const sal_uInt8* pData, short )
+{
+ if (pAktColl) // only for Styledef, sonst anders geloest
+ {
+ SwWW8StyInf& rSI = pCollA[nAktColl];
+ WW8FlyPara* pFly = rSI.pWWFly ? rSI.pWWFly : new WW8FlyPara(bVer67);
+ pCollA[nAktColl].pWWFly = pFly;
+ pFly->Read(pData, pStyles);
+ if (pFly->IsEmpty())
+ delete pCollA[nAktColl].pWWFly, pCollA[nAktColl].pWWFly = 0;
+ }
+}
+
+bool SwWW8ImplReader::ParseTabPos(WW8_TablePos *pTabPos, WW8PLCFx_Cp_FKP* pPap)
+{
+ bool bRet = false;
+ const sal_uInt8 *pRes=0;
+ memset(pTabPos, 0, sizeof(WW8_TablePos));
+ if (0 != (pRes = pPap->HasSprm(0x360D)))
+ {
+ pTabPos->nSp29 = *pRes;
+ pTabPos->nSp37 = 2; //Possible fail area, always parallel wrap
+ if (0 != (pRes = pPap->HasSprm(0x940E)))
+ pTabPos->nSp26 = SVBT16ToShort(pRes);
+ if (0 != (pRes = pPap->HasSprm(0x940F)))
+ pTabPos->nSp27 = SVBT16ToShort(pRes);
+ if (0 != (pRes = pPap->HasSprm(0x9410)))
+ pTabPos->nLeMgn = SVBT16ToShort(pRes);
+ if (0 != (pRes = pPap->HasSprm(0x941E)))
+ pTabPos->nRiMgn = SVBT16ToShort(pRes);
+ if (0 != (pRes = pPap->HasSprm(0x9411)))
+ pTabPos->nUpMgn = SVBT16ToShort(pRes);
+ if (0 != (pRes = pPap->HasSprm(0x941F)))
+ pTabPos->nLoMgn = SVBT16ToShort(pRes);
+ bRet = true;
+ }
+ return bRet;
+}
+
+/***************************************************************************
+# Seiten - Attribute werden nicht mehr als Attribute gehandhabt
+# ( ausser OLST )
+#**************************************************************************/
+
+
+long SwWW8ImplReader::ImportExtSprm(WW8PLCFManResult* pRes)
+{
+ /*************************************************************************
+ # Arrays zum Lesen der erweiterten ( selbstdefinierten ) SPRMs
+ #*************************************************************************/
+ typedef long (SwWW8ImplReader:: *FNReadRecordExt)(WW8PLCFManResult*);
+
+ static const FNReadRecordExt aWwSprmTab[] =
+ {
+ /* 0 (256) */ &SwWW8ImplReader::Read_Ftn, // FootNote
+ /* 1 (257) */ &SwWW8ImplReader::Read_Ftn, // EndNote
+ /* 2 (258) */ &SwWW8ImplReader::Read_Field, // Feld
+ /* 3 (259) */ &SwWW8ImplReader::Read_Book, // Bookmark
+ /* 4 (260) */ &SwWW8ImplReader::Read_And // Annotation
+ };
+
+ if( pRes->nSprmId < 280 )
+ {
+ sal_uInt8 nIdx = static_cast< sal_uInt8 >(pRes->nSprmId - eFTN);
+ if( nIdx < sizeof( aWwSprmTab ) / sizeof( *aWwSprmTab )
+ && aWwSprmTab[nIdx] )
+ return (this->*aWwSprmTab[nIdx])(pRes);
+ else
+ return 0;
+ }
+ else
+ return 0;
+}
+
+void SwWW8ImplReader::EndExtSprm(sal_uInt16 nSprmId)
+{
+ typedef sal_uInt16 (SwWW8ImplReader:: *FNReadRecordExt)();
+
+ static const FNReadRecordExt aWwSprmTab[] =
+ {
+ /* 0 (256) */ &SwWW8ImplReader::End_Ftn, // FootNote
+ /* 1 (257) */ &SwWW8ImplReader::End_Ftn, // EndNote
+ /* 2 (258) */ &SwWW8ImplReader::End_Field, // Feld
+ /* 3 (259) */ 0, // Bookmark
+ /* 4 (260) */ 0 // Annotation
+ };
+
+ sal_uInt8 nIdx = static_cast< sal_uInt8 >(nSprmId - eFTN);
+ if( nIdx < sizeof( aWwSprmTab ) / sizeof( *aWwSprmTab )
+ && aWwSprmTab[nIdx] )
+ (this->*aWwSprmTab[nIdx])();
+}
+
+/***************************************************************************
+# Arrays zum Lesen der SPRMs
+#**************************************************************************/
+
+// Funktion zum Einlesen von Sprms. Par1: SprmId
+typedef void (SwWW8ImplReader:: *FNReadRecord)( sal_uInt16, const sal_uInt8*, short );
+
+struct SprmReadInfo
+{
+ sal_uInt16 nId;
+ FNReadRecord pReadFnc;
+};
+
+bool operator==(const SprmReadInfo &rFirst, const SprmReadInfo &rSecond)
+{
+ return (rFirst.nId == rSecond.nId);
+}
+
+bool operator<(const SprmReadInfo &rFirst, const SprmReadInfo &rSecond)
+{
+ return (rFirst.nId < rSecond.nId);
+}
+
+typedef ww::SortedArray<SprmReadInfo> wwSprmDispatcher;
+
+const wwSprmDispatcher *GetWW2SprmDispatcher()
+{
+ static SprmReadInfo aSprms[] =
+ {
+ {0, 0}, // "0" Default bzw. Error
+ //wird uebersprungen! ,
+ {2, &SwWW8ImplReader::Read_StyleCode}, //"sprmPIstd", pap.istd
+ //(style code)
+ {3, 0}, //"sprmPIstdPermute", pap.istd
+ //permutation
+ {4, 0}, //"sprmPIncLv1",
+ //pap.istddifference
+ {5, &SwWW8ImplReader::Read_Justify}, //"sprmPJc", pap.jc
+ //(justification)
+ {6, 0}, //"sprmPFSideBySide",
+ //pap.fSideBySide
+ {7, &SwWW8ImplReader::Read_KeepLines}, //"sprmPFKeep", pap.fKeep
+ {8, &SwWW8ImplReader::Read_KeepParas}, //"sprmPFKeepFollow ",
+ //pap.fKeepFollow
+ {9, &SwWW8ImplReader::Read_BreakBefore}, //"sprmPPageBreakBefore",
+ //pap.fPageBreakBefore
+ {10, 0}, //"sprmPBrcl", pap.brcl
+ {11, 0}, //"sprmPBrcp ", pap.brcp
+ {12, &SwWW8ImplReader::Read_ANLevelDesc}, //"sprmPAnld", pap.anld (ANLD
+ //structure)
+ {13, &SwWW8ImplReader::Read_ANLevelNo}, //"sprmPNLvlAnm", pap.nLvlAnm
+ //nn
+ {14, &SwWW8ImplReader::Read_NoLineNumb}, //"sprmPFNoLineNumb", ap.fNoLnn
+ {15, &SwWW8ImplReader::Read_Tab}, //"?sprmPChgTabsPapx",
+ //pap.itbdMac, ...
+ {16, &SwWW8ImplReader::Read_LR}, //"sprmPDxaRight", pap.dxaRight
+ {17, &SwWW8ImplReader::Read_LR}, //"sprmPDxaLeft", pap.dxaLeft
+ {18, 0}, //"sprmPNest", pap.dxaLeft
+ {19, &SwWW8ImplReader::Read_LR}, //"sprmPDxaLeft1", pap.dxaLeft1
+ {20, &SwWW8ImplReader::Read_LineSpace}, //"sprmPDyaLine", pap.lspd
+ //an LSPD
+ {21, &SwWW8ImplReader::Read_UL}, //"sprmPDyaBefore",
+ //pap.dyaBefore
+ {22, &SwWW8ImplReader::Read_UL}, //"sprmPDyaAfter", pap.dyaAfter
+ {23, 0}, //"?sprmPChgTabs", pap.itbdMac,
+ //pap.rgdxaTab, ...
+ {24, 0}, //"sprmPFInTable", pap.fInTable
+ {25, &SwWW8ImplReader::Read_TabRowEnd}, //"sprmPTtp", pap.fTtp
+ {26, 0}, //"sprmPDxaAbs", pap.dxaAbs
+ {27, 0}, //"sprmPDyaAbs", pap.dyaAbs
+ {28, 0}, //"sprmPDxaWidth", pap.dxaWidth
+ {29, &SwWW8ImplReader::Read_ApoPPC}, //"sprmPPc", pap.pcHorz,
+ //pap.pcVert
+ {30, 0}, //"sprmPBrcTop10", pap.brcTop
+ //BRC10
+ {31, 0}, //"sprmPBrcLeft10",
+ //pap.brcLeft BRC10
+ {32, 0}, //"sprmPBrcBottom10",
+ //pap.brcBottom BRC10
+ {33, 0}, //"sprmPBrcRight10",
+ //pap.brcRight BRC10
+ {34, 0}, //"sprmPBrcBetween10",
+ //pap.brcBetween BRC10
+ {35, 0}, //"sprmPBrcBar10", pap.brcBar
+ //BRC10
+ {36, 0}, //"sprmPFromText10",
+ //pap.dxaFromText dxa
+ {37, 0}, //"sprmPWr", pap.wr wr
+ {38, &SwWW8ImplReader::Read_Border}, //"sprmPBrcTop", pap.brcTop BRC
+ {39, &SwWW8ImplReader::Read_Border}, //"sprmPBrcLeft",
+ //pap.brcLeft BRC
+ {40, &SwWW8ImplReader::Read_Border}, //"sprmPBrcBottom",
+ //pap.brcBottom BRC
+ {41, &SwWW8ImplReader::Read_Border}, //"sprmPBrcRight",
+ //pap.brcRight BRC
+ {42, &SwWW8ImplReader::Read_Border}, //"sprmPBrcBetween",
+ //pap.brcBetween BRC
+ {43, 0}, //"sprmPBrcBar", pap.brcBar
+ //BRC word
+ {44, &SwWW8ImplReader::Read_Hyphenation}, //"sprmPFNoAutoHyph",
+ //pap.fNoAutoHyph
+ {45, 0}, //"sprmPWHeightAbs",
+ //pap.wHeightAbs w
+ {46, 0}, //"sprmPDcs", pap.dcs DCS
+ {47, &SwWW8ImplReader::Read_Shade}, //"sprmPShd", pap.shd SHD
+ {48, 0}, //"sprmPDyaFromText",
+ //pap.dyaFromText dya
+ {49, 0}, //"sprmPDxaFromText",
+ //pap.dxaFromText dxa
+ {50, 0}, //"sprmPFLocked", pap.fLocked
+ //0 or 1 byte
+ {51, &SwWW8ImplReader::Read_WidowControl}, //"sprmPFWidowControl",
+ //pap.fWidowControl 0 or 1 byte
+ {52, 0}, //"?sprmPRuler 52",
+ {53, 0}, //"??53",
+ {54, 0}, //"??54",
+ {55, 0}, //"??55",
+ {56, 0}, //"??56",
+ {57, 0}, //"??57",
+ {58, 0}, //"??58",
+ {59, 0}, //"??59",
+
+ {60, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFBold", chp.fBold 0,1,
+ //128, or 129 byte
+ {61, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFItalic", chp.fItalic
+ //0,1, 128, or 129 byte
+ {62, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFStrike", chp.fStrike
+ //0,1, 128, or 129 byte
+ {63, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFOutline", chp.fOutline
+ //0,1, 128, or 129 byte
+ {64, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFShadow", chp.fShadow
+ //0,1, 128, or 129 byte
+ {65, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFSmallCaps",
+ //chp.fSmallCaps 0,1, 128, or
+ //129 byte
+ {66, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFCaps", chp.fCaps 0,1,
+ //128, or 129 byte
+ {67, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFVanish", chp.fVanish
+ //0,1, 128, or 129 byte
+ {68, &SwWW8ImplReader::Read_FontCode}, //"sprmCFtc", chp.ftc ftc word
+ {69, &SwWW8ImplReader::Read_Underline}, // "sprmCKul", chp.kul kul byte
+ {70, 0}, //"sprmCSizePos", chp.hps,
+ //chp.hpsPos 3 bytes
+ {71, &SwWW8ImplReader::Read_Kern}, //"sprmCDxaSpace",
+ //chp.dxaSpace dxa word
+ {72, &SwWW8ImplReader::Read_Language}, //"sprmCLid", chp.lid LID word
+ {73, &SwWW8ImplReader::Read_TxtColor}, //"sprmCIco", chp.ico ico byte
+ {74, &SwWW8ImplReader::Read_FontSize}, //"sprmCHps", chp.hps hps word!
+ {75, 0}, //"sprmCHpsInc", chp.hps byte
+ {76, &SwWW8ImplReader::Read_SubSuperProp}, //"sprmCHpsPos", chp.hpsPos
+ //hps byte
+ {77, 0}, //"sprmCHpsPosAdj", chp.hpsPos
+ //hps byte
+ {78, &SwWW8ImplReader::Read_Majority}, //"?sprmCMajority", chp.fBold,
+ //chp.fItalic, chp.fSmallCaps
+ {80, &SwWW8ImplReader::Read_BoldBiDiUsw}, //sprmCFBoldBi
+ {81, &SwWW8ImplReader::Read_BoldBiDiUsw}, //sprmCFItalicBi
+ {82, &SwWW8ImplReader::Read_FontCode}, //sprmCFtcBi
+ {83, &SwWW8ImplReader::Read_Language}, //sprmClidBi
+ {84, &SwWW8ImplReader::Read_TxtColor}, //sprmCIcoBi
+ {85, &SwWW8ImplReader::Read_FontSize}, //sprmCHpsBi
+ {86, 0}, //sprmCFBiDi
+ {87, 0}, //sprmCFDiacColor
+ {94, 0}, //"sprmPicBrcl", pic.brcl brcl
+ //(see PIC structure
+ //definition) byte
+ {95, 0}, //"sprmPicScale", pic.mx,
+ //pic.my, pic.dxaCropleft,
+ {96, 0}, //"sprmPicBrcTop", pic.brcTop
+ //BRC word
+ {97, 0}, //"sprmPicBrcLeft",
+ //pic.brcLeft BRC word
+ {98, 0}, //"sprmPicBrcBottom",
+ //pic.brcBottom BRC word
+ {99, 0} //"sprmPicBrcRight",
+ };
+
+ static wwSprmDispatcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms));
+ return &aSprmSrch;
+}
+
+const wwSprmDispatcher *GetWW6SprmDispatcher()
+{
+ static SprmReadInfo aSprms[] =
+ {
+ {0, 0}, // "0" Default bzw. Error
+ //wird uebersprungen! ,
+ {2, &SwWW8ImplReader::Read_StyleCode}, //"sprmPIstd", pap.istd
+ //(style code)
+ {3, 0}, //"sprmPIstdPermute", pap.istd
+ //permutation
+ {4, 0}, //"sprmPIncLv1",
+ //pap.istddifference
+ {5, &SwWW8ImplReader::Read_Justify}, //"sprmPJc", pap.jc
+ //(justification)
+ {6, 0}, //"sprmPFSideBySide",
+ //pap.fSideBySide
+ {7, &SwWW8ImplReader::Read_KeepLines}, //"sprmPFKeep", pap.fKeep
+ {8, &SwWW8ImplReader::Read_KeepParas}, //"sprmPFKeepFollow ",
+ //pap.fKeepFollow
+ {9, &SwWW8ImplReader::Read_BreakBefore}, //"sprmPPageBreakBefore",
+ //pap.fPageBreakBefore
+ {10, 0}, //"sprmPBrcl", pap.brcl
+ {11, 0}, //"sprmPBrcp ", pap.brcp
+ {12, &SwWW8ImplReader::Read_ANLevelDesc}, //"sprmPAnld", pap.anld (ANLD
+ //structure)
+ {13, &SwWW8ImplReader::Read_ANLevelNo}, //"sprmPNLvlAnm", pap.nLvlAnm
+ //nn
+ {14, &SwWW8ImplReader::Read_NoLineNumb}, //"sprmPFNoLineNumb", ap.fNoLnn
+ {15, &SwWW8ImplReader::Read_Tab}, //"?sprmPChgTabsPapx",
+ //pap.itbdMac, ...
+ {16, &SwWW8ImplReader::Read_LR}, //"sprmPDxaRight", pap.dxaRight
+ {17, &SwWW8ImplReader::Read_LR}, //"sprmPDxaLeft", pap.dxaLeft
+ {18, 0}, //"sprmPNest", pap.dxaLeft
+ {19, &SwWW8ImplReader::Read_LR}, //"sprmPDxaLeft1", pap.dxaLeft1
+ {20, &SwWW8ImplReader::Read_LineSpace}, //"sprmPDyaLine", pap.lspd
+ //an LSPD
+ {21, &SwWW8ImplReader::Read_UL}, //"sprmPDyaBefore",
+ //pap.dyaBefore
+ {22, &SwWW8ImplReader::Read_UL}, //"sprmPDyaAfter", pap.dyaAfter
+ {23, 0}, //"?sprmPChgTabs", pap.itbdMac,
+ //pap.rgdxaTab, ...
+ {24, 0}, //"sprmPFInTable", pap.fInTable
+ {25, &SwWW8ImplReader::Read_TabRowEnd}, //"sprmPTtp", pap.fTtp
+ {26, 0}, //"sprmPDxaAbs", pap.dxaAbs
+ {27, 0}, //"sprmPDyaAbs", pap.dyaAbs
+ {28, 0}, //"sprmPDxaWidth", pap.dxaWidth
+ {29, &SwWW8ImplReader::Read_ApoPPC}, //"sprmPPc", pap.pcHorz,
+ //pap.pcVert
+ {30, 0}, //"sprmPBrcTop10", pap.brcTop
+ //BRC10
+ {31, 0}, //"sprmPBrcLeft10",
+ //pap.brcLeft BRC10
+ {32, 0}, //"sprmPBrcBottom10",
+ //pap.brcBottom BRC10
+ {33, 0}, //"sprmPBrcRight10",
+ //pap.brcRight BRC10
+ {34, 0}, //"sprmPBrcBetween10",
+ //pap.brcBetween BRC10
+ {35, 0}, //"sprmPBrcBar10", pap.brcBar
+ //BRC10
+ {36, 0}, //"sprmPFromText10",
+ //pap.dxaFromText dxa
+ {37, 0}, //"sprmPWr", pap.wr wr
+ {38, &SwWW8ImplReader::Read_Border}, //"sprmPBrcTop", pap.brcTop BRC
+ {39, &SwWW8ImplReader::Read_Border}, //"sprmPBrcLeft",
+ //pap.brcLeft BRC
+ {40, &SwWW8ImplReader::Read_Border}, //"sprmPBrcBottom",
+ //pap.brcBottom BRC
+ {41, &SwWW8ImplReader::Read_Border}, //"sprmPBrcRight",
+ //pap.brcRight BRC
+ {42, &SwWW8ImplReader::Read_Border}, //"sprmPBrcBetween",
+ //pap.brcBetween BRC
+ {43, 0}, //"sprmPBrcBar", pap.brcBar
+ //BRC word
+ {44, &SwWW8ImplReader::Read_Hyphenation}, //"sprmPFNoAutoHyph",
+ //pap.fNoAutoHyph
+ {45, 0}, //"sprmPWHeightAbs",
+ //pap.wHeightAbs w
+ {46, 0}, //"sprmPDcs", pap.dcs DCS
+ {47, &SwWW8ImplReader::Read_Shade}, //"sprmPShd", pap.shd SHD
+ {48, 0}, //"sprmPDyaFromText",
+ //pap.dyaFromText dya
+ {49, 0}, //"sprmPDxaFromText",
+ //pap.dxaFromText dxa
+ {50, 0}, //"sprmPFLocked", pap.fLocked
+ //0 or 1 byte
+ {51, &SwWW8ImplReader::Read_WidowControl}, //"sprmPFWidowControl",
+ //pap.fWidowControl 0 or 1 byte
+ {52, 0}, //"?sprmPRuler 52",
+ {53, 0}, //"??53",
+ {54, 0}, //"??54",
+ {55, 0}, //"??55",
+ {56, 0}, //"??56",
+ {57, 0}, //"??57",
+ {58, 0}, //"??58",
+ {59, 0}, //"??59",
+ {60, 0}, //"??60",
+ {61, 0}, //"??61",
+ {62, 0}, //"??62",
+ {63, 0}, //"??63",
+ {64, &SwWW8ImplReader::Read_ParaBiDi}, //"rtl bidi ?
+ {65, &SwWW8ImplReader::Read_CFRMarkDel}, //"sprmCFStrikeRM",
+ //chp.fRMarkDel 1 or 0 bit
+ {66, &SwWW8ImplReader::Read_CFRMark}, //"sprmCFRMark", chp.fRMark
+ //1 or 0 bit
+ {67, &SwWW8ImplReader::Read_FldVanish}, //"sprmCFFldVanish",
+ //chp.fFldVanish 1 or 0 bit
+ {68, &SwWW8ImplReader::Read_PicLoc}, //"sprmCPicLocation",
+ //chp.fcPic and chp.fSpec
+ {69, 0}, //"sprmCIbstRMark",
+ //chp.ibstRMark index into
+ //sttbRMark
+ {70, 0}, //"sprmCDttmRMark", chp.dttm
+ //DTTM long
+ {71, 0}, //"sprmCFData", chp.fData 1 or
+ //0 bit
+ {72, 0}, //"sprmCRMReason",
+ //chp.idslRMReason an index to
+ //a table
+ {73, &SwWW8ImplReader::Read_CharSet}, //"sprmCChse", chp.fChsDiff
+ //and chp.chse 3 bytes
+ {74, &SwWW8ImplReader::Read_Symbol}, //"sprmCSymbol", chp.fSpec,
+ //chp.chSym and chp.ftcSym
+ {75, &SwWW8ImplReader::Read_Obj}, //"sprmCFOle2", chp.fOle2 1
+ //or 0 bit
+ {76, 0}, //"??76",
+ {77, 0}, //"??77",
+ {78, 0}, //"??78",
+ {79, 0}, //"??79",
+ {80, &SwWW8ImplReader::Read_CColl}, //"sprmCIstd", chp.istd istd,
+ //see stylesheet definition
+ //short
+ {81, 0}, //"sprmCIstdPermute", chp.istd
+ //permutation vector
+ {82, 0}, //"sprmCDefault", whole CHP
+ //none variable length
+ {83, 0}, //"sprmCPlain", whole CHP
+ //none 0
+ {84, 0}, //"??84",
+ {85, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFBold", chp.fBold 0,1,
+ //128, or 129 byte
+ {86, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFItalic", chp.fItalic
+ //0,1, 128, or 129 byte
+ {87, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFStrike", chp.fStrike
+ //0,1, 128, or 129 byte
+ {88, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFOutline", chp.fOutline
+ //0,1, 128, or 129 byte
+ {89, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFShadow", chp.fShadow
+ //0,1, 128, or 129 byte
+ {90, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFSmallCaps",
+ //chp.fSmallCaps 0,1, 128, or
+ //129 byte
+ {91, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFCaps", chp.fCaps 0,1,
+ //128, or 129 byte
+ {92, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFVanish", chp.fVanish
+ //0,1, 128, or 129 byte
+ {93, &SwWW8ImplReader::Read_FontCode}, //"sprmCFtc", chp.ftc ftc word
+ {94, &SwWW8ImplReader::Read_Underline}, // "sprmCKul", chp.kul kul byte
+ {95, 0}, //"sprmCSizePos", chp.hps,
+ //chp.hpsPos 3 bytes
+ {96, &SwWW8ImplReader::Read_Kern}, //"sprmCDxaSpace",
+ //chp.dxaSpace dxa word
+ {97, &SwWW8ImplReader::Read_Language}, //"sprmCLid", chp.lid LID word
+ {98, &SwWW8ImplReader::Read_TxtColor}, //"sprmCIco", chp.ico ico byte
+ {99, &SwWW8ImplReader::Read_FontSize}, //"sprmCHps", chp.hps hps word!
+ {100, 0}, //"sprmCHpsInc", chp.hps byte
+ {101, &SwWW8ImplReader::Read_SubSuperProp}, //"sprmCHpsPos", chp.hpsPos
+ //hps byte
+ {102, 0}, //"sprmCHpsPosAdj", chp.hpsPos
+ //hps byte
+ {103, &SwWW8ImplReader::Read_Majority}, //"?sprmCMajority", chp.fBold,
+ //chp.fItalic, chp.fSmallCaps
+ {104, &SwWW8ImplReader::Read_SubSuper}, //"sprmCIss", chp.iss iss byte
+ {105, 0}, //"sprmCHpsNew50", chp.hps hps
+ //variable width, length
+ //always recorded as 2
+ {106, 0}, //"sprmCHpsInc1", chp.hps
+ //complex variable width,
+ //length always recorded as 2
+ {107, &SwWW8ImplReader::Read_FontKern}, //"sprmCHpsKern", chp.hpsKern
+ //hps short
+ {108, &SwWW8ImplReader::Read_Majority}, //"sprmCMajority50", chp.fBold,
+ //chp.fItalic, chp.fSmallCaps,
+ // chp.fVanish, ...
+ {109, 0}, //"sprmCHpsMul", chp.hps
+ //percentage to grow hps short
+ {110, 0}, //"sprmCCondHyhen", chp.ysri
+ //ysri short
+ {111, &SwWW8ImplReader::Read_FontCode}, //ww7 font
+ {112, &SwWW8ImplReader::Read_FontCode}, //ww7 CJK font
+ {113, &SwWW8ImplReader::Read_FontCode}, //ww7 rtl font
+ {114, &SwWW8ImplReader::Read_Language}, //ww7 lid
+ {115, &SwWW8ImplReader::Read_TxtColor}, //ww7 rtl colour ?
+ {116, &SwWW8ImplReader::Read_FontSize},
+ {117, &SwWW8ImplReader::Read_Special}, //"sprmCFSpec", chp.fSpec 1
+ //or 0 bit
+ {118, &SwWW8ImplReader::Read_Obj}, //"sprmCFObj", chp.fObj 1 or 0
+ //bit
+ {119, 0}, //"sprmPicBrcl", pic.brcl brcl
+ //(see PIC structure
+ //definition) byte
+ {120, 0}, //"sprmPicScale", pic.mx,
+ //pic.my, pic.dxaCropleft,
+ {121, 0}, //"sprmPicBrcTop", pic.brcTop
+ //BRC word
+ {122, 0}, //"sprmPicBrcLeft",
+ //pic.brcLeft BRC word
+ {123, 0}, //"sprmPicBrcBottom",
+ //pic.brcBottom BRC word
+ {124, 0}, //"sprmPicBrcRight",
+ //pic.brcRight BRC word
+ {125, 0}, //"??125",
+ {126, 0}, //"??126",
+ {127, 0}, //"??127",
+ {128, 0}, //"??128",
+ {129, 0}, //"??129",
+ {130, 0}, //"??130",
+ {131, 0}, //"sprmSScnsPgn", sep.cnsPgn
+ //cns byte
+ {132, 0}, //"sprmSiHeadingPgn",
+ //sep.iHeadingPgn heading
+ //number level byte
+ {133, &SwWW8ImplReader::Read_OLST}, //"sprmSOlstAnm", sep.olstAnm
+ //OLST variable length
+ {134, 0}, //"??135",
+ {135, 0}, //"??135",
+ {136, 0}, //"sprmSDxaColWidth",
+ //sep.rgdxaColWidthSpacing
+ //complex 3 bytes
+ {137, 0}, //"sprmSDxaColSpacing",
+ //sep.rgdxaColWidthSpacing
+ //complex 3 bytes
+ {138, 0}, //"sprmSFEvenlySpaced",
+ //sep.fEvenlySpaced 1 or 0 byte
+ {139, 0}, //"sprmSFProtected",
+ //sep.fUnlocked 1 or 0 byte
+ {140, 0}, //"sprmSDmBinFirst",
+ //sep.dmBinFirst word
+ {141, 0}, //"sprmSDmBinOther",
+ //sep.dmBinOther word
+ {142, 0}, //"sprmSBkc", sep.bkc bkc
+ //byte BreakCode
+ {143, 0}, //"sprmSFTitlePage",
+ //sep.fTitlePage 0 or 1 byte
+ {144, 0}, //"sprmSCcolumns", sep.ccolM1
+ //# of cols - 1 word
+ {145, 0}, //"sprmSDxaColumns",
+ //sep.dxaColumns dxa word
+ {146, 0}, //"sprmSFAutoPgn",
+ //sep.fAutoPgn obsolete byte
+ {147, 0}, //"sprmSNfcPgn", sep.nfcPgn
+ //nfc byte
+ {148, 0}, //"sprmSDyaPgn", sep.dyaPgn
+ //dya short
+ {149, 0}, //"sprmSDxaPgn", sep.dxaPgn
+ //dya short
+ {150, 0}, //"sprmSFPgnRestart",
+ //sep.fPgnRestart 0 or 1 byte
+ {151, 0}, //"sprmSFEndnote", sep.fEndnote
+ //0 or 1 byte
+ {152, 0}, //"sprmSLnc", sep.lnc lnc byte
+ {153, 0}, //"sprmSGprfIhdt", sep.grpfIhdt
+ //grpfihdt byte
+ {154, 0}, //"sprmSNLnnMod", sep.nLnnMod
+ //non-neg int. word
+ {155, 0}, //"sprmSDxaLnn", sep.dxaLnn
+ //dxa word
+ {156, 0}, //"sprmSDyaHdrTop",
+ //sep.dyaHdrTop dya word
+ {157, 0}, //"sprmSDyaHdrBottom",
+ //sep.dyaHdrBottom dya word
+ {158, 0}, //"sprmSLBetween",
+ //sep.fLBetween 0 or 1 byte
+ {159, 0}, //"sprmSVjc", sep.vjc vjc byte
+ {160, 0}, //"sprmSLnnMin", sep.lnnMin
+ //lnn word
+ {161, 0}, //"sprmSPgnStart", sep.pgnStart
+ //pgn word
+ {162, 0}, //"sprmSBOrientation",
+ //sep.dmOrientPage dm byte
+ {163, 0}, //"?SprmSBCustomize 163", ?
+ {164, 0}, //"sprmSXaPage", sep.xaPage xa
+ //word
+ {165, 0}, //"sprmSYaPage", sep.yaPage ya
+ //word
+ {166, 0}, //"sprmSDxaLeft", sep.dxaLeft
+ //dxa word
+ {167, 0}, //"sprmSDxaRight", sep.dxaRight
+ //dxa word
+ {168, 0}, //"sprmSDyaTop", sep.dyaTop //dya word
+ {169, 0}, //"sprmSDyaBottom",
+ //sep.dyaBottom dya word
+ {170, 0}, //"sprmSDzaGutter",
+ //sep.dzaGutter dza word
+ {171, 0}, //"sprmSDMPaperReq",
+ //sep.dmPaperReq dm word
+ {172, 0}, //"??172",
+ {173, 0}, //"??173",
+ {174, 0}, //"??174",
+ {175, 0}, //"??175",
+ {176, 0}, //"??176",
+ {177, 0}, //"??177",
+ {178, 0}, //"??178",
+ {179, 0}, //"??179",
+ {180, 0}, //"??180",
+ {181, 0}, //"??181",
+ {182, 0}, //"sprmTJc", tap.jc jc word
+ //(low order byte is
+ //significant)
+ {183, 0}, //"sprmTDxaLeft",
+ //tap.rgdxaCenter dxa word
+ {184, 0}, //"sprmTDxaGapHalf",
+ //tap.dxaGapHalf,
+ //tap.rgdxaCenter dxa word
+ {185, 0}, //"sprmTFCantSplit"
+ //tap.fCantSplit 1 or 0 byte
+ {186, 0}, //"sprmTTableHeader",
+ //tap.fTableHeader 1 or 0 byte
+ {187, 0}, //"sprmTTableBorders",
+ //tap.rgbrcTable complex
+ //12 bytes
+ {188, 0}, //"sprmTDefTable10",
+ //tap.rgdxaCenter, tap.rgtc
+ //complex variable length
+ {189, 0}, //"sprmTDyaRowHeight",
+ //tap.dyaRowHeight dya word
+ {190, 0}, //"?sprmTDefTable", tap.rgtc
+ //complex
+ {191, 0}, //"?sprmTDefTableShd",
+ //tap.rgshd complex
+ {192, 0}, //"sprmTTlp", tap.tlp TLP
+ //4 bytes
+ {193, 0}, //"sprmTSetBrc",
+ //tap.rgtc[].rgbrc complex
+ //5 bytes
+ {194, 0}, //"sprmTInsert",
+ //tap.rgdxaCenter,
+ //tap.rgtc complex 4 bytes
+ {195, 0}, //"sprmTDelete",
+ //tap.rgdxaCenter,
+ //tap.rgtc complex word
+ {196, 0}, //"sprmTDxaCol",
+ //tap.rgdxaCenter complex
+ //4 bytes
+ {197, 0}, //"sprmTMerge",
+ //tap.fFirstMerged,
+ //tap.fMerged complex word
+ {198, 0}, //"sprmTSplit",
+ //tap.fFirstMerged,
+ //tap.fMerged complex word
+ {199, 0}, //"sprmTSetBrc10",
+ //tap.rgtc[].rgbrc complex
+ //5 bytes
+ {200, 0}, //"sprmTSetShd", tap.rgshd
+ //complex 4 bytes
+ {207, 0}, //dunno
+ };
+
+ static wwSprmDispatcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms));
+ return &aSprmSrch;
+}
+
+const wwSprmDispatcher *GetWW8SprmDispatcher()
+{
+ static SprmReadInfo aSprms[] =
+ {
+ {0, 0}, // "0" Default bzw. Error
+
+ {0x4600, &SwWW8ImplReader::Read_StyleCode}, //"sprmPIstd" pap.istd;istd
+ //(style code);short;
+ {0xC601, 0}, //"sprmPIstdPermute" pap.istd;
+ //permutation vector;
+ //variable length;
+ {0x2602, 0}, //"sprmPIncLvl" pap.istd,
+ //pap.lvl;difference between
+ //istd of base PAP and istd of
+ //PAP to be produced; byte;
+ {0x2403, &SwWW8ImplReader::Read_Justify}, //"sprmPJc" pap.jc;jc
+ //(justification);byte;
+ {0x2404, 0}, //"sprmPFSideBySide"
+ //pap.fSideBySide;0 or 1;byte;
+ {0x2405, &SwWW8ImplReader::Read_KeepLines}, //"sprmPFKeep" pap.fKeep;0 or
+ //1;byte;
+ {0x2406, &SwWW8ImplReader::Read_KeepParas}, //"sprmPFKeepFollow"
+ //pap.fKeepFollow;0 or 1;byte;
+ {0x2407, &SwWW8ImplReader::Read_BreakBefore},//"sprmPFPageBreakBefore"
+ //pap.fPageBreakBefore;0 or 1;
+ //byte;
+ {0x2408, 0}, //"sprmPBrcl" pap.brcl;brcl;
+ //byte;
+ {0x2409, 0}, //"sprmPBrcp" pap.brcp;brcp;
+ //byte;
+ {0x260A, &SwWW8ImplReader::Read_ListLevel}, //"sprmPIlvl" pap.ilvl;ilvl;
+ //byte;
+ {0x460B, &SwWW8ImplReader::Read_LFOPosition},//"sprmPIlfo" pap.ilfo;ilfo
+ //(list index) ;short;
+ {0x240C, &SwWW8ImplReader::Read_NoLineNumb}, //"sprmPFNoLineNumb"
+ //pap.fNoLnn;0 or 1;byte;
+ {0xC60D, &SwWW8ImplReader::Read_Tab}, //"sprmPChgTabsPapx"
+ //pap.itbdMac, pap.rgdxaTab,
+ //pap.rgtbd;complex;variable
+ //length
+ {0x840E, &SwWW8ImplReader::Read_LR}, //Word 97 version of "sprmPDxaRight" pap.dxaRight;
+ //dxa;word;
+ {0x840F, &SwWW8ImplReader::Read_LR}, //Apparently Word 97 version of "sprmPDxaLeft" pap.dxaLeft;
+ //dxa;word;
+ {0x4610, 0}, //"sprmPNest" pap.dxaLeft;
+ //dxa;word;
+ {0x8411, &SwWW8ImplReader::Read_LR}, //Word 97 version of "sprmPDxaLeft1" pap.dxaLeft1;
+ //dxa;word;
+ {0x6412, &SwWW8ImplReader::Read_LineSpace}, //"sprmPDyaLine" pap.lspd;
+ //an LSPD, a long word
+ //structure consisting of a
+ //short of dyaLine followed by
+ //a short of fMultLinespace;
+ //long;
+ {0xA413, &SwWW8ImplReader::Read_UL}, //"sprmPDyaBefore"
+ //pap.dyaBefore;dya;word;
+ {0xA414, &SwWW8ImplReader::Read_UL}, //"sprmPDyaAfter" pap.dyaAfter;
+ //dya;word;
+ {0xC615, 0}, //"sprmPChgTabs" pap.itbdMac,
+ //pap.rgdxaTab, pap.rgtbd;
+ //complex;variable length;
+ {0x2416, 0}, //"sprmPFInTable" pap.fInTable;
+ //0 or 1;byte;
+ {0x2417, &SwWW8ImplReader::Read_TabRowEnd}, //"sprmPFTtp" pap.fTtp;0 or 1;
+ //byte;
+ {0x8418, 0}, //"sprmPDxaAbs" pap.dxaAbs;dxa;
+ //word;
+ {0x8419, 0}, //"sprmPDyaAbs" pap.dyaAbs;dya;
+ //word;
+ {0x841A, 0}, //"sprmPDxaWidth" pap.dxaWidth;
+ //dxa;word;
+ {0x261B, &SwWW8ImplReader::Read_ApoPPC}, //"sprmPPc" pap.pcHorz,
+ //pap.pcVert;complex;byte;
+ {0x461C, 0}, //"sprmPBrcTop10" pap.brcTop;
+ //BRC10;word;
+ {0x461D, 0}, //"sprmPBrcLeft10" pap.brcLeft;
+ //BRC10;word;
+ {0x461E, 0}, //"sprmPBrcBottom10"
+ //pap.brcBottom;BRC10;word;
+ {0x461F, 0}, //"sprmPBrcRight10"
+ //pap.brcRight;BRC10;word;
+ {0x4620, 0}, //"sprmPBrcBetween10"
+ //pap.brcBetween;BRC10;word;
+ {0x4621, 0}, //"sprmPBrcBar10" pap.brcBar;
+ //BRC10;word;
+ {0x4622, 0}, //"sprmPDxaFromText10"
+ //pap.dxaFromText;dxa;word;
+ {0x2423, 0}, //"sprmPWr" pap.wr;wr;byte;
+ {0x6424, &SwWW8ImplReader::Read_Border}, //"sprmPBrcTop" pap.brcTop;BRC;
+ //long;
+ {0x6425, &SwWW8ImplReader::Read_Border}, //"sprmPBrcLeft" pap.brcLeft;
+ //BRC;long;
+ {0x6426, &SwWW8ImplReader::Read_Border}, //"sprmPBrcBottom"
+ //pap.brcBottom;BRC;long;
+ {0x6427, &SwWW8ImplReader::Read_Border}, //"sprmPBrcRight" pap.brcRight;
+ //BRC;long;
+ {0x6428, &SwWW8ImplReader::Read_Border}, //"sprmPBrcBetween"
+ //pap.brcBetween;BRC;long;
+ {0x6629, 0}, //"sprmPBrcBar" pap.brcBar;BRC;
+ //long;
+ {0x242A, &SwWW8ImplReader::Read_Hyphenation},//"sprmPFNoAutoHyph"
+ //pap.fNoAutoHyph;0 or 1;byte;
+ {0x442B, 0}, //"sprmPWHeightAbs"
+ //pap.wHeightAbs;w;word;
+ {0x442C, 0}, //"sprmPDcs" pap.dcs;DCS;short;
+ {0x442D, &SwWW8ImplReader::Read_Shade}, //"sprmPShd" pap.shd;SHD;word;
+ {0x842E, 0}, //"sprmPDyaFromText"
+ //pap.dyaFromText;dya;word;
+ {0x842F, 0}, //"sprmPDxaFromText"
+ //pap.dxaFromText;dxa;word;
+ {0x2430, 0}, //"sprmPFLocked" pap.fLocked;
+ //0 or 1;byte;
+ {0x2431, &SwWW8ImplReader::Read_WidowControl},//"sprmPFWidowControl"
+ //pap.fWidowControl;0 or 1;byte
+ {0xC632, 0}, //"sprmPRuler" variable length;
+ {0x2433, &SwWW8ImplReader::Read_BoolItem}, //"sprmPFKinsoku" pap.fKinsoku;
+ //0 or 1;byte;
+ {0x2434, 0}, //"sprmPFWordWrap"
+ //pap.fWordWrap;0 or 1;byte;
+ {0x2435, &SwWW8ImplReader::Read_BoolItem}, //"sprmPFOverflowPunct"
+ //pap.fOverflowPunct; 0 or 1;
+ //byte;
+ {0x2436, 0}, //"sprmPFTopLinePunct"
+ //pap.fTopLinePunct;0 or 1;byte
+ {0x2437, &SwWW8ImplReader::Read_BoolItem}, //"sprmPFAutoSpaceDE"
+ //pap.fAutoSpaceDE;0 or 1;byte;
+ {0x2438, 0}, //"sprmPFAutoSpaceDN"
+ //pap.fAutoSpaceDN;0 or 1;byte;
+ {0x4439, &SwWW8ImplReader::Read_AlignFont}, //"sprmPWAlignFont"
+ //pap.wAlignFont;iFa; word;
+ {0x443A, 0}, //"sprmPFrameTextFlow"
+ //pap.fVertical pap.fBackward
+ //pap.fRotateFont;complex; word
+ {0x243B, 0}, //"sprmPISnapBaseLine" obsolete
+ //not applicable in Word97
+ //and later versions;;byte;
+ {0xC63E, &SwWW8ImplReader::Read_ANLevelDesc},//"sprmPAnld" pap.anld;;
+ //variable length;
+ {0xC63F, 0}, //"sprmPPropRMark"
+ //pap.fPropRMark;complex;
+ //variable length;
+ {0x2640, &SwWW8ImplReader::Read_POutLvl}, //"sprmPOutLvl" pap.lvl;has no
+ //effect if pap.istd is < 1 or
+ //is > 9;byte;
+ {0x2441, &SwWW8ImplReader::Read_ParaBiDi}, //"sprmPFBiDi" ;;byte;
+ {0x2443, 0}, //"sprmPFNumRMIns"
+ //pap.fNumRMIns;1 or 0;bit;
+ {0x2444, 0}, //"sprmPCrLf" ;;byte;
+ {0xC645, 0}, //"sprmPNumRM" pap.numrm;;
+ //variable length;
+ {0x6645, 0}, //"sprmPHugePapx" ;fc in the
+ //data stream to locate the
+ //huge grpprl; long;
+ {0x6646, 0}, //"sprmPHugePapx" ;fc in the
+ //data stream to locate the
+ //huge grpprl; long;
+ {0x2447, &SwWW8ImplReader::Read_UsePgsuSettings},//"sprmPFUsePgsuSettings"
+ //pap.fUsePgsuSettings;1 or 0;
+ //byte;
+ {0x2448, 0}, //"sprmPFAdjustRight"
+ //pap.fAdjustRight;1 or 0;byte;
+ {0x0800, &SwWW8ImplReader::Read_CFRMarkDel}, //"sprmCFRMarkDel"
+ //chp.fRMarkDel;1 or 0;bit;
+ {0x0801, &SwWW8ImplReader::Read_CFRMark}, //"sprmCFRMark" chp.fRMark;1
+ //or 0;bit;
+ {0x0802, &SwWW8ImplReader::Read_FldVanish}, //"sprmCFFldVanish"
+ //chp.fFldVanish;1 or 0;bit;
+ {0x6A03, &SwWW8ImplReader::Read_PicLoc}, //"sprmCPicLocation" chp.fcPic
+ //and chp.fSpec;variable
+ //length, length recorded is
+ //always 4;
+ {0x4804, 0}, //"sprmCIbstRMark"
+ //chp.ibstRMark;index into
+ //sttbRMark;short;
+ {0x6805, 0}, //"sprmCDttmRMark"
+ //chp.dttmRMark;DTTM;long;
+ {0x0806, 0}, //"sprmCFData" chp.fData;1 or
+ //0;bit;
+ {0x4807, 0}, //"sprmCIdslRMark"
+ //chp.idslRMReason;an index to
+ //a table of strings defined in
+ //Word 6.0 executables;short;
+ {0xEA08, &SwWW8ImplReader::Read_CharSet}, //"sprmCChs" chp.fChsDiff and
+ //chp.chse;3 bytes;
+ {0x6A09, &SwWW8ImplReader::Read_Symbol}, //"sprmCSymbol" chp.fSpec,
+ //chp.xchSym and chp.ftcSym;
+ //variable length, length
+ //recorded is always 4;
+ {0x080A, &SwWW8ImplReader::Read_Obj}, //"sprmCFOle2" chp.fOle2;1 or
+ //0;bit;
+ //0x480B, //"sprmCIdCharType", obsolete:
+ //not applicable in Word97
+ //and later versions
+ {0x2A0C, &SwWW8ImplReader::Read_CharHighlight},//"sprmCHighlight"
+ //chp.fHighlight,
+ //chp.icoHighlight;ico
+ //(fHighlight is set to 1 iff
+ //ico is not 0);byte;
+ {0x680E, &SwWW8ImplReader::Read_PicLoc}, //"sprmCObjLocation" chp.fcObj;
+ //FC;long;
+ //0x2A10, ? ? ?, //"sprmCFFtcAsciSymb"
+ {0x4A30, &SwWW8ImplReader::Read_CColl}, //"sprmCIstd" chp.istd;istd,
+ //short;
+ {0xCA31, 0}, //"sprmCIstdPermute" chp.istd;
+ //permutation vector; variable
+ //length;
+ {0x2A32, 0}, //"sprmCDefault" whole CHP;none
+ //;variable length;
+ {0x2A33, 0}, //"sprmCPlain" whole CHP;none;
+ //Laenge: 0;
+ {0x2A34, &SwWW8ImplReader::Read_Emphasis}, //"sprmCKcd"
+ {0x0835, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFBold" chp.fBold;0,1,
+ //128, or 129; byte;
+ {0x0836, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFItalic" chp.fItalic;0,
+ //1, 128, or 129; byte;
+ {0x0837, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFStrike" chp.fStrike;0,
+ //1, 128, or 129; byte;
+ {0x0838, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFOutline" chp.fOutline;
+ //0,1, 128, or 129; byte;
+ {0x0839, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFShadow" chp.fShadow;0,
+ //1, 128, or 129; byte;
+ {0x083A, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFSmallCaps"
+ //chp.fSmallCaps;0,1, 128, or
+ //129;byte;
+ {0x083B, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFCaps" chp.fCaps;0,1,
+ //128, or 129; byte;
+ {0x083C, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFVanish" chp.fVanish;0,
+ //1, 128, or 129; byte;
+ //0x4A3D, 0, //"sprmCFtcDefault" ftc, only
+ //used internally, never
+ //stored in file;word;
+ {0x2A3E, &SwWW8ImplReader::Read_Underline}, //"sprmCKul" chp.kul;kul;byte;
+ {0xEA3F, 0}, //"sprmCSizePos" chp.hps,
+ //chp.hpsPos;3 bytes;
+ {0x8840, &SwWW8ImplReader::Read_Kern}, //"sprmCDxaSpace" chp.dxaSpace;
+ //dxa;word;
+ {0x4A41, &SwWW8ImplReader::Read_Language}, //"sprmCLid" ;only used
+ //internally never stored;word;
+ {0x2A42, &SwWW8ImplReader::Read_TxtColor}, //"sprmCIco" chp.ico;ico;byte;
+ {0x4A43, &SwWW8ImplReader::Read_FontSize}, //"sprmCHps" chp.hps;hps;byte;
+ {0x2A44, 0}, //"sprmCHpsInc" chp.hps;byte;
+ {0x4845, &SwWW8ImplReader::Read_SubSuperProp},//"sprmCHpsPos" chp.hpsPos;
+ //hps; byte;
+ {0x2A46, 0}, //"sprmCHpsPosAdj" chp.hpsPos;
+ //hps; byte;
+ {0xCA47, &SwWW8ImplReader::Read_Majority}, //"sprmCMajority" chp.fBold,
+ //chp.fItalic, chp.fSmallCaps,
+ //chp.fVanish, chp.fStrike,
+ //chp.fCaps, chp.rgftc,
+ //chp.hps, chp.hpsPos, chp.kul,
+ //chp.dxaSpace, chp.ico,
+ //chp.rglid;complex;variable
+ //length, length byte plus
+ //size of following grpprl;
+ {0x2A48, &SwWW8ImplReader::Read_SubSuper}, //"sprmCIss" chp.iss;iss;byte;
+ {0xCA49, 0}, //"sprmCHpsNew50" chp.hps;hps;
+ //variable width, length
+ //always recorded as 2;
+ {0xCA4A, 0}, //"sprmCHpsInc1" chp.hps;
+ //complex; variable width,
+ //length always recorded as 2;
+ {0x484B, &SwWW8ImplReader::Read_FontKern}, //"sprmCHpsKern" chp.hpsKern;
+ //hps;short;
+ {0xCA4C, &SwWW8ImplReader::Read_Majority}, //"sprmCMajority50" chp.fBold,
+ //chp.fItalic, chp.fSmallCaps,
+ //chp.fVanish, chp.fStrike,
+ //chp.fCaps, chp.ftc, chp.hps,
+ //chp.hpsPos, chp.kul,
+ //chp.dxaSpace, chp.ico;
+ //complex; variable length;
+ {0x4A4D, 0}, //"sprmCHpsMul" chp.hps;
+ //percentage to grow hps;short;
+ {0x484E, 0}, //"sprmCYsri" chp.ysri;ysri;
+ //short;
+ {0x4A4F, &SwWW8ImplReader::Read_FontCode}, //"sprmCRgFtc0" chp.rgftc[0];
+ //ftc for ASCII text; short;
+ {0x4A50, &SwWW8ImplReader::Read_FontCode}, //"sprmCRgFtc1" chp.rgftc[1];
+ //ftc for Far East text;short;
+ {0x4A51, &SwWW8ImplReader::Read_FontCode}, //"sprmCRgFtc2" chp.rgftc[2];
+ //ftc for non-Far East text;
+ //short;
+ {0x4852, &SwWW8ImplReader::Read_ScaleWidth}, //"sprmCCharScale"
+ {0x2A53, &SwWW8ImplReader::Read_BoldUsw}, //"sprmCFDStrike" chp.fDStrike;
+ //;byte;
+ {0x0854, &SwWW8ImplReader::Read_Relief}, //"sprmCFImprint" chp.fImprint;
+ //1 or 0;bit;
+ {0x0855, &SwWW8ImplReader::Read_Special}, //"sprmCFSpec" chp.fSpec;
+ //1 or 0;bit;
+ {0x0856, &SwWW8ImplReader::Read_Obj}, //"sprmCFObj" chp.fObj;1 or 0;
+ //bit;
+ {0xCA57, &SwWW8ImplReader::Read_CPropRMark}, //"sprmCPropRMark"
+ //chp.fPropRMark,
+ //chp.ibstPropRMark,
+ //chp.dttmPropRMark;Complex;
+ //variable length always
+ //recorded as 7 bytes;
+ {0x0858, &SwWW8ImplReader::Read_Relief}, //"sprmCFEmboss" chp.fEmboss;
+ //1 or 0;bit;
+ {0x2859, &SwWW8ImplReader::Read_TxtAnim}, //"sprmCSfxText" chp.sfxtText;
+ //text animation;byte;
+ {0x085A, &SwWW8ImplReader::Read_Bidi}, //"sprmCFBiDi"
+ {0x085B, 0}, //"sprmCFDiacColor"
+ {0x085C, &SwWW8ImplReader::Read_BoldBiDiUsw},//"sprmCFBoldBi"
+ {0x085D, &SwWW8ImplReader::Read_BoldBiDiUsw},//"sprmCFItalicBi"
+ {0x4A5E, &SwWW8ImplReader::Read_FontCode}, //"sprmCFtcBi"
+ {0x485F, &SwWW8ImplReader::Read_Language}, //"sprmCLidBi"
+ //0x4A60, ? ? ?, //"sprmCIcoBi",
+ {0x4A61, &SwWW8ImplReader::Read_FontSize}, //"sprmCHpsBi"
+ {0xCA62, 0}, //"sprmCDispFldRMark"
+ //chp.fDispFldRMark,
+ //chp.ibstDispFldRMark,
+ //chp.dttmDispFldRMark ;
+ //Complex;variable length
+ //always recorded as 39 bytes;
+ {0x4863, 0}, //"sprmCIbstRMarkDel"
+ //chp.ibstRMarkDel;index into
+ //sttbRMark;short;
+ {0x6864, 0}, //"sprmCDttmRMarkDel"
+ //chp.dttmRMarkDel;DTTM;long;
+ {0x6865, 0}, //"sprmCBrc" chp.brc;BRC;long;
+ {0x4866, &SwWW8ImplReader::Read_CharShadow}, //"sprmCShd" chp.shd;SHD;short;
+ {0x4867, 0}, //"sprmCIdslRMarkDel"
+ //chp.idslRMReasonDel;an index
+ //to a table of strings
+ //defined in Word 6.0
+ //executables;short;
+ {0x0868, 0}, //"sprmCFUsePgsuSettings"
+ //chp.fUsePgsuSettings; 1 or 0;
+ //bit;
+ {0x486B, 0}, //"sprmCCpg" ;;word;
+ {0x486D, &SwWW8ImplReader::Read_Language}, //"sprmCRgLid0_80" chp.rglid[0];
+ //LID: for non-Far East text;
+ //word;
+ {0x486E, &SwWW8ImplReader::Read_Language}, //"sprmCRgLid1_80" chp.rglid[1];
+ //LID: for Far East text;word;
+ {0x286F, &SwWW8ImplReader::Read_IdctHint}, //"sprmCIdctHint" chp.idctHint;
+ //IDCT: byte;
+ {0x2E00, 0}, //"sprmPicBrcl" pic.brcl;brcl
+ //(see PIC structure
+ //definition);byte;
+ {0xCE01, 0}, //"sprmPicScale" pic.mx,
+ //pic.my, pic.dxaCropleft,
+ //pic.dyaCropTop
+ //pic.dxaCropRight,
+ //pic.dyaCropBottom;Complex;
+ //length byte plus 12 bytes;
+ {0x6C02, 0}, //"sprmPicBrcTop" pic.brcTop;
+ //BRC;long;
+ {0x6C03, 0}, //"sprmPicBrcLeft" pic.brcLeft;
+ //BRC;long;
+ {0x6C04, 0}, //"sprmPicBrcBottom"
+ //pic.brcBottom;BRC;long;
+ {0x6C05, 0}, //"sprmPicBrcRight"
+ //pic.brcRight;BRC;long;
+ {0x3000, 0}, //"sprmScnsPgn" sep.cnsPgn;cns;
+ //byte;
+ {0x3001, 0}, //"sprmSiHeadingPgn"
+ //sep.iHeadingPgn;heading
+ //number level;byte;
+ {0xD202, &SwWW8ImplReader::Read_OLST}, //"sprmSOlstAnm" sep.olstAnm;
+ //OLST;variable length;
+ {0xF203, 0}, //"sprmSDxaColWidth"
+ //sep.rgdxaColWidthSpacing;
+ //complex; 3 bytes;
+ {0xF204, 0}, //"sprmSDxaColSpacing"
+ //sep.rgdxaColWidthSpacing;
+ //complex; 3 bytes;
+ {0x3005, 0}, //"sprmSFEvenlySpaced"
+ //sep.fEvenlySpaced; 1 or 0;
+ //byte;
+ {0x3006, 0}, //"sprmSFProtected"
+ //sep.fUnlocked;1 or 0;byte;
+ {0x5007, 0}, //"sprmSDmBinFirst"
+ //sep.dmBinFirst;;word;
+ {0x5008, 0}, //"sprmSDmBinOther"
+ //sep.dmBinOther;;word;
+ {0x3009, 0}, //"sprmSBkc" sep.bkc;bkc;byte;
+ {0x300A, 0}, //"sprmSFTitlePage"
+ //sep.fTitlePage;0 or 1;byte;
+ {0x500B, 0}, //"sprmSCcolumns" sep.ccolM1;
+ //# of cols - 1;word;
+ {0x900C, 0}, //"sprmSDxaColumns"
+ //sep.dxaColumns;dxa;word;
+ {0x300D, 0}, //"sprmSFAutoPgn" sep.fAutoPgn;
+ //obsolete;byte;
+ {0x300E, 0}, //"sprmSNfcPgn" sep.nfcPgn;nfc;
+ //byte;
+ {0xB00F, 0}, //"sprmSDyaPgn" sep.dyaPgn;dya;
+ //short;
+ {0xB010, 0}, //"sprmSDxaPgn" sep.dxaPgn;dya;
+ //short;
+ {0x3011, 0}, //"sprmSFPgnRestart"
+ //sep.fPgnRestart;0 or 1;byte;
+ {0x3012, 0}, //"sprmSFEndnote" sep.fEndnote;
+ //0 or 1;byte;
+ {0x3013, 0}, //"sprmSLnc" sep.lnc;lnc;byte;
+ {0x3014, 0}, //"sprmSGprfIhdt" sep.grpfIhdt;
+ //grpfihdt; byte;
+ {0x5015, 0}, //"sprmSNLnnMod" sep.nLnnMod;
+ //non-neg int.;word;
+ {0x9016, 0}, //"sprmSDxaLnn" sep.dxaLnn;dxa;
+ //word;
+ {0xB017, 0}, //"sprmSDyaHdrTop"
+ //sep.dyaHdrTop;dya;word;
+ {0xB018, 0}, //"sprmSDyaHdrBottom"
+ //sep.dyaHdrBottom;dya;word;
+ {0x3019, 0}, //"sprmSLBetween"
+ //sep.fLBetween;0 or 1;byte;
+ {0x301A, 0}, //"sprmSVjc" sep.vjc;vjc;byte;
+ {0x501B, 0}, //"sprmSLnnMin" sep.lnnMin;lnn;
+ //word;
+ {0x501C, 0}, //"sprmSPgnStart" sep.pgnStart;
+ //pgn;word;
+ {0x301D, 0}, //"sprmSBOrientation"
+ //sep.dmOrientPage;dm;byte;
+ //0x301E, ? ? ?, //"sprmSBCustomize"
+ {0xB01F, 0}, //"sprmSXaPage" sep.xaPage;xa;
+ //word;
+ {0xB020, 0}, //"sprmSYaPage" sep.yaPage;ya;
+ //word;
+ {0x2205, 0}, //"sprmSDxaLeft" sep.dxaLeft;
+ //dxa;word;
+ {0xB022, 0}, //"sprmSDxaRight" sep.dxaRight;
+ //dxa;word;
+ {0x9023, 0}, //"sprmSDyaTop" sep.dyaTop;dya;
+ //word;
+ {0x9024, 0}, //"sprmSDyaBottom"
+ //sep.dyaBottom;dya;word;
+ {0xB025, 0}, //"sprmSDzaGutter"
+ //sep.dzaGutter;dza;word;
+ {0x5026, 0}, //"sprmSDmPaperReq"
+ //sep.dmPaperReq;dm;word;
+ {0xD227, 0}, //"sprmSPropRMark"
+ //sep.fPropRMark,
+ //sep.ibstPropRMark,
+ //sep.dttmPropRMark ;complex;
+ //variable length always
+ //recorded as 7 bytes;
+ //0x3228, ? ? ?, //"sprmSFBiDi",
+ //0x3229, ? ? ?, //"sprmSFFacingCol"
+ {0x322A, 0}, //"sprmSFRTLGutter", set to 1
+ //if gutter is on the right.
+ {0x702B, 0}, //"sprmSBrcTop" sep.brcTop;BRC;
+ //long;
+ {0x702C, 0}, //"sprmSBrcLeft" sep.brcLeft;
+ //BRC;long;
+ {0x702D, 0}, //"sprmSBrcBottom"
+ //sep.brcBottom;BRC;long;
+ {0x702E, 0}, //"sprmSBrcRight" sep.brcRight;
+ //BRC;long;
+ {0x522F, 0}, //"sprmSPgbProp" sep.pgbProp;
+ //word;
+ {0x7030, 0}, //"sprmSDxtCharSpace"
+ //sep.dxtCharSpace;dxt;long;
+ {0x9031, 0}, //"sprmSDyaLinePitch"
+ //sep.dyaLinePitch;dya;
+ //WRONG:long; RIGHT:short; !
+ //0x5032, ? ? ?, //"sprmSClm"
+ {0x5033, 0}, //"sprmSTextFlow"
+ //sep.wTextFlow;complex ;short
+ {0x5400, 0}, //"sprmTJc" tap.jc;jc;word (low
+ //order byte is significant);
+ {0x9601, 0}, //"sprmTDxaLeft"
+ //tap.rgdxaCenter; dxa; word;
+ {0x9602, 0}, //"sprmTDxaGapHalf"
+ //tap.dxaGapHalf,
+ //tap.rgdxaCenter; dxa; word;
+ {0x3403, 0}, //"sprmTFCantSplit"
+ //tap.fCantSplit;1 or 0;byte;
+ {0x3404, 0}, //"sprmTTableHeader"
+ //tap.fTableHeader;1 or 0;byte;
+ {0x3466, 0}, //"sprmTFCantSplit90"
+ //tap.fCantSplit90;1 or 0;byte;
+ {0xD605, 0}, //"sprmTTableBorders"
+ //tap.rgbrcTable;complex;
+ //24 bytes;
+ {0xD606, 0}, //"sprmTDefTable10"
+ //tap.rgdxaCenter,
+ //tap.rgtc;complex; variable
+ //length;
+ {0x9407, 0}, //"sprmTDyaRowHeight"
+ //tap.dyaRowHeight;dya;word;
+ {0xD608, 0}, //"sprmTDefTable"
+ //tap.rgtc;complex
+ {0xD609, 0}, //"sprmTDefTableShd"
+ //tap.rgshd;complex
+ {0x740A, 0}, //"sprmTTlp" tap.tlp;TLP;
+ //4 bytes;
+ //0x560B, ? ? ?, //"sprmTFBiDi"
+ //0x740C, ? ? ?, //"sprmTHTMLProps"
+ {0xD620, 0}, //"sprmTSetBrc"
+ //tap.rgtc[].rgbrc;complex;
+ //5 bytes;
+ {0x7621, 0}, //"sprmTInsert"
+ //tap.rgdxaCenter,
+ //tap.rgtc;complex ;4 bytes;
+ {0x5622, 0}, //"sprmTDelete"
+ //tap.rgdxaCenter,
+ //tap.rgtc;complex ;word;
+ {0x7623, 0}, //"sprmTDxaCol"
+ //tap.rgdxaCenter;complex;
+ //4 bytes;
+ {0x5624, 0}, //"sprmTMerge"
+ //tap.fFirstMerged,
+ //tap.fMerged;complex; word;
+ {0x5625, 0}, //"sprmTSplit"
+ //tap.fFirstMerged,
+ //tap.fMerged;complex ;word;
+ {0xD626, 0}, //"sprmTSetBrc10"
+ //tap.rgtc[].rgbrc;complex;
+ //5 bytes;
+ {0x7627, 0}, //"sprmTSetShd" tap.rgshd;
+ //complex; 4 bytes;
+ {0x7628, 0}, //"sprmTSetShdOdd"
+ //tap.rgshd;complex;4 bytes;
+ {0x7629, 0}, //"sprmTTextFlow"
+ //tap.rgtc[].fVertical
+ //tap.rgtc[].fBackward
+ //tap.rgtc[].fRotateFont
+ //0 or 10 or 10 or 1;word;
+ //0xD62A, ? ? ? , //"sprmTDiagLine"
+ {0xD62B, 0}, //"sprmTVertMerge"
+ //tap.rgtc[].vertMerge;complex;
+ //variable length always
+ //recorded as 2 bytes;
+ {0xD62C, 0}, //"sprmTVertAlign"
+ //tap.rgtc[].vertAlign;complex
+ //variable length always
+ //recorded as 3 byte;
+ {0xCA78, &SwWW8ImplReader::Read_DoubleLine_Rotate},
+ {0x6649, 0}, //undocumented
+ {0xF614, 0}, //"sprmTTableWidth"
+ //recorded as 3 bytes;
+ {0xD612, 0}, //undocumented
+ {0xD613, 0}, //undocumented
+ {0xD61A, 0}, //undocumented
+ {0xD61B, 0}, //undocumented
+ {0xD61C, 0}, //undocumented
+ {0xD61D, 0}, //undocumented
+ {0xD634, 0}, //undocumented
+ {0xD632, 0}, //undocumented
+ {0xD238, 0}, //undocumented sep
+ {0xC64E, 0}, //undocumented
+ {0xC64F, 0}, //undocumented
+ {0xC650, 0}, //undocumented
+ {0xC651, 0}, //undocumented
+ {0xF661, 0}, //undocumented
+ {0x4873, &SwWW8ImplReader::Read_Language}, //"sprmCRgLid0" chp.rglid[0];
+ //LID: for non-Far East text;
+ //(like a duplicate of 486D)
+ {0x4874, 0}, //"sprmCRgLid1" chp.rglid[1];
+ //LID: for Far East text
+ //(like a duplicate of 486E)
+ {0x6463, 0}, //undocumented
+ {0x2461, &SwWW8ImplReader::Read_RTLJustify}, //undoc, must be asian version
+ //of "sprmPJc"
+ {0x845E, &SwWW8ImplReader::Read_LR}, //Apparently post-Word 97 version of "sprmPDxaLeft"
+ {0x8460, &SwWW8ImplReader::Read_LR}, //Post-Word 97 version of "sprmPDxaLeft1"
+ {0x845D, &SwWW8ImplReader::Read_LR}, //Post-Word 97 version of "sprmPDxaRight"
+ {0x3615, 0}, //undocumented
+ {0x360D, 0}, //undocumented
+ {0x940E, 0}, //undocumented
+ {0x940F, 0}, //undocumented
+ {0x9410, 0}, //undocumented
+ {0x703A, 0}, //undocumented
+ {0x303B, 0}, //undocumented
+ {0x244B, &SwWW8ImplReader::Read_TabCellEnd}, //undocumented, must be
+ //subtable "sprmPFInTable"
+ {0x244C, &SwWW8ImplReader::Read_TabRowEnd}, //undocumented, must be
+ // subtable "sprmPFTtp"
+ {0x6815, 0}, //undocumented
+ {0x6816, 0}, //undocumented
+ {0x6870, &SwWW8ImplReader::Read_TxtForeColor},
+ {0xC64D, &SwWW8ImplReader::Read_ParaBackColor},
+ {0x6467, 0}, //undocumented
+ {0xF617, 0}, //undocumented
+ {0xD660, 0}, //undocumented
+ {0xD670, 0}, //undocumented
+ {0xCA71, &SwWW8ImplReader::Read_TxtBackColor},//undocumented
+ {0x303C, 0}, //undocumented
+ {0x245B, &SwWW8ImplReader::Read_ParaAutoBefore},//undocumented, para
+ {0x245C, &SwWW8ImplReader::Read_ParaAutoAfter},//undocumented, para
+ {0x246D, &SwWW8ImplReader::Read_DontAddEqual}//undocumented, para
+ };
+
+ static wwSprmDispatcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms));
+ return &aSprmSrch;
+}
+
+//-----------------------------------------
+// Hilfsroutinen : SPRM finden
+//-----------------------------------------
+
+const SprmReadInfo& SwWW8ImplReader::GetSprmReadInfo(sal_uInt16 nId) const
+{
+ ww::WordVersion eVersion = pWwFib->GetFIBVersion();
+ const wwSprmDispatcher *pDispatcher;
+ if (eVersion <= ww::eWW2)
+ pDispatcher = GetWW2SprmDispatcher();
+ else if (eVersion < ww::eWW8)
+ pDispatcher = GetWW6SprmDispatcher();
+ else
+ pDispatcher = GetWW8SprmDispatcher();
+
+ SprmReadInfo aSrch = {0, 0};
+ aSrch.nId = nId;
+ const SprmReadInfo* pFound = pDispatcher->search(aSrch);
+
+ if (!pFound)
+ {
+ aSrch.nId = 0;
+ pFound = pDispatcher->search(aSrch);
+ }
+
+ return *pFound;
+}
+
+//-----------------------------------------
+// Hilfsroutinen : SPRMs
+//-----------------------------------------
+void SwWW8ImplReader::EndSprm( sal_uInt16 nId )
+{
+ if( ( nId > 255 ) && ( nId < 0x0800 ) ) return;
+
+ const SprmReadInfo& rSprm = GetSprmReadInfo( nId );
+
+ if (rSprm.pReadFnc)
+ (this->*rSprm.pReadFnc)( nId, 0, -1 );
+}
+
+short SwWW8ImplReader::ImportSprm(const sal_uInt8* pPos,sal_uInt16 nId)
+{
+ if (!nId)
+ nId = mpSprmParser->GetSprmId(pPos);
+
+#if OSL_DEBUG_LEVEL > 1
+ OSL_ENSURE( nId != 0xff, "Sprm FF !!!!" );
+#endif
+
+ const SprmReadInfo& rSprm = GetSprmReadInfo(nId);
+
+ sal_uInt16 nFixedLen = mpSprmParser->DistanceToData(nId);
+ sal_uInt16 nL = mpSprmParser->GetSprmSize(nId, pPos);
+
+ if (rSprm.pReadFnc)
+ (this->*rSprm.pReadFnc)(nId, pPos + nFixedLen, nL - nFixedLen);
+
+ return nL;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8scan.cxx b/sw/source/filter/ww8/ww8scan.cxx
new file mode 100644
index 000000000000..4c5e3916306f
--- /dev/null
+++ b/sw/source/filter/ww8/ww8scan.cxx
@@ -0,0 +1,7301 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_sw.hxx"
+#include "ww8scan.hxx"
+
+#include <functional>
+#include <algorithm>
+
+#include <string.h> // memset()
+#include <rtl/tencinfo.h>
+#include <sal/macros.h>
+
+#ifdef DUMP
+
+#define ERR_SWG_READ_ERROR 1234
+#define OSL_ENSURE( a, b )
+
+#else // dump
+#include <swerror.h> // ERR_WW6_...
+#include <swtypes.hxx> // DELETEZ
+
+#endif // dump
+#include <comphelper/processfactory.hxx>
+#include <unotools/localedatawrapper.hxx>
+#include <tools/debug.hxx>
+#include <i18npool/lang.h>
+#include <editeng/unolingu.hxx>
+#include <vcl/svapp.hxx> // Application #i90932#
+
+#include <stdio.h>
+
+#define ASSERT_RET_ON_FAIL( aCon, aError, aRet ) \
+ OSL_ENSURE(aCon, aError); \
+ if (!(aCon)) \
+ return aRet;
+
+using namespace ::com::sun::star::lang;
+
+//-begin
+namespace SL
+{
+# define IMPLCONSTSTRINGARRAY(X) const char a##X[] = "" #X ""
+ IMPLCONSTSTRINGARRAY(ObjectPool);
+ IMPLCONSTSTRINGARRAY(1Table);
+ IMPLCONSTSTRINGARRAY(0Table);
+ IMPLCONSTSTRINGARRAY(Data);
+ IMPLCONSTSTRINGARRAY(CheckBox);
+ IMPLCONSTSTRINGARRAY(ListBox);
+ IMPLCONSTSTRINGARRAY(TextBox);
+ IMPLCONSTSTRINGARRAY(TextField);
+ IMPLCONSTSTRINGARRAY(MSMacroCmds);
+}
+
+template<class C> bool wwString<C>::TestBeltAndBraces(const SvStream& rStrm)
+{
+ bool bRet = false;
+ sal_uInt32 nOldPos = rStrm.Tell();
+ SvStream &rMutableStrm = const_cast<SvStream &>(rStrm);
+ sal_uInt32 nLen = rMutableStrm.Seek(STREAM_SEEK_TO_END);
+ rMutableStrm.Seek(nOldPos);
+ C nBelt;
+ rMutableStrm >> nBelt;
+ nBelt *= sizeof(C);
+ if (nOldPos + sizeof(C) + nBelt + sizeof(C) <= nLen &&
+ !rStrm.GetError() && !rStrm.IsEof())
+ {
+ rMutableStrm.SeekRel(nBelt);
+ if (!rStrm.GetError())
+ {
+ C cBraces;
+ rMutableStrm >> cBraces;
+ if (!rMutableStrm.GetError() && cBraces == 0)
+ bRet = true;
+ }
+ }
+ rMutableStrm.Seek(nOldPos);
+ return bRet;
+}
+
+inline bool operator==(const SprmInfo &rFirst, const SprmInfo &rSecond)
+{
+ return (rFirst.nId == rSecond.nId);
+}
+
+const wwSprmSearcher *wwSprmParser::GetWW2SprmSearcher()
+{
+ //double lock me
+ // WW7- Sprms
+ static const SprmInfo aSprms[] =
+ {
+ { 0, 0, L_FIX}, // "Default-sprm", wird uebersprungen
+ { 2, 1, L_FIX}, // "sprmPIstd", pap.istd (style code)
+ { 3, 0, L_VAR}, // "sprmPIstdPermute pap.istd permutation
+ { 4, 1, L_FIX}, // "sprmPIncLv1" pap.istddifference
+ { 5, 1, L_FIX}, // "sprmPJc" pap.jc (justification)
+ { 6, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide
+ { 7, 1, L_FIX}, // "sprmPFKeep" pap.fKeep
+ { 8, 1, L_FIX}, // "sprmPFKeepFollow " pap.fKeepFollow
+ { 9, 1, L_FIX}, // "sprmPPageBreakBefore" pap.fPageBreakBefore
+ { 10, 1, L_FIX}, // "sprmPBrcl" pap.brcl
+ { 11, 1, L_FIX}, // "sprmPBrcp" pap.brcp
+ { 12, 1, L_FIX}, // "sprmPNfcSeqNumb" pap.nfcSeqNumb
+ { 13, 1, L_FIX}, // "sprmPNoSeqNumb" pap.nnSeqNumb
+ { 14, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn
+ { 15, 0, L_VAR}, // "?sprmPChgTabsPapx" pap.itbdMac, ...
+ { 16, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight
+ { 17, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft
+ { 18, 2, L_FIX}, // "sprmPNest" pap.dxaLeft
+ { 19, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1
+ { 20, 2, L_FIX}, // "sprmPDyaLine" pap.lspd an LSPD
+ { 21, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore
+ { 22, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter
+ { 23, 0, L_VAR}, // "?sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, ...
+ { 24, 1, L_FIX}, // "sprmPFInTable" pap.fInTable
+ { 25, 1, L_FIX}, // "sprmPTtp" pap.fTtp
+ { 26, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs
+ { 27, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs
+ { 28, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth
+ { 29, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert
+ { 30, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop BRC10
+ { 31, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft BRC10
+ { 32, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom BRC10
+ { 33, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight BRC10
+ { 34, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween BRC10
+ { 35, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar BRC10
+ { 36, 2, L_FIX}, // "sprmPFromText10" pap.dxaFromText dxa
+ { 37, 1, L_FIX}, // "sprmPWr" pap.wr wr
+ { 38, 2, L_FIX}, // "sprmPBrcTop" pap.brcTop BRC
+ { 39, 2, L_FIX}, // "sprmPBrcLeft" pap.brcLeft BRC
+ { 40, 2, L_FIX}, // "sprmPBrcBottom" pap.brcBottom BRC
+ { 41, 2, L_FIX}, // "sprmPBrcRight" pap.brcRight BRC
+ { 42, 2, L_FIX}, // "sprmPBrcBetween" pap.brcBetween BRC
+ { 43, 2, L_FIX}, // "sprmPBrcBar" pap.brcBar BRC word
+ { 44, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph
+ { 45, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs w
+ { 46, 2, L_FIX}, // "sprmPDcs" pap.dcs DCS
+ { 47, 2, L_FIX}, // "sprmPShd" pap.shd SHD
+ { 48, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText dya
+ { 49, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText dxa
+ { 50, 1, L_FIX}, // "sprmPFBiDi" pap.fBiDi 0 or 1 byte
+ { 51, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl 0 or 1 byte
+ { 52, 0, L_FIX}, // "?sprmPRuler 52"
+ { 53, 1, L_FIX}, // "sprmCFStrikeRM" chp.fRMarkDel 1 or 0 bit
+ { 54, 1, L_FIX}, // "sprmCFRMark" chp.fRMark 1 or 0 bit
+ { 55, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish 1 or 0 bit
+ { 57, 0, L_VAR}, // "sprmCDefault" whole CHP
+ { 58, 0, L_FIX}, // "sprmCPlain" whole CHP
+ { 60, 1, L_FIX}, // "sprmCFBold" chp.fBold 0,1, 128, or 129
+ { 61, 1, L_FIX}, // "sprmCFItalic" chp.fItalic 0,1, 128, or 129
+ { 62, 1, L_FIX}, // "sprmCFStrike" chp.fStrike 0,1, 128, or 129
+ { 63, 1, L_FIX}, // "sprmCFOutline" chp.fOutline 0,1, 128, or 129
+ { 64, 1, L_FIX}, // "sprmCFShadow" chp.fShadow 0,1, 128, or 129
+ { 65, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps 0,1, 128, or 129
+ { 66, 1, L_FIX}, // "sprmCFCaps" chp.fCaps 0,1, 128, or 129
+ { 67, 1, L_FIX}, // "sprmCFVanish" chp.fVanish 0,1, 128, or 129
+ { 68, 2, L_FIX}, // "sprmCFtc" chp.ftc ftc word
+ { 69, 1, L_FIX}, // "sprmCKul" chp.kul kul byte
+ { 70, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos
+ { 71, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace dxa
+ { 72, 2, L_FIX}, // "sprmCLid" chp.lid LID
+ { 73, 1, L_FIX}, // "sprmCIco" chp.ico ico byte
+ { 74, 1, L_FIX}, // "sprmCHps" chp.hps hps !word!
+ { 75, 1, L_FIX}, // "sprmCHpsInc" chp.hps
+ { 76, 1, L_FIX}, // "sprmCHpsPos" chp.hpsPos hps !word!
+ { 77, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos hps
+ { 78, 0, L_VAR}, // "?sprmCMajority" chp.fBold, chp.fItalic, ...
+ { 80, 1, L_FIX}, // "sprmCFBoldBi" chp.fBoldBi
+ { 81, 1, L_FIX}, // "sprmCFItalicBi" chp.fItalicBi
+ { 82, 2, L_FIX}, // "sprmCFtcBi" chp.ftcBi
+ { 83, 2, L_FIX}, // "sprmClidBi" chp.lidBi
+ { 84, 1, L_FIX}, // "sprmCIcoBi" chp.icoBi
+ { 85, 1, L_FIX}, // "sprmCHpsBi" chp.hpsBi
+ { 86, 1, L_FIX}, // "sprmCFBiDi" chp.fBiDi
+ { 87, 1, L_FIX}, // "sprmCFDiacColor" chp.fDiacUSico
+ { 94, 1, L_FIX}, // "sprmPicBrcl" pic.brcl brcl (see PIC definition)
+ { 95,12, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
+ { 96, 2, L_FIX}, // "sprmPicBrcTop" pic.brcTop BRC word
+ { 97, 2, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft BRC word
+ { 98, 2, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom BRC word
+ { 99, 2, L_FIX}, // "sprmPicBrcRight" pic.brcRight BRC word
+ {112, 1, L_FIX}, // "sprmSFRTLGutter", set to one if gutter is on
+ {114, 1, L_FIX}, // "sprmSFBiDi" ;;;
+ {115, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst word
+ {116, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther word
+ {117, 1, L_FIX}, // "sprmSBkc" sep.bkc bkc byte
+ {118, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage 0 or 1 byte
+ {119, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1 # of cols - 1 word
+ {120, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns dxa word
+ {121, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn obsolete byte
+ {122, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn nfc byte
+ {123, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn dya short
+ {124, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn dya short
+ {125, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart 0 or 1 byte
+ {126, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote 0 or 1 byte
+ {127, 1, L_FIX}, // "sprmSLnc" sep.lnc lnc byte
+ {128, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt grpfihdt
+ {129, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod non-neg int. word
+ {130, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn dxa word
+ {131, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop dya word
+ {132, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom dya word
+ {133, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween 0 or 1 byte
+ {134, 1, L_FIX}, // "sprmSVjc" sep.vjc vjc byte
+ {135, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin lnn word
+ {136, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart pgn word
+ {137, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage dm byte
+ {138, 1, L_FIX}, // "sprmSFFacingCol" ;;;
+ {139, 2, L_FIX}, // "sprmSXaPage" sep.xaPage xa word
+ {140, 2, L_FIX}, // "sprmSYaPage" sep.yaPage ya word
+ {141, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft dxa word
+ {142, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight dxa word
+ {143, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop dya word
+ {144, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom dya word
+ {145, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter dza word
+ {146, 2, L_FIX}, // "sprmTJc" tap.jc jc (low order byte is significant)
+ {147, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter dxa word
+ {148, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf, tap.rgdxaCenter
+ {149, 1, L_FIX}, // "sprmTFBiDi" ;;;
+ {152, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter, tap.rgtc complex
+ {153, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight dya word
+ {154, 0, L_VAR2},// "sprmTDefTable" tap.rgtc complex
+ {155, 1, L_VAR}, // "sprmTDefTableShd" tap.rgshd complex
+ {157, 5, L_FIX}, // "sprmTSetBrc" tap.rgtc[].rgbrc complex 5 bytes
+ {158, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter,tap.rgtc complex
+ {159, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc complex
+ {160, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter complex
+ {161, 2, L_FIX}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged complex
+ {162, 2, L_FIX}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged complex
+ {163, 5, L_FIX}, // "sprmTSetBrc10" tap.rgtc[].rgbrc complex 5 bytes
+ {164, 4, L_FIX}, // "sprmTSetShd", tap.rgshd complex 4 bytes
+ };
+
+ static wwSprmSearcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms));
+ return &aSprmSrch;
+};
+
+
+const wwSprmSearcher *wwSprmParser::GetWW6SprmSearcher()
+{
+ //double lock me
+ // WW7- Sprms
+ static const SprmInfo aSprms[] =
+ {
+ { 0, 0, L_FIX}, // "Default-sprm", wird uebersprungen
+ { 2, 2, L_FIX}, // "sprmPIstd", pap.istd (style code)
+ { 3, 3, L_VAR}, // "sprmPIstdPermute pap.istd permutation
+ { 4, 1, L_FIX}, // "sprmPIncLv1" pap.istddifference
+ { 5, 1, L_FIX}, // "sprmPJc" pap.jc (justification)
+ { 6, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide
+ { 7, 1, L_FIX}, // "sprmPFKeep" pap.fKeep
+ { 8, 1, L_FIX}, // "sprmPFKeepFollow " pap.fKeepFollow
+ { 9, 1, L_FIX}, // "sprmPPageBreakBefore" pap.fPageBreakBefore
+ { 10, 1, L_FIX}, // "sprmPBrcl" pap.brcl
+ { 11, 1, L_FIX}, // "sprmPBrcp" pap.brcp
+ { 12, 0, L_VAR}, // "sprmPAnld" pap.anld (ANLD structure)
+ { 13, 1, L_FIX}, // "sprmPNLvlAnm" pap.nLvlAnm nn
+ { 14, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn
+ { 15, 0, L_VAR}, // "?sprmPChgTabsPapx" pap.itbdMac, ...
+ { 16, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight
+ { 17, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft
+ { 18, 2, L_FIX}, // "sprmPNest" pap.dxaLeft
+ { 19, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1
+ { 20, 4, L_FIX}, // "sprmPDyaLine" pap.lspd an LSPD
+ { 21, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore
+ { 22, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter
+ { 23, 0, L_VAR}, // "?sprmPChgTabs" pap.itbdMac, pap.rgdxaTab, ...
+ { 24, 1, L_FIX}, // "sprmPFInTable" pap.fInTable
+ { 25, 1, L_FIX}, // "sprmPTtp" pap.fTtp
+ { 26, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs
+ { 27, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs
+ { 28, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth
+ { 29, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert
+ { 30, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop BRC10
+ { 31, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft BRC10
+ { 32, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom BRC10
+ { 33, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight BRC10
+ { 34, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween BRC10
+ { 35, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar BRC10
+ { 36, 2, L_FIX}, // "sprmPFromText10" pap.dxaFromText dxa
+ { 37, 1, L_FIX}, // "sprmPWr" pap.wr wr
+ { 38, 2, L_FIX}, // "sprmPBrcTop" pap.brcTop BRC
+ { 39, 2, L_FIX}, // "sprmPBrcLeft" pap.brcLeft BRC
+ { 40, 2, L_FIX}, // "sprmPBrcBottom" pap.brcBottom BRC
+ { 41, 2, L_FIX}, // "sprmPBrcRight" pap.brcRight BRC
+ { 42, 2, L_FIX}, // "sprmPBrcBetween" pap.brcBetween BRC
+ { 43, 2, L_FIX}, // "sprmPBrcBar" pap.brcBar BRC word
+ { 44, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph
+ { 45, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs w
+ { 46, 2, L_FIX}, // "sprmPDcs" pap.dcs DCS
+ { 47, 2, L_FIX}, // "sprmPShd" pap.shd SHD
+ { 48, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText dya
+ { 49, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText dxa
+ { 50, 1, L_FIX}, // "sprmPFLocked" pap.fLocked 0 or 1 byte
+ { 51, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl 0 or 1 byte
+ { 52, 0, L_FIX}, // "?sprmPRuler 52"
+ { 64, 0, L_VAR}, // rtl property ?
+ { 65, 1, L_FIX}, // "sprmCFStrikeRM" chp.fRMarkDel 1 or 0 bit
+ { 66, 1, L_FIX}, // "sprmCFRMark" chp.fRMark 1 or 0 bit
+ { 67, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish 1 or 0 bit
+ { 68, 0, L_VAR}, // "sprmCPicLocation" chp.fcPic and chp.fSpec
+ { 69, 2, L_FIX}, // "sprmCIbstRMark" chp.ibstRMark index into sttbRMark
+ { 70, 4, L_FIX}, // "sprmCDttmRMark" chp.dttm DTTM long
+ { 71, 1, L_FIX}, // "sprmCFData" chp.fData 1 or 0 bit
+ { 72, 2, L_FIX}, // "sprmCRMReason" chp.idslRMReason an index to a table
+ { 73, 3, L_FIX}, // "sprmCChse" chp.fChsDiff and chp.chse
+ { 74, 0, L_VAR}, // "sprmCSymbol" chp.fSpec, chp.chSym and chp.ftcSym
+ { 75, 1, L_FIX}, // "sprmCFOle2" chp.fOle2 1 or 0 bit
+ { 77, 0, L_VAR}, // unknown
+ { 79, 0, L_VAR}, // unknown
+ { 80, 2, L_FIX}, // "sprmCIstd" chp.istd istd, see stylesheet definition
+ { 81, 0, L_VAR}, // "sprmCIstdPermute" chp.istd permutation vector
+ { 82, 0, L_VAR}, // "sprmCDefault" whole CHP
+ { 83, 0, L_FIX}, // "sprmCPlain" whole CHP
+ { 85, 1, L_FIX}, // "sprmCFBold" chp.fBold 0,1, 128, or 129
+ { 86, 1, L_FIX}, // "sprmCFItalic" chp.fItalic 0,1, 128, or 129
+ { 87, 1, L_FIX}, // "sprmCFStrike" chp.fStrike 0,1, 128, or 129
+ { 88, 1, L_FIX}, // "sprmCFOutline" chp.fOutline 0,1, 128, or 129
+ { 89, 1, L_FIX}, // "sprmCFShadow" chp.fShadow 0,1, 128, or 129
+ { 90, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps 0,1, 128, or 129
+ { 91, 1, L_FIX}, // "sprmCFCaps" chp.fCaps 0,1, 128, or 129
+ { 92, 1, L_FIX}, // "sprmCFVanish" chp.fVanish 0,1, 128, or 129
+ { 93, 2, L_FIX}, // "sprmCFtc" chp.ftc ftc word
+ { 94, 1, L_FIX}, // "sprmCKul" chp.kul kul byte
+ { 95, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos
+ { 96, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace dxa
+ { 97, 2, L_FIX}, // "sprmCLid" chp.lid LID
+ { 98, 1, L_FIX}, // "sprmCIco" chp.ico ico byte
+ { 99, 2, L_FIX}, // "sprmCHps" chp.hps hps !word!
+ {100, 1, L_FIX}, // "sprmCHpsInc" chp.hps
+ {101, 2, L_FIX}, // "sprmCHpsPos" chp.hpsPos hps !word!
+ {102, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos hps
+ {103, 0, L_VAR}, // "?sprmCMajority" chp.fBold, chp.fItalic, ...
+ {104, 1, L_FIX}, // "sprmCIss" chp.iss iss
+ {105, 0, L_VAR}, // "sprmCHpsNew50" chp.hps hps variable width
+ {106, 0, L_VAR}, // "sprmCHpsInc1" chp.hps complex
+ {107, 2, L_FIX}, // "sprmCHpsKern" chp.hpsKern hps
+ {108, 0, L_VAR}, // "sprmCMajority50" chp.fBold, chp.fItalic, ...
+ {109, 2, L_FIX}, // "sprmCHpsMul" chp.hps percentage to grow hps
+ {110, 2, L_FIX}, // "sprmCCondHyhen" chp.ysri ysri
+ {111, 2, L_FIX}, // rtl bold
+ {112, 2, L_FIX}, // rtl italic
+ {113, 0, L_VAR}, // rtl property ?
+ {115, 0, L_VAR}, // rtl property ?
+ {116, 0, L_VAR}, // unknown
+ {117, 1, L_FIX}, // "sprmCFSpec" chp.fSpec 1 or 0 bit
+ {118, 1, L_FIX}, // "sprmCFObj" chp.fObj 1 or 0 bit
+ {119, 1, L_FIX}, // "sprmPicBrcl" pic.brcl brcl (see PIC definition)
+ {120,12, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
+ {121, 2, L_FIX}, // "sprmPicBrcTop" pic.brcTop BRC word
+ {122, 2, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft BRC word
+ {123, 2, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom BRC word
+ {124, 2, L_FIX}, // "sprmPicBrcRight" pic.brcRight BRC word
+ {131, 1, L_FIX}, // "sprmSScnsPgn" sep.cnsPgn cns byte
+ {132, 1, L_FIX}, // "sprmSiHeadingPgn" sep.iHeadingPgn
+ {133, 0, L_VAR}, // "sprmSOlstAnm" sep.olstAnm OLST variable length
+ {136, 3, L_FIX}, // "sprmSDxaColWidth" sep.rgdxaColWidthSpacing complex
+ {137, 3, L_FIX}, // "sprmSDxaColSpacing" sep.rgdxaColWidthSpacing
+ {138, 1, L_FIX}, // "sprmSFEvenlySpaced" sep.fEvenlySpaced 1 or 0
+ {139, 1, L_FIX}, // "sprmSFProtected" sep.fUnlocked 1 or 0 byte
+ {140, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst word
+ {141, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther word
+ {142, 1, L_FIX}, // "sprmSBkc" sep.bkc bkc byte
+ {143, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage 0 or 1 byte
+ {144, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1 # of cols - 1 word
+ {145, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns dxa word
+ {146, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn obsolete byte
+ {147, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn nfc byte
+ {148, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn dya short
+ {149, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn dya short
+ {150, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart 0 or 1 byte
+ {151, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote 0 or 1 byte
+ {152, 1, L_FIX}, // "sprmSLnc" sep.lnc lnc byte
+ {153, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt grpfihdt
+ {154, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod non-neg int. word
+ {155, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn dxa word
+ {156, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop dya word
+ {157, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom dya word
+ {158, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween 0 or 1 byte
+ {159, 1, L_FIX}, // "sprmSVjc" sep.vjc vjc byte
+ {160, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin lnn word
+ {161, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart pgn word
+ {162, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage dm byte
+ {163, 0, L_FIX}, // "?SprmSBCustomize 163"
+ {164, 2, L_FIX}, // "sprmSXaPage" sep.xaPage xa word
+ {165, 2, L_FIX}, // "sprmSYaPage" sep.yaPage ya word
+ {166, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft dxa word
+ {167, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight dxa word
+ {168, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop dya word
+ {169, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom dya word
+ {170, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter dza word
+ {171, 2, L_FIX}, // "sprmSDMPaperReq" sep.dmPaperReq dm word
+ {179, 0, L_VAR}, // rtl property ?
+ {181, 0, L_VAR}, // rtl property ?
+ {182, 2, L_FIX}, // "sprmTJc" tap.jc jc (low order byte is significant)
+ {183, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter dxa word
+ {184, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf, tap.rgdxaCenter
+ {185, 1, L_FIX}, // "sprmTFCantSplit" tap.fCantSplit 1 or 0 byte
+ {186, 1, L_FIX}, // "sprmTTableHeader" tap.fTableHeader 1 or 0 byte
+ {187,12, L_FIX}, // "sprmTTableBorders" tap.rgbrcTable complex 12 bytes
+ {188, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter, tap.rgtc complex
+ {189, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight dya word
+ {190, 0, L_VAR2},// "sprmTDefTable" tap.rgtc complex
+ {191, 1, L_VAR}, // "sprmTDefTableShd" tap.rgshd complex
+ {192, 4, L_FIX}, // "sprmTTlp" tap.tlp TLP 4 bytes
+ {193, 5, L_FIX}, // "sprmTSetBrc" tap.rgtc[].rgbrc complex 5 bytes
+ {194, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter,tap.rgtc complex
+ {195, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc complex
+ {196, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter complex
+ {197, 2, L_FIX}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged complex
+ {198, 2, L_FIX}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged complex
+ {199, 5, L_FIX}, // "sprmTSetBrc10" tap.rgtc[].rgbrc complex 5 bytes
+ {200, 4, L_FIX}, // "sprmTSetShd", tap.rgshd complex 4 bytes
+ {207, 0, L_VAR} // rtl property ?
+ };
+
+ static wwSprmSearcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms));
+ return &aSprmSrch;
+};
+
+const wwSprmSearcher *wwSprmParser::GetWW8SprmSearcher()
+{
+ //double lock me
+ //WW8+ Sprms
+ static const SprmInfo aSprms[] =
+ {
+ { 0, 0, L_FIX}, // "Default-sprm"/ wird uebersprungen
+ {0x4600, 2, L_FIX}, // "sprmPIstd" pap.istd;istd (style code);short;
+ {0xC601, 0, L_VAR}, // "sprmPIstdPermute" pap.istd;permutation vector
+ {0x2602, 1, L_FIX}, // "sprmPIncLvl" pap.istd, pap.lvl;difference
+ // between istd of base PAP and istd of PAP to be
+ // produced
+ {0x2403, 1, L_FIX}, // "sprmPJc" pap.jc;jc (justification);byte;
+ {0x2404, 1, L_FIX}, // "sprmPFSideBySide" pap.fSideBySide;0 or 1;byte;
+ {0x2405, 1, L_FIX}, // "sprmPFKeep" pap.fKeep;0 or 1;byte;
+ {0x2406, 1, L_FIX}, // "sprmPFKeepFollow" pap.fKeepFollow;0 or 1;byte;
+ {0x2407, 1, L_FIX}, // "sprmPFPageBreakBefore" pap.fPageBreakBefore;
+ // 0 or 1
+ {0x2408, 1, L_FIX}, // "sprmPBrcl" pap.brcl;brcl;byte;
+ {0x2409, 1, L_FIX}, // "sprmPBrcp" pap.brcp;brcp;byte;
+ {0x260A, 1, L_FIX}, // "sprmPIlvl" pap.ilvl;ilvl;byte;
+ {0x460B, 2, L_FIX}, // "sprmPIlfo" pap.ilfo;ilfo (list index) ;short;
+ {0x240C, 1, L_FIX}, // "sprmPFNoLineNumb" pap.fNoLnn;0 or 1;byte;
+ {0xC60D, 0, L_VAR}, // "sprmPChgTabsPapx" pap.itbdMac, pap.rgdxaTab,
+ // pap.rgtbd;complex
+ {0x840E, 2, L_FIX}, // "sprmPDxaRight" pap.dxaRight;dxa;word;
+ {0x840F, 2, L_FIX}, // "sprmPDxaLeft" pap.dxaLeft;dxa;word;
+ {0x4610, 2, L_FIX}, // "sprmPNest" pap.dxaLeft;dxa
+ {0x8411, 2, L_FIX}, // "sprmPDxaLeft1" pap.dxaLeft1;dxa;word;
+ {0x6412, 4, L_FIX}, // "sprmPDyaLine" pap.lspd;an LSPD, a long word
+ // structure consisting of a short of dyaLine
+ // followed by a short of fMultLinespace
+ {0xA413, 2, L_FIX}, // "sprmPDyaBefore" pap.dyaBefore;dya;word;
+ {0xA414, 2, L_FIX}, // "sprmPDyaAfter" pap.dyaAfter;dya;word;
+ {0xC615, 0, L_VAR}, // "sprmPChgTabs" pap.itbdMac, pap.rgdxaTab,
+ // pap.rgtbd;complex
+ {0x2416, 1, L_FIX}, // "sprmPFInTable" pap.fInTable;0 or 1;byte;
+ {0x2417, 1, L_FIX}, // "sprmPFTtp" pap.fTtp;0 or 1;byte;
+ {0x8418, 2, L_FIX}, // "sprmPDxaAbs" pap.dxaAbs;dxa;word;
+ {0x8419, 2, L_FIX}, // "sprmPDyaAbs" pap.dyaAbs;dya;word;
+ {0x841A, 2, L_FIX}, // "sprmPDxaWidth" pap.dxaWidth;dxa;word;
+ {0x261B, 1, L_FIX}, // "sprmPPc" pap.pcHorz, pap.pcVert;complex
+ {0x461C, 2, L_FIX}, // "sprmPBrcTop10" pap.brcTop;BRC10;word;
+ {0x461D, 2, L_FIX}, // "sprmPBrcLeft10" pap.brcLeft;BRC10;word;
+ {0x461E, 2, L_FIX}, // "sprmPBrcBottom10" pap.brcBottom;BRC10;word;
+ {0x461F, 2, L_FIX}, // "sprmPBrcRight10" pap.brcRight;BRC10;word;
+ {0x4620, 2, L_FIX}, // "sprmPBrcBetween10" pap.brcBetween;BRC10;word;
+ {0x4621, 2, L_FIX}, // "sprmPBrcBar10" pap.brcBar;BRC10;word;
+ {0x4622, 2, L_FIX}, // "sprmPDxaFromText10" pap.dxaFromText;dxa;word;
+ {0x2423, 1, L_FIX}, // "sprmPWr" pap.wr;wr
+ {0x6424, 4, L_FIX}, // "sprmPBrcTop" pap.brcTop;BRC;long;
+ {0x6425, 4, L_FIX}, // "sprmPBrcLeft" pap.brcLeft;BRC;long;
+ {0x6426, 4, L_FIX}, // "sprmPBrcBottom" pap.brcBottom;BRC;long;
+ {0x6427, 4, L_FIX}, // "sprmPBrcRight" pap.brcRight;BRC;long;
+ {0x6428, 4, L_FIX}, // "sprmPBrcBetween" pap.brcBetween;BRC;long;
+ {0x6629, 4, L_FIX}, // "sprmPBrcBar" pap.brcBar;BRC;long;
+ {0x242A, 1, L_FIX}, // "sprmPFNoAutoHyph" pap.fNoAutoHyph;0 or 1;byte;
+ {0x442B, 2, L_FIX}, // "sprmPWHeightAbs" pap.wHeightAbs;w;word;
+ {0x442C, 2, L_FIX}, // "sprmPDcs" pap.dcs;DCS;short;
+ {0x442D, 2, L_FIX}, // "sprmPShd" pap.shd;SHD;word;
+ {0x842E, 2, L_FIX}, // "sprmPDyaFromText" pap.dyaFromText;dya;word;
+ {0x842F, 2, L_FIX}, // "sprmPDxaFromText" pap.dxaFromText;dxa;word;
+ {0x2430, 1, L_FIX}, // "sprmPFLocked" pap.fLocked;0 or 1;byte;
+ {0x2431, 1, L_FIX}, // "sprmPFWidowControl" pap.fWidowControl;0 or 1
+ {0xC632, 0, L_VAR}, // "sprmPRuler" ;;variable length;
+ {0x2433, 1, L_FIX}, // "sprmPFKinsoku" pap.fKinsoku;0 or 1;byte;
+ {0x2434, 1, L_FIX}, // "sprmPFWordWrap" pap.fWordWrap;0 or 1;byte;
+ {0x2435, 1, L_FIX}, // "sprmPFOverflowPunct" pap.fOverflowPunct;0 or 1
+ {0x2436, 1, L_FIX}, // "sprmPFTopLinePunct" pap.fTopLinePunct;0 or 1
+ {0x2437, 1, L_FIX}, // "sprmPFAutoSpaceDE" pap.fAutoSpaceDE;0 or 1
+ {0x2438, 1, L_FIX}, // "sprmPFAutoSpaceDN" pap.fAutoSpaceDN;0 or 1
+ {0x4439, 2, L_FIX}, // "sprmPWAlignFont" pap.wAlignFont;iFa
+ {0x443A, 2, L_FIX}, // "sprmPFrameTextFlow" pap.fVertical pap.fBackward
+ // pap.fRotateFont;complex
+ {0x243B, 1, L_FIX}, // "sprmPISnapBaseLine" obsolete: not applicable in
+ // Word97 and later versions;
+ {0xC63E, 0, L_VAR}, // "sprmPAnld" pap.anld;;variable length;
+ {0xC63F, 0, L_VAR}, // "sprmPPropRMark" pap.fPropRMark;complex
+ {0x2640, 1, L_FIX}, // "sprmPOutLvl" pap.lvl;has no effect if pap.istd
+ // is < 1 or is > 9
+ {0x2441, 1, L_FIX}, // "sprmPFBiDi" ;;byte;
+ {0x2443, 1, L_FIX}, // "sprmPFNumRMIns" pap.fNumRMIns;1 or 0;bit;
+ {0x2444, 1, L_FIX}, // "sprmPCrLf" ;;byte;
+ {0xC645, 0, L_VAR}, // "sprmPNumRM" pap.numrm;;variable length;
+ {0x6645, 4, L_FIX}, // "sprmPHugePapx" fc in the data stream to locate
+ // the huge grpprl
+ {0x6646, 4, L_FIX}, // "sprmPHugePapx" fc in the data stream to locate
+ // the huge grpprl
+ {0x2447, 1, L_FIX}, // "sprmPFUsePgsuSettings" pap.fUsePgsuSettings;
+ // 1 or 0
+ {0x2448, 1, L_FIX}, // "sprmPFAdjustRight" pap.fAdjustRight;1 or 0;byte;
+ {0x0800, 1, L_FIX}, // "sprmCFRMarkDel" chp.fRMarkDel;1 or 0;bit;
+ {0x0801, 1, L_FIX}, // "sprmCFRMark" chp.fRMark;1 or 0;bit;
+ {0x0802, 1, L_FIX}, // "sprmCFFldVanish" chp.fFldVanish;1 or 0;bit;
+ {0x6A03, 4, L_FIX}, // "sprmCPicLocation" chp.fcPic and chp.fSpec;
+ {0x4804, 2, L_FIX}, // "sprmCIbstRMark" chp.ibstRMark;index into
+ // sttbRMark
+ {0x6805, 4, L_FIX}, // "sprmCDttmRMark" chp.dttmRMark;DTTM;long;
+ {0x0806, 1, L_FIX}, // "sprmCFData" chp.fData;1 or 0;bit;
+ {0x4807, 2, L_FIX}, // "sprmCIdslRMark" chp.idslRMReason;an index to a
+ // table of strings defined in Word 6.0
+ // executables;short;
+ {0xEA08, 1, L_FIX}, // "sprmCChs" chp.fChsDiff and chp.chse;
+ {0x6A09, 4, L_FIX}, // "sprmCSymbol" chp.fSpec, chp.xchSym and
+ // chp.ftcSym
+ {0x080A, 1, L_FIX}, // "sprmCFOle2" chp.fOle2;1 or 0;bit;
+ {0x480B, 0, L_FIX}, // "sprmCIdCharType" obsolete: not applicable in
+ // Word97 and later versions;;;
+ {0x2A0C, 1, L_FIX}, // "sprmCHighlight" chp.fHighlight,
+ // chp.icoHighlight;ico (fHighlight is set to 1 iff
+ // ico is not 0)
+ {0x680E, 4, L_FIX}, // "sprmCObjLocation" chp.fcObj;FC;long;
+ {0x2A10, 0, L_FIX}, // "sprmCFFtcAsciSymb" ;;;
+ {0x4A30, 2, L_FIX}, // "sprmCIstd" chp.istd;istd, see stylesheet def
+ {0xCA31, 0, L_VAR}, // "sprmCIstdPermute" chp.istd;permutation vector
+ {0x2A32, 0, L_VAR}, // "sprmCDefault" whole CHP;none;variable length;
+ {0x2A33, 0, L_FIX}, // "sprmCPlain" whole CHP;none;0;
+ {0x2A34, 1, L_FIX}, // "sprmCKcd" ;;;
+ {0x0835, 1, L_FIX}, // "sprmCFBold" chp.fBold;0,1, 128, or 129
+ {0x0836, 1, L_FIX}, // "sprmCFItalic" chp.fItalic;0,1, 128, or 129
+ {0x0837, 1, L_FIX}, // "sprmCFStrike" chp.fStrike;0,1, 128, or 129
+ {0x0838, 1, L_FIX}, // "sprmCFOutline" chp.fOutline;0,1, 128, or 129
+ {0x0839, 1, L_FIX}, // "sprmCFShadow" chp.fShadow;0,1, 128, or 129
+ {0x083A, 1, L_FIX}, // "sprmCFSmallCaps" chp.fSmallCaps;0,1, 128, or 129
+ {0x083B, 1, L_FIX}, // "sprmCFCaps" chp.fCaps;0,1, 128, or 129
+ {0x083C, 1, L_FIX}, // "sprmCFVanish" chp.fVanish;0,1, 128, or 129
+ {0x4A3D, 2, L_FIX}, // "sprmCFtcDefault" ;ftc, only used internally
+ {0x2A3E, 1, L_FIX}, // "sprmCKul" chp.kul;kul;byte;
+ {0xEA3F, 3, L_FIX}, // "sprmCSizePos" chp.hps, chp.hpsPos;3 bytes;
+ {0x8840, 2, L_FIX}, // "sprmCDxaSpace" chp.dxaSpace;dxa;word;
+ {0x4A41, 2, L_FIX}, // "sprmCLid" ;only used internally never stored
+ {0x2A42, 1, L_FIX}, // "sprmCIco" chp.ico;ico;byte;
+ {0x4A43, 2, L_FIX}, // "sprmCHps" chp.hps;hps
+ {0x2A44, 1, L_FIX}, // "sprmCHpsInc" chp.hps;
+ {0x4845, 2, L_FIX}, // "sprmCHpsPos" chp.hpsPos;hps;short; (doc wrong)
+ {0x2A46, 1, L_FIX}, // "sprmCHpsPosAdj" chp.hpsPos;hps
+ {0xCA47, 0, L_VAR}, // "sprmCMajority" chp.fBold, chp.fItalic,
+ // chp.fSmallCaps, chp.fVanish, chp.fStrike,
+ // chp.fCaps, chp.rgftc, chp.hps, chp.hpsPos,
+ // chp.kul, chp.dxaSpace, chp.ico,
+ // chp.rglid;complex;variable length, length byte
+ // plus size of following grpprl;
+ {0x2A48, 1, L_FIX}, // "sprmCIss" chp.iss;iss;byte;
+ {0xCA49, 0, L_VAR}, // "sprmCHpsNew50" chp.hps;hps;variable width
+ {0xCA4A, 0, L_VAR}, // "sprmCHpsInc1" chp.hps;complex
+ {0x484B, 2, L_FIX}, // "sprmCHpsKern" chp.hpsKern;hps;short;
+ {0xCA4C, 2, L_FIX}, // "sprmCMajority50" chp.fBold, chp.fItalic,
+ // chp.fSmallCaps, chp.fVanish, chp.fStrike,
+ // chp.fCaps, chp.ftc, chp.hps, chp.hpsPos, chp.kul,
+ // chp.dxaSpace, chp.ico,;complex
+ {0x4A4D, 2, L_FIX}, // "sprmCHpsMul" chp.hps;percentage to grow hps
+ {0x484E, 2, L_FIX}, // "sprmCYsri" chp.ysri;ysri;short;
+ {0x4A4F, 2, L_FIX}, // "sprmCRgFtc0" chp.rgftc[0];ftc for ASCII text
+ {0x4A50, 2, L_FIX}, // "sprmCRgFtc1" chp.rgftc[1];ftc for Far East text
+ {0x4A51, 2, L_FIX}, // "sprmCRgFtc2" chp.rgftc[2];ftc for non-FE text
+ {0x4852, 2, L_FIX}, // "sprmCCharScale"
+ {0x2A53, 1, L_FIX}, // "sprmCFDStrike" chp.fDStrike;;byte;
+ {0x0854, 1, L_FIX}, // "sprmCFImprint" chp.fImprint;1 or 0;bit;
+ {0x0855, 1, L_FIX}, // "sprmCFSpec" chp.fSpec ;1 or 0;bit;
+ {0x0856, 1, L_FIX}, // "sprmCFObj" chp.fObj;1 or 0;bit;
+ {0xCA57, 0, L_VAR}, // "sprmCPropRMark" chp.fPropRMark,
+ // chp.ibstPropRMark, chp.dttmPropRMark;Complex
+ {0x0858, 1, L_FIX}, // "sprmCFEmboss" chp.fEmboss;1 or 0;bit;
+ {0x2859, 1, L_FIX}, // "sprmCSfxText" chp.sfxtText;text animation;byte;
+ {0x085A, 1, L_FIX}, // "sprmCFBiDi" ;;;
+ {0x085B, 1, L_FIX}, // "sprmCFDiacColor" ;;;
+ {0x085C, 1, L_FIX}, // "sprmCFBoldBi" ;;;
+ {0x085D, 1, L_FIX}, // "sprmCFItalicBi" ;;;
+ {0x4A5E, 2, L_FIX},
+ {0x485F, 2, L_FIX}, // "sprmCLidBi" ;;;
+ {0x4A60, 1, L_FIX}, // "sprmCIcoBi" ;;;
+ {0x4A61, 2, L_FIX}, // "sprmCHpsBi" ;;;
+ {0xCA62, 0, L_VAR}, // "sprmCDispFldRMark" chp.fDispFldRMark,
+ // chp.ibstDispFldRMark, chp.dttmDispFldRMark ;
+ {0x4863, 2, L_FIX}, // "sprmCIbstRMarkDel" chp.ibstRMarkDel;index into
+ // sttbRMark;short;
+ {0x6864, 4, L_FIX}, // "sprmCDttmRMarkDel" chp.dttmRMarkDel;DTTM;long;
+ {0x6865, 4, L_FIX}, // "sprmCBrc" chp.brc;BRC;long;
+ {0x4866, 2, L_FIX}, // "sprmCShd" chp.shd;SHD;short;
+ {0x4867, 2, L_FIX}, // "sprmCIdslRMarkDel" chp.idslRMReasonDel;an index
+ // to a table of strings defined in Word 6.0
+ // executables;short;
+ {0x0868, 1, L_FIX}, // "sprmCFUsePgsuSettings"
+ // chp.fUsePgsuSettings;1 or 0
+ {0x486B, 2, L_FIX}, // "sprmCCpg" ;;word;
+ {0x486D, 2, L_FIX}, // "sprmCRgLid0_80" chp.rglid[0];LID: for non-FE text
+ {0x486E, 2, L_FIX}, // "sprmCRgLid1_80" chp.rglid[1];LID: for Far East text
+ {0x286F, 1, L_FIX}, // "sprmCIdctHint" chp.idctHint;IDCT:
+ {0x2E00, 1, L_FIX}, // "sprmPicBrcl" pic.brcl;brcl (see PIC definition)
+ {0xCE01, 0, L_VAR}, // "sprmPicScale" pic.mx, pic.my, pic.dxaCropleft,
+ // pic.dyaCropTop pic.dxaCropRight,
+ // pic.dyaCropBottom;Complex
+ {0x6C02, 4, L_FIX}, // "sprmPicBrcTop" pic.brcTop;BRC;long;
+ {0x6C03, 4, L_FIX}, // "sprmPicBrcLeft" pic.brcLeft;BRC;long;
+ {0x6C04, 4, L_FIX}, // "sprmPicBrcBottom" pic.brcBottom;BRC;long;
+ {0x6C05, 4, L_FIX}, // "sprmPicBrcRight" pic.brcRight;BRC;long;
+ {0x3000, 1, L_FIX}, // "sprmScnsPgn" sep.cnsPgn;cns;byte;
+ {0x3001, 1, L_FIX}, // "sprmSiHeadingPgn" sep.iHeadingPgn;heading number
+ // level;byte;
+ {0xD202, 0, L_VAR}, // "sprmSOlstAnm" sep.olstAnm;OLST;variable length;
+ {0xF203, 3, L_FIX}, // "sprmSDxaColWidth" sep.rgdxaColWidthSpacing;
+ {0xF204, 3, L_FIX}, // "sprmSDxaColSpacing" sep.rgdxaColWidthSpacing;
+ // complex
+ {0x3005, 1, L_FIX}, // "sprmSFEvenlySpaced" sep.fEvenlySpaced;1 or 0
+ {0x3006, 1, L_FIX}, // "sprmSFProtected" sep.fUnlocked;1 or 0;byte;
+ {0x5007, 2, L_FIX}, // "sprmSDmBinFirst" sep.dmBinFirst;;word;
+ {0x5008, 2, L_FIX}, // "sprmSDmBinOther" sep.dmBinOther;;word;
+ {0x3009, 1, L_FIX}, // "sprmSBkc" sep.bkc;bkc;byte;
+ {0x300A, 1, L_FIX}, // "sprmSFTitlePage" sep.fTitlePage;0 or 1;byte;
+ {0x500B, 2, L_FIX}, // "sprmSCcolumns" sep.ccolM1;# of cols - 1;word;
+ {0x900C, 2, L_FIX}, // "sprmSDxaColumns" sep.dxaColumns;dxa;word;
+ {0x300D, 1, L_FIX}, // "sprmSFAutoPgn" sep.fAutoPgn;obsolete;byte;
+ {0x300E, 1, L_FIX}, // "sprmSNfcPgn" sep.nfcPgn;nfc;byte;
+ {0xB00F, 2, L_FIX}, // "sprmSDyaPgn" sep.dyaPgn;dya;short;
+ {0xB010, 2, L_FIX}, // "sprmSDxaPgn" sep.dxaPgn;dya;short;
+ {0x3011, 1, L_FIX}, // "sprmSFPgnRestart" sep.fPgnRestart;0 or 1;byte;
+ {0x3012, 1, L_FIX}, // "sprmSFEndnote" sep.fEndnote;0 or 1;byte;
+ {0x3013, 1, L_FIX}, // "sprmSLnc" sep.lnc;lnc;byte;
+ {0x3014, 1, L_FIX}, // "sprmSGprfIhdt" sep.grpfIhdt;grpfihdt
+ {0x5015, 2, L_FIX}, // "sprmSNLnnMod" sep.nLnnMod;non-neg int.;word;
+ {0x9016, 2, L_FIX}, // "sprmSDxaLnn" sep.dxaLnn;dxa;word;
+ {0xB017, 2, L_FIX}, // "sprmSDyaHdrTop" sep.dyaHdrTop;dya;word;
+ {0xB018, 2, L_FIX}, // "sprmSDyaHdrBottom" sep.dyaHdrBottom;dya;word;
+ {0x3019, 1, L_FIX}, // "sprmSLBetween" sep.fLBetween;0 or 1;byte;
+ {0x301A, 1, L_FIX}, // "sprmSVjc" sep.vjc;vjc;byte;
+ {0x501B, 2, L_FIX}, // "sprmSLnnMin" sep.lnnMin;lnn;word;
+ {0x501C, 2, L_FIX}, // "sprmSPgnStart" sep.pgnStart;pgn;word;
+ {0x301D, 1, L_FIX}, // "sprmSBOrientation" sep.dmOrientPage;dm;byte;
+ {0x301E, 1, L_FIX}, // "sprmSBCustomize" ;;;
+ {0xB01F, 2, L_FIX}, // "sprmSXaPage" sep.xaPage;xa;word;
+ {0xB020, 2, L_FIX}, // "sprmSYaPage" sep.yaPage;ya;word;
+ {0xB021, 2, L_FIX}, // "sprmSDxaLeft" sep.dxaLeft;dxa;word;
+ {0xB022, 2, L_FIX}, // "sprmSDxaRight" sep.dxaRight;dxa;word;
+ {0x9023, 2, L_FIX}, // "sprmSDyaTop" sep.dyaTop;dya;word;
+ {0x9024, 2, L_FIX}, // "sprmSDyaBottom" sep.dyaBottom;dya;word;
+ {0xB025, 2, L_FIX}, // "sprmSDzaGutter" sep.dzaGutter;dza;word;
+ {0x5026, 2, L_FIX}, // "sprmSDmPaperReq" sep.dmPaperReq;dm;word;
+ {0xD227, 0, L_VAR}, // "sprmSPropRMark" sep.fPropRMark,
+ // sep.ibstPropRMark, sep.dttmPropRMark ;complex
+ {0x3228, 1, L_FIX}, // "sprmSFBiDi" ;;;
+ {0x3229, 1, L_FIX}, // "sprmSFFacingCol" ;;;
+ {0x322A, 1, L_FIX}, // "sprmSFRTLGutter", set to one if gutter is on
+ // right
+ {0x702B, 4, L_FIX}, // "sprmSBrcTop" sep.brcTop;BRC;long;
+ {0x702C, 4, L_FIX}, // "sprmSBrcLeft" sep.brcLeft;BRC;long;
+ {0x702D, 4, L_FIX}, // "sprmSBrcBottom" sep.brcBottom;BRC;long;
+ {0x702E, 4, L_FIX}, // "sprmSBrcRight" sep.brcRight;BRC;long;
+ {0x522F, 2, L_FIX}, // "sprmSPgbProp" sep.pgbProp;;word;
+ {0x7030, 4, L_FIX}, // "sprmSDxtCharSpace" sep.dxtCharSpace;dxt;long;
+ {0x9031, 2, L_FIX}, // "sprmSDyaLinePitch"
+ // sep.dyaLinePitch;dya; WRONG:long; RIGHT:short; !
+ {0x5032, 2, L_FIX}, // "sprmSClm" ;;;
+ {0x5033, 2, L_FIX}, // "sprmSTextFlow" sep.wTextFlow;complex
+ {0x5400, 2, L_FIX}, // "sprmTJc" tap.jc;jc;word (low order byte is
+ // significant);
+ {0x9601, 2, L_FIX}, // "sprmTDxaLeft" tap.rgdxaCenter
+ {0x9602, 2, L_FIX}, // "sprmTDxaGapHalf" tap.dxaGapHalf,
+ // tap.rgdxaCenter
+ {0x3403, 1, L_FIX}, // "sprmTFCantSplit" tap.fCantSplit;1 or 0;byte;
+ {0x3404, 1, L_FIX}, // "sprmTTableHeader" tap.fTableHeader;1 or 0;byte;
+ {0x3466, 1, L_FIX}, // "sprmTFCantSplit90" tap.fCantSplit90;1 or 0;byte;
+ {0xD605, 0, L_VAR}, // "sprmTTableBorders" tap.rgbrcTable;complex
+ {0xD606, 0, L_VAR}, // "sprmTDefTable10" tap.rgdxaCenter,
+ // tap.rgtc;complex
+ {0x9407, 2, L_FIX}, // "sprmTDyaRowHeight" tap.dyaRowHeight;dya;word;
+ {0xD608, 0, L_VAR}, // "sprmTDefTable" tap.rgtc;complex
+ {0xD609, 0, L_VAR}, // "sprmTDefTableShd" tap.rgshd;complex
+ {0x740A, 4, L_FIX}, // "sprmTTlp" tap.tlp;TLP;4 bytes;
+ {0x560B, 2, L_FIX}, // "sprmTFBiDi" ;;;
+ {0x740C, 1, L_FIX}, // "sprmTHTMLProps" ;;;
+ {0xD620, 0, L_VAR}, // "sprmTSetBrc" tap.rgtc[].rgbrc;complex
+ {0x7621, 4, L_FIX}, // "sprmTInsert" tap.rgdxaCenter, tap.rgtc;complex
+ {0x5622, 2, L_FIX}, // "sprmTDelete" tap.rgdxaCenter, tap.rgtc;complex
+ {0x7623, 4, L_FIX}, // "sprmTDxaCol" tap.rgdxaCenter;complex
+ {0x5624, 0, L_VAR}, // "sprmTMerge" tap.fFirstMerged, tap.fMerged;
+ {0x5625, 0, L_VAR}, // "sprmTSplit" tap.fFirstMerged, tap.fMerged;
+ {0xD626, 0, L_VAR}, // "sprmTSetBrc10" tap.rgtc[].rgbrc;complex
+ {0x7627, 0, L_VAR}, // "sprmTSetShd" tap.rgshd;complex
+ {0x7628, 0, L_VAR}, // "sprmTSetShdOdd" tap.rgshd;complex
+ {0x7629, 4, L_FIX}, // "sprmTTextFlow" tap.rgtc[].fVerticaltap,
+ // rgtc[].fBackwardtap, rgtc[].fRotateFont;0 or 10
+ // or 10 or 1;word;
+ {0xD62A, 1, L_FIX}, // "sprmTDiagLine" ;;;
+ {0xD62B, 0, L_VAR}, // "sprmTVertMerge" tap.rgtc[].vertMerge
+ {0xD62C, 0, L_VAR}, // "sprmTVertAlign" tap.rgtc[].vertAlign
+ {0xCA78, 0, L_VAR}, // undocumented "sprmCDoubleLine ?"
+ {0x6649, 4, L_FIX}, // undocumented
+ {0xF614, 3, L_FIX}, // undocumented
+ {0xD612, 0, L_VAR}, // undocumented, new background colours.
+ {0xD613, 0, L_VAR}, // undocumented
+ {0xD61A, 0, L_VAR}, // undocumented
+ {0xD61B, 0, L_VAR}, // undocumented
+ {0xD61C, 0, L_VAR}, // undocumented
+ {0xD61D, 0, L_VAR}, // undocumented
+ {0xD632, 0, L_VAR}, // undocumented
+ {0xD634, 0, L_VAR}, // undocumented
+ {0xD238, 0, L_VAR}, // undocumented sep
+ {0xC64E, 0, L_VAR}, // undocumented
+ {0xC64F, 0, L_VAR}, // undocumented
+ {0xC650, 0, L_VAR}, // undocumented
+ {0xC651, 0, L_VAR}, // undocumented
+ {0xF661, 3, L_FIX}, // undocumented
+ {0x4873, 2, L_FIX}, // "sprmCRgLid0" chp.rglid[0];LID: for non-FE text
+ {0x4874, 2, L_FIX}, // "sprmCRgLid1" chp.rglid[1];LID: for Far East text
+ {0x6463, 4, L_FIX}, // undocumented
+ {0x2461, 1, L_FIX}, // undoc, must be asian version of "sprmPJc"
+ {0x845D, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaRight"
+ {0x845E, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaLeft"
+ {0x8460, 2, L_FIX}, // undoc, must be asian version of "sprmPDxaLeft1"
+ {0x3615, 1, L_FIX}, // undocumented
+ {0x360D, 1, L_FIX}, // undocumented
+ {0x703A, 4, L_FIX}, // undocumented, sep, perhaps related to textgrids ?
+ {0x303B, 1, L_FIX}, // undocumented, sep
+ {0x244B, 1, L_FIX}, // undocumented, subtable "sprmPFInTable" equiv ?
+ {0x244C, 1, L_FIX}, // undocumented, subtable "sprmPFTtp" equiv ?
+ {0x940E, 2, L_FIX}, // undocumented
+ {0x940F, 2, L_FIX}, // undocumented
+ {0x9410, 2, L_FIX}, // undocumented
+ {0x6815, 4, L_FIX}, // undocumented
+ {0x6816, 4, L_FIX}, // undocumented
+ {0x6870, 4, L_FIX}, // undocumented, text colour
+ {0xC64D, 0, L_VAR}, // undocumented, para back colour
+ {0x6467, 4, L_FIX}, // undocumented
+ {0x646B, 4, L_FIX}, // undocumented
+ {0xF617, 3, L_FIX}, // undocumented
+ {0xD660, 0, L_VAR}, // undocumented, something to do with colour.
+ {0xD670, 0, L_VAR}, // undocumented, something to do with colour.
+ {0xCA71, 0, L_VAR}, // undocumented, text backcolour
+ {0x303C, 1, L_FIX}, // undocumented, sep
+ {0x245B, 1, L_FIX}, // undocumented, para autobefore
+ {0x245C, 1, L_FIX}, // undocumented, para autoafter
+ // undocumented, don't add space between para of the same style
+ {0x246D, 1, L_FIX}
+ };
+
+ static wwSprmSearcher aSprmSrch(aSprms, SAL_N_ELEMENTS(aSprms));
+ return &aSprmSrch;
+};
+
+wwSprmParser::wwSprmParser(ww::WordVersion eVersion) : meVersion(eVersion)
+{
+ OSL_ENSURE((meVersion >= ww::eWW2 && meVersion <= ww::eWW8),
+ "Impossible value for version");
+
+ mnDelta = (ww::IsSevenMinus(meVersion)) ? 0 : 1;
+
+ if (meVersion <= ww::eWW2)
+ mpKnownSprms = GetWW2SprmSearcher();
+ else if (meVersion < ww::eWW8)
+ mpKnownSprms = GetWW6SprmSearcher();
+ else
+ mpKnownSprms = GetWW8SprmSearcher();
+}
+
+SprmInfo wwSprmParser::GetSprmInfo(sal_uInt16 nId) const
+{
+ // Find sprm
+ SprmInfo aSrch={0,0,0};
+ aSrch.nId = nId;
+ const SprmInfo* pFound = mpKnownSprms->search(aSrch);
+ if (pFound == 0)
+ {
+ OSL_ENSURE(ww::IsEightPlus(meVersion),
+ "Unknown ww7- sprm, dangerous, report to development");
+
+ aSrch.nId = 0;
+ aSrch.nLen = 0;
+ //All the unknown ww7 sprms appear to be variable (which makes sense)
+ aSrch.nVari = L_VAR;
+
+ if (ww::IsEightPlus(meVersion)) //We can recover perfectly in this case
+ {
+ aSrch.nVari = L_FIX;
+ switch (nId >> 13)
+ {
+ case 0:
+ case 1:
+ aSrch.nLen = 1;
+ break;
+ case 2:
+ aSrch.nLen = 2;
+ break;
+ case 3:
+ aSrch.nLen = 4;
+ break;
+ case 4:
+ case 5:
+ aSrch.nLen = 2;
+ break;
+ case 6:
+ aSrch.nLen = 0;
+ aSrch.nVari = L_VAR;
+ break;
+ case 7:
+ default:
+ aSrch.nLen = 3;
+ break;
+ }
+ }
+
+ pFound = &aSrch;
+ }
+ return *pFound;
+}
+
+//-end
+
+inline sal_uInt8 Get_Byte( sal_uInt8 *& p )
+{
+ sal_uInt8 n = SVBT8ToByte( *(SVBT8*)p );
+ p += 1;
+ return n;
+}
+
+inline sal_uInt16 Get_UShort( sal_uInt8 *& p )
+{
+ sal_uInt16 n = SVBT16ToShort( *(SVBT16*)p );
+ p += 2;
+ return n;
+}
+
+inline short Get_Short( sal_uInt8 *& p )
+{
+ return Get_UShort(p);
+}
+
+inline sal_uLong Get_ULong( sal_uInt8 *& p )
+{
+ sal_uLong n = SVBT32ToUInt32( *(SVBT32*)p );
+ p += 4;
+ return n;
+}
+
+inline long Get_Long( sal_uInt8 *& p )
+{
+ return Get_ULong(p);
+}
+
+WW8SprmIter::WW8SprmIter(const sal_uInt8* pSprms_, long nLen_,
+ const wwSprmParser &rParser)
+ : mrSprmParser(rParser), pSprms( pSprms_), nRemLen( nLen_)
+{
+ UpdateMyMembers();
+}
+
+void WW8SprmIter::SetSprms(const sal_uInt8* pSprms_, long nLen_)
+{
+ pSprms = pSprms_;
+ nRemLen = nLen_;
+ UpdateMyMembers();
+}
+
+void WW8SprmIter::advance()
+{
+ if (nRemLen > 0 )
+ {
+ sal_uInt16 nSize = nAktSize;
+ if (nSize > nRemLen)
+ nSize = nRemLen;
+ pSprms += nSize;
+ nRemLen -= nSize;
+ UpdateMyMembers();
+ }
+}
+
+void WW8SprmIter::UpdateMyMembers()
+{
+ if (pSprms && nRemLen > (mrSprmParser.getVersion()?1:0))
+ {
+ nAktId = mrSprmParser.GetSprmId(pSprms);
+ pAktParams = pSprms + mrSprmParser.DistanceToData(nAktId);
+ nAktSize = mrSprmParser.GetSprmSize(nAktId, pSprms);
+ }
+ else
+ {
+ nAktId = 0;
+ pAktParams = 0;
+ nAktSize = 0;
+ nRemLen = 0;
+ }
+}
+
+const sal_uInt8* WW8SprmIter::FindSprm(sal_uInt16 nId)
+{
+ while(GetSprms())
+ {
+ if( GetAktId() == nId )
+ return GetAktParams(); // SPRM found!
+ advance();
+ }
+
+ return 0; // SPRM _not_ found
+}
+
+//-----------------------------------------
+// temporaerer Test
+//-----------------------------------------
+// WW8PLCFx_PCDAttrs halten sich an WW8PLCF_Pcd fest und besitzen deshalb keine
+// eigenen Iteratoren. Alle sich auf Iteratoren beziehenden Methoden
+// sind deshalb Dummies.
+
+WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(ww::WordVersion eVersion,
+ WW8PLCFx_PCD* pPLCFx_PCD, const WW8ScannerBase* pBase)
+ : WW8PLCFx(eVersion, true), pPcdI(pPLCFx_PCD->GetPLCFIter()),
+ pPcd(pPLCFx_PCD), pGrpprls(pBase->pPieceGrpprls),
+ nGrpprls(pBase->nPieceGrpprls)
+{
+}
+
+sal_uLong WW8PLCFx_PCDAttrs::GetIdx() const
+{
+ return 0;
+}
+
+void WW8PLCFx_PCDAttrs::SetIdx( sal_uLong )
+{
+}
+
+bool WW8PLCFx_PCDAttrs::SeekPos(WW8_CP )
+{
+ return true;
+}
+
+WW8PLCFx& WW8PLCFx_PCDAttrs::operator ++( int )
+{
+ return *this;
+}
+
+WW8_CP WW8PLCFx_PCDAttrs::Where()
+{
+ return ( pPcd ) ? pPcd->Where() : WW8_CP_MAX;
+}
+
+void WW8PLCFx_PCDAttrs::GetSprms(WW8PLCFxDesc* p)
+{
+ void* pData;
+
+ p->bRealLineEnd = false;
+ if ( !pPcdI || !pPcdI->Get(p->nStartPos, p->nEndPos, pData) )
+ {
+ // PLCF fully processed
+ p->nStartPos = p->nEndPos = WW8_CP_MAX;
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ return;
+ }
+
+ sal_uInt16 nPrm = SVBT16ToShort( ( (WW8_PCD*)pData )->prm );
+ if ( nPrm & 1 )
+ {
+ // PRM Variant 2
+ sal_uInt16 nSprmIdx = nPrm >> 1;
+
+ if( nSprmIdx >= nGrpprls )
+ {
+ // Invalid Index
+ p->nStartPos = p->nEndPos = WW8_CP_MAX;
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ return;
+ }
+ const sal_uInt8* pSprms = pGrpprls[ nSprmIdx ];
+
+ p->nSprmsLen = SVBT16ToShort( pSprms ); // Length
+ pSprms += 2;
+ p->pMemPos = pSprms; // Position
+ }
+ else
+ {
+ // PRM Variante 1: Sprm wird direkt in Member-Var abgelegt
+ /*
+ Dies sind die Attr, die in der Piece-Table stehen, statt im Text !
+ */
+
+ if (IsSevenMinus(GetFIBVersion()))
+ {
+ aShortSprm[0] = (sal_uInt8)( ( nPrm & 0xfe) >> 1 );
+ aShortSprm[1] = (sal_uInt8)( nPrm >> 8 );
+ p->nSprmsLen = ( nPrm ) ? 2 : 0; // Laenge
+
+ // store Postion of internal mini storage in Data Pointer
+ p->pMemPos = aShortSprm;
+ }
+ else
+ {
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ sal_uInt8 nSprmListIdx = (sal_uInt8)((nPrm & 0xfe) >> 1);
+ if( nSprmListIdx )
+ {
+ // process Sprm Id Matching as explained in MS Doku
+ //
+ // ''Property Modifier(variant 1) (PRM)''
+ // see file: s62f39.htm
+ //
+ // Since isprm is 7 bits, rgsprmPrm can hold 0x80 entries.
+ static const sal_uInt16 aSprmId[0x80] =
+ {
+ // sprmNoop, sprmNoop, sprmNoop, sprmNoop
+ 0x0000,0x0000,0x0000,0x0000,
+ // sprmPIncLvl, sprmPJc, sprmPFSideBySide, sprmPFKeep
+ 0x2402,0x2403,0x2404,0x2405,
+ // sprmPFKeepFollow, sprmPFPageBreakBefore, sprmPBrcl,
+ // sprmPBrcp
+ 0x2406,0x2407,0x2408,0x2409,
+ // sprmPIlvl, sprmNoop, sprmPFNoLineNumb, sprmNoop
+ 0x260A,0x0000,0x240C,0x0000,
+ // sprmNoop, sprmNoop, sprmNoop, sprmNoop
+ 0x0000,0x0000,0x0000,0x0000,
+ // sprmNoop, sprmNoop, sprmNoop, sprmNoop
+ 0x0000,0x0000,0x0000,0x0000,
+ // sprmPFInTable, sprmPFTtp, sprmNoop, sprmNoop
+ 0x2416,0x2417,0x0000,0x0000,
+ // sprmNoop, sprmPPc, sprmNoop, sprmNoop
+ 0x0000,0x261B,0x0000,0x0000,
+ // sprmNoop, sprmNoop, sprmNoop, sprmNoop
+ 0x0000,0x0000,0x0000,0x0000,
+ // sprmNoop, sprmPWr, sprmNoop, sprmNoop
+ 0x0000,0x2423,0x0000,0x0000,
+ // sprmNoop, sprmNoop, sprmNoop, sprmNoop
+ 0x0000,0x0000,0x0000,0x0000,
+ // sprmPFNoAutoHyph, sprmNoop, sprmNoop, sprmNoop
+ 0x242A,0x0000,0x0000,0x0000,
+ // sprmNoop, sprmNoop, sprmPFLocked, sprmPFWidowControl
+ 0x0000,0x0000,0x2430,0x2431,
+ // sprmNoop, sprmPFKinsoku, sprmPFWordWrap,
+ // sprmPFOverflowPunct
+ 0x0000,0x2433,0x2434,0x2435,
+ // sprmPFTopLinePunct, sprmPFAutoSpaceDE,
+ // sprmPFAutoSpaceDN, sprmNoop
+ 0x2436,0x2437,0x2438,0x0000,
+ // sprmNoop, sprmPISnapBaseLine, sprmNoop, sprmNoop
+ 0x0000,0x243B,0x000,0x0000,
+ // sprmNoop, sprmCFStrikeRM, sprmCFRMark, sprmCFFldVanish
+ 0x0000,0x0800,0x0801,0x0802,
+ // sprmNoop, sprmNoop, sprmNoop, sprmCFData
+ 0x0000,0x0000,0x0000,0x0806,
+ // sprmNoop, sprmNoop, sprmNoop, sprmCFOle2
+ 0x0000,0x0000,0x0000,0x080A,
+ // sprmNoop, sprmCHighlight, sprmCFEmboss, sprmCSfxText
+ 0x0000,0x2A0C,0x0858,0x2859,
+ // sprmNoop, sprmNoop, sprmNoop, sprmCPlain
+ 0x0000,0x0000,0x0000,0x2A33,
+ // sprmNoop, sprmCFBold, sprmCFItalic, sprmCFStrike
+ 0x0000,0x0835,0x0836,0x0837,
+ // sprmCFOutline, sprmCFShadow, sprmCFSmallCaps, sprmCFCaps,
+ 0x0838,0x0839,0x083a,0x083b,
+ // sprmCFVanish, sprmNoop, sprmCKul, sprmNoop,
+ 0x083C,0x0000,0x2A3E,0x0000,
+ // sprmNoop, sprmNoop, sprmCIco, sprmNoop,
+ 0x0000,0x0000,0x2A42,0x0000,
+ // sprmCHpsInc, sprmNoop, sprmCHpsPosAdj, sprmNoop,
+ 0x2A44,0x0000,0x2A46,0x0000,
+ // sprmCIss, sprmNoop, sprmNoop, sprmNoop,
+ 0x2A48,0x0000,0x0000,0x0000,
+ // sprmNoop, sprmNoop, sprmNoop, sprmNoop,
+ 0x0000,0x0000,0x0000,0x0000,
+ // sprmNoop, sprmNoop, sprmNoop, sprmCFDStrike,
+ 0x0000,0x0000,0x0000,0x2A53,
+ // sprmCFImprint, sprmCFSpec, sprmCFObj, sprmPicBrcl,
+ 0x0854,0x0855,0x0856,0x2E00,
+ // sprmPOutLvl, sprmPFBiDi, sprmNoop, sprmNoop,
+ 0x2640,0x2441,0x0000,0x0000,
+ // sprmNoop, sprmNoop, sprmPPnbrRMarkNot
+ 0x0000,0x0000,0x0000,0x0000
+ };
+
+ // find real Sprm Id:
+ sal_uInt16 nSprmId = aSprmId[ nSprmListIdx ];
+
+ if( nSprmId )
+ {
+ // move Sprm Id and Sprm Param to internal mini storage:
+ aShortSprm[0] = (sal_uInt8)( ( nSprmId & 0x00ff) );
+ aShortSprm[1] = (sal_uInt8)( ( nSprmId & 0xff00) >> 8 );
+ aShortSprm[2] = (sal_uInt8)( nPrm >> 8 );
+
+ // store Sprm Length in member:
+ p->nSprmsLen = ( nPrm ) ? 3 : 0;
+
+ // store Postion of internal mini storage in Data Pointer
+ p->pMemPos = aShortSprm;
+ }
+ }
+ }
+ }
+}
+
+//------------------------------------------------------------------------
+
+WW8PLCFx_PCD::WW8PLCFx_PCD(ww::WordVersion eVersion, WW8PLCFpcd* pPLCFpcd,
+ WW8_CP nStartCp, bool bVer67P)
+ : WW8PLCFx(eVersion, false), nClipStart(-1)
+{
+ // eigenen Iterator konstruieren
+ pPcdI = new WW8PLCFpcd_Iter(*pPLCFpcd, nStartCp);
+ bVer67= bVer67P;
+}
+
+WW8PLCFx_PCD::~WW8PLCFx_PCD()
+{
+ // pPcd-Dtor which in called from WW8ScannerBase
+ delete pPcdI;
+}
+
+sal_uLong WW8PLCFx_PCD::GetIMax() const
+{
+ return pPcdI ? pPcdI->GetIMax() : 0;
+}
+
+sal_uLong WW8PLCFx_PCD::GetIdx() const
+{
+ return pPcdI ? pPcdI->GetIdx() : 0;
+}
+
+void WW8PLCFx_PCD::SetIdx( sal_uLong nIdx )
+{
+ if (pPcdI)
+ pPcdI->SetIdx( nIdx );
+}
+
+bool WW8PLCFx_PCD::SeekPos(WW8_CP nCpPos)
+{
+ return pPcdI ? pPcdI->SeekPos( nCpPos ) : false;
+}
+
+WW8_CP WW8PLCFx_PCD::Where()
+{
+ return pPcdI ? pPcdI->Where() : WW8_CP_MAX;
+}
+
+long WW8PLCFx_PCD::GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen )
+{
+ void* pData;
+ rLen = 0;
+
+ if ( !pPcdI || !pPcdI->Get(rStart, rEnd, pData) )
+ {
+ rStart = rEnd = WW8_CP_MAX;
+ return -1;
+ }
+ return pPcdI->GetIdx();
+}
+
+WW8PLCFx& WW8PLCFx_PCD::operator ++( int )
+{
+ if (pPcdI)
+ (*pPcdI)++;
+ else {
+ OSL_ENSURE( !this, "pPcdI fehlt");
+ }
+ return *this;
+}
+
+WW8_FC WW8PLCFx_PCD::AktPieceStartCp2Fc( WW8_CP nCp )
+{
+ WW8_CP nCpStart, nCpEnd;
+ void* pData;
+
+ if ( !pPcdI->Get(nCpStart, nCpEnd, pData) )
+ {
+ OSL_ENSURE( !this, "AktPieceStartCp2Fc() with false Cp found (1)" );
+ return WW8_FC_MAX;
+ }
+
+ OSL_ENSURE( nCp >= nCpStart && nCp < nCpEnd,
+ "AktPieceCp2Fc() with false Cp found (2)" );
+
+ if( nCp < nCpStart )
+ nCp = nCpStart;
+ if( nCp >= nCpEnd )
+ nCp = nCpEnd - 1;
+
+ bool bIsUnicode = false;
+ WW8_FC nFC = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
+ if( !bVer67 )
+ nFC = WW8PLCFx_PCD::TransformPieceAddress( nFC, bIsUnicode );
+
+ return nFC + (nCp - nCpStart) * (bIsUnicode ? 2 : 1);
+}
+
+
+void WW8PLCFx_PCD::AktPieceFc2Cp( WW8_CP& rStartPos, WW8_CP& rEndPos,
+ const WW8ScannerBase *pSBase )
+{
+ //No point going anywhere with this
+ if ((rStartPos == WW8_CP_MAX) && (rEndPos == WW8_CP_MAX))
+ return;
+
+ rStartPos = pSBase->WW8Fc2Cp( rStartPos );
+ rEndPos = pSBase->WW8Fc2Cp( rEndPos );
+}
+
+WW8_CP WW8PLCFx_PCD::AktPieceStartFc2Cp( WW8_FC nStartPos )
+{
+ WW8_CP nCpStart, nCpEnd;
+ void* pData;
+ if ( !pPcdI->Get( nCpStart, nCpEnd, pData ) )
+ {
+ OSL_ENSURE( !this, "AktPieceStartFc2Cp() - Fehler" );
+ return WW8_CP_MAX;
+ }
+ bool bIsUnicode = false;
+ sal_Int32 nFcStart = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
+ if( !bVer67 )
+ nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart, bIsUnicode );
+
+ sal_Int32 nUnicodeFactor = bIsUnicode ? 2 : 1;
+
+ if( nStartPos < nFcStart )
+ nStartPos = nFcStart;
+
+ if( nStartPos >= nFcStart + (nCpEnd - nCpStart) * nUnicodeFactor )
+ nStartPos = nFcStart + (nCpEnd - nCpStart - 1) * nUnicodeFactor;
+
+ return nCpStart + (nStartPos - nFcStart) / nUnicodeFactor;
+}
+
+//-----------------------------------------
+// Hilfsroutinen fuer alle
+//-----------------------------------------
+
+short WW8_BRC::DetermineBorderProperties(bool bVer67, short *pSpace,
+ sal_uInt8 *pCol, short *pIdx) const
+{
+ /*
+ Word does not factor the width of the border into the width/height
+ stored in the information for graphic/table/object widths, so we need
+ to figure out this extra width here and utilize the returned size in
+ our calculations
+ */
+ short nMSTotalWidth;
+ sal_uInt8 nCol;
+ short nIdx,nSpace;
+ if( bVer67 )
+ {
+ sal_uInt16 aBrc1 = SVBT16ToShort(aBits1);
+ nCol = static_cast< sal_uInt8 >((aBrc1 >> 6) & 0x1f); // aBor.ico
+ nSpace = (aBrc1 & 0xF800) >> 11;
+
+ nMSTotalWidth = aBrc1 & 0x07;
+ nIdx = (aBrc1 & 0x18) >> 3;
+ //Dashed/Dotted unsets double/thick
+ if (nMSTotalWidth > 5)
+ {
+ nIdx = nMSTotalWidth;
+ nMSTotalWidth=1;
+ }
+ nMSTotalWidth = nMSTotalWidth * nIdx * 15;
+ }
+ else
+ {
+ nIdx = aBits1[1];
+ nCol = aBits2[0]; // aBor.ico
+ nSpace = aBits2[1] & 0x1F; //space between line and object
+
+ //Specification in 8ths of a point, 1 Point = 20 Twips, so by 2.5
+ nMSTotalWidth = aBits1[ 0 ] * 20 / 8;
+
+ //Figure out the real size of the border according to word
+ switch (nIdx)
+ {
+ //Note that codes over 25 are undocumented, and I can't create
+ //these 4 here in the wild.
+ case 2:
+ case 4:
+ case 5:
+ case 22:
+ DBG_WARNING("Can't create these from the menus, please report");
+ default:
+ case 23: //Only 3pt in the menus, but honours the size setting.
+ break;
+ case 10:
+ /*
+ triple line is five times the width of an ordinary line,
+ except that the smallest 1/4 point size appears to have
+ exactly the same total border width as a 3/4 point size
+ ordinary line, i.e. three times the nominal line width. The
+ second smallest 1/2 point size appears to have exactly the
+ total border width as a 2 1/4 border, i.e 4.5 times the size.
+ */
+ if (nMSTotalWidth == 5)
+ nMSTotalWidth*=3;
+ else if (nMSTotalWidth == 10)
+ nMSTotalWidth = nMSTotalWidth*9/2;
+ else
+ nMSTotalWidth*=5;
+ break;
+ case 20:
+ /*
+ wave, the dimensions appear to be created by the drawing of
+ the wave, so we have only two possibilites in the menus, 3/4
+ point is equal to solid 3 point. This calculation seems to
+ match well to results.
+ */
+ nMSTotalWidth +=45;
+ break;
+ case 21:
+ /*
+ double wave, the dimensions appear to be created by the
+ drawing of the wave, so we have only one possibilites in the
+ menus, that of 3/4 point is equal to solid 3 point. This
+ calculation seems to match well to results.
+ */
+ nMSTotalWidth += 45*2;
+ break;
+ }
+ }
+
+ if (pIdx)
+ *pIdx = nIdx;
+ if (pSpace)
+ *pSpace = nSpace*20;
+ if (pCol)
+ *pCol = nCol;
+ return nMSTotalWidth;
+}
+
+/*
+ * WW8Cp2Fc is a good method, a CP always maps to a FC
+ * WW8Fc2Cp on the other hand is more dubious, a random FC
+ * may not map to a valid CP. Try and avoid WW8Fc2Cp where
+ * possible
+ */
+WW8_CP WW8ScannerBase::WW8Fc2Cp( WW8_FC nFcPos ) const
+{
+ WW8_CP nFallBackCpEnd = WW8_CP_MAX;
+ if( nFcPos == WW8_FC_MAX )
+ return nFallBackCpEnd;
+
+ if( pPieceIter ) // Complex File ?
+ {
+ bool bIsUnicode = false;
+ sal_uLong nOldPos = pPieceIter->GetIdx();
+
+ for (pPieceIter->SetIdx(0);
+ pPieceIter->GetIdx() < pPieceIter->GetIMax();(*pPieceIter)++)
+ {
+ WW8_CP nCpStart, nCpEnd;
+ void* pData;
+ if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
+ { // ausserhalb PLCFfpcd ?
+ OSL_ENSURE( !this, "PLCFpcd-WW8Fc2Cp() ging schief" );
+ break;
+ }
+ sal_Int32 nFcStart = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
+ if( 8 <= pWw8Fib->nVersion )
+ {
+ nFcStart = WW8PLCFx_PCD::TransformPieceAddress( nFcStart,
+ bIsUnicode );
+ }
+ else
+ {
+ if (pWw8Fib->fExtChar)
+ bIsUnicode=true;
+ }
+ sal_Int32 nLen = (nCpEnd - nCpStart) * (bIsUnicode ? 2 : 1);
+
+ /*
+ If this cp is inside this piece, or its the last piece and we are
+ on the very last cp of that piece
+ */
+ if (nFcPos >= nFcStart)
+ {
+ // found
+ WW8_CP nTempCp =
+ nCpStart + ((nFcPos - nFcStart) / (bIsUnicode ? 2 : 1));
+ if (nFcPos < nFcStart + nLen)
+ {
+ pPieceIter->SetIdx( nOldPos );
+ return nTempCp;
+ }
+ else if (nFcPos == nFcStart + nLen)
+ {
+ //Keep this cp as its on a piece boundary because we might
+ //need it if tests fail
+ nFallBackCpEnd = nTempCp;
+ }
+ }
+ }
+ // not found
+ pPieceIter->SetIdx( nOldPos ); // not found
+ /*
+ If it was not found, then this is because it has fallen between two
+ stools, i.e. either it is the last cp/fc of the last piece, or it is
+ the last cp/fc of a disjoint piece.
+ */
+ return nFallBackCpEnd;
+ }
+ // No complex file
+ if (!pWw8Fib->fExtChar)
+ nFallBackCpEnd = (nFcPos - pWw8Fib->fcMin);
+ else
+ nFallBackCpEnd = (nFcPos - pWw8Fib->fcMin + 1) / 2;
+ return nFallBackCpEnd;
+}
+
+WW8_FC WW8ScannerBase::WW8Cp2Fc(WW8_CP nCpPos, bool* pIsUnicode,
+ WW8_CP* pNextPieceCp, bool* pTestFlag) const
+{
+ if( pTestFlag )
+ *pTestFlag = true;
+ if( WW8_CP_MAX == nCpPos )
+ return WW8_CP_MAX;
+
+ bool bIsUnicode;
+ if( !pIsUnicode )
+ pIsUnicode = &bIsUnicode;
+
+ if( pPieceIter )
+ { // Complex File
+ if( pNextPieceCp )
+ *pNextPieceCp = WW8_CP_MAX;
+
+ if( !pPieceIter->SeekPos( nCpPos ) )
+ {
+ if( pTestFlag )
+ *pTestFlag = false;
+ else {
+ OSL_ENSURE( !this, "Falscher CP an WW8Cp2Fc() uebergeben" );
+ }
+ return WW8_FC_MAX;
+ }
+ WW8_CP nCpStart, nCpEnd;
+ void* pData;
+ if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
+ {
+ if( pTestFlag )
+ *pTestFlag = false;
+ else {
+ OSL_ENSURE( !this, "PLCFfpcd-Get ging schief" );
+ }
+ return WW8_FC_MAX;
+ }
+ if( pNextPieceCp )
+ *pNextPieceCp = nCpEnd;
+
+ WW8_FC nRet = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
+ if (8 > pWw8Fib->nVersion)
+ {
+ if (pWw8Fib->fExtChar)
+ *pIsUnicode=true;
+ else
+ *pIsUnicode = false;
+ }
+ else
+ nRet = WW8PLCFx_PCD::TransformPieceAddress( nRet, *pIsUnicode );
+
+
+ nRet += (nCpPos - nCpStart) * (*pIsUnicode ? 2 : 1);
+
+ return nRet;
+ }
+
+ // No complex file
+ if (pWw8Fib->fExtChar)
+ *pIsUnicode = true;
+ else
+ *pIsUnicode = false;
+ return pWw8Fib->fcMin + nCpPos * (*pIsUnicode ? 2 : 1);
+}
+
+//-----------------------------------------
+// class WW8ScannerBase
+//-----------------------------------------
+
+WW8PLCFpcd* WW8ScannerBase::OpenPieceTable( SvStream* pStr, const WW8Fib* pWwF )
+{
+ if ( ((8 > pWw8Fib->nVersion) && !pWwF->fComplex) || !pWwF->lcbClx )
+ return 0;
+
+ WW8_FC nClxPos = pWwF->fcClx;
+ sal_Int32 nClxLen = pWwF->lcbClx;
+ sal_Int32 nLeft = nClxLen;
+ sal_Int16 nGrpprl = 0;
+ sal_uInt8 clxt;
+
+ pStr->Seek( nClxPos );
+ while( 1 ) // Zaehle Zahl der Grpprls
+ {
+ *pStr >> clxt;
+ nLeft--;
+ if( 2 == clxt ) // PLCFfpcd ?
+ break; // PLCFfpcd gefunden
+ if( 1 == clxt ) // clxtGrpprl ?
+ nGrpprl++;
+ sal_uInt16 nLen;
+ *pStr >> nLen;
+ nLeft -= 2 + nLen;
+ if( nLeft < 0 )
+ return 0; // schiefgegangen
+ pStr->SeekRel( nLen ); // ueberlies grpprl
+ }
+ pStr->Seek( nClxPos );
+ nLeft = nClxLen;
+ pPieceGrpprls = new sal_uInt8*[nGrpprl + 1];
+ memset( pPieceGrpprls, 0, ( nGrpprl + 1 ) * sizeof(sal_uInt8 *) );
+ nPieceGrpprls = nGrpprl;
+ sal_Int16 nAktGrpprl = 0; // lies Grpprls ein
+ while( 1 )
+ {
+ *pStr >> clxt;
+ nLeft--;
+ if( 2 == clxt) // PLCFfpcd ?
+ break; // PLCFfpcd gefunden
+ sal_uInt16 nLen;
+ *pStr >> nLen;
+ nLeft -= 2 + nLen;
+ if( nLeft < 0 )
+ return 0; // schiefgegangen
+ if( 1 == clxt ) // clxtGrpprl ?
+ {
+ sal_uInt8* p = new sal_uInt8[nLen+2]; // alloziere
+ ShortToSVBT16(nLen, p); // trage Laenge ein
+ pStr->Read( p+2, nLen ); // lies grpprl
+ pPieceGrpprls[nAktGrpprl++] = p; // trage in Array ein
+ }
+ else
+ pStr->SeekRel( nLen ); // ueberlies nicht-Grpprl
+ }
+ // lies Piece Table PLCF ein
+ sal_Int32 nPLCFfLen;
+ if (pWwF->GetFIBVersion() <= ww::eWW2)
+ {
+ sal_Int16 nWordTwoLen;
+ *pStr >> nWordTwoLen;
+ nPLCFfLen = nWordTwoLen;
+ }
+ else
+ *pStr >> nPLCFfLen;
+ OSL_ENSURE( 65536 > nPLCFfLen, "PLCFfpcd ueber 64 k" );
+ return new WW8PLCFpcd( pStr, pStr->Tell(), nPLCFfLen, 8 );
+}
+
+void WW8ScannerBase::DeletePieceTable()
+{
+ if( pPieceGrpprls )
+ {
+ for( sal_uInt8** p = pPieceGrpprls; *p; p++ )
+ delete[] (*p);
+ delete[] pPieceGrpprls;
+ pPieceGrpprls = 0;
+ }
+}
+
+WW8ScannerBase::WW8ScannerBase( SvStream* pSt, SvStream* pTblSt,
+ SvStream* pDataSt, const WW8Fib* pWwFib )
+ : pWw8Fib(pWwFib), pMainFdoa(0), pHdFtFdoa(0), pMainTxbx(0),
+ pMainTxbxBkd(0), pHdFtTxbx(0), pHdFtTxbxBkd(0), pMagicTables(0),
+ pSubdocs(0), pExtendedAtrds(0), pPieceGrpprls(0)
+{
+ pPiecePLCF = OpenPieceTable( pTblSt, pWw8Fib ); // Complex
+ if( pPiecePLCF )
+ {
+ pPieceIter = new WW8PLCFpcd_Iter( *pPiecePLCF );
+ pPLCFx_PCD = new WW8PLCFx_PCD(pWwFib->GetFIBVersion(), pPiecePLCF, 0,
+ IsSevenMinus(pWw8Fib->GetFIBVersion()));
+ pPLCFx_PCDAttrs = new WW8PLCFx_PCDAttrs(pWwFib->GetFIBVersion(),
+ pPLCFx_PCD, this);
+ }
+ else
+ {
+ pPieceIter = 0;
+ pPLCFx_PCD = 0;
+ pPLCFx_PCDAttrs = 0;
+ }
+
+ // pChpPLCF and pPapPLCF may NOT be created before pPLCFx_PCD !!
+ pChpPLCF = new WW8PLCFx_Cp_FKP( pSt, pTblSt, pDataSt, *this, CHP ); // CHPX
+ pPapPLCF = new WW8PLCFx_Cp_FKP( pSt, pTblSt, pDataSt, *this, PAP ); // PAPX
+
+ pSepPLCF = new WW8PLCFx_SEPX( pSt, pTblSt, *pWwFib, 0 ); // SEPX
+
+ // Footnotes
+ pFtnPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->GetFIBVersion(), 0,
+ pWwFib->fcPlcffndRef, pWwFib->lcbPlcffndRef, pWwFib->fcPlcffndTxt,
+ pWwFib->lcbPlcffndTxt, 2 );
+ // Endnotes
+ pEdnPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->GetFIBVersion(), 0,
+ pWwFib->fcPlcfendRef, pWwFib->lcbPlcfendRef, pWwFib->fcPlcfendTxt,
+ pWwFib->lcbPlcfendTxt, 2 );
+ // Anmerkungen
+ pAndPLCF = new WW8PLCFx_SubDoc( pTblSt, pWwFib->GetFIBVersion(), 0,
+ pWwFib->fcPlcfandRef, pWwFib->lcbPlcfandRef, pWwFib->fcPlcfandTxt,
+ pWwFib->lcbPlcfandTxt, IsSevenMinus(pWwFib->GetFIBVersion()) ? 20 : 30);
+
+ // Fields Main Text
+ pFldPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_MAINTEXT);
+ // Fields Header / Footer
+ pFldHdFtPLCF= new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_HDFT);
+ // Fields Footnote
+ pFldFtnPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_FTN);
+ // Fields Endnote
+ pFldEdnPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_EDN);
+ // Fields Anmerkungen
+ pFldAndPLCF = new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_AND);
+ // Fields in Textboxes in Main Text
+ pFldTxbxPLCF= new WW8PLCFx_FLD(pTblSt, *pWwFib, MAN_TXBX);
+ // Fields in Textboxes in Header / Footer
+ pFldTxbxHdFtPLCF = new WW8PLCFx_FLD(pTblSt,*pWwFib,MAN_TXBX_HDFT);
+
+ // Note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
+ switch( pWw8Fib->nVersion )
+ {
+ case 6:
+ case 7:
+ if( pWwFib->fcPlcfdoaMom && pWwFib->lcbPlcfdoaMom )
+ {
+ pMainFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfdoaMom,
+ pWwFib->lcbPlcfdoaMom, 6 );
+ }
+ if( pWwFib->fcPlcfdoaHdr && pWwFib->lcbPlcfdoaHdr )
+ {
+ pHdFtFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfdoaHdr,
+ pWwFib->lcbPlcfdoaHdr, 6 );
+ }
+ break;
+ case 8:
+ if( pWwFib->fcPlcfspaMom && pWwFib->lcbPlcfspaMom )
+ {
+ pMainFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfspaMom,
+ pWwFib->lcbPlcfspaMom, 26 );
+ }
+ if( pWwFib->fcPlcfspaHdr && pWwFib->lcbPlcfspaHdr )
+ {
+ pHdFtFdoa = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfspaHdr,
+ pWwFib->lcbPlcfspaHdr, 26 );
+ }
+ // PLCF fuer TextBox-Break-Deskriptoren im Maintext
+ if( pWwFib->fcPlcftxbxBkd && pWwFib->lcbPlcftxbxBkd )
+ {
+ pMainTxbxBkd = new WW8PLCFspecial( pTblSt,
+ pWwFib->fcPlcftxbxBkd, pWwFib->lcbPlcftxbxBkd, 0);
+ }
+ // PLCF fuer TextBox-Break-Deskriptoren im Header-/Footer-Bereich
+ if( pWwFib->fcPlcfHdrtxbxBkd && pWwFib->lcbPlcfHdrtxbxBkd )
+ {
+ pHdFtTxbxBkd = new WW8PLCFspecial( pTblSt,
+ pWwFib->fcPlcfHdrtxbxBkd, pWwFib->lcbPlcfHdrtxbxBkd, 0);
+ }
+ // Sub table cp positions
+ if (pWwFib->fcPlcfTch && pWwFib->lcbPlcfTch)
+ {
+ pMagicTables = new WW8PLCFspecial( pTblSt,
+ pWwFib->fcPlcfTch, pWwFib->lcbPlcfTch, 4);
+ }
+ // Sub document cp positions
+ if (pWwFib->fcPlcfwkb && pWwFib->lcbPlcfwkb)
+ {
+ pSubdocs = new WW8PLCFspecial( pTblSt,
+ pWwFib->fcPlcfwkb, pWwFib->lcbPlcfwkb, 12);
+ }
+ // Extended ATRD
+ if (pWwFib->fcAtrdExtra && pWwFib->lcbAtrdExtra)
+ {
+ pExtendedAtrds = new sal_uInt8[pWwFib->lcbAtrdExtra];
+ long nOldPos = pTblSt->Tell();
+ pTblSt->Seek(pWwFib->fcAtrdExtra);
+ pTblSt->Read(pExtendedAtrds, pWwFib->lcbAtrdExtra);
+ pTblSt->Seek(nOldPos);
+ }
+
+ break;
+ default:
+ OSL_ENSURE( !this, "Es wurde vergessen, nVersion zu kodieren!" );
+ break;
+ }
+
+ // PLCF fuer TextBox-Stories im Maintext
+ long nLenTxBxS = (8 > pWw8Fib->nVersion) ? 0 : 22;
+ if( pWwFib->fcPlcftxbxTxt && pWwFib->lcbPlcftxbxTxt )
+ {
+ pMainTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcftxbxTxt,
+ pWwFib->lcbPlcftxbxTxt, nLenTxBxS );
+ }
+
+ // PLCF fuer TextBox-Stories im Header-/Footer-Bereich
+ if( pWwFib->fcPlcfHdrtxbxTxt && pWwFib->lcbPlcfHdrtxbxTxt )
+ {
+ pHdFtTxbx = new WW8PLCFspecial( pTblSt, pWwFib->fcPlcfHdrtxbxTxt,
+ pWwFib->lcbPlcfHdrtxbxTxt, nLenTxBxS );
+ }
+
+ pBook = new WW8PLCFx_Book(pTblSt, *pWwFib);
+}
+
+WW8ScannerBase::~WW8ScannerBase()
+{
+ DeletePieceTable();
+ delete pPLCFx_PCDAttrs;
+ delete pPLCFx_PCD;
+ delete pPieceIter;
+ delete pPiecePLCF;
+ delete pBook;
+ delete pFldEdnPLCF;
+ delete pFldFtnPLCF;
+ delete pFldAndPLCF;
+ delete pFldHdFtPLCF;
+ delete pFldPLCF;
+ delete pFldTxbxPLCF;
+ delete pFldTxbxHdFtPLCF;
+ delete pEdnPLCF;
+ delete pFtnPLCF;
+ delete pAndPLCF;
+ delete pSepPLCF;
+ delete pPapPLCF;
+ delete pChpPLCF;
+ // vergessene Schaeflein
+ delete pMainFdoa;
+ delete pHdFtFdoa;
+ delete pMainTxbx;
+ delete pMainTxbxBkd;
+ delete pHdFtTxbx;
+ delete pHdFtTxbxBkd;
+ delete pMagicTables;
+ delete pSubdocs;
+ delete [] pExtendedAtrds;
+}
+
+//-----------------------------------------
+// Fields
+//-----------------------------------------
+static bool WW8SkipField(WW8PLCFspecial& rPLCF)
+{
+ void* pData;
+ WW8_CP nP;
+
+ if (!rPLCF.Get(nP, pData)) // Ende des PLCFspecial ?
+ return false;
+
+ rPLCF++;
+
+ if((((sal_uInt8*)pData)[0] & 0x1f ) != 0x13 ) // Kein Anfang ?
+ return true; // Bei Fehler nicht abbrechen
+
+ if( !rPLCF.Get( nP, pData ) )
+ return false;
+
+
+ while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
+ {
+ // immer noch neue (nested) Anfaenge ?
+ WW8SkipField( rPLCF ); // nested Field im Beschreibungsteil
+ if( !rPLCF.Get( nP, pData ) )
+ return false;
+ }
+
+ if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x14 )
+ {
+
+ // Field Separator ?
+ rPLCF++;
+
+ if( !rPLCF.Get( nP, pData ) )
+ return false;
+
+ while ((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13)
+ {
+ // immer noch neue (nested) Anfaenge ?
+ WW8SkipField( rPLCF ); // nested Field im Resultatteil
+ if( !rPLCF.Get( nP, pData ) )
+ return false;
+ }
+ }
+ rPLCF++;
+
+ return true;
+}
+
+static bool WW8GetFieldPara(WW8PLCFspecial& rPLCF, WW8FieldDesc& rF)
+{
+ void* pData;
+ sal_uLong nOldIdx = rPLCF.GetIdx();
+
+ rF.nLen = rF.nId = rF.nOpt = rF.bCodeNest = rF.bResNest = 0;
+
+ if( !rPLCF.Get( rF.nSCode, pData ) ) // Ende des PLCFspecial ?
+ goto Err;
+
+ rPLCF++;
+
+ if((((sal_uInt8*)pData)[0] & 0x1f ) != 0x13 ) // Kein Anfang ?
+ goto Err;
+
+ rF.nId = ((sal_uInt8*)pData)[1];
+
+ if( !rPLCF.Get( rF.nLCode, pData ) )
+ goto Err;
+
+ rF.nSRes = rF.nLCode; // Default
+ rF.nSCode++; // ohne Marken
+ rF.nLCode -= rF.nSCode; // Pos zu Laenge
+
+ while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
+ {
+ // immer noch neue (nested) Anfaenge ?
+ WW8SkipField( rPLCF ); // nested Field im Beschreibungsteil
+ rF.bCodeNest = true;
+ if( !rPLCF.Get( rF.nSRes, pData ) )
+ goto Err;
+ }
+
+ if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x14 ){ // Field Separator ?
+ rPLCF++;
+
+ if( !rPLCF.Get( rF.nLRes, pData ) )
+ goto Err;
+
+ while((((sal_uInt8*)pData)[0] & 0x1f ) == 0x13 )
+ {
+ // immer noch neue (nested) Anfaenge ?
+ WW8SkipField( rPLCF ); // nested Field im Resultatteil
+ rF.bResNest = true;
+ if( !rPLCF.Get( rF.nLRes, pData ) )
+ goto Err;
+ }
+ rF.nLen = rF.nLRes - rF.nSCode + 2; // nLRes ist noch die Endposition
+ rF.nLRes -= rF.nSRes; // nun: nLRes = Laenge
+ rF.nSRes++; // Endpos encl. Marken
+ rF.nLRes--;
+
+ }else{
+ rF.nLRes = 0; // Kein Result vorhanden
+ rF.nLen = rF.nSRes - rF.nSCode + 2; // Gesamtlaenge
+ }
+
+ rPLCF++;
+ if((((sal_uInt8*)pData)[0] & 0x1f ) == 0x15 )
+ {
+ // Field Ende ?
+ // INDEX-Fld hat Bit7 gesetzt!?!
+ rF.nOpt = ((sal_uInt8*)pData)[1]; // Ja -> Flags uebernehmen
+ }else{
+ rF.nId = 0; // Nein -> Feld ungueltig
+ }
+
+ rPLCF.SetIdx( nOldIdx );
+ return true;
+Err:
+ rPLCF.SetIdx( nOldIdx );
+ return false;
+}
+
+
+//-----------------------------------------
+
+
+// WW8ReadPString liest einen Pascal-String ein und gibt ihn zurueck. Der
+// Pascal- String hat am Ende ein \0, der aber im Laengenbyte nicht
+// mitgezaehlt wird. Der Speicher fuer den Pascalstring wird alloziert.
+String WW8ReadPString(SvStream& rStrm, rtl_TextEncoding eEnc,
+ bool bAtEndSeekRel1)
+{
+ ByteString aByteStr;
+ sal_uInt8 b;
+ rStrm >> b;
+
+ if (b)
+ {
+ // Alloc methode automatically sets Zero at the end
+ sal_Char* pByteData = aByteStr.AllocBuffer( b );
+
+ sal_uLong nWasRead = rStrm.Read( pByteData, b );
+ if( nWasRead != b )
+ aByteStr.ReleaseBufferAccess(static_cast<xub_StrLen>(nWasRead));
+ }
+
+ if( bAtEndSeekRel1 )
+ rStrm.SeekRel( 1 ); // ueberspringe das Null-Byte am Ende.
+
+
+ return String( aByteStr, eEnc );
+}
+
+String WW8Read_xstz(SvStream& rStrm, sal_uInt16 nChars, bool bAtEndSeekRel1)
+{
+ sal_uInt16 b;
+
+ if( nChars )
+ b = nChars;
+ else
+ rStrm >> b;
+
+ String aStr;
+ if (b)
+ {
+ // Alloc methode automatically sets Zero at the end
+ sal_Unicode* pData = aStr.AllocBuffer( b );
+
+ sal_uLong nWasRead = rStrm.Read( (sal_Char*)pData, b * 2 );
+ if( nWasRead != static_cast<sal_uLong>(b*2) )
+ {
+ b = static_cast<sal_uInt16>(nWasRead / 2);
+ aStr.ReleaseBufferAccess( b );
+ pData = aStr.GetBufferAccess();
+ }
+
+#ifdef OSL_BIGENDIAN
+ sal_uLong n;
+ sal_Unicode *pWork;
+ for( n = 0, pWork = pData; n < b; ++n, ++pWork )
+ *pWork = SWAPSHORT( *pWork );
+#endif // ifdef OSL_BIGENDIAN
+ }
+
+ if( bAtEndSeekRel1 )
+ rStrm.SeekRel( 2 ); // ueberspringe das Null-Character am Ende.
+
+ return aStr;
+}
+
+sal_uLong SafeReadString(ByteString &rStr,sal_uInt16 nLen,SvStream &rStrm)
+{
+ sal_uLong nWasRead=0;
+ if (nLen)
+ {
+ nWasRead = rStrm.Read( rStr.AllocBuffer( nLen ), nLen);
+ if( nWasRead != nLen )
+ rStr.ReleaseBufferAccess(static_cast<xub_StrLen>(nWasRead));
+ }
+ return nWasRead;
+}
+
+xub_StrLen WW8ScannerBase::WW8ReadString( SvStream& rStrm, String& rStr,
+ WW8_CP nAktStartCp, long nTotalLen, rtl_TextEncoding eEnc ) const
+{
+ // Klartext einlesen, der sich ueber mehrere Pieces erstrecken kann
+ rStr.Erase();
+
+ long nTotalRead = 0;
+ WW8_CP nBehindTextCp = nAktStartCp + nTotalLen;
+ WW8_CP nNextPieceCp = nBehindTextCp; // Initialisierung wichtig fuer Ver6
+ do
+ {
+ bool bIsUnicode, bPosOk;
+ WW8_FC fcAct = WW8Cp2Fc(nAktStartCp,&bIsUnicode,&nNextPieceCp,&bPosOk);
+
+ // vermutlich uebers Dateiende hinaus gezielt, macht nix!
+ if( !bPosOk )
+ break;
+
+ rStrm.Seek( fcAct );
+
+ long nLen = ( (nNextPieceCp < nBehindTextCp) ? nNextPieceCp
+ : nBehindTextCp ) - nAktStartCp;
+
+ if( 0 >= nLen )
+ break;
+
+ if( nLen > USHRT_MAX - 1 )
+ nLen = USHRT_MAX - 1;
+
+ if( bIsUnicode )
+ rStr.Append(WW8Read_xstz(rStrm, (sal_uInt16)nLen, false));
+ else
+ {
+ // Alloc method automatically sets Zero at the end
+ ByteString aByteStr;
+ SafeReadString(aByteStr,(sal_uInt16)nLen,rStrm);
+ rStr += String( aByteStr, eEnc );
+ }
+ nTotalRead += nLen;
+ nAktStartCp += nLen;
+ if ( nTotalRead != rStr.Len() )
+ break;
+ }
+ while( nTotalRead < nTotalLen );
+
+ return rStr.Len();
+}
+
+//-----------------------------------------
+// WW8PLCFspecial
+//-----------------------------------------
+
+// Bei nStartPos < 0 wird das erste Element des PLCFs genommen
+WW8PLCFspecial::WW8PLCFspecial(SvStream* pSt, long nFilePos, long nPLCF,
+ long nStruct, long nStartPos)
+ : nIdx(0), nStru(nStruct)
+{
+ nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
+ // Pointer auf Pos- u. Struct-Array
+ pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ];
+
+ long nOldPos = pSt->Tell();
+
+ pSt->Seek( nFilePos );
+ pSt->Read( pPLCF_PosArray, nPLCF );
+#ifdef OSL_BIGENDIAN
+ for( nIdx = 0; nIdx <= nIMax; nIdx++ )
+ pPLCF_PosArray[nIdx] = SWAPLONG( pPLCF_PosArray[nIdx] );
+ nIdx = 0;
+#endif // OSL_BIGENDIAN
+ if( nStruct ) // Pointer auf Inhalts-Array
+ pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
+ else
+ pPLCF_Contents = 0; // kein Inhalt
+ if( nStartPos >= 0 )
+ SeekPos( nStartPos );
+
+ pSt->Seek( nOldPos );
+}
+
+// WW8PLCFspecial::SeekPos() stellt den WW8PLCFspecial auf die Stelle nPos, wobei auch noch der
+// Eintrag benutzt wird, der vor nPos beginnt und bis hinter nPos reicht.
+// geeignet fuer normale Attribute. Allerdings wird der Attributanfang nicht
+// auf die Position nPos korrigiert.
+bool WW8PLCFspecial::SeekPos(long nP)
+{
+ if( nP < pPLCF_PosArray[0] )
+ {
+ nIdx = 0;
+ return false; // Not found: nP unterhalb kleinstem Eintrag
+ }
+
+ // Search from beginning?
+ if( (1 > nIdx) || (nP < pPLCF_PosArray[ nIdx-1 ]) )
+ nIdx = 1;
+
+ long nI = nIdx ? nIdx : 1;
+ long nEnd = nIMax;
+
+ for(int n = (1==nIdx ? 1 : 2); n; --n )
+ {
+ for( ; nI <=nEnd; ++nI)
+ { // Suchen mit um 1 erhoehtem Index
+ if( nP < pPLCF_PosArray[nI] )
+ { // Position gefunden
+ nIdx = nI - 1; // nI - 1 ist der richtige Index
+ return true; // ... und fertig
+ }
+ }
+ nI = 1;
+ nEnd = nIdx-1;
+ }
+ nIdx = nIMax; // Nicht gefunden, groesser als alle Eintraege
+ return false;
+}
+
+// WW8PLCFspecial::SeekPosExact() wie SeekPos(), aber es wird sichergestellt,
+// dass kein Attribut angeschnitten wird, d.h. das naechste gelieferte
+// Attribut beginnt auf oder hinter nPos. Wird benutzt fuer Felder +
+// Bookmarks.
+bool WW8PLCFspecial::SeekPosExact(long nP)
+{
+ if( nP < pPLCF_PosArray[0] )
+ {
+ nIdx = 0;
+ return false; // Not found: nP unterhalb kleinstem Eintrag
+ }
+ // Search from beginning?
+ if( nP <=pPLCF_PosArray[nIdx] )
+ nIdx = 0;
+
+ long nI = nIdx ? nIdx-1 : 0;
+ long nEnd = nIMax;
+
+ for(int n = (0==nIdx ? 1 : 2); n; --n )
+ {
+ for( ; nI < nEnd; ++nI)
+ {
+ if( nP <=pPLCF_PosArray[nI] )
+ { // Position gefunden
+ nIdx = nI; // nI ist der richtige Index
+ return true; // ... und fertig
+ }
+ }
+ nI = 0;
+ nEnd = nIdx;
+ }
+ nIdx = nIMax; // Not found, groesser als alle Eintraege
+ return false;
+}
+
+bool WW8PLCFspecial::Get(WW8_CP& rPos, void*& rpValue) const
+{
+ return GetData( nIdx, rPos, rpValue );
+}
+
+bool WW8PLCFspecial::GetData(long nInIdx, WW8_CP& rPos, void*& rpValue) const
+{
+ if ( nInIdx >= nIMax )
+ {
+ rPos = WW8_CP_MAX;
+ return false;
+ }
+ rPos = pPLCF_PosArray[nInIdx];
+ rpValue = pPLCF_Contents ? (void*)&pPLCF_Contents[nInIdx * nStru] : 0;
+ return true;
+}
+
+//-----------------------------------------
+// WW8PLCF z.B. fuer SEPX
+//-----------------------------------------
+
+// Ctor fuer *andere* als Fkps
+// Bei nStartPos < 0 wird das erste Element des PLCFs genommen
+WW8PLCF::WW8PLCF( SvStream* pSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
+ WW8_CP nStartPos ) : pPLCF_PosArray(0), nIdx(0), nStru(nStruct)
+{
+ OSL_ENSURE( nPLCF, "WW8PLCF: nPLCF ist Null!" );
+
+ nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
+
+ ReadPLCF( pSt, nFilePos, nPLCF );
+
+ if( nStartPos >= 0 )
+ SeekPos( nStartPos );
+}
+
+// Ctor *nur* fuer Fkps
+// Die letzten 2 Parameter sind fuer PLCF.Chpx und PLCF.Papx noetig. ist ncpN
+// != 0, dann wird ein unvollstaendiger PLCF vervollstaendigt. Das ist bei
+// WW6 bei Resourcenmangel und bei WordPad (W95) immer noetig. Bei nStartPos
+// < 0 wird das erste Element des PLCFs genommen
+WW8PLCF::WW8PLCF( SvStream* pSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
+ WW8_CP nStartPos, sal_Int32 nPN, sal_Int32 ncpN ) : pPLCF_PosArray(0), nIdx(0),
+ nStru(nStruct)
+{
+ nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
+
+ if( nIMax >= ncpN )
+ ReadPLCF( pSt, nFilePos, nPLCF );
+ else
+ GeneratePLCF( pSt, nPN, ncpN );
+
+ if( nStartPos >= 0 )
+ SeekPos( nStartPos );
+}
+
+void WW8PLCF::ReadPLCF( SvStream* pSt, WW8_FC nFilePos, sal_Int32 nPLCF )
+{
+ bool failure = false;
+
+ // Pointer auf Pos-Array
+ pPLCF_PosArray = new WW8_CP[ ( nPLCF + 3 ) / 4 ];
+
+ sal_Size nOldPos = pSt->Tell();
+
+ pSt->Seek( nFilePos );
+ failure = pSt->GetError();
+
+ if (!failure)
+ {
+ pSt->Read( pPLCF_PosArray, nPLCF );
+ failure = pSt->GetError();
+ }
+
+ if (!failure)
+ {
+#ifdef OSL_BIGENDIAN
+ for( nIdx = 0; nIdx <= nIMax; nIdx++ )
+ pPLCF_PosArray[nIdx] = SWAPLONG( pPLCF_PosArray[nIdx] );
+ nIdx = 0;
+#endif // OSL_BIGENDIAN
+ // Pointer auf Inhalts-Array
+ pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
+ }
+
+ pSt->Seek( nOldPos );
+
+ OSL_ENSURE( !failure, "Document has corrupt PLCF, ignoring it" );
+
+ if (failure)
+ MakeFailedPLCF();
+}
+
+void WW8PLCF::MakeFailedPLCF()
+{
+ nIMax = 0;
+ delete[] pPLCF_PosArray;
+ pPLCF_PosArray = new sal_Int32[2];
+ pPLCF_PosArray[0] = pPLCF_PosArray[1] = WW8_CP_MAX;
+ pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
+}
+
+void WW8PLCF::GeneratePLCF( SvStream* pSt, sal_Int32 nPN, sal_Int32 ncpN )
+{
+ OSL_ENSURE( nIMax < ncpN, "Pcl.Fkp: Warum ist PLCF zu gross ?" );
+
+ bool failure = false;
+ nIMax = ncpN;
+
+ if ((nIMax < 1) || (nIMax > (WW8_CP_MAX - 4)/6) || ((nPN + ncpN) > USHRT_MAX))
+ failure = true;
+
+ if (!failure)
+ {
+ size_t nSiz = 6 * nIMax + 4;
+ size_t nElems = ( nSiz + 3 ) / 4;
+ pPLCF_PosArray = new sal_Int32[ nElems ]; // Pointer auf Pos-Array
+
+ for (sal_Int32 i = 0; i < ncpN && !pSt->GetError(); ++i)
+ {
+ // Baue FC-Eintraege
+ pSt->Seek( ( nPN + i ) << 9 ); // erster FC-Eintrag jedes Fkp
+ WW8_CP nFc;
+ *pSt >> nFc;
+ pPLCF_PosArray[i] = nFc;
+ }
+
+ failure = pSt->GetError();
+ }
+
+ if (!failure)
+ {
+ sal_Size nLastFkpPos = ( ( nPN + nIMax - 1 ) << 9 );
+ pSt->Seek( nLastFkpPos + 511 ); // Anz. Fkp-Eintraege des letzten Fkp
+
+ sal_uInt8 nb;
+ *pSt >> nb;
+ pSt->Seek( nLastFkpPos + nb * 4 ); // letzer FC-Eintrag des letzten Fkp
+
+ WW8_CP nFc;
+ *pSt >> nFc;
+ pPLCF_PosArray[nIMax] = nFc; // Ende des letzten Fkp
+
+ failure = pSt->GetError();
+ }
+
+ if (!failure)
+ {
+ // Pointer auf Inhalts-Array
+ pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
+ sal_uInt8* p = pPLCF_Contents;
+
+ for (sal_Int32 i = 0; i < ncpN; ++i) // Baue PNs
+ {
+ ShortToSVBT16(static_cast<sal_uInt16>(nPN + i), p);
+ p+=2;
+ }
+ }
+
+ OSL_ENSURE( !failure, "Document has corrupt PLCF, ignoring it" );
+
+ if (failure)
+ MakeFailedPLCF();
+}
+
+bool WW8PLCF::SeekPos(WW8_CP nPos)
+{
+ WW8_CP nP = nPos;
+
+ if( nP < pPLCF_PosArray[0] )
+ {
+ nIdx = 0;
+ // Nicht gefunden: nPos unterhalb kleinstem Eintrag
+ return false;
+ }
+
+ // Search from beginning?
+ if( (1 > nIdx) || (nP < pPLCF_PosArray[ nIdx-1 ]) )
+ nIdx = 1;
+
+ sal_Int32 nI = nIdx ? nIdx : 1;
+ sal_Int32 nEnd = nIMax;
+
+ for(int n = (1==nIdx ? 1 : 2); n; --n )
+ {
+ for( ; nI <=nEnd; ++nI) // Suchen mit um 1 erhoehtem Index
+ {
+ if( nP < pPLCF_PosArray[nI] ) // Position gefunden
+ {
+ nIdx = nI - 1; // nI - 1 ist der richtige Index
+ return true; // ... und fertig
+ }
+ }
+ nI = 1;
+ nEnd = nIdx-1;
+ }
+
+ nIdx = nIMax; // Nicht gefunden, groesser als alle Eintraege
+ return false;
+}
+
+bool WW8PLCF::Get(WW8_CP& rStart, WW8_CP& rEnd, void*& rpValue) const
+{
+ if ( nIdx >= nIMax )
+ {
+ rStart = rEnd = WW8_CP_MAX;
+ return false;
+ }
+ rStart = pPLCF_PosArray[ nIdx ];
+ rEnd = pPLCF_PosArray[ nIdx + 1 ];
+ rpValue = (void*)&pPLCF_Contents[nIdx * nStru];
+ return true;
+}
+
+WW8_CP WW8PLCF::Where() const
+{
+ if ( nIdx >= nIMax )
+ return WW8_CP_MAX;
+
+ return pPLCF_PosArray[nIdx];
+}
+
+//-----------------------------------------
+// WW8PLCFpcd
+//-----------------------------------------
+
+WW8PLCFpcd::WW8PLCFpcd( SvStream* pSt, long nFilePos, long nPLCF, long nStruct )
+ :nStru( nStruct )
+{
+ nIMax = ( nPLCF - 4 ) / ( 4 + nStruct );
+ pPLCF_PosArray = new sal_Int32[ ( nPLCF + 3 ) / 4 ]; // Pointer auf Pos-Array
+
+ long nOldPos = pSt->Tell();
+
+ pSt->Seek( nFilePos );
+ pSt->Read( pPLCF_PosArray, nPLCF );
+#ifdef OSL_BIGENDIAN
+ for( long nI = 0; nI <= nIMax; nI++ )
+ pPLCF_PosArray[nI] = SWAPLONG( pPLCF_PosArray[nI] );
+#endif // OSL_BIGENDIAN
+
+ // Pointer auf Inhalts-Array
+ pPLCF_Contents = (sal_uInt8*)&pPLCF_PosArray[nIMax + 1];
+
+ pSt->Seek( nOldPos );
+}
+
+// Bei nStartPos < 0 wird das erste Element des PLCFs genommen
+WW8PLCFpcd_Iter::WW8PLCFpcd_Iter( WW8PLCFpcd& rPLCFpcd, long nStartPos )
+ :rPLCF( rPLCFpcd ), nIdx( 0 )
+{
+ if( nStartPos >= 0 )
+ SeekPos( nStartPos );
+}
+
+bool WW8PLCFpcd_Iter::SeekPos(long nPos)
+{
+ long nP = nPos;
+
+ if( nP < rPLCF.pPLCF_PosArray[0] )
+ {
+ nIdx = 0;
+ return false; // Nicht gefunden: nPos unterhalb kleinstem Eintrag
+ }
+ // Search from beginning?
+ if( (1 > nIdx) || (nP < rPLCF.pPLCF_PosArray[ nIdx-1 ]) )
+ nIdx = 1;
+
+ long nI = nIdx ? nIdx : 1;
+ long nEnd = rPLCF.nIMax;
+
+ for(int n = (1==nIdx ? 1 : 2); n; --n )
+ {
+ for( ; nI <=nEnd; ++nI)
+ { // Suchen mit um 1 erhoehtem Index
+ if( nP < rPLCF.pPLCF_PosArray[nI] )
+ { // Position gefunden
+ nIdx = nI - 1; // nI - 1 ist der richtige Index
+ return true; // ... und fertig
+ }
+ }
+ nI = 1;
+ nEnd = nIdx-1;
+ }
+ nIdx = rPLCF.nIMax; // Nicht gefunden, groesser als alle Eintraege
+ return false;
+}
+
+bool WW8PLCFpcd_Iter::Get(WW8_CP& rStart, WW8_CP& rEnd, void*& rpValue) const
+{
+ if( nIdx >= rPLCF.nIMax )
+ {
+ rStart = rEnd = WW8_CP_MAX;
+ return false;
+ }
+ rStart = rPLCF.pPLCF_PosArray[nIdx];
+ rEnd = rPLCF.pPLCF_PosArray[nIdx + 1];
+ rpValue = (void*)&rPLCF.pPLCF_Contents[nIdx * rPLCF.nStru];
+ return true;
+}
+
+sal_Int32 WW8PLCFpcd_Iter::Where() const
+{
+ if ( nIdx >= rPLCF.nIMax )
+ return SAL_MAX_INT32;
+
+ return rPLCF.pPLCF_PosArray[nIdx];
+}
+
+//-----------------------------------------
+bool WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator<
+ (const WW8PLCFx_Fc_FKP::WW8Fkp::Entry& rSecond) const
+{
+ return (mnFC < rSecond.mnFC);
+}
+
+bool IsReplaceAllSprm(sal_uInt16 nSpId)
+{
+ return (0x6645 == nSpId || 0x6646 == nSpId);
+}
+
+bool IsExpandableSprm(sal_uInt16 nSpId)
+{
+ return 0x646B == nSpId;
+}
+
+WW8PLCFx_Fc_FKP::WW8Fkp::WW8Fkp(ww::WordVersion eVersion, SvStream* pSt,
+ SvStream* pDataSt, long _nFilePos, long nItemSiz, ePLCFT ePl,
+ WW8_FC nStartFc)
+ : nItemSize(nItemSiz), nFilePos(_nFilePos), mnIdx(0), ePLCF(ePl),
+ maSprmParser(eVersion)
+{
+ long nOldPos = pSt->Tell();
+
+ pSt->Seek(nFilePos);
+ memset(maRawData, 0, 512);
+ pSt->Read(maRawData, 512);
+ mnIMax = maRawData[511];
+
+ sal_uInt8 *pStart = maRawData;
+ // Pointer to Offset-Location in maRawData
+ sal_uInt8* pOfs = maRawData + (mnIMax + 1) * 4;
+
+ for (mnIdx = 0; mnIdx < mnIMax; ++mnIdx)
+ {
+ unsigned int nOfs = (*(pOfs + mnIdx * nItemSize)) * 2;
+ Entry aEntry(Get_Long(pStart));
+
+ if (nOfs)
+ {
+ switch (ePLCF)
+ {
+ case CHP:
+ aEntry.mnLen = maRawData[nOfs];
+ aEntry.mpData = maRawData + nOfs + 1;
+
+ if (aEntry.mnLen && eVersion == ww::eWW2)
+ {
+ Word2CHPX aChpx = ReadWord2Chpx(*pSt, nFilePos + nOfs + 1, static_cast< sal_uInt8 >(aEntry.mnLen));
+ std::vector<sal_uInt8> aSprms = ChpxToSprms(aChpx);
+ aEntry.mnLen = static_cast< sal_uInt16 >(aSprms.size());
+ if (aEntry.mnLen)
+ {
+ aEntry.mpData = new sal_uInt8[aEntry.mnLen];
+ memcpy(aEntry.mpData, &(aSprms[0]), aEntry.mnLen);
+ aEntry.mbMustDelete = true;
+ }
+ }
+
+ break;
+ case PAP:
+ {
+ sal_uInt8 nDelta = 0;
+
+ aEntry.mnLen = maRawData[nOfs];
+ if (IsEightPlus(eVersion) && !aEntry.mnLen)
+ {
+ aEntry.mnLen = maRawData[nOfs+1];
+ nDelta++;
+ }
+ aEntry.mnLen *= 2;
+
+ //stylecode, std/istd
+ if (eVersion == ww::eWW2)
+ {
+ if (aEntry.mnLen >= 1)
+ {
+ aEntry.mnIStd = *(maRawData+nOfs+1+nDelta);
+ aEntry.mnLen--; //style code
+ if (aEntry.mnLen >= 6)
+ {
+ aEntry.mnLen-=6; //PHE
+ //skipi stc, len byte + 6 byte PHE
+ aEntry.mpData = maRawData + nOfs + 8;
+ }
+ else
+ aEntry.mnLen=0; //Too short
+ }
+ }
+ else
+ {
+ if (aEntry.mnLen >= 2)
+ {
+ aEntry.mnIStd = SVBT16ToShort(maRawData+nOfs+1+nDelta);
+ aEntry.mnLen-=2; //istd
+ //skip istd, len byte + optional extra len byte
+ aEntry.mpData = maRawData + nOfs + 3 + nDelta;
+ }
+ else
+ aEntry.mnLen=0; //Too short, ignore
+ }
+
+ sal_uInt16 nSpId = aEntry.mnLen ? maSprmParser.GetSprmId(aEntry.mpData) : 0;
+
+ /*
+ If we replace then we throw away the old data, if we
+ are expanding, then we tack the old data onto the end
+ of the new data
+ */
+ bool bExpand = IsExpandableSprm(nSpId);
+ if (IsReplaceAllSprm(nSpId) || bExpand)
+ {
+ sal_uInt16 nOrigLen = bExpand ? aEntry.mnLen : 0;
+ sal_uInt8 *pOrigData = bExpand ? aEntry.mpData : 0;
+
+ sal_uInt32 nCurr = pDataSt->Tell();
+
+ sal_uInt32 nPos = SVBT32ToUInt32(aEntry.mpData + 2);
+ pDataSt->Seek(nPos);
+ *pDataSt >> aEntry.mnLen;
+ aEntry.mpData =
+ new sal_uInt8[aEntry.mnLen + nOrigLen];
+ aEntry.mbMustDelete = true;
+ pDataSt->Read(aEntry.mpData, aEntry.mnLen);
+
+ pDataSt->Seek( nCurr );
+
+ if (pOrigData)
+ {
+ memcpy(aEntry.mpData + aEntry.mnLen,
+ pOrigData, nOrigLen);
+ aEntry.mnLen = aEntry.mnLen + nOrigLen;
+ }
+ }
+ }
+ break;
+ default:
+ OSL_FAIL("sweet god, what have you done!");
+ break;
+ }
+ }
+
+ maEntries.push_back(aEntry);
+
+#ifdef DEBUGSPRMREADER
+ {
+ sal_Int32 nLen;
+ sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
+
+ WW8SprmIter aIter(pSprms, nLen, maSprmParser);
+ while(aIter.GetSprms())
+ aIter.advance();
+ }
+#endif
+ }
+
+ //one more FC than grrpl entries
+ maEntries.push_back(Entry(Get_Long(pStart)));
+
+ //we expect them sorted, but it appears possible for them to arive unsorted
+ std::sort(maEntries.begin(), maEntries.end());
+
+ mnIdx = 0;
+
+ if (nStartFc >= 0)
+ SeekPos(nStartFc);
+
+ pSt->Seek(nOldPos);
+}
+
+WW8PLCFx_Fc_FKP::WW8Fkp::Entry::Entry(const Entry &rEntry)
+ : mnFC(rEntry.mnFC), mnLen(rEntry.mnLen), mnIStd(rEntry.mnIStd),
+ mbMustDelete(rEntry.mbMustDelete)
+{
+ if (mbMustDelete)
+ {
+ mpData = new sal_uInt8[mnLen];
+ memcpy(mpData, rEntry.mpData, mnLen);
+ }
+ else
+ mpData = rEntry.mpData;
+}
+
+WW8PLCFx_Fc_FKP::WW8Fkp::Entry&
+ WW8PLCFx_Fc_FKP::WW8Fkp::Entry::operator=(const Entry &rEntry)
+{
+ if (this == &rEntry)
+ return *this;
+
+ if (mbMustDelete)
+ delete[] mpData;
+
+ mnFC = rEntry.mnFC;
+ mnLen = rEntry.mnLen;
+ mnIStd = rEntry.mnIStd;
+ mbMustDelete = rEntry.mbMustDelete;
+
+ if (mbMustDelete)
+ {
+ mpData = new sal_uInt8[mnLen];
+ memcpy(mpData, rEntry.mpData, mnLen);
+ }
+ else
+ mpData = rEntry.mpData;
+ return *this;
+}
+
+WW8PLCFx_Fc_FKP::WW8Fkp::Entry::~Entry()
+{
+ if (mbMustDelete)
+ delete[] mpData;
+}
+
+void WW8PLCFx_Fc_FKP::WW8Fkp::Reset(WW8_FC nFc)
+{
+ SetIdx(0);
+ if (nFc >= 0)
+ SeekPos(nFc);
+}
+
+bool WW8PLCFx_Fc_FKP::WW8Fkp::SeekPos(WW8_FC nFc)
+{
+ if (nFc < maEntries[0].mnFC)
+ {
+ mnIdx = 0;
+ return false; // Nicht gefunden: nPos unterhalb kleinstem Eintrag
+ }
+
+ // Search from beginning?
+ if ((1 > mnIdx) || (nFc < maEntries[mnIdx-1].mnFC))
+ mnIdx = 1;
+
+ sal_uInt8 nI = mnIdx ? mnIdx : 1;
+ sal_uInt8 nEnd = mnIMax;
+
+ for(sal_uInt8 n = (1==mnIdx ? 1 : 2); n; --n )
+ {
+ for( ; nI <=nEnd; ++nI)
+ { // Suchen mit um 1 erhoehtem Index
+ if (nFc < maEntries[nI].mnFC)
+ { // Position gefunden
+ mnIdx = nI - 1; // nI - 1 ist der richtige Index
+ return true; // ... und fertig
+ }
+ }
+ nI = 1;
+ nEnd = mnIdx-1;
+ }
+ mnIdx = mnIMax; // Nicht gefunden, groesser als alle Eintraege
+ return false;
+}
+
+sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::Get(WW8_FC& rStart, WW8_FC& rEnd, sal_Int32& rLen)
+ const
+{
+ rLen = 0;
+
+ if (mnIdx >= mnIMax)
+ {
+ rStart = WW8_FC_MAX;
+ return 0;
+ }
+
+ rStart = maEntries[mnIdx].mnFC;
+ rEnd = maEntries[mnIdx + 1].mnFC;
+
+ sal_uInt8* pSprms = GetLenAndIStdAndSprms( rLen );
+ return pSprms;
+}
+
+bool WW8PLCFx_Fc_FKP::WW8Fkp::SetIdx(sal_uInt8 nI)
+{
+ if (nI < mnIMax)
+ {
+ mnIdx = nI;
+ return true;
+ }
+ return false;
+}
+
+sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::GetLenAndIStdAndSprms(sal_Int32& rLen) const
+{
+ rLen = maEntries[mnIdx].mnLen;
+ return maEntries[mnIdx].mpData;
+}
+
+const sal_uInt8* WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm( sal_uInt16 nId )
+{
+ if (mnIdx >= mnIMax)
+ return 0;
+
+ sal_Int32 nLen;
+ sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
+
+ WW8SprmIter aIter(pSprms, nLen, maSprmParser);
+ return aIter.FindSprm(nId);
+}
+
+bool WW8PLCFx_Fc_FKP::WW8Fkp::HasSprm(sal_uInt16 nId,
+ std::vector<const sal_uInt8 *> &rResult)
+{
+ if (mnIdx >= mnIMax)
+ return false;
+
+ sal_Int32 nLen;
+ sal_uInt8* pSprms = GetLenAndIStdAndSprms( nLen );
+
+ WW8SprmIter aIter(pSprms, nLen, maSprmParser);
+
+ while(aIter.GetSprms())
+ {
+ if (aIter.GetAktId() == nId)
+ rResult.push_back(aIter.GetAktParams());
+ aIter.advance();
+ };
+ return !rResult.empty();
+}
+
+//-----------------------------------------
+void WW8PLCFx::GetSprms( WW8PLCFxDesc* p )
+{
+ OSL_ENSURE( !this, "Falsches GetSprms gerufen" );
+ p->nStartPos = p->nEndPos = WW8_CP_MAX;
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ p->bRealLineEnd = false;
+ return;
+}
+
+long WW8PLCFx::GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen )
+{
+ OSL_ENSURE( !this, "Falsches GetNoSprms gerufen" );
+ rStart = rEnd = WW8_CP_MAX;
+ rLen = 0;
+ return 0;
+}
+
+// ...Idx2: Default: ignorieren
+sal_uLong WW8PLCFx::GetIdx2() const
+{
+ return 0;
+}
+
+void WW8PLCFx::SetIdx2(sal_uLong )
+{
+}
+
+class SamePos :
+ public std::unary_function<const WW8PLCFx_Fc_FKP::WW8Fkp *, bool>
+{
+private:
+ long mnPo;
+public:
+ SamePos(long nPo) : mnPo(nPo) {};
+ bool operator()(const WW8PLCFx_Fc_FKP::WW8Fkp *pFkp)
+ {return mnPo == pFkp->GetFilePos();}
+};
+
+//-----------------------------------------
+bool WW8PLCFx_Fc_FKP::NewFkp()
+{
+ WW8_CP nPLCFStart, nPLCFEnd;
+ void* pPage;
+
+ static const int WW8FkpSizeTabVer2[ PLCF_END ] =
+ {
+ 1, 1, 0 /*, 0, 0, 0*/
+ };
+ static const int WW8FkpSizeTabVer6[ PLCF_END ] =
+ {
+ 1, 7, 0 /*, 0, 0, 0*/
+ };
+ static const int WW8FkpSizeTabVer8[ PLCF_END ] =
+ {
+ 1, 13, 0 /*, 0, 0, 0*/
+ };
+ const int* pFkpSizeTab;
+
+ switch (GetFIBVersion())
+ {
+ case ww::eWW2:
+ pFkpSizeTab = WW8FkpSizeTabVer2;
+ break;
+ case ww::eWW6:
+ case ww::eWW7:
+ pFkpSizeTab = WW8FkpSizeTabVer6;
+ break;
+ case ww::eWW8:
+ pFkpSizeTab = WW8FkpSizeTabVer8;
+ break;
+ default:
+ // Programm-Fehler!
+ OSL_ENSURE( !this, "Es wurde vergessen, nVersion zu kodieren!" );
+ return false;
+ }
+
+ if (!pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ))
+ {
+ pFkp = 0;
+ return false; // PLCF fertig abgearbeitet
+ }
+ (*pPLCF)++;
+ long nPo = SVBT16ToShort( (sal_uInt8 *)pPage );
+ nPo <<= 9; // shift als LONG
+
+ long nAktFkpFilePos = pFkp ? pFkp->GetFilePos() : -1;
+ if (nAktFkpFilePos == nPo)
+ pFkp->Reset(GetStartFc());
+ else
+ {
+ myiter aIter =
+ std::find_if(maFkpCache.begin(), maFkpCache.end(), SamePos(nPo));
+ if (aIter != maFkpCache.end())
+ {
+ pFkp = *aIter;
+ pFkp->Reset(GetStartFc());
+ }
+ else if (0 != (pFkp = new WW8Fkp(GetFIBVersion(), pFKPStrm, pDataStrm, nPo,
+ pFkpSizeTab[ ePLCF ], ePLCF, GetStartFc())))
+ {
+ maFkpCache.push_back(pFkp);
+
+ if (maFkpCache.size() > eMaxCache)
+ {
+ delete maFkpCache.front();
+ maFkpCache.pop_front();
+ }
+ }
+ }
+
+ SetStartFc( -1 ); // Nur das erste Mal
+ return true;
+}
+
+WW8PLCFx_Fc_FKP::WW8PLCFx_Fc_FKP(SvStream* pSt, SvStream* pTblSt,
+ SvStream* pDataSt, const WW8Fib& rFib, ePLCFT ePl, WW8_FC nStartFcL)
+ : WW8PLCFx(rFib.GetFIBVersion(), true), pFKPStrm(pSt), pDataStrm(pDataSt),
+ pFkp(0), ePLCF(ePl), pPCDAttrs(0)
+{
+ SetStartFc(nStartFcL);
+ long nLenStruct = (8 > rFib.nVersion) ? 2 : 4;
+ if (ePl == CHP)
+ {
+ pPLCF = new WW8PLCF(pTblSt, rFib.fcPlcfbteChpx, rFib.lcbPlcfbteChpx,
+ nLenStruct, GetStartFc(), rFib.pnChpFirst, rFib.cpnBteChp);
+ }
+ else
+ {
+ pPLCF = new WW8PLCF(pTblSt, rFib.fcPlcfbtePapx, rFib.lcbPlcfbtePapx,
+ nLenStruct, GetStartFc(), rFib.pnPapFirst, rFib.cpnBtePap);
+ }
+}
+
+WW8PLCFx_Fc_FKP::~WW8PLCFx_Fc_FKP()
+{
+ myiter aEnd = maFkpCache.end();
+ for (myiter aIter = maFkpCache.begin(); aIter != aEnd; ++aIter)
+ delete *aIter;
+ delete pPLCF;
+ delete pPCDAttrs;
+}
+
+sal_uLong WW8PLCFx_Fc_FKP::GetIdx() const
+{
+ sal_uLong u = pPLCF->GetIdx() << 8;
+ if (pFkp)
+ u |= pFkp->GetIdx();
+ return u;
+}
+
+void WW8PLCFx_Fc_FKP::SetIdx( sal_uLong nIdx )
+{
+ if( !( nIdx & 0xffffff00L ) )
+ {
+ pPLCF->SetIdx( nIdx >> 8 );
+ pFkp = 0;
+ }
+ else
+ { //Es gab einen Fkp
+ //Lese PLCF um 1 Pos zurueck, um die Adresse des Fkp wiederzubekommen
+ pPLCF->SetIdx( ( nIdx >> 8 ) - 1 );
+ if (NewFkp()) // und lese Fkp wieder ein
+ {
+ sal_uInt8 nFkpIdx = static_cast<sal_uInt8>(nIdx & 0xff);
+ pFkp->SetIdx(nFkpIdx); // Dann stelle Fkp-Pos wieder ein
+ }
+ }
+}
+
+bool WW8PLCFx_Fc_FKP::SeekPos(WW8_FC nFcPos)
+{
+ // StartPos for next Where()
+ SetStartFc( nFcPos );
+
+ // find StartPos for next pPLCF->Get()
+ bool bRet = pPLCF->SeekPos(nFcPos);
+
+ // make FKP invalid?
+ WW8_CP nPLCFStart, nPLCFEnd;
+ void* pPage;
+ if( pFkp && pPLCF->Get( nPLCFStart, nPLCFEnd, pPage ) )
+ {
+ long nPo = SVBT16ToShort( (sal_uInt8 *)pPage );
+ nPo <<= 9; // shift als LONG
+ if (nPo != pFkp->GetFilePos())
+ pFkp = 0;
+ else
+ pFkp->SeekPos( nFcPos );
+ }
+ return bRet;
+}
+
+WW8_FC WW8PLCFx_Fc_FKP::Where()
+{
+ if( !pFkp )
+ {
+ if( !NewFkp() )
+ return WW8_FC_MAX;
+ }
+ WW8_FC nP = pFkp->Where();
+ if( nP != WW8_FC_MAX )
+ return nP;
+
+ pFkp = 0; // FKP beendet -> hole neuen
+ return Where(); // am einfachsten rekursiv
+}
+
+sal_uInt8* WW8PLCFx_Fc_FKP::GetSprmsAndPos(WW8_FC& rStart, WW8_FC& rEnd, sal_Int32& rLen)
+{
+ rLen = 0; // Default
+ rStart = rEnd = WW8_FC_MAX;
+
+ if( !pFkp ) // Fkp not there ?
+ {
+ if( !NewFkp() )
+ return 0;
+ }
+
+ sal_uInt8* pPos = pFkp->Get( rStart, rEnd, rLen );
+ if( rStart == WW8_FC_MAX ) //Not found
+ return 0;
+ return pPos;
+}
+
+WW8PLCFx& WW8PLCFx_Fc_FKP::operator ++( int )
+{
+ if( !pFkp )
+ {
+ if( !NewFkp() )
+ return *this;
+ }
+
+ (*pFkp)++;
+ if( pFkp->Where() == WW8_FC_MAX )
+ NewFkp();
+
+ return *this;
+}
+
+sal_uInt16 WW8PLCFx_Fc_FKP::GetIstd() const
+{
+ return pFkp ? pFkp->GetIstd() : 0xFFFF;
+}
+
+void WW8PLCFx_Fc_FKP::GetPCDSprms( WW8PLCFxDesc& rDesc )
+{
+ rDesc.pMemPos = 0;
+ rDesc.nSprmsLen = 0;
+ if( pPCDAttrs )
+ {
+ if( !pFkp )
+ {
+ DBG_WARNING(
+ "+Problem: GetPCDSprms: NewFkp necessay (not possible!)" );
+ if( !NewFkp() )
+ return;
+ }
+ pPCDAttrs->GetSprms(&rDesc);
+ }
+}
+
+const sal_uInt8* WW8PLCFx_Fc_FKP::HasSprm( sal_uInt16 nId )
+{
+ // const waere schoener, aber dafuer muesste NewFkp() ersetzt werden oder
+ // wegfallen
+ if( !pFkp )
+ {
+ DBG_WARNING( "+Motz: HasSprm: NewFkp noetig ( kein const moeglich )" );
+ // Passiert bei BugDoc 31722
+ if( !NewFkp() )
+ return 0;
+ }
+
+ const sal_uInt8* pRes = pFkp->HasSprm( nId );
+
+ if( !pRes )
+ {
+ WW8PLCFxDesc aDesc;
+ GetPCDSprms( aDesc );
+
+ if (aDesc.pMemPos)
+ {
+ WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen,
+ pFkp->GetSprmParser());
+ pRes = aIter.FindSprm(nId);
+ }
+ }
+
+ return pRes;
+}
+
+bool WW8PLCFx_Fc_FKP::HasSprm(sal_uInt16 nId, std::vector<const sal_uInt8 *> &rResult)
+{
+ // const waere schoener, aber dafuer muesste NewFkp() ersetzt werden oder
+ // wegfallen
+ if (!pFkp)
+ {
+ DBG_WARNING( "+Motz: HasSprm: NewFkp noetig ( kein const moeglich )" );
+ // Passiert bei BugDoc 31722
+ if( !NewFkp() )
+ return 0;
+ }
+
+ pFkp->HasSprm(nId, rResult);
+
+ WW8PLCFxDesc aDesc;
+ GetPCDSprms( aDesc );
+
+ if (aDesc.pMemPos)
+ {
+ WW8SprmIter aIter(aDesc.pMemPos, aDesc.nSprmsLen,
+ pFkp->GetSprmParser());
+ while(aIter.GetSprms())
+ {
+ if (aIter.GetAktId() == nId)
+ rResult.push_back(aIter.GetAktParams());
+ aIter.advance();
+ };
+ }
+ return !rResult.empty();
+}
+
+//-----------------------------------------
+
+WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream* pSt, SvStream* pTblSt,
+ SvStream* pDataSt, const WW8ScannerBase& rBase, ePLCFT ePl )
+ : WW8PLCFx_Fc_FKP(pSt, pTblSt, pDataSt, *rBase.pWw8Fib, ePl,
+ rBase.WW8Cp2Fc(0)), rSBase(rBase), nAttrStart(-1), nAttrEnd(-1),
+ bLineEnd(false),
+ bComplex( (7 < rBase.pWw8Fib->nVersion) || (0 != rBase.pWw8Fib->fComplex) )
+{
+ ResetAttrStartEnd();
+
+ pPcd = rSBase.pPiecePLCF ? new WW8PLCFx_PCD(GetFIBVersion(),
+ rBase.pPiecePLCF, 0, IsSevenMinus(GetFIBVersion())) : 0;
+
+ /*
+ Make a copy of the piece attributes for so that the calls to HasSprm on a
+ Fc_FKP will be able to take into account the current piece attributes,
+ despite the fact that such attributes can only be found through a cp based
+ mechanism.
+ */
+ if (pPcd)
+ {
+ pPCDAttrs = rSBase.pPLCFx_PCDAttrs ? new WW8PLCFx_PCDAttrs(
+ rSBase.pWw8Fib->GetFIBVersion(), pPcd, &rSBase) : 0;
+ }
+
+ pPieceIter = rSBase.pPieceIter;
+}
+
+WW8PLCFx_Cp_FKP::~WW8PLCFx_Cp_FKP()
+{
+ delete pPcd;
+}
+
+void WW8PLCFx_Cp_FKP::ResetAttrStartEnd()
+{
+ nAttrStart = -1;
+ nAttrEnd = -1;
+ bLineEnd = false;
+}
+
+sal_uLong WW8PLCFx_Cp_FKP::GetPCDIMax() const
+{
+ return pPcd ? pPcd->GetIMax() : 0;
+}
+
+sal_uLong WW8PLCFx_Cp_FKP::GetPCDIdx() const
+{
+ return pPcd ? pPcd->GetIdx() : 0;
+}
+
+void WW8PLCFx_Cp_FKP::SetPCDIdx( sal_uLong nIdx )
+{
+ if( pPcd )
+ pPcd->SetIdx( nIdx );
+}
+
+bool WW8PLCFx_Cp_FKP::SeekPos(WW8_CP nCpPos)
+{
+ if( pPcd ) // Complex
+ {
+ if( !pPcd->SeekPos( nCpPos ) ) // Piece setzen
+ return false;
+ if (pPCDAttrs && !pPCDAttrs->GetIter()->SeekPos(nCpPos))
+ return false;
+ return WW8PLCFx_Fc_FKP::SeekPos(pPcd->AktPieceStartCp2Fc(nCpPos));
+ }
+ // KEINE Piece-Table !!!
+ return WW8PLCFx_Fc_FKP::SeekPos( rSBase.WW8Cp2Fc(nCpPos) );
+}
+
+WW8_CP WW8PLCFx_Cp_FKP::Where()
+{
+ WW8_FC nFc = WW8PLCFx_Fc_FKP::Where();
+ if( pPcd )
+ return pPcd->AktPieceStartFc2Cp( nFc ); // Piece ermitteln
+ return rSBase.WW8Fc2Cp( nFc ); // KEINE Piece-Table !!!
+}
+
+void WW8PLCFx_Cp_FKP::GetSprms(WW8PLCFxDesc* p)
+{
+ WW8_CP nOrigCp = p->nStartPos;
+
+ if (!GetDirty()) //Normal case
+ {
+ p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(p->nStartPos, p->nEndPos,
+ p->nSprmsLen);
+ }
+ else
+ {
+ /*
+ For the odd case where we have a location in a fastsaved file which
+ does not have an entry in the FKP, perhaps its para end is in the next
+ piece, or perhaps the cp just doesn't exist at all in this document.
+ AdvSprm doesn't know so it sets the PLCF as dirty and we figure out
+ in this method what the situation is
+
+ It doesn't exist then the piece iterator will not be able to find it.
+ Otherwise our cool fastsave algorithm can be brought to bear on the
+ problem.
+ */
+ if( !pPieceIter )
+ return;
+ sal_uLong nOldPos = pPieceIter->GetIdx();
+ bool bOk = pPieceIter->SeekPos(nOrigCp);
+ pPieceIter->SetIdx( nOldPos );
+ if (!bOk)
+ return;
+ }
+
+ if( pPcd ) // Piece-Table vorhanden !!!
+ {
+ // Init ( noch kein ++ gerufen )
+ if( (nAttrStart > nAttrEnd) || (nAttrStart == -1) )
+ {
+ p->bRealLineEnd = (ePLCF == PAP);
+
+ if ( ((ePLCF == PAP ) || (ePLCF == CHP)) && (nOrigCp != WW8_CP_MAX) )
+ {
+ bool bIsUnicode=false;
+ /*
+ To find the end of a paragraph for a character in a
+ complex format file.
+
+ It is necessary to know the piece that contains the
+ character and the FC assigned to the character.
+ */
+
+ //We set the piece iterator to the piece that contains the
+ //character, now we have the correct piece for this character
+ sal_uLong nOldPos = pPieceIter->GetIdx();
+ p->nStartPos = nOrigCp;
+ pPieceIter->SeekPos( p->nStartPos);
+
+ //This is the FC assigned to the character, but we already
+ //have the result of the next stage, so we can skip this step
+ //WW8_FC nStartFc = rSBase.WW8Cp2Fc(p->nStartPos, &bIsUnicode);
+
+ /*
+ Using the FC of the character, first search the FKP that
+ describes the character to find the smallest FC in the rgfc
+ that is larger than the character FC.
+ */
+ //But the search has already been done, the next largest FC is
+ //p->nEndPos.
+ WW8_FC nOldEndPos = p->nEndPos;
+
+ /*
+ If the FC found in the FKP is less than or equal to the limit
+ FC of the piece, the end of the paragraph that contains the
+ character is at the FKP FC minus 1.
+ */
+ WW8_CP nCpStart, nCpEnd;
+ void* pData=NULL;
+ pPieceIter->Get(nCpStart, nCpEnd, pData);
+
+ WW8_FC nLimitFC = SVBT32ToUInt32( ((WW8_PCD*)pData)->fc );
+ WW8_FC nBeginLimitFC = nLimitFC;
+ if (IsEightPlus(GetFIBVersion()))
+ {
+ nBeginLimitFC =
+ WW8PLCFx_PCD::TransformPieceAddress(nLimitFC,
+ bIsUnicode);
+ }
+
+ nLimitFC = nBeginLimitFC +
+ (nCpEnd - nCpStart) * (bIsUnicode ? 2 : 1);
+
+ if (nOldEndPos <= nLimitFC)
+ {
+ p->nEndPos = nCpEnd -
+ (nLimitFC-nOldEndPos) / (bIsUnicode ? 2 : 1);
+ }
+ else
+ {
+ if (ePLCF == CHP)
+ p->nEndPos = nCpEnd;
+ else
+ {
+ /*
+ If the FKP FC that was found was greater than the FC
+ of the end of the piece, scan piece by piece toward
+ the end of the document until a piece is found that
+ contains a paragraph end mark.
+ */
+
+ /*
+ It's possible to check if a piece contains a paragraph
+ mark by using the FC of the beginning of the piece to
+ search in the FKPs for the smallest FC in the FKP rgfc
+ that is greater than the FC of the beginning of the
+ piece. If the FC found is less than or equal to the
+ limit FC of the piece, then the character that ends
+ the paragraph is the character immediately before the
+ FKP fc
+ */
+
+ (*pPieceIter)++;
+
+ for (;pPieceIter->GetIdx() < pPieceIter->GetIMax();
+ (*pPieceIter)++)
+ {
+ if( !pPieceIter->Get( nCpStart, nCpEnd, pData ) )
+ {
+ OSL_ENSURE( !this, "piece iter broken!" );
+ break;
+ }
+ bIsUnicode = false;
+ sal_Int32 nFcStart=SVBT32ToUInt32(((WW8_PCD*)pData)->fc);
+
+ if (IsEightPlus(GetFIBVersion()))
+ {
+ nFcStart =
+ WW8PLCFx_PCD::TransformPieceAddress(
+ nFcStart,bIsUnicode );
+ }
+
+ nLimitFC = nFcStart + (nCpEnd - nCpStart) *
+ (bIsUnicode ? 2 : 1);
+
+ //if it doesn't exist, skip it
+ if (!SeekPos(nCpStart))
+ continue;
+
+ WW8_FC nOne,nSmallest;
+ p->pMemPos = WW8PLCFx_Fc_FKP::GetSprmsAndPos(nOne,
+ nSmallest, p->nSprmsLen);
+
+ if (nSmallest <= nLimitFC)
+ {
+ p->nEndPos = nCpEnd -
+ (nLimitFC-nSmallest) / (bIsUnicode ? 2 : 1);
+ break;
+ }
+ }
+ }
+ }
+ pPieceIter->SetIdx( nOldPos );
+ }
+ else
+ pPcd->AktPieceFc2Cp( p->nStartPos, p->nEndPos,&rSBase );
+ }
+ else
+ {
+ p->nStartPos = nAttrStart;
+ p->nEndPos = nAttrEnd;
+ p->bRealLineEnd = bLineEnd;
+ }
+ }
+ else // KEINE Piece-Table !!!
+ {
+ p->nStartPos = rSBase.WW8Fc2Cp( p->nStartPos );
+ p->nEndPos = rSBase.WW8Fc2Cp( p->nEndPos );
+ p->bRealLineEnd = ePLCF == PAP;
+ }
+}
+
+WW8PLCFx& WW8PLCFx_Cp_FKP::operator ++( int )
+{
+ WW8PLCFx_Fc_FKP::operator ++( 0 );
+ // !pPcd: Notbremse
+ if ( !bComplex || !pPcd )
+ return *this;
+
+ if( GetPCDIdx() >= GetPCDIMax() ) // End of PLCF
+ {
+ nAttrStart = nAttrEnd = WW8_CP_MAX;
+ return *this;
+ }
+
+ sal_Int32 nFkpLen; // Fkp-Eintrag
+ // Fkp-Eintrag holen
+ WW8PLCFx_Fc_FKP::GetSprmsAndPos(nAttrStart, nAttrEnd, nFkpLen);
+
+ pPcd->AktPieceFc2Cp( nAttrStart, nAttrEnd, &rSBase );
+ bLineEnd = (ePLCF == PAP);
+ return *this;
+}
+
+//-----------------------------------------
+//-----------------------------------------
+
+WW8PLCFx_SEPX::WW8PLCFx_SEPX(SvStream* pSt, SvStream* pTblSt,
+ const WW8Fib& rFib, WW8_CP nStartCp)
+ : WW8PLCFx(rFib.GetFIBVersion(), true), maSprmParser(rFib.GetFIBVersion()),
+ pStrm(pSt), nArrMax(256), nSprmSiz(0)
+{
+ pPLCF = rFib.lcbPlcfsed
+ ? new WW8PLCF(pTblSt, rFib.fcPlcfsed, rFib.lcbPlcfsed,
+ GetFIBVersion() <= ww::eWW2 ? 6 : 12, nStartCp)
+ : 0;
+
+ pSprms = new sal_uInt8[nArrMax]; // maximum length
+}
+
+WW8PLCFx_SEPX::~WW8PLCFx_SEPX()
+{
+ delete pPLCF;
+ delete[] pSprms;
+}
+
+sal_uLong WW8PLCFx_SEPX::GetIdx() const
+{
+ return pPLCF ? pPLCF->GetIdx() : 0;
+}
+
+void WW8PLCFx_SEPX::SetIdx( sal_uLong nIdx )
+{
+ if( pPLCF ) pPLCF->SetIdx( nIdx );
+}
+
+bool WW8PLCFx_SEPX::SeekPos(WW8_CP nCpPos)
+{
+ return pPLCF ? pPLCF->SeekPos( nCpPos ) : 0;
+}
+
+WW8_CP WW8PLCFx_SEPX::Where()
+{
+ return pPLCF ? pPLCF->Where() : 0;
+}
+
+void WW8PLCFx_SEPX::GetSprms(WW8PLCFxDesc* p)
+{
+ if( !pPLCF ) return;
+
+ void* pData;
+
+ p->bRealLineEnd = false;
+ if (!pPLCF->Get( p->nStartPos, p->nEndPos, pData ))
+ {
+ p->nStartPos = p->nEndPos = WW8_CP_MAX; // PLCF fertig abgearbeitet
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ }
+ else
+ {
+ sal_uInt32 nPo = SVBT32ToUInt32( (sal_uInt8*)pData+2 );
+ if (nPo == 0xFFFFFFFF)
+ {
+ p->nStartPos = p->nEndPos = WW8_CP_MAX; // Sepx empty
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ }
+ else
+ {
+ pStrm->Seek( nPo );
+
+ // read len
+ if (GetFIBVersion() <= ww::eWW2) // eWW6 ?, docs say yes, but...
+ {
+ sal_uInt8 nSiz(0);
+ *pStrm >> nSiz;
+ nSprmSiz = nSiz;
+ }
+ else
+ *pStrm >> nSprmSiz;
+
+ if( nSprmSiz > nArrMax )
+ { // passt nicht
+ delete[] pSprms;
+ nArrMax = nSprmSiz; // Hole mehr Speicher
+ pSprms = new sal_uInt8[nArrMax];
+ }
+ pStrm->Read( pSprms, nSprmSiz ); // read Sprms
+
+ p->nSprmsLen = nSprmSiz;
+ p->pMemPos = pSprms; // return Position
+ }
+ }
+}
+
+WW8PLCFx& WW8PLCFx_SEPX::operator ++( int )
+{
+ if( pPLCF )
+ (*pPLCF)++;
+ return *this;
+}
+
+const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId ) const
+{
+ return HasSprm( nId, pSprms, nSprmSiz);
+}
+
+const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, const sal_uInt8* pOtherSprms,
+ long nOtherSprmSiz ) const
+{
+ const sal_uInt8 *pRet = 0;
+ if (pPLCF)
+ {
+ WW8SprmIter aIter(pOtherSprms, nOtherSprmSiz, maSprmParser);
+ pRet = aIter.FindSprm(nId);
+ }
+ return pRet;
+}
+
+bool WW8PLCFx_SEPX::Find4Sprms(sal_uInt16 nId1,sal_uInt16 nId2,sal_uInt16 nId3,sal_uInt16 nId4,
+ sal_uInt8*& p1, sal_uInt8*& p2, sal_uInt8*& p3, sal_uInt8*& p4) const
+{
+ if( !pPLCF )
+ return 0;
+
+ bool bFound = false;
+ p1 = 0;
+ p2 = 0;
+ p3 = 0;
+ p4 = 0;
+
+ sal_uInt8* pSp = pSprms;
+ sal_uInt16 i=0;
+ while (i + maSprmParser.MinSprmLen() <= nSprmSiz)
+ {
+ // Sprm gefunden?
+ sal_uInt16 nAktId = maSprmParser.GetSprmId(pSp);
+ bool bOk = true;
+ if( nAktId == nId1 )
+ p1 = pSp + maSprmParser.DistanceToData(nId1);
+ else if( nAktId == nId2 )
+ p2 = pSp + maSprmParser.DistanceToData(nId2);
+ else if( nAktId == nId3 )
+ p3 = pSp + maSprmParser.DistanceToData(nId3);
+ else if( nAktId == nId4 )
+ p4 = pSp + maSprmParser.DistanceToData(nId4);
+ else
+ bOk = false;
+ bFound |= bOk;
+ // erhoehe Zeiger, so dass er auf naechsten Sprm zeigt
+ sal_uInt16 x = maSprmParser.GetSprmSize(nAktId, pSp);
+ i = i + x;
+ pSp += x;
+ }
+ return bFound;
+}
+
+const sal_uInt8* WW8PLCFx_SEPX::HasSprm( sal_uInt16 nId, sal_uInt8 n2nd ) const
+{
+ if( !pPLCF )
+ return 0;
+
+ sal_uInt8* pSp = pSprms;
+
+ sal_uInt16 i=0;
+ while (i + maSprmParser.MinSprmLen() <= nSprmSiz)
+ {
+ // Sprm gefunden?
+ sal_uInt16 nAktId = maSprmParser.GetSprmId(pSp);
+ if (nAktId == nId)
+ {
+ sal_uInt8 *pRet = pSp + maSprmParser.DistanceToData(nId);
+ if (*pRet == n2nd)
+ return pRet;
+ }
+ // erhoehe Zeiger, so dass er auf naechsten Sprm zeigt
+ sal_uInt16 x = maSprmParser.GetSprmSize(nAktId, pSp);
+ i = i + x;
+ pSp += x;
+ }
+
+ return 0; // Sprm nicht gefunden
+}
+
+//-----------------------------------------
+WW8PLCFx_SubDoc::WW8PLCFx_SubDoc(SvStream* pSt, ww::WordVersion eVersion,
+ WW8_CP nStartCp, long nFcRef, long nLenRef, long nFcTxt, long nLenTxt,
+ long nStruct)
+ : WW8PLCFx(eVersion, true), pRef(0), pTxt(0)
+{
+ if( nLenRef && nLenTxt )
+ {
+ pRef = new WW8PLCF( pSt, nFcRef, nLenRef, nStruct, nStartCp );
+ pTxt = new WW8PLCF( pSt, nFcTxt, nLenTxt, 0, nStartCp );
+ }
+}
+
+WW8PLCFx_SubDoc::~WW8PLCFx_SubDoc()
+{
+ delete pRef;
+ delete pTxt;
+}
+
+sal_uLong WW8PLCFx_SubDoc::GetIdx() const
+{
+ // Wahrscheinlich pTxt... nicht noetig
+ if( pRef )
+ return ( pRef->GetIdx() << 16 | pTxt->GetIdx() );
+ return 0;
+}
+
+void WW8PLCFx_SubDoc::SetIdx( sal_uLong nIdx )
+{
+ if( pRef )
+ {
+ pRef->SetIdx( nIdx >> 16 );
+ // Wahrscheinlich pTxt... nicht noetig
+ pTxt->SetIdx( nIdx & 0xFFFF );
+ }
+}
+
+bool WW8PLCFx_SubDoc::SeekPos( WW8_CP nCpPos )
+{
+ return ( pRef ) ? pRef->SeekPos( nCpPos ) : false;
+}
+
+WW8_CP WW8PLCFx_SubDoc::Where()
+{
+ return ( pRef ) ? pRef->Where() : WW8_CP_MAX;
+}
+
+void WW8PLCFx_SubDoc::GetSprms(WW8PLCFxDesc* p)
+{
+ p->nStartPos = p->nEndPos = WW8_CP_MAX;
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ p->bRealLineEnd = false;
+
+ if (!pRef)
+ return;
+
+ sal_uLong nNr = pRef->GetIdx();
+
+ void *pData;
+ WW8_CP nFoo;
+ if (!pRef->Get(p->nStartPos, nFoo, pData))
+ {
+ p->nEndPos = p->nStartPos = WW8_CP_MAX;
+ return;
+ }
+
+ p->nEndPos = p->nStartPos + 1;
+
+ if (!pTxt)
+ return;
+
+ pTxt->SetIdx(nNr);
+
+ if (!pTxt->Get(p->nCp2OrIdx, p->nSprmsLen, pData))
+ {
+ p->nEndPos = p->nStartPos = WW8_CP_MAX;
+ p->nSprmsLen = 0;
+ return;
+ }
+
+ p->nSprmsLen -= p->nCp2OrIdx;
+}
+
+WW8PLCFx& WW8PLCFx_SubDoc::operator ++( int )
+{
+ if( pRef && pTxt )
+ {
+ (*pRef)++;
+ (*pTxt)++;
+ }
+ return *this;
+}
+
+//-----------------------------------------
+// Felder
+//-----------------------------------------
+
+WW8PLCFx_FLD::WW8PLCFx_FLD( SvStream* pSt, const WW8Fib& rMyFib, short nType)
+ : WW8PLCFx(rMyFib.GetFIBVersion(), true), pPLCF(0), rFib(rMyFib)
+{
+ long nFc, nLen;
+
+ switch( nType )
+ {
+ case MAN_HDFT:
+ nFc = rFib.fcPlcffldHdr;
+ nLen = rFib.lcbPlcffldHdr;
+ break;
+ case MAN_FTN:
+ nFc = rFib.fcPlcffldFtn;
+ nLen = rFib.lcbPlcffldFtn;
+ break;
+ case MAN_EDN:
+ nFc = rFib.fcPlcffldEdn;
+ nLen = rFib.lcbPlcffldEdn;
+ break;
+ case MAN_AND:
+ nFc = rFib.fcPlcffldAtn;
+ nLen = rFib.lcbPlcffldAtn;
+ break;
+ case MAN_TXBX:
+ nFc = rFib.fcPlcffldTxbx;
+ nLen = rFib.lcbPlcffldTxbx;
+ break;
+ case MAN_TXBX_HDFT:
+ nFc = rFib.fcPlcffldHdrTxbx;
+ nLen = rFib.lcbPlcffldHdrTxbx;
+ break;
+ default:
+ nFc = rFib.fcPlcffldMom;
+ nLen = rFib.lcbPlcffldMom;
+ break;
+ }
+
+ if( nLen )
+ pPLCF = new WW8PLCFspecial( pSt, nFc, nLen, 2 );
+}
+
+WW8PLCFx_FLD::~WW8PLCFx_FLD()
+{
+ delete pPLCF;
+}
+
+sal_uLong WW8PLCFx_FLD::GetIdx() const
+{
+ return pPLCF ? pPLCF->GetIdx() : 0;
+}
+
+void WW8PLCFx_FLD::SetIdx( sal_uLong nIdx )
+{
+ if( pPLCF )
+ pPLCF->SetIdx( nIdx );
+}
+
+bool WW8PLCFx_FLD::SeekPos(WW8_CP nCpPos)
+{
+ return pPLCF ? pPLCF->SeekPosExact( nCpPos ) : false;
+}
+
+WW8_CP WW8PLCFx_FLD::Where()
+{
+ return pPLCF ? pPLCF->Where() : WW8_CP_MAX;
+}
+
+bool WW8PLCFx_FLD::StartPosIsFieldStart()
+{
+ void* pData;
+ sal_Int32 nTest;
+ if (
+ (!pPLCF || !pPLCF->Get(nTest, pData) ||
+ ((((sal_uInt8*)pData)[0] & 0x1f) != 0x13))
+ )
+ return false;
+ return true;
+}
+
+bool WW8PLCFx_FLD::EndPosIsFieldEnd()
+{
+ bool bRet = false;
+
+ if (pPLCF)
+ {
+ long n = pPLCF->GetIdx();
+
+ (*pPLCF)++;
+
+ void* pData;
+ sal_Int32 nTest;
+ if ( pPLCF->Get(nTest, pData) && ((((sal_uInt8*)pData)[0] & 0x1f) == 0x15) )
+ bRet = true;
+
+ pPLCF->SetIdx(n);
+ }
+
+ return bRet;
+}
+
+void WW8PLCFx_FLD::GetSprms(WW8PLCFxDesc* p)
+{
+ p->nStartPos = p->nEndPos = WW8_CP_MAX;
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ p->bRealLineEnd = false;
+
+ if (!pPLCF)
+ {
+ p->nStartPos = WW8_CP_MAX; // Es gibt keine Felder
+ return;
+ }
+
+ long n = pPLCF->GetIdx();
+
+ sal_Int32 nP;
+ void *pData;
+ if (!pPLCF->Get(nP, pData)) // Ende des PLCFspecial ?
+ {
+ p->nStartPos = WW8_CP_MAX; // PLCF fertig abgearbeitet
+ return;
+ }
+
+ p->nStartPos = nP;
+
+ (*pPLCF)++;
+ if (!pPLCF->Get(nP, pData)) // Ende des PLCFspecial ?
+ {
+ p->nStartPos = WW8_CP_MAX; // PLCF fertig abgearbeitet
+ return;
+ }
+
+ p->nEndPos = nP;
+
+ pPLCF->SetIdx(n);
+
+ p->nCp2OrIdx = pPLCF->GetIdx();
+}
+
+WW8PLCFx& WW8PLCFx_FLD::operator ++( int )
+{
+ (*pPLCF)++;
+ return *this;
+}
+
+bool WW8PLCFx_FLD::GetPara(long nIdx, WW8FieldDesc& rF)
+{
+ OSL_ENSURE( pPLCF, "Aufruf ohne Feld PLCFspecial" );
+ if( !pPLCF )
+ return false;
+
+ long n = pPLCF->GetIdx();
+ pPLCF->SetIdx(nIdx);
+
+ bool bOk = WW8GetFieldPara(*pPLCF, rF);
+
+ pPLCF->SetIdx(n);
+ return bOk;
+}
+
+//-----------------------------------------
+// class WW8PLCF_Book
+//-----------------------------------------
+
+/* to be optimized like this: */
+void WW8ReadSTTBF(bool bVer8, SvStream& rStrm, sal_uInt32 nStart, sal_Int32 nLen,
+ sal_uInt16 nExtraLen, rtl_TextEncoding eCS, std::vector<String> &rArray,
+ std::vector<ww::bytes>* pExtraArray, ::std::vector<String>* pValueArray)
+{
+ if(nLen==0) // Handle Empty STTBF
+ return;
+
+ sal_uLong nOldPos = rStrm.Tell();
+ rStrm.Seek( nStart );
+
+ sal_uInt16 nLen2;
+ rStrm >> nLen2; // bVer67: total length of structure
+ // bVer8 : count of strings
+
+ if( bVer8 )
+ {
+ sal_uInt16 nStrings;
+ bool bUnicode = (0xFFFF == nLen2);
+ if( bUnicode )
+ rStrm >> nStrings;
+ else
+ nStrings = nLen2;
+
+ rStrm >> nExtraLen;
+
+ for( sal_uInt16 i=0; i < nStrings; i++ )
+ {
+ if( bUnicode )
+ rArray.push_back(WW8Read_xstz(rStrm, 0, false));
+ else
+ {
+ sal_uInt8 nBChar;
+ rStrm >> nBChar;
+ ByteString aTmp;
+ SafeReadString(aTmp,nBChar,rStrm);
+ rArray.push_back(String(aTmp, eCS));
+ }
+
+ // Skip the extra data
+ if( nExtraLen )
+ {
+ if (pExtraArray)
+ {
+ ww::bytes extraData;
+ sal_uInt8 iTmp;
+ for(int j = 0; j < nExtraLen; ++j)
+ {
+ rStrm >> iTmp;
+ extraData.push_back(iTmp);
+ }
+ pExtraArray->push_back(extraData);
+ }
+ else
+ rStrm.SeekRel( nExtraLen );
+ }
+ }
+ // read the value of the document variables, if requested.
+ if (pValueArray)
+ {
+ for( sal_uInt16 i=0; i < nStrings; i++ )
+ {
+ if( bUnicode )
+ pValueArray->push_back(WW8Read_xstz(rStrm, 0, false));
+ else
+ {
+ sal_uInt8 nBChar;
+ rStrm >> nBChar;
+ ByteString aTmp;
+ SafeReadString(aTmp,nBChar,rStrm);
+ pValueArray->push_back(String(aTmp, eCS));
+ }
+ }
+ }
+ }
+ else
+ {
+ sal_uInt8 nBChar;
+ if( nLen2 != nLen )
+ {
+ OSL_ENSURE( nLen2 == nLen, "Fib length and read length are different" );
+ if (nLen > USHRT_MAX)
+ nLen = USHRT_MAX;
+ else if (nLen < 2 )
+ nLen = 2;
+ nLen2 = static_cast<sal_uInt16>(nLen);
+ }
+ sal_uLong nRead = 0;
+ for( nLen2 -= 2; nRead < nLen2; )
+ {
+ rStrm >> nBChar; ++nRead;
+ if (nBChar)
+ {
+ ByteString aTmp;
+ nRead += SafeReadString(aTmp,nBChar,rStrm);
+ rArray.push_back(String(aTmp, eCS));
+ }
+ else
+ rArray.push_back(aEmptyStr);
+
+ // Skip the extra data (for bVer67 versions this must come from external knowledge)
+ if (nExtraLen)
+ {
+ if (pExtraArray)
+ {
+ ww::bytes extraData;
+ for(int i =0;i < nExtraLen;i++)
+ {
+ sal_uInt8 iTmp;
+ rStrm >> iTmp;
+ extraData.push_back(iTmp);
+ }
+ pExtraArray->push_back(extraData);
+ }
+ else
+ rStrm.SeekRel( nExtraLen );
+ nRead+=nExtraLen;
+ }
+ }
+ }
+ rStrm.Seek( nOldPos );
+}
+
+WW8PLCFx_Book::WW8PLCFx_Book(SvStream* pTblSt, const WW8Fib& rFib)
+ : WW8PLCFx(rFib.GetFIBVersion(), false), pStatus(0), nIsEnd(0), nBookmarkId(1)
+{
+ if( !rFib.fcPlcfbkf || !rFib.lcbPlcfbkf || !rFib.fcPlcfbkl ||
+ !rFib.lcbPlcfbkl || !rFib.fcSttbfbkmk || !rFib.lcbSttbfbkmk )
+ {
+ pBook[0] = pBook[1] = 0;
+ nIMax = 0;
+ }
+ else
+ {
+ pBook[0] = new WW8PLCFspecial(pTblSt,rFib.fcPlcfbkf,rFib.lcbPlcfbkf,4);
+
+ pBook[1] = new WW8PLCFspecial(pTblSt,rFib.fcPlcfbkl,rFib.lcbPlcfbkl,0);
+
+ rtl_TextEncoding eStructChrSet = WW8Fib::GetFIBCharset(rFib.chseTables);
+
+ WW8ReadSTTBF( (7 < rFib.nVersion), *pTblSt, rFib.fcSttbfbkmk,
+ rFib.lcbSttbfbkmk, 0, eStructChrSet, aBookNames );
+
+ nIMax = aBookNames.size();
+
+ if( pBook[0]->GetIMax() < nIMax ) // Count of Bookmarks
+ nIMax = pBook[0]->GetIMax();
+ if( pBook[1]->GetIMax() < nIMax )
+ nIMax = pBook[1]->GetIMax();
+ pStatus = new eBookStatus[ nIMax ];
+ memset( pStatus, 0, nIMax * sizeof( eBookStatus ) );
+ }
+}
+
+WW8PLCFx_Book::~WW8PLCFx_Book()
+{
+ delete[] pStatus;
+ delete pBook[1];
+ delete pBook[0];
+}
+
+sal_uLong WW8PLCFx_Book::GetIdx() const
+{
+ return nIMax ? pBook[0]->GetIdx() : 0;
+}
+
+void WW8PLCFx_Book::SetIdx( sal_uLong nI )
+{
+ if( nIMax )
+ pBook[0]->SetIdx( nI );
+}
+
+sal_uLong WW8PLCFx_Book::GetIdx2() const
+{
+ return nIMax ? ( pBook[1]->GetIdx() | ( ( nIsEnd ) ? 0x80000000 : 0 ) ) : 0;
+}
+
+void WW8PLCFx_Book::SetIdx2( sal_uLong nI )
+{
+ if( nIMax )
+ {
+ pBook[1]->SetIdx( nI & 0x7fffffff );
+ nIsEnd = (sal_uInt16)( ( nI >> 31 ) & 1 ); // 0 oder 1
+ }
+}
+
+bool WW8PLCFx_Book::SeekPos(WW8_CP nCpPos)
+{
+ if( !pBook[0] )
+ return false;
+
+ bool bOk = pBook[0]->SeekPosExact( nCpPos );
+ bOk &= pBook[1]->SeekPosExact( nCpPos );
+ nIsEnd = 0;
+
+ return bOk;
+}
+
+WW8_CP WW8PLCFx_Book::Where()
+{
+ return pBook[nIsEnd]->Where();
+}
+
+long WW8PLCFx_Book::GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen )
+{
+ void* pData;
+ rEnd = WW8_CP_MAX;
+ rLen = 0;
+
+ if (!pBook[0] || !pBook[1] || !nIMax || (pBook[nIsEnd]->GetIdx()) >= nIMax)
+ {
+ rStart = rEnd = WW8_CP_MAX;
+ return -1;
+ }
+
+ pBook[nIsEnd]->Get( rStart, pData ); // Pos. abfragen
+
+ return pBook[nIsEnd]->GetIdx();
+}
+
+// Der Operator ++ hat eine Tuecke: Wenn 2 Bookmarks aneinandergrenzen, dann
+// sollte erst das Ende des ersten und dann der Anfang des 2. erreicht werden.
+// Liegen jedoch 2 Bookmarks der Laenge 0 aufeinander, *muss* von jedem Bookmark
+// erst der Anfang und dann das Ende gefunden werden.
+// Der Fall: ][
+// [...]
+// ][
+// ist noch nicht geloest, dabei muesste ich in den Anfangs- und Endindices
+// vor- und zurueckspringen, wobei ein weiterer Index oder ein Bitfeld
+// oder etwas aehnliches zum Merken der bereits abgearbeiteten Bookmarks
+// noetig wird.
+WW8PLCFx& WW8PLCFx_Book::operator ++( int )
+{
+ if( pBook[0] && pBook[1] && nIMax )
+ {
+ (*pBook[nIsEnd])++;
+
+ sal_uLong l0 = pBook[0]->Where();
+ sal_uLong l1 = pBook[1]->Where();
+ if( l0 < l1 )
+ nIsEnd = 0;
+ else if( l1 < l0 )
+ nIsEnd = 1;
+ else
+ nIsEnd = ( nIsEnd ) ? 0 : 1;
+ }
+ return *this;
+}
+
+long WW8PLCFx_Book::GetLen() const
+{
+ if( nIsEnd )
+ {
+ OSL_ENSURE( !this, "Falscher Aufruf (1) von PLCF_Book::GetLen()" );
+ return 0;
+ }
+ void * p;
+ WW8_CP nStartPos;
+ if( !pBook[0]->Get( nStartPos, p ) )
+ {
+ OSL_ENSURE( !this, "Falscher Aufruf (2) von PLCF_Book::GetLen()" );
+ return 0;
+ }
+ sal_uInt16 nEndIdx = SVBT16ToShort( *((SVBT16*)p) );
+ long nNum = pBook[1]->GetPos( nEndIdx );
+ nNum -= nStartPos;
+ return nNum;
+}
+
+void WW8PLCFx_Book::SetStatus(sal_uInt16 nIndex, eBookStatus eStat )
+{
+ OSL_ENSURE(nIndex < nIMax, "set status of non existing bookmark!");
+ pStatus[nIndex] = (eBookStatus)( pStatus[nIndex] | eStat );
+}
+
+eBookStatus WW8PLCFx_Book::GetStatus() const
+{
+ if( !pStatus )
+ return BOOK_NORMAL;
+ long nEndIdx = GetHandle();
+ return ( nEndIdx < nIMax ) ? pStatus[nEndIdx] : BOOK_NORMAL;
+}
+
+long WW8PLCFx_Book::GetHandle() const
+{
+ if( !pBook[0] || !pBook[1] )
+ return LONG_MAX;
+
+ if( nIsEnd )
+ return pBook[1]->GetIdx();
+ else
+ {
+ if (const void* p = pBook[0]->GetData(pBook[0]->GetIdx()))
+ return SVBT16ToShort( *((SVBT16*)p) );
+ else
+ return LONG_MAX;
+ }
+}
+
+String WW8PLCFx_Book::GetBookmark(long nStart,long nEnd, sal_uInt16 &nIndex)
+{
+ bool bFound = false;
+ sal_uInt16 i = 0;
+ if( pBook[0] && pBook[1] )
+ {
+ WW8_CP nStartAkt, nEndAkt;
+ do
+ {
+ void* p;
+ sal_uInt16 nEndIdx;
+
+ if( pBook[0]->GetData( i, nStartAkt, p ) && p )
+ nEndIdx = SVBT16ToShort( *((SVBT16*)p) );
+ else
+ {
+ OSL_ENSURE( !this, "Bookmark-EndIdx nicht lesbar" );
+ nEndIdx = i;
+ }
+
+ nEndAkt = pBook[1]->GetPos( nEndIdx );
+
+ if ((nStartAkt >= nStart) && (nEndAkt <= nEnd))
+ {
+ nIndex = i;
+ bFound=true;
+ break;
+ }
+ ++i;
+ }
+ while (i < pBook[0]->GetIMax());
+ }
+ return bFound ? aBookNames[i] : aEmptyStr;
+}
+
+String WW8PLCFx_Book::GetUniqueBookmarkName(String &suggestedName)
+{
+ String aRet=(suggestedName.Len()==0?String::CreateFromAscii("Unnamed"):suggestedName);
+ unsigned int i=0;
+ while(i<aBookNames.size()) {
+ String &s=aBookNames[i];
+ if (aRet.CompareTo(s)==0) {
+ int len=aRet.Len();
+ int p=len-1;
+ while(p>0 && aRet.GetChar(static_cast<sal_uInt16>(p))>='0' && aRet.GetChar(static_cast<sal_uInt16>(p))<='9')
+ p--;
+ aRet=String(aRet, 0, static_cast<sal_uInt16>(p+1));
+ aRet += String::CreateFromInt32( nBookmarkId++ );
+ i=0; // start search from beginning
+ } else {
+ i++;
+ }
+ }
+ return aRet;
+}
+
+bool WW8PLCFx_Book::MapName(String& rName)
+{
+ if( !pBook[0] || !pBook[1] )
+ return false;
+
+ bool bFound = false;
+ sal_uInt16 i = 0;
+ do
+ {
+ if (COMPARE_EQUAL == rName.CompareIgnoreCaseToAscii(aBookNames[i]))
+ {
+ rName = aBookNames[i];
+ bFound = true;
+ }
+ ++i;
+ }
+ while (!bFound && i < pBook[0]->GetIMax());
+ return bFound;
+}
+
+const String* WW8PLCFx_Book::GetName() const
+{
+ const String *pRet = 0;
+ if (!nIsEnd && (pBook[0]->GetIdx() < nIMax))
+ pRet = &(aBookNames[pBook[0]->GetIdx()]);
+ return pRet;
+}
+
+//-----------------------------------------
+// WW8PLCFMan
+//-----------------------------------------
+
+#ifndef DUMP
+
+// Am Ende eines Absatzes reichen bei WW6 die Attribute bis hinter das <CR>.
+// Das wird fuer die Verwendung mit dem SW um 1 Zeichen zurueckgesetzt, wenn
+// dadurch kein AErger zu erwarten ist.
+void WW8PLCFMan::AdjustEnds( WW8PLCFxDesc& rDesc )
+{
+ //Store old end position for supercool new property finder that uses
+ //cp instead of fc's as nature intended
+ rDesc.nOrigEndPos = rDesc.nEndPos;
+ rDesc.nOrigStartPos = rDesc.nStartPos;
+
+ /*
+ Normally given ^XXX{para end}^ we don't actually insert a para end
+ character into the document, so we clip the para end property one to the
+ left to make the para properties end when the paragraph text does. In a
+ drawing textbox we actually do insert a para end character, so we don't
+ clip it. Making the para end properties end after the para end char.
+ */
+ if (GetDoingDrawTextBox())
+ return;
+
+ if ( (&rDesc == pPap) && rDesc.bRealLineEnd )
+ {
+ if ( pPap->nEndPos != WW8_CP_MAX ) // Para adjust
+ {
+ nLineEnd = pPap->nEndPos;// nLineEnd zeigt *hinter* das <CR>
+ pPap->nEndPos--; // Absatzende um 1 Zeichen verkuerzen
+
+ // gibt es bereits ein CharAttr-Ende das auf das jetzige
+ // Absatzende zeigt ? ... dann auch um 1 Zeichen verkuerzen
+ if (pChp->nEndPos == nLineEnd)
+ pChp->nEndPos--;
+
+ // gibt es bereits ein Sep-Ende, das auf das jetzige Absatzende
+ // zeigt ? ... dann auch um 1 Zeichen verkuerzen
+ if( pSep->nEndPos == nLineEnd )
+ pSep->nEndPos--;
+ }
+ }
+ else if ( (&rDesc == pChp) || (&rDesc == pSep) )
+ {
+ // Char Adjust oder Sep Adjust Wenn Ende Char-Attr == Absatzende ...
+ if( (rDesc.nEndPos == nLineEnd) && (rDesc.nEndPos > rDesc.nStartPos) )
+ rDesc.nEndPos--; // ... dann um 1 Zeichen verkuerzen
+ }
+}
+
+void WW8PLCFxDesc::ReduceByOffset()
+{
+ OSL_ENSURE((WW8_CP_MAX == nStartPos) || (nStartPos <= nEndPos),
+ "Attr-Anfang und -Ende ueber Kreuz" );
+
+ if( nStartPos != WW8_CP_MAX )
+ {
+ /*
+ ##516##,##517##
+ Force the property change to happen at the beginning of this
+ subdocument, same as in GetNewNoSprms, except that the target type is
+ attributes attached to a piece that might span subdocument boundaries
+ */
+ if (nCpOfs > nStartPos)
+ nStartPos = 0;
+ else
+ nStartPos -= nCpOfs;
+ }
+ if( nEndPos != WW8_CP_MAX )
+ {
+ OSL_ENSURE(nCpOfs <= nEndPos,
+ "oh oh, so much for the subdocument piece theory");
+ nEndPos -= nCpOfs;
+ }
+}
+
+void WW8PLCFMan::GetNewSprms( WW8PLCFxDesc& rDesc )
+{
+ rDesc.pPLCFx->GetSprms(&rDesc);
+ rDesc.ReduceByOffset();
+
+ rDesc.bFirstSprm = true;
+ AdjustEnds( rDesc );
+ rDesc.nOrigSprmsLen = rDesc.nSprmsLen;
+}
+
+void WW8PLCFMan::GetNewNoSprms( WW8PLCFxDesc& rDesc )
+{
+ rDesc.nCp2OrIdx = rDesc.pPLCFx->GetNoSprms(rDesc.nStartPos, rDesc.nEndPos,
+ rDesc.nSprmsLen);
+
+ OSL_ENSURE((WW8_CP_MAX == rDesc.nStartPos) || (rDesc.nStartPos <= rDesc.nEndPos),
+ "Attr-Anfang und -Ende ueber Kreuz" );
+
+ rDesc.ReduceByOffset();
+
+ rDesc.bFirstSprm = true;
+ rDesc.nOrigSprmsLen = rDesc.nSprmsLen;
+}
+
+sal_uInt16 WW8PLCFMan::GetId(const WW8PLCFxDesc* p) const
+{
+ sal_uInt16 nId;
+
+ if (p == pFld)
+ nId = eFLD;
+ else if (p == pFtn)
+ nId = eFTN;
+ else if (p == pEdn)
+ nId = eEDN;
+ else if (p == pAnd)
+ nId = eAND;
+ else if (p->nSprmsLen > 0)
+ nId = maSprmParser.GetSprmId(p->pMemPos);
+ else
+ nId = 0; // Id = 0 for empty attributes
+
+ return nId;
+}
+
+WW8PLCFMan::WW8PLCFMan(WW8ScannerBase* pBase, ManTypes nType, long nStartCp,
+ bool bDoingDrawTextBox)
+ : maSprmParser(pBase->pWw8Fib->GetFIBVersion()),
+ mbDoingDrawTextBox(bDoingDrawTextBox)
+{
+ pWwFib = pBase->pWw8Fib;
+
+ nLastWhereIdxCp = 0;
+ memset( aD, 0, sizeof( aD ) );
+ nLineEnd = WW8_CP_MAX;
+ nManType = nType;
+ sal_uInt16 i;
+
+ if( MAN_MAINTEXT == nType )
+ {
+ // Suchreihenfolge der Attribute
+ nPLCF = MAN_ANZ_PLCF;
+ pFld = &aD[0];
+ pBkm = &aD[1];
+ pEdn = &aD[2];
+ pFtn = &aD[3];
+ pAnd = &aD[4];
+
+ pPcd = ( pBase->pPLCFx_PCD ) ? &aD[5] : 0;
+ //pPcdA index == pPcd index + 1
+ pPcdA = ( pBase->pPLCFx_PCDAttrs ) ? &aD[6] : 0;
+
+ pChp = &aD[7];
+ pPap = &aD[8];
+ pSep = &aD[9];
+
+ pSep->pPLCFx = pBase->pSepPLCF;
+ pFtn->pPLCFx = pBase->pFtnPLCF;
+ pEdn->pPLCFx = pBase->pEdnPLCF;
+ pBkm->pPLCFx = pBase->pBook;
+ pAnd->pPLCFx = pBase->pAndPLCF;
+
+ }
+ else
+ {
+ // Suchreihenfolge der Attribute
+ nPLCF = 7;
+ pFld = &aD[0];
+ pBkm = ( pBase->pBook ) ? &aD[1] : 0;
+
+ pPcd = ( pBase->pPLCFx_PCD ) ? &aD[2] : 0;
+ //pPcdA index == pPcd index + 1
+ pPcdA= ( pBase->pPLCFx_PCDAttrs ) ? &aD[3] : 0;
+
+ pChp = &aD[4];
+ pPap = &aD[5];
+ pSep = &aD[6]; // Dummy
+
+ pAnd = pFtn = pEdn = 0; // unbenutzt bei SpezText
+ }
+
+ pChp->pPLCFx = pBase->pChpPLCF;
+ pPap->pPLCFx = pBase->pPapPLCF;
+ if( pPcd )
+ pPcd->pPLCFx = pBase->pPLCFx_PCD;
+ if( pPcdA )
+ pPcdA->pPLCFx= pBase->pPLCFx_PCDAttrs;
+ if( pBkm )
+ pBkm->pPLCFx = pBase->pBook;
+
+ pMagicTables = pBase->pMagicTables;
+ pSubdocs = pBase->pSubdocs;
+ pExtendedAtrds = pBase->pExtendedAtrds;
+
+ switch( nType ) // Feld-Initialisierung
+ {
+ case MAN_HDFT:
+ pFld->pPLCFx = pBase->pFldHdFtPLCF;
+ pFdoa = pBase->pHdFtFdoa;
+ pTxbx = pBase->pHdFtTxbx;
+ pTxbxBkd = pBase->pHdFtTxbxBkd;
+ break;
+ case MAN_FTN:
+ pFld->pPLCFx = pBase->pFldFtnPLCF;
+ pFdoa = pTxbx = pTxbxBkd = 0;
+ break;
+ case MAN_EDN:
+ pFld->pPLCFx = pBase->pFldEdnPLCF;
+ pFdoa = pTxbx = pTxbxBkd = 0;
+ break;
+ case MAN_AND:
+ pFld->pPLCFx = pBase->pFldAndPLCF;
+ pFdoa = pTxbx = pTxbxBkd = 0;
+ break;
+ case MAN_TXBX:
+ pFld->pPLCFx = pBase->pFldTxbxPLCF;
+ pTxbx = pBase->pMainTxbx;
+ pTxbxBkd = pBase->pMainTxbxBkd;
+ pFdoa = 0;
+ break;
+ case MAN_TXBX_HDFT:
+ pFld->pPLCFx = pBase->pFldTxbxHdFtPLCF;
+ pTxbx = pBase->pHdFtTxbx;
+ pTxbxBkd = pBase->pHdFtTxbxBkd;
+ pFdoa = 0;
+ break;
+ default:
+ pFld->pPLCFx = pBase->pFldPLCF;
+ pFdoa = pBase->pMainFdoa;
+ pTxbx = pBase->pMainTxbx;
+ pTxbxBkd = pBase->pMainTxbxBkd;
+ break;
+ }
+
+ nCpO = pWwFib->GetBaseCp(nType);
+
+ if( nStartCp || nCpO )
+ SeekPos( nStartCp ); // PLCFe auf Text-StartPos einstellen
+
+ // initialisieren der Member-Vars Low-Level
+ GetChpPLCF()->ResetAttrStartEnd();
+ GetPapPLCF()->ResetAttrStartEnd();
+ for( i=0; i < nPLCF; i++)
+ {
+ WW8PLCFxDesc* p = &aD[i];
+
+ /*
+ ##516##,##517##
+ For subdocuments we modify the cp of properties to be relative to
+ the beginning of subdocuments, we should also do the same for
+ piecetable changes, and piecetable properties, otherwise a piece
+ change that happens in a subdocument is lost.
+ */
+ p->nCpOfs = ( p == pChp || p == pPap || p == pBkm || p == pPcd ||
+ p == pPcdA ) ? nCpO : 0;
+
+ p->nCp2OrIdx = 0;
+ p->bFirstSprm = false;
+ p->pIdStk = 0;
+
+ if ((p == pChp) || (p == pPap))
+ p->nStartPos = p->nEndPos = nStartCp;
+ else
+ p->nStartPos = p->nEndPos = WW8_CP_MAX;
+ }
+
+ // initialisieren der Member-Vars High-Level
+ for( i=0; i<nPLCF; i++){
+ WW8PLCFxDesc* p = &aD[i];
+
+ if( !p->pPLCFx )
+ {
+ p->nStartPos = p->nEndPos = WW8_CP_MAX;
+ continue;
+ }
+
+ if( p->pPLCFx->IsSprm() )
+ {
+ // Vorsicht: nEndPos muss bereits
+ p->pIdStk = new std::stack<sal_uInt16>;
+ if ((p == pChp) || (p == pPap))
+ {
+ WW8_CP nTemp = p->nEndPos+p->nCpOfs;
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ p->nStartPos = nTemp;
+ if (!(*p->pPLCFx).SeekPos(p->nStartPos))
+ p->nEndPos = p->nStartPos = WW8_CP_MAX;
+ else
+ GetNewSprms( *p );
+ }
+ else
+ GetNewSprms( *p ); // bei allen PLCFen initialisiert sein
+ }
+ else if( p->pPLCFx )
+ GetNewNoSprms( *p );
+ }
+}
+
+WW8PLCFMan::~WW8PLCFMan()
+{
+ for( sal_uInt16 i=0; i<nPLCF; i++)
+ delete aD[i].pIdStk;
+}
+
+// 0. welche Attr.-Klasse,
+// 1. ob ein Attr.-Start ist,
+// 2. CP, wo ist naechste Attr.-Aenderung
+sal_uInt16 WW8PLCFMan::WhereIdx(bool* pbStart, long* pPos) const
+{
+ OSL_ENSURE(nPLCF,"What the hell");
+ long nNext = LONG_MAX; // SuchReihenfolge:
+ sal_uInt16 nNextIdx = nPLCF;// first ending found ( CHP, PAP, ( SEP ) ),
+ bool bStart = true; // dann Anfaenge finden ( ( SEP ), PAP, CHP )
+ sal_uInt16 i;
+ const WW8PLCFxDesc* pD;
+ for (i=0; i < nPLCF; i++)
+ {
+ pD = &aD[i];
+ if (pD != pPcdA)
+ {
+ if( (pD->nEndPos < nNext) && (pD->nStartPos == WW8_CP_MAX) )
+ {
+ // sonst ist Anfang = Ende
+ nNext = pD->nEndPos;
+ nNextIdx = i;
+ bStart = false;
+ }
+ }
+ }
+ for (i=nPLCF; i > 0; i--)
+ {
+ pD = &aD[i-1];
+ if (pD != pPcdA)
+ {
+ if( pD->nStartPos < nNext )
+ {
+ nNext = pD->nStartPos;
+ nNextIdx = i-1;
+ bStart = true;
+ }
+ }
+ }
+ if( pPos )
+ *pPos = nNext;
+ if( pbStart )
+ *pbStart = bStart;
+ return nNextIdx;
+}
+
+// gibt die CP-Pos der naechsten Attribut-Aenderung zurueck
+WW8_CP WW8PLCFMan::Where() const
+{
+ long l;
+ WhereIdx(0, &l);
+ return l;
+}
+
+void WW8PLCFMan::SeekPos( long nNewCp )
+{
+ pChp->pPLCFx->SeekPos( nNewCp + nCpO ); // Attribute neu
+ pPap->pPLCFx->SeekPos( nNewCp + nCpO ); // aufsetzen
+ pFld->pPLCFx->SeekPos( nNewCp );
+ if( pPcd )
+ pPcd->pPLCFx->SeekPos( nNewCp + nCpO );
+ if( pBkm )
+ pBkm->pPLCFx->SeekPos( nNewCp + nCpO );
+}
+
+void WW8PLCFMan::SaveAllPLCFx( WW8PLCFxSaveAll& rSave ) const
+{
+ sal_uInt16 i, n=0;
+ if( pPcd )
+ pPcd->Save( rSave.aS[n++] );
+ if( pPcdA )
+ pPcdA->Save( rSave.aS[n++] );
+
+ for(i=0; i<nPLCF; ++i)
+ if( pPcd != &aD[i] && pPcdA != &aD[i] )
+ aD[i].Save( rSave.aS[n++] );
+}
+
+void WW8PLCFMan::RestoreAllPLCFx( const WW8PLCFxSaveAll& rSave )
+{
+ sal_uInt16 i, n=0;
+ if( pPcd )
+ pPcd->Restore( rSave.aS[n++] );
+ if( pPcdA )
+ pPcdA->Restore( rSave.aS[n++] );
+
+ for(i=0; i<nPLCF; ++i)
+ if( pPcd != &aD[i] && pPcdA != &aD[i] )
+ aD[i].Restore( rSave.aS[n++] );
+}
+
+void WW8PLCFMan::GetSprmStart( short nIdx, WW8PLCFManResult* pRes ) const
+{
+ memset( pRes, 0, sizeof( WW8PLCFManResult ) );
+
+ // Pruefen !!!
+
+ pRes->nMemLen = 0;
+
+ const WW8PLCFxDesc* p = &aD[nIdx];
+
+ // first Sprm in a Group
+ if( p->bFirstSprm )
+ {
+ if( p == pPap )
+ pRes->nFlags |= MAN_MASK_NEW_PAP;
+ else if( p == pSep )
+ pRes->nFlags |= MAN_MASK_NEW_SEP;
+ }
+ pRes->pMemPos = p->pMemPos;
+ pRes->nSprmId = GetId(p);
+ pRes->nCp2OrIdx = p->nCp2OrIdx;
+ if ((p == pFtn) || (p == pEdn) || (p == pAnd))
+ pRes->nMemLen = p->nSprmsLen;
+ else if (p->nSprmsLen) //Normal
+ {
+ // Length of actual sprm
+ pRes->nMemLen = maSprmParser.GetSprmSize(pRes->nSprmId, pRes->pMemPos);
+ }
+}
+
+void WW8PLCFMan::GetSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const
+{
+ memset( pRes, 0, sizeof( WW8PLCFManResult ) );
+
+ const WW8PLCFxDesc* p = &aD[nIdx];
+
+ if (!(p->pIdStk->empty()))
+ pRes->nSprmId = p->pIdStk->top(); // get end position
+ else
+ {
+ OSL_ENSURE( !this, "No Id on the Stack" );
+ pRes->nSprmId = 0;
+ }
+}
+
+void WW8PLCFMan::GetNoSprmStart( short nIdx, WW8PLCFManResult* pRes ) const
+{
+ const WW8PLCFxDesc* p = &aD[nIdx];
+
+ pRes->nCpPos = p->nStartPos;
+ pRes->nMemLen = p->nSprmsLen;
+ pRes->nCp2OrIdx = p->nCp2OrIdx;
+
+ if( p == pFld )
+ pRes->nSprmId = eFLD;
+ else if( p == pFtn )
+ pRes->nSprmId = eFTN;
+ else if( p == pEdn )
+ pRes->nSprmId = eEDN;
+ else if( p == pBkm )
+ pRes->nSprmId = eBKN;
+ else if( p == pAnd )
+ pRes->nSprmId = eAND;
+ else if( p == pPcd )
+ {
+ //We slave the piece table attributes to the piece table, the piece
+ //table attribute iterator contains the sprms for this piece.
+ GetSprmStart( nIdx+1, pRes );
+ }
+ else
+ pRes->nSprmId = 0; // default: not found
+}
+
+void WW8PLCFMan::GetNoSprmEnd( short nIdx, WW8PLCFManResult* pRes ) const
+{
+ pRes->nMemLen = -1; // Ende-Kennzeichen
+
+ if( &aD[nIdx] == pBkm )
+ pRes->nSprmId = eBKN;
+ else if( &aD[nIdx] == pPcd )
+ {
+ //We slave the piece table attributes to the piece table, the piece
+ //table attribute iterator contains the sprms for this piece.
+ GetSprmEnd( nIdx+1, pRes );
+ }
+ else
+ pRes->nSprmId = 0;
+}
+
+bool WW8PLCFMan::TransferOpenSprms(std::stack<sal_uInt16> &rStack)
+{
+ for (int i = 0; i < nPLCF; ++i)
+ {
+ WW8PLCFxDesc* p = &aD[i];
+ if (!p || !p->pIdStk)
+ continue;
+ while (!p->pIdStk->empty())
+ {
+ rStack.push(p->pIdStk->top());
+ p->pIdStk->pop();
+ }
+ }
+ return rStack.empty();
+}
+
+void WW8PLCFMan::AdvSprm(short nIdx, bool bStart)
+{
+ WW8PLCFxDesc* p = &aD[nIdx]; // Sprm-Klasse(!) ermitteln
+
+ p->bFirstSprm = false;
+ if( bStart )
+ {
+ sal_uInt16 nLastId = GetId(p);
+ p->pIdStk->push(nLastId); // merke Id fuer Attribut-Ende
+
+ if( p->nSprmsLen )
+ { /*
+ Pruefe, ob noch Sprm(s) abzuarbeiten sind
+ */
+ if( p->pMemPos )
+ {
+ // Length of last sprm
+ sal_uInt16 nSprmL = maSprmParser.GetSprmSize(nLastId, p->pMemPos);
+
+ // Gesamtlaenge Sprms um SprmLaenge verringern
+ p->nSprmsLen -= nSprmL;
+
+ // Pos des evtl. naechsten Sprm
+ if (p->nSprmsLen < maSprmParser.MinSprmLen())
+ {
+ // sicherheitshalber auf Null setzen, da Enden folgen!
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ }
+ else
+ p->pMemPos += nSprmL;
+ }
+ else
+ p->nSprmsLen = 0;
+ }
+ if (p->nSprmsLen < maSprmParser.MinSprmLen())
+ p->nStartPos = WW8_CP_MAX; // es folgen Enden
+ }
+ else
+ {
+ if (!(p->pIdStk->empty()))
+ p->pIdStk->pop();
+ if (p->pIdStk->empty())
+ {
+ if ( (p == pChp) || (p == pPap) )
+ {
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ p->nStartPos = p->nOrigEndPos+p->nCpOfs;
+
+ /*
+ On failed seek we have run out of sprms, probably. But if its
+ a fastsaved file (has pPcd) then we may be just in a sprm free
+ gap between pieces that have them, so set dirty flag in sprm
+ finder to consider than.
+ */
+ if (!(*p->pPLCFx).SeekPos(p->nStartPos))
+ {
+ p->nEndPos = WW8_CP_MAX;
+ p->pPLCFx->SetDirty(true);
+ }
+ if (!p->pPLCFx->GetDirty() || pPcd)
+ GetNewSprms( *p );
+ p->pPLCFx->SetDirty(false);
+
+ /*
+ #i2325#
+ To get the character and paragraph properties you first get
+ the pap and chp and then apply the fastsaved pPcd properties
+ to the range. If a pap or chp starts inside the pPcd range
+ then we must bring the current pPcd range to a halt so as to
+ end those sprms, then the pap/chp will be processed, and then
+ we must force a restart of the pPcd on that pap/chp starting
+ boundary. Doing that effectively means that the pPcd sprms will
+ be applied to the new range. Not doing it means that the pPcd
+ sprms will only be applied to the first pap/chp set of
+ properties contained in the pap/chp range.
+
+ So we bring the pPcd to a halt on this location here, by
+ settings its end to the current start, then store the starting
+ position of the current range to clipstart. The pPcd sprms
+ will end as normal (albeit earlier than originally expected),
+ and the existance of a clipstart will force the pPcd iterater
+ to reread the current set of sprms instead of advancing to its
+ next set. Then the clipstart will be set as the starting
+ position which will force them to be applied directly after
+ the pap and chps.
+ */
+ if (pPcd && ((p->nStartPos > pPcd->nStartPos) ||
+ (pPcd->nStartPos == WW8_CP_MAX)) &&
+ (pPcd->nEndPos != p->nStartPos))
+ {
+ pPcd->nEndPos = p->nStartPos;
+ ((WW8PLCFx_PCD *)(pPcd->pPLCFx))->SetClipStart(
+ p->nStartPos);
+ }
+
+ }
+ else
+ {
+ (*p->pPLCFx)++; // next Group of Sprms
+ p->pMemPos = 0; // !!!
+ p->nSprmsLen = 0;
+ GetNewSprms( *p );
+ }
+ OSL_ENSURE( p->nStartPos <= p->nEndPos, "Attribut ueber Kreuz" );
+ }
+ }
+}
+
+void WW8PLCFMan::AdvNoSprm(short nIdx, bool bStart)
+{
+ /*
+ For the case of a piece table we slave the piece table attribute iterator
+ to the piece table and access it through that only. They are two seperate
+ structures, but act together as one logical one. The attributes only go
+ to the next entry when the piece changes
+ */
+ WW8PLCFxDesc* p = &aD[nIdx];
+
+ if( p == pPcd )
+ {
+ AdvSprm(nIdx+1,bStart);
+ if( bStart )
+ p->nStartPos = aD[nIdx+1].nStartPos;
+ else
+ {
+ if (aD[nIdx+1].pIdStk->empty())
+ {
+ WW8PLCFx_PCD *pTemp = (WW8PLCFx_PCD*)(pPcd->pPLCFx);
+ /*
+ #i2325#
+ As per normal, go on to the next set of properties, i.e. we
+ have traversed over to the next piece. With a clipstart set
+ we are being told to reread the current piece sprms so as to
+ reapply them to a new chp or pap range.
+ */
+ if (pTemp->GetClipStart() == -1)
+ (*p->pPLCFx)++;
+ p->pMemPos = 0;
+ p->nSprmsLen = 0;
+ GetNewSprms( aD[nIdx+1] );
+ GetNewNoSprms( *p );
+ if (pTemp->GetClipStart() != -1)
+ {
+ /*
+ #i2325#, now we will force our starting position to the
+ clipping start so as to force the application of these
+ sprms after the current pap/chp sprms so as to apply the
+ fastsave sprms to the current range.
+ */
+ p->nStartPos = pTemp->GetClipStart();
+ pTemp->SetClipStart(-1);
+ }
+ }
+ }
+ }
+ else
+ { // NoSprm ohne Ende
+ (*p->pPLCFx)++;
+ p->pMemPos = 0; // MemPos ungueltig
+ p->nSprmsLen = 0;
+ GetNewNoSprms( *p );
+ }
+}
+
+WW8PLCFMan& WW8PLCFMan::operator ++(int)
+{
+ bool bStart;
+ sal_uInt16 nIdx = WhereIdx(&bStart);
+ if (nIdx < nPLCF)
+ {
+ WW8PLCFxDesc* p = &aD[nIdx];
+
+ p->bFirstSprm = true; // Default
+
+ if( p->pPLCFx->IsSprm() )
+ AdvSprm( nIdx, bStart );
+ else // NoSprm
+ AdvNoSprm( nIdx, bStart );
+ }
+ return *this;
+}
+
+// Rueckgabe true fuer Anfang eines Attributes oder Fehler,
+// false fuer Ende d. Attr
+// Restliche Rueckgabewerte werden in der vom Aufrufer zu stellenden Struktur
+// WW8PclxManResults geliefert.
+bool WW8PLCFMan::Get(WW8PLCFManResult* pRes) const
+{
+ memset( pRes, 0, sizeof( WW8PLCFManResult ) );
+ bool bStart;
+ sal_uInt16 nIdx = WhereIdx(&bStart);
+
+ if( nIdx >= nPLCF )
+ {
+ OSL_ENSURE( !this, "Position not found" );
+ return true;
+ }
+
+ if( aD[nIdx].pPLCFx->IsSprm() )
+ {
+ if( bStart )
+ {
+ GetSprmStart( nIdx, pRes );
+ return true;
+ }
+ else
+ {
+ GetSprmEnd( nIdx, pRes );
+ return false;
+ }
+ }
+ else
+ {
+ if( bStart )
+ {
+ GetNoSprmStart( nIdx, pRes );
+ return true;
+ }
+ else
+ {
+ GetNoSprmEnd( nIdx, pRes );
+ return false;
+ }
+ }
+}
+
+sal_uInt16 WW8PLCFMan::GetColl() const
+{
+ if( pPap->pPLCFx )
+ return pPap->pPLCFx->GetIstd();
+ else
+ {
+ OSL_ENSURE( !this, "GetColl ohne PLCF_Pap" );
+ return 0;
+ }
+}
+
+WW8PLCFx_FLD* WW8PLCFMan::GetFld() const
+{
+ return (WW8PLCFx_FLD*)pFld->pPLCFx;
+}
+
+const sal_uInt8* WW8PLCFMan::HasParaSprm( sal_uInt16 nId ) const
+{
+ return ((WW8PLCFx_Cp_FKP*)pPap->pPLCFx)->HasSprm( nId );
+}
+
+const sal_uInt8* WW8PLCFMan::HasCharSprm( sal_uInt16 nId ) const
+{
+ return ((WW8PLCFx_Cp_FKP*)pChp->pPLCFx)->HasSprm( nId );
+}
+
+bool WW8PLCFMan::HasCharSprm(sal_uInt16 nId,
+ std::vector<const sal_uInt8 *> &rResult) const
+{
+ return ((WW8PLCFx_Cp_FKP*)pChp->pPLCFx)->HasSprm(nId, rResult);
+}
+
+#endif // !DUMP
+
+void WW8PLCFx::Save( WW8PLCFxSave1& rSave ) const
+{
+ rSave.nPLCFxPos = GetIdx();
+ rSave.nPLCFxPos2 = GetIdx2();
+ rSave.nPLCFxMemOfs = 0;
+ rSave.nStartFC = GetStartFc();
+}
+
+void WW8PLCFx::Restore( const WW8PLCFxSave1& rSave )
+{
+ SetIdx( rSave.nPLCFxPos );
+ SetIdx2( rSave.nPLCFxPos2 );
+ SetStartFc( rSave.nStartFC );
+}
+
+sal_uLong WW8PLCFx_Cp_FKP::GetIdx2() const
+{
+ return GetPCDIdx();
+}
+
+void WW8PLCFx_Cp_FKP::SetIdx2( sal_uLong nIdx )
+{
+ SetPCDIdx( nIdx );
+}
+
+void WW8PLCFx_Cp_FKP::Save( WW8PLCFxSave1& rSave ) const
+{
+ WW8PLCFx::Save( rSave );
+
+ rSave.nAttrStart = nAttrStart;
+ rSave.nAttrEnd = nAttrEnd;
+ rSave.bLineEnd = bLineEnd;
+}
+
+void WW8PLCFx_Cp_FKP::Restore( const WW8PLCFxSave1& rSave )
+{
+ WW8PLCFx::Restore( rSave );
+
+ nAttrStart = rSave.nAttrStart;
+ nAttrEnd = rSave.nAttrEnd;
+ bLineEnd = rSave.bLineEnd;
+}
+
+void WW8PLCFxDesc::Save( WW8PLCFxSave1& rSave ) const
+{
+ if( pPLCFx )
+ {
+ pPLCFx->Save( rSave );
+ if( pPLCFx->IsSprm() )
+ {
+ WW8PLCFxDesc aD;
+ aD.nStartPos = nOrigStartPos+nCpOfs;
+ aD.nCpOfs = rSave.nCpOfs = nCpOfs;
+ if (!(pPLCFx->SeekPos(aD.nStartPos)))
+ {
+ aD.nEndPos = WW8_CP_MAX;
+ pPLCFx->SetDirty(true);
+ }
+ pPLCFx->GetSprms(&aD);
+ pPLCFx->SetDirty(false);
+ aD.ReduceByOffset();
+ rSave.nStartCp = aD.nStartPos;
+ rSave.nPLCFxMemOfs = nOrigSprmsLen - nSprmsLen;
+ }
+ }
+}
+
+void WW8PLCFxDesc::Restore( const WW8PLCFxSave1& rSave )
+{
+ if( pPLCFx )
+ {
+ pPLCFx->Restore( rSave );
+ if( pPLCFx->IsSprm() )
+ {
+ WW8PLCFxDesc aD;
+ aD.nStartPos = rSave.nStartCp+rSave.nCpOfs;
+ nCpOfs = aD.nCpOfs = rSave.nCpOfs;
+ if (!(pPLCFx->SeekPos(aD.nStartPos)))
+ {
+ aD.nEndPos = WW8_CP_MAX;
+ pPLCFx->SetDirty(true);
+ }
+ pPLCFx->GetSprms(&aD);
+ pPLCFx->SetDirty(false);
+ aD.ReduceByOffset();
+ pMemPos = aD.pMemPos + rSave.nPLCFxMemOfs;
+ }
+ }
+}
+
+//-----------------------------------------
+
+namespace
+{
+ sal_uInt32 Readcb(SvStream& rSt, ww::WordVersion eVer)
+ {
+ if (eVer <= ww::eWW2)
+ {
+ sal_uInt16 nShort;
+ rSt >> nShort;
+ return nShort;
+ }
+ else
+ {
+ sal_uInt32 nLong;
+ rSt >> nLong;
+ return nLong;
+ }
+ }
+}
+
+WW8_CP WW8Fib::GetBaseCp(ManTypes nType) const
+{
+ WW8_CP nOffset = 0;
+
+ switch( nType )
+ {
+ default:
+ case MAN_MAINTEXT:
+ break;
+ case MAN_FTN:
+ nOffset = ccpText;
+ break;
+ case MAN_HDFT:
+ nOffset = ccpText + ccpFtn;
+ break;
+ /*
+ A subdocument of this kind (MAN_MACRO) probably exists in some defunct
+ version of MSWord, but now ccpMcr is always 0. If some example that
+ uses this comes to light, this is the likely calculation required
+
+ case MAN_MACRO:
+ nOffset = ccpText + ccpFtn + ccpHdr;
+ break;
+
+ */
+ case MAN_AND:
+ nOffset = ccpText + ccpFtn + ccpHdr + ccpMcr;
+ break;
+ case MAN_EDN:
+ nOffset = ccpText + ccpFtn + ccpHdr + ccpMcr + ccpAtn;
+ break;
+ case MAN_TXBX:
+ nOffset = ccpText + ccpFtn + ccpHdr + ccpMcr + ccpAtn + ccpEdn;
+ break;
+ case MAN_TXBX_HDFT:
+ nOffset = ccpText + ccpFtn + ccpHdr + ccpMcr + ccpAtn + ccpEdn +
+ ccpTxbx;
+ break;
+ }
+ return nOffset;
+}
+
+ww::WordVersion WW8Fib::GetFIBVersion() const
+{
+ ww::WordVersion eVer = ww::eWW8;
+ /*
+ * Word for Windows 2 I think (1.X might work too if anyone has an example.
+ * Various pages claim that the fileformats of Word 1 and 2 for Windows are
+ * equivalent to Word for Macintosh 4 and 5. On the other hand
+ *
+ * wIdents for Word for Mac versions...
+ * 0xFE32 for Word 1
+ * 0xFE34 for Word 3
+ * 0xFE37 for Word 4 et 5.
+ *
+ * and this document
+ * http://cmsdoc.cern.ch/documents/docformat/CMS_CERN_LetterHead.word is
+ * claimed to be "Word 5 for Mac" by Office etc and has that wIdent, but
+ * its format isn't the same as that of Word 2 for windows. Nor is it
+ * the same as that of Word for DOS/PCWord 5
+ */
+ if (wIdent == 0xa5db)
+ eVer = ww::eWW2;
+ else
+ {
+ switch (nVersion)
+ {
+ case 6:
+ eVer = ww::eWW6;
+ break;
+ case 7:
+ eVer = ww::eWW7;
+ break;
+ case 8:
+ eVer = ww::eWW8;
+ break;
+ }
+ }
+ return eVer;
+}
+
+WW8Fib::WW8Fib(SvStream& rSt, sal_uInt8 nWantedVersion, sal_uInt32 nOffset)
+ : nFibError( 0 )
+{
+ memset(this, 0, sizeof(*this));
+ sal_uInt8 aBits1;
+ sal_uInt8 aBits2;
+ sal_uInt8 aVer8Bits1; // nur ab WinWord 8 benutzt
+ rSt.Seek( nOffset );
+ /*
+ Wunsch-Nr vermerken, File-Versionsnummer ermitteln
+ und gegen Wunsch-Nr. checken !
+ */
+ nVersion = nWantedVersion;
+ rSt >> wIdent;
+ rSt >> nFib;
+ rSt >> nProduct;
+ if( 0 != rSt.GetError() )
+ {
+ sal_Int16 nFibMin;
+ sal_Int16 nFibMax;
+ // note: 6 stands for "6 OR 7", 7 stands for "ONLY 7"
+ switch( nVersion )
+ {
+ case 6:
+ nFibMin = 0x0065; // von 101 WinWord 6.0
+ // 102 "
+ // und 103 WinWord 6.0 fuer Macintosh
+ // 104 "
+ nFibMax = 0x0069; // bis 105 WinWord 95
+ break;
+ case 7:
+ nFibMin = 0x0069; // von 105 WinWord 95
+ nFibMax = 0x0069; // bis 105 WinWord 95
+ break;
+ case 8:
+ nFibMin = 0x006A; // von 106 WinWord 97
+ nFibMax = 0x00c1; // bis 193 WinWord 97 (?)
+ break;
+ default:
+ nFibMin = 0; // Programm-Fehler!
+ nFibMax = 0;
+ nFib = 1;
+ OSL_ENSURE( !this, "Es wurde vergessen, nVersion zu kodieren!" );
+ break;
+ }
+ if ( (nFib < nFibMin) || (nFib > nFibMax) )
+ {
+ nFibError = ERR_SWG_READ_ERROR; // Error melden
+ return; // und hopp raus!
+ }
+ }
+
+ ww::WordVersion eVer = GetFIBVersion();
+
+ // Hilfs-Varis fuer Ver67:
+ sal_Int16 pnChpFirst_Ver67=0;
+ sal_Int16 pnPapFirst_Ver67=0;
+ sal_Int16 cpnBteChp_Ver67=0;
+ sal_Int16 cpnBtePap_Ver67=0;
+
+ // und auf gehts: FIB einlesen
+ rSt >> lid;
+ rSt >> pnNext;
+ rSt >> aBits1;
+ rSt >> aBits2;
+ rSt >> nFibBack;
+ rSt >> nHash;
+ rSt >> nKey;
+ rSt >> envr;
+ rSt >> aVer8Bits1; // unter Ver67 nur leeres Reservefeld
+ // Inhalt von aVer8Bits1
+ //
+ // sal_uInt8 fMac :1;
+ // sal_uInt8 fEmptySpecial :1;
+ // sal_uInt8 fLoadOverridePage :1;
+ // sal_uInt8 fFuturesavedUndo :1;
+ // sal_uInt8 fWord97Saved :1;
+ // sal_uInt8 :3;
+ rSt >> chse;
+ rSt >> chseTables;
+ rSt >> fcMin;
+ rSt >> fcMac;
+
+// Einschub fuer WW8 *****************************************************
+ if (IsEightPlus(eVer))
+ {
+ rSt >> csw;
+
+ // Marke: "rgsw" Beginning of the array of shorts
+ rSt >> wMagicCreated;
+ rSt >> wMagicRevised;
+ rSt >> wMagicCreatedPrivate;
+ rSt >> wMagicRevisedPrivate;
+ rSt.SeekRel( 9 * sizeof( sal_Int16 ) );
+
+ /*
+ // dies sind die 9 unused Felder:
+ && (bVer67 || WW8ReadINT16( rSt, pnFbpChpFirst_W6 )) // 1
+ && (bVer67 || WW8ReadINT16( rSt, pnChpFirst_W6 )) // 2
+ && (bVer67 || WW8ReadINT16( rSt, cpnBteChp_W6 )) // 3
+ && (bVer67 || WW8ReadINT16( rSt, pnFbpPapFirst_W6 )) // 4
+ && (bVer67 || WW8ReadINT16( rSt, pnPapFirst_W6 )) // 5
+ && (bVer67 || WW8ReadINT16( rSt, cpnBtePap_W6 )) // 6
+ && (bVer67 || WW8ReadINT16( rSt, pnFbpLvcFirst_W6 )) // 7
+ && (bVer67 || WW8ReadINT16( rSt, pnLvcFirst_W6 )) // 8
+ && (bVer67 || WW8ReadINT16( rSt, cpnBteLvc_W6 )) // 9
+ */
+ rSt >> lidFE;
+ rSt >> clw;
+ }
+
+// Ende des Einschubs fuer WW8 *******************************************
+
+ // Marke: "rglw" Beginning of the array of longs
+ rSt >> cbMac;
+
+ // 2 Longs uebergehen, da unwichtiger Quatsch
+ rSt.SeekRel( 2 * sizeof( sal_Int32) );
+
+ // weitere 2 Longs nur bei Ver67 ueberspringen
+ if (IsSevenMinus(eVer))
+ rSt.SeekRel( 2 * sizeof( sal_Int32) );
+
+ rSt >> ccpText;
+ rSt >> ccpFtn;
+ rSt >> ccpHdr;
+ rSt >> ccpMcr;
+ rSt >> ccpAtn;
+ rSt >> ccpEdn;
+ rSt >> ccpTxbx;
+ rSt >> ccpHdrTxbx;
+
+ // weiteres Long nur bei Ver67 ueberspringen
+ if (IsSevenMinus(eVer))
+ rSt.SeekRel( 1 * sizeof( sal_Int32) );
+ else
+ {
+// Einschub fuer WW8 *****************************************************
+ rSt >> pnFbpChpFirst;
+ rSt >> pnChpFirst;
+ rSt >> cpnBteChp;
+ rSt >> pnFbpPapFirst;
+ rSt >> pnPapFirst;
+ rSt >> cpnBtePap;
+ rSt >> pnFbpLvcFirst;
+ rSt >> pnLvcFirst;
+ rSt >> cpnBteLvc;
+ rSt >> fcIslandFirst;
+ rSt >> fcIslandLim;
+ rSt >> cfclcb;
+ }
+
+// Ende des Einschubs fuer WW8 *******************************************
+
+ // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
+ rSt >> fcStshfOrig;
+ lcbStshfOrig = Readcb(rSt, eVer);
+ rSt >> fcStshf;
+ lcbStshf = Readcb(rSt, eVer);
+ rSt >> fcPlcffndRef;
+ lcbPlcffndRef = Readcb(rSt, eVer);
+ rSt >> fcPlcffndTxt;
+ lcbPlcffndTxt = Readcb(rSt, eVer);
+ rSt >> fcPlcfandRef;
+ lcbPlcfandRef = Readcb(rSt, eVer);
+ rSt >> fcPlcfandTxt;
+ lcbPlcfandTxt = Readcb(rSt, eVer);
+ rSt >> fcPlcfsed;
+ lcbPlcfsed = Readcb(rSt, eVer);
+ rSt >> fcPlcfpad;
+ lcbPlcfpad = Readcb(rSt, eVer);
+ rSt >> fcPlcfphe;
+ lcbPlcfphe = Readcb(rSt, eVer);
+ rSt >> fcSttbfglsy;
+ lcbSttbfglsy = Readcb(rSt, eVer);
+ rSt >> fcPlcfglsy;
+ lcbPlcfglsy = Readcb(rSt, eVer);
+ rSt >> fcPlcfhdd;
+ lcbPlcfhdd = Readcb(rSt, eVer);
+ rSt >> fcPlcfbteChpx;
+ lcbPlcfbteChpx = Readcb(rSt, eVer);
+ rSt >> fcPlcfbtePapx;
+ lcbPlcfbtePapx = Readcb(rSt, eVer);
+ rSt >> fcPlcfsea;
+ lcbPlcfsea = Readcb(rSt, eVer);
+ rSt >> fcSttbfffn;
+ lcbSttbfffn = Readcb(rSt, eVer);
+ rSt >> fcPlcffldMom;
+ lcbPlcffldMom = Readcb(rSt, eVer);
+ rSt >> fcPlcffldHdr;
+ lcbPlcffldHdr = Readcb(rSt, eVer);
+ rSt >> fcPlcffldFtn;
+ lcbPlcffldFtn = Readcb(rSt, eVer);
+ rSt >> fcPlcffldAtn;
+ lcbPlcffldAtn = Readcb(rSt, eVer);
+ rSt >> fcPlcffldMcr;
+ lcbPlcffldMcr = Readcb(rSt, eVer);
+ rSt >> fcSttbfbkmk;
+ lcbSttbfbkmk = Readcb(rSt, eVer);
+ rSt >> fcPlcfbkf;
+ lcbPlcfbkf = Readcb(rSt, eVer);
+ rSt >> fcPlcfbkl;
+ lcbPlcfbkl = Readcb(rSt, eVer);
+ rSt >> fcCmds;
+ lcbCmds = Readcb(rSt, eVer);
+ rSt >> fcPlcfmcr;
+ lcbPlcfmcr = Readcb(rSt, eVer);
+ rSt >> fcSttbfmcr;
+ lcbSttbfmcr = Readcb(rSt, eVer);
+ rSt >> fcPrDrvr;
+ lcbPrDrvr = Readcb(rSt, eVer);
+ rSt >> fcPrEnvPort;
+ lcbPrEnvPort = Readcb(rSt, eVer);
+ rSt >> fcPrEnvLand;
+ lcbPrEnvLand = Readcb(rSt, eVer);
+ rSt >> fcWss;
+ lcbWss = Readcb(rSt, eVer);
+ rSt >> fcDop;
+ lcbDop = Readcb(rSt, eVer);
+ rSt >> fcSttbfAssoc;
+ lcbSttbfAssoc = Readcb(rSt, eVer);
+ rSt >> fcClx;
+ lcbClx = Readcb(rSt, eVer);
+ rSt >> fcPlcfpgdFtn;
+ lcbPlcfpgdFtn = Readcb(rSt, eVer);
+ rSt >> fcAutosaveSource;
+ lcbAutosaveSource = Readcb(rSt, eVer);
+ rSt >> fcGrpStAtnOwners;
+ lcbGrpStAtnOwners = Readcb(rSt, eVer);
+ rSt >> fcSttbfAtnbkmk;
+ lcbSttbfAtnbkmk = Readcb(rSt, eVer);
+
+ // weiteres short nur bei Ver67 ueberspringen
+ if (IsSevenMinus(eVer))
+ {
+ rSt.SeekRel( 1*sizeof( sal_Int16) );
+
+ // folgende 4 Shorts existieren nur bei Ver67;
+ rSt >> pnChpFirst_Ver67;
+ rSt >> pnPapFirst_Ver67;
+ rSt >> cpnBteChp_Ver67;
+ rSt >> cpnBtePap_Ver67;
+ }
+
+ if (eVer > ww::eWW2)
+ {
+ rSt >> fcPlcfdoaMom;
+ rSt >> lcbPlcfdoaMom;
+ rSt >> fcPlcfdoaHdr;
+ rSt >> lcbPlcfdoaHdr;
+ rSt >> fcPlcfspaMom;
+ rSt >> lcbPlcfspaMom;
+ rSt >> fcPlcfspaHdr;
+ rSt >> lcbPlcfspaHdr;
+
+ rSt >> fcPlcfAtnbkf;
+ rSt >> lcbPlcfAtnbkf;
+ rSt >> fcPlcfAtnbkl;
+ rSt >> lcbPlcfAtnbkl;
+ rSt >> fcPms;
+ rSt >> lcbPMS;
+ rSt >> fcFormFldSttbf;
+ rSt >> lcbFormFldSttbf;
+ rSt >> fcPlcfendRef;
+ rSt >> lcbPlcfendRef;
+ rSt >> fcPlcfendTxt;
+ rSt >> lcbPlcfendTxt;
+ rSt >> fcPlcffldEdn;
+ rSt >> lcbPlcffldEdn;
+ rSt >> fcPlcfpgdEdn;
+ rSt >> lcbPlcfpgdEdn;
+ rSt >> fcDggInfo;
+ rSt >> lcbDggInfo;
+ rSt >> fcSttbfRMark;
+ rSt >> lcbSttbfRMark;
+ rSt >> fcSttbfCaption;
+ rSt >> lcbSttbfCaption;
+ rSt >> fcSttbAutoCaption;
+ rSt >> lcbSttbAutoCaption;
+ rSt >> fcPlcfwkb;
+ rSt >> lcbPlcfwkb;
+ rSt >> fcPlcfspl;
+ rSt >> lcbPlcfspl;
+ rSt >> fcPlcftxbxTxt;
+ rSt >> lcbPlcftxbxTxt;
+ rSt >> fcPlcffldTxbx;
+ rSt >> lcbPlcffldTxbx;
+ rSt >> fcPlcfHdrtxbxTxt;
+ rSt >> lcbPlcfHdrtxbxTxt;
+ rSt >> fcPlcffldHdrTxbx;
+ rSt >> lcbPlcffldHdrTxbx;
+ rSt >> fcStwUser;
+ rSt >> lcbStwUser;
+ rSt >> fcSttbttmbd;
+ rSt >> lcbSttbttmbd;
+ }
+
+ if( 0 == rSt.GetError() )
+ {
+ // Bit-Flags setzen
+ fDot = aBits1 & 0x01 ;
+ fGlsy = ( aBits1 & 0x02 ) >> 1;
+ fComplex = ( aBits1 & 0x04 ) >> 2;
+ fHasPic = ( aBits1 & 0x08 ) >> 3;
+ cQuickSaves = ( aBits1 & 0xf0 ) >> 4;
+ fEncrypted = aBits2 & 0x01 ;
+ fWhichTblStm= ( aBits2 & 0x02 ) >> 1;
+ fReadOnlyRecommended = (aBits2 & 0x4) >> 2;
+ fWriteReservation = (aBits2 & 0x8) >> 3;
+ fExtChar = ( aBits2 & 0x10 ) >> 4;
+ // dummy = ( aBits2 & 0x20 ) >> 5;
+ fFarEast = ( aBits2 & 0x40 ) >> 6; // #i90932#
+ // dummy = ( aBits2 & 0x80 ) >> 7;
+
+ /*
+ ggfs. Ziel-Varaiblen, aus xxx_Ver67 fuellen
+ oder Flags setzen
+ */
+ if (IsSevenMinus(eVer))
+ {
+ pnChpFirst = pnChpFirst_Ver67;
+ pnPapFirst = pnPapFirst_Ver67;
+ cpnBteChp = cpnBteChp_Ver67;
+ cpnBtePap = cpnBtePap_Ver67;
+ }
+ else if (IsEightPlus(eVer))
+ {
+ fMac = aVer8Bits1 & 0x01 ;
+ fEmptySpecial = ( aVer8Bits1 & 0x02 ) >> 1;
+ fLoadOverridePage = ( aVer8Bits1 & 0x04 ) >> 2;
+ fFuturesavedUndo = ( aVer8Bits1 & 0x08 ) >> 3;
+ fWord97Saved = ( aVer8Bits1 & 0x10 ) >> 4;
+ fWord2000Saved = ( aVer8Bits1 & 0x20 ) >> 5;
+
+ /*
+ speziell fuer WW8:
+ ermittle die Werte fuer PLCF LST und PLF LFO
+ und PLCF fuer TextBox-Break-Deskriptoren
+ */
+ long nOldPos = rSt.Tell();
+
+ rSt.Seek( 0x02da );
+ rSt >> fcSttbFnm;
+ rSt >> lcbSttbFnm;
+ rSt >> fcPlcfLst;
+ rSt >> lcbPlcfLst;
+ rSt >> fcPlfLfo;
+ rSt >> lcbPlfLfo;
+ rSt >> fcPlcftxbxBkd;
+ rSt >> lcbPlcftxbxBkd;
+ rSt >> fcPlcfHdrtxbxBkd;
+ rSt >> lcbPlcfHdrtxbxBkd;
+ if( 0 != rSt.GetError() )
+ {
+ nFibError = ERR_SWG_READ_ERROR;
+ }
+
+ rSt.Seek( 0x372 ); // fcSttbListNames
+ rSt >> fcSttbListNames;
+ rSt >> lcbSttbListNames;
+
+ if (cfclcb > 93)
+ {
+ rSt.Seek( 0x382 ); // MagicTables
+ rSt >> fcPlcfTch;
+ rSt >> lcbPlcfTch;
+ }
+
+ if (cfclcb > 113)
+ {
+ rSt.Seek( 0x41A ); // new ATRD
+ rSt >> fcAtrdExtra;
+ rSt >> lcbAtrdExtra;
+ }
+
+ if( 0 != rSt.GetError() )
+ nFibError = ERR_SWG_READ_ERROR;
+
+ rSt.Seek( 0x5bc ); // Actual nFib introduced in Word 2003
+ rSt >> nFib_actual;
+
+ rSt.Seek( nOldPos );
+ }
+ }
+ else
+ {
+ nFibError = ERR_SWG_READ_ERROR; // Error melden
+ }
+}
+
+
+WW8Fib::WW8Fib(sal_uInt8 nVer)
+{
+ memset(this, 0, sizeof(*this));
+ nVersion = nVer;
+ if (8 == nVer)
+ {
+ fcMin = 0x800;
+ wIdent = 0xa5ec;
+ nFib = 0x0101;
+ nFibBack = 0xbf;
+ nProduct = 0x204D;
+
+ csw = 0x0e; // muss das sein ???
+ cfclcb = 0x88; // -""-
+ clw = 0x16; // -""-
+ pnFbpChpFirst = pnFbpPapFirst = pnFbpLvcFirst = 0x000fffff;
+ fExtChar = true;
+ fWord97Saved = fWord2000Saved = true;
+
+ wMagicCreated = 0x6143;
+ wMagicRevised = 0x6C6F;
+ wMagicCreatedPrivate = 0x6E61;
+ wMagicRevisedPrivate = 0x3038;
+ }
+ else
+ {
+ fcMin = 0x300;
+ wIdent = 0xa5dc;
+ nFib = nFibBack = 0x65;
+ nProduct = 0xc02d;
+ }
+
+ // --> #i90932#
+ lid = 0x409; // LANGUAGE_ENGLISH_US
+
+ LanguageType nLang = Application::GetSettings().GetLanguage();
+ switch( nLang )
+ {
+ case LANGUAGE_CHINESE:
+ case LANGUAGE_CHINESE_SIMPLIFIED:
+ case LANGUAGE_CHINESE_HONGKONG:
+ case LANGUAGE_CHINESE_SINGAPORE:
+ case LANGUAGE_CHINESE_MACAU:
+ case LANGUAGE_CHINESE_TRADITIONAL:
+ case LANGUAGE_KOREAN:
+ case LANGUAGE_KOREAN_JOHAB:
+ case LANGUAGE_JAPANESE:
+ lidFE = nLang;
+ fFarEast = true;
+ break;
+ default:
+ lidFE = lid;
+ fFarEast = false;
+ break;
+ };
+ // <--
+
+ Locale aTempLocale;
+ SvxLanguageToLocale( aTempLocale, lid );
+ LocaleDataWrapper aLocaleWrapper( ::comphelper::getProcessServiceFactory(), aTempLocale );
+ nNumDecimalSep = aLocaleWrapper.getNumDecimalSep().GetChar( 0 );
+}
+
+sal_Unicode WW8Fib::getNumDecimalSep() const
+{
+ return nNumDecimalSep;
+}
+
+bool WW8Fib::WriteHeader(SvStream& rStrm)
+{
+ bool bVer8 = 8 == nVersion;
+
+ size_t nUnencryptedHdr = bVer8 ? 0x44 : 0x24;
+ sal_uInt8 *pDataPtr = new sal_uInt8[ nUnencryptedHdr ];
+ sal_uInt8 *pData = pDataPtr;
+ memset( pData, 0, nUnencryptedHdr );
+
+ sal_uLong nPos = rStrm.Tell();
+ cbMac = rStrm.Seek( STREAM_SEEK_TO_END );
+ rStrm.Seek( nPos );
+
+ Set_UInt16( pData, wIdent );
+ Set_UInt16( pData, nFib );
+ Set_UInt16( pData, nProduct );
+ Set_UInt16( pData, lid );
+ Set_UInt16( pData, pnNext );
+
+ sal_uInt16 nBits16 = 0;
+ if( fDot ) nBits16 |= 0x0001;
+ if( fGlsy) nBits16 |= 0x0002;
+ if( fComplex ) nBits16 |= 0x0004;
+ if( fHasPic ) nBits16 |= 0x0008;
+ nBits16 |= (0xf0 & ( cQuickSaves << 4 ));
+ if( fEncrypted ) nBits16 |= 0x0100;
+ if( fWhichTblStm ) nBits16 |= 0x0200;
+
+ if (fReadOnlyRecommended)
+ nBits16 |= 0x0400;
+ if (fWriteReservation)
+ nBits16 |= 0x0800;
+
+ if( fExtChar ) nBits16 |= 0x1000;
+ if( fFarEast ) nBits16 |= 0x4000; // #i90932#
+ if( fObfuscated ) nBits16 |= 0x8000;
+ Set_UInt16( pData, nBits16 );
+
+ Set_UInt16( pData, nFibBack );
+ Set_UInt16( pData, nHash );
+ Set_UInt16( pData, nKey );
+ Set_UInt8( pData, envr );
+
+ sal_uInt8 nBits8 = 0;
+ if( bVer8 )
+ {
+ if( fMac ) nBits8 |= 0x0001;
+ if( fEmptySpecial ) nBits8 |= 0x0002;
+ if( fLoadOverridePage ) nBits8 |= 0x0004;
+ if( fFuturesavedUndo ) nBits8 |= 0x0008;
+ if( fWord97Saved ) nBits8 |= 0x0010;
+ if( fWord2000Saved ) nBits8 |= 0x0020;
+ }
+ // unter Ver67 these are only reserved
+ Set_UInt8( pData, nBits8 );
+
+ Set_UInt16( pData, chse );
+ Set_UInt16( pData, chseTables );
+ Set_UInt32( pData, fcMin );
+ Set_UInt32( pData, fcMac );
+
+// Einschub fuer WW8 *****************************************************
+
+ // Marke: "rgsw" Beginning of the array of shorts
+ if( bVer8 )
+ {
+ Set_UInt16( pData, csw );
+ Set_UInt16( pData, wMagicCreated );
+ Set_UInt16( pData, wMagicRevised );
+ Set_UInt16( pData, wMagicCreatedPrivate );
+ Set_UInt16( pData, wMagicRevisedPrivate );
+ pData += 9 * sizeof( sal_Int16 );
+ Set_UInt16( pData, lidFE );
+ Set_UInt16( pData, clw );
+ }
+
+// Ende des Einschubs fuer WW8 *******************************************
+
+ // Marke: "rglw" Beginning of the array of longs
+ Set_UInt32( pData, cbMac );
+
+ rStrm.Write( pDataPtr, nUnencryptedHdr );
+ delete[] pDataPtr;
+ return 0 == rStrm.GetError();
+}
+
+bool WW8Fib::Write(SvStream& rStrm)
+{
+ bool bVer8 = 8 == nVersion;
+
+ WriteHeader( rStrm );
+
+ size_t nUnencryptedHdr = bVer8 ? 0x44 : 0x24;
+
+ sal_uInt8 *pDataPtr = new sal_uInt8[ fcMin - nUnencryptedHdr ];
+ sal_uInt8 *pData = pDataPtr;
+ memset( pData, 0, fcMin - nUnencryptedHdr );
+
+ sal_uLong nPos = rStrm.Tell();
+ cbMac = rStrm.Seek( STREAM_SEEK_TO_END );
+ rStrm.Seek( nPos );
+
+ // 2 Longs uebergehen, da unwichtiger Quatsch
+ pData += 2 * sizeof( sal_Int32);
+
+ // weitere 2 Longs nur bei Ver67 ueberspringen
+ if( !bVer8 )
+ pData += 2 * sizeof( sal_Int32);
+
+ Set_UInt32( pData, ccpText );
+ Set_UInt32( pData, ccpFtn );
+ Set_UInt32( pData, ccpHdr );
+ Set_UInt32( pData, ccpMcr );
+ Set_UInt32( pData, ccpAtn );
+ Set_UInt32( pData, ccpEdn );
+ Set_UInt32( pData, ccpTxbx );
+ Set_UInt32( pData, ccpHdrTxbx );
+
+ // weiteres Long nur bei Ver67 ueberspringen
+ if( !bVer8 )
+ pData += 1 * sizeof( sal_Int32);
+
+// Einschub fuer WW8 *****************************************************
+ if( bVer8 )
+ {
+ Set_UInt32( pData, pnFbpChpFirst );
+ Set_UInt32( pData, pnChpFirst );
+ Set_UInt32( pData, cpnBteChp );
+ Set_UInt32( pData, pnFbpPapFirst );
+ Set_UInt32( pData, pnPapFirst );
+ Set_UInt32( pData, cpnBtePap );
+ Set_UInt32( pData, pnFbpLvcFirst );
+ Set_UInt32( pData, pnLvcFirst );
+ Set_UInt32( pData, cpnBteLvc );
+ Set_UInt32( pData, fcIslandFirst );
+ Set_UInt32( pData, fcIslandLim );
+ Set_UInt16( pData, cfclcb );
+ }
+// Ende des Einschubs fuer WW8 *******************************************
+
+ // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
+ Set_UInt32( pData, fcStshfOrig );
+ Set_UInt32( pData, lcbStshfOrig );
+ Set_UInt32( pData, fcStshf );
+ Set_UInt32( pData, lcbStshf );
+ Set_UInt32( pData, fcPlcffndRef );
+ Set_UInt32( pData, lcbPlcffndRef );
+ Set_UInt32( pData, fcPlcffndTxt );
+ Set_UInt32( pData, lcbPlcffndTxt );
+ Set_UInt32( pData, fcPlcfandRef );
+ Set_UInt32( pData, lcbPlcfandRef );
+ Set_UInt32( pData, fcPlcfandTxt );
+ Set_UInt32( pData, lcbPlcfandTxt );
+ Set_UInt32( pData, fcPlcfsed );
+ Set_UInt32( pData, lcbPlcfsed );
+ Set_UInt32( pData, fcPlcfpad );
+ Set_UInt32( pData, lcbPlcfpad );
+ Set_UInt32( pData, fcPlcfphe );
+ Set_UInt32( pData, lcbPlcfphe );
+ Set_UInt32( pData, fcSttbfglsy );
+ Set_UInt32( pData, lcbSttbfglsy );
+ Set_UInt32( pData, fcPlcfglsy );
+ Set_UInt32( pData, lcbPlcfglsy );
+ Set_UInt32( pData, fcPlcfhdd );
+ Set_UInt32( pData, lcbPlcfhdd );
+ Set_UInt32( pData, fcPlcfbteChpx );
+ Set_UInt32( pData, lcbPlcfbteChpx );
+ Set_UInt32( pData, fcPlcfbtePapx );
+ Set_UInt32( pData, lcbPlcfbtePapx );
+ Set_UInt32( pData, fcPlcfsea );
+ Set_UInt32( pData, lcbPlcfsea );
+ Set_UInt32( pData, fcSttbfffn );
+ Set_UInt32( pData, lcbSttbfffn );
+ Set_UInt32( pData, fcPlcffldMom );
+ Set_UInt32( pData, lcbPlcffldMom );
+ Set_UInt32( pData, fcPlcffldHdr );
+ Set_UInt32( pData, lcbPlcffldHdr );
+ Set_UInt32( pData, fcPlcffldFtn );
+ Set_UInt32( pData, lcbPlcffldFtn );
+ Set_UInt32( pData, fcPlcffldAtn );
+ Set_UInt32( pData, lcbPlcffldAtn );
+ Set_UInt32( pData, fcPlcffldMcr );
+ Set_UInt32( pData, lcbPlcffldMcr );
+ Set_UInt32( pData, fcSttbfbkmk );
+ Set_UInt32( pData, lcbSttbfbkmk );
+ Set_UInt32( pData, fcPlcfbkf );
+ Set_UInt32( pData, lcbPlcfbkf );
+ Set_UInt32( pData, fcPlcfbkl );
+ Set_UInt32( pData, lcbPlcfbkl );
+ Set_UInt32( pData, fcCmds );
+ Set_UInt32( pData, lcbCmds );
+ Set_UInt32( pData, fcPlcfmcr );
+ Set_UInt32( pData, lcbPlcfmcr );
+ Set_UInt32( pData, fcSttbfmcr );
+ Set_UInt32( pData, lcbSttbfmcr );
+ Set_UInt32( pData, fcPrDrvr );
+ Set_UInt32( pData, lcbPrDrvr );
+ Set_UInt32( pData, fcPrEnvPort );
+ Set_UInt32( pData, lcbPrEnvPort );
+ Set_UInt32( pData, fcPrEnvLand );
+ Set_UInt32( pData, lcbPrEnvLand );
+ Set_UInt32( pData, fcWss );
+ Set_UInt32( pData, lcbWss );
+ Set_UInt32( pData, fcDop );
+ Set_UInt32( pData, lcbDop );
+ Set_UInt32( pData, fcSttbfAssoc );
+ Set_UInt32( pData, lcbSttbfAssoc );
+ Set_UInt32( pData, fcClx );
+ Set_UInt32( pData, lcbClx );
+ Set_UInt32( pData, fcPlcfpgdFtn );
+ Set_UInt32( pData, lcbPlcfpgdFtn );
+ Set_UInt32( pData, fcAutosaveSource );
+ Set_UInt32( pData, lcbAutosaveSource );
+ Set_UInt32( pData, fcGrpStAtnOwners );
+ Set_UInt32( pData, lcbGrpStAtnOwners );
+ Set_UInt32( pData, fcSttbfAtnbkmk );
+ Set_UInt32( pData, lcbSttbfAtnbkmk );
+
+ // weiteres short nur bei Ver67 ueberspringen
+ if( !bVer8 )
+ {
+ pData += 1*sizeof( sal_Int16);
+ Set_UInt16( pData, (sal_uInt16)pnChpFirst );
+ Set_UInt16( pData, (sal_uInt16)pnPapFirst );
+ Set_UInt16( pData, (sal_uInt16)cpnBteChp );
+ Set_UInt16( pData, (sal_uInt16)cpnBtePap );
+ }
+
+ Set_UInt32( pData, fcPlcfdoaMom ); // nur bei Ver67, in Ver8 unused
+ Set_UInt32( pData, lcbPlcfdoaMom ); // nur bei Ver67, in Ver8 unused
+ Set_UInt32( pData, fcPlcfdoaHdr ); // nur bei Ver67, in Ver8 unused
+ Set_UInt32( pData, lcbPlcfdoaHdr ); // nur bei Ver67, in Ver8 unused
+
+ Set_UInt32( pData, fcPlcfspaMom ); // in Ver67 leere Reserve
+ Set_UInt32( pData, lcbPlcfspaMom ); // in Ver67 leere Reserve
+ Set_UInt32( pData, fcPlcfspaHdr ); // in Ver67 leere Reserve
+ Set_UInt32( pData, lcbPlcfspaHdr ); // in Ver67 leere Reserve
+
+ Set_UInt32( pData, fcPlcfAtnbkf );
+ Set_UInt32( pData, lcbPlcfAtnbkf );
+ Set_UInt32( pData, fcPlcfAtnbkl );
+ Set_UInt32( pData, lcbPlcfAtnbkl );
+ Set_UInt32( pData, fcPms );
+ Set_UInt32( pData, lcbPMS );
+ Set_UInt32( pData, fcFormFldSttbf );
+ Set_UInt32( pData, lcbFormFldSttbf );
+ Set_UInt32( pData, fcPlcfendRef );
+ Set_UInt32( pData, lcbPlcfendRef );
+ Set_UInt32( pData, fcPlcfendTxt );
+ Set_UInt32( pData, lcbPlcfendTxt );
+ Set_UInt32( pData, fcPlcffldEdn );
+ Set_UInt32( pData, lcbPlcffldEdn );
+ Set_UInt32( pData, fcPlcfpgdEdn );
+ Set_UInt32( pData, lcbPlcfpgdEdn );
+ Set_UInt32( pData, fcDggInfo ); // in Ver67 leere Reserve
+ Set_UInt32( pData, lcbDggInfo ); // in Ver67 leere Reserve
+ Set_UInt32( pData, fcSttbfRMark );
+ Set_UInt32( pData, lcbSttbfRMark );
+ Set_UInt32( pData, fcSttbfCaption );
+ Set_UInt32( pData, lcbSttbfCaption );
+ Set_UInt32( pData, fcSttbAutoCaption );
+ Set_UInt32( pData, lcbSttbAutoCaption );
+ Set_UInt32( pData, fcPlcfwkb );
+ Set_UInt32( pData, lcbPlcfwkb );
+ Set_UInt32( pData, fcPlcfspl ); // in Ver67 leere Reserve
+ Set_UInt32( pData, lcbPlcfspl ); // in Ver67 leere Reserve
+ Set_UInt32( pData, fcPlcftxbxTxt );
+ Set_UInt32( pData, lcbPlcftxbxTxt );
+ Set_UInt32( pData, fcPlcffldTxbx );
+ Set_UInt32( pData, lcbPlcffldTxbx );
+ Set_UInt32( pData, fcPlcfHdrtxbxTxt );
+ Set_UInt32( pData, lcbPlcfHdrtxbxTxt );
+ Set_UInt32( pData, fcPlcffldHdrTxbx );
+ Set_UInt32( pData, lcbPlcffldHdrTxbx );
+
+ if( bVer8 )
+ {
+ pData += 0x2da - 0x27a; // Pos + Offset (fcPlcfLst - fcStwUser)
+ Set_UInt32( pData, fcSttbFnm);
+ Set_UInt32( pData, lcbSttbFnm);
+ Set_UInt32( pData, fcPlcfLst );
+ Set_UInt32( pData, lcbPlcfLst );
+ Set_UInt32( pData, fcPlfLfo );
+ Set_UInt32( pData, lcbPlfLfo );
+ Set_UInt32( pData, fcPlcftxbxBkd );
+ Set_UInt32( pData, lcbPlcftxbxBkd );
+ Set_UInt32( pData, fcPlcfHdrtxbxBkd );
+ Set_UInt32( pData, lcbPlcfHdrtxbxBkd );
+
+ pData += 0x372 - 0x302; // Pos + Offset (fcSttbListNames - fcDocUndo)
+ Set_UInt32( pData, fcSttbListNames );
+ Set_UInt32( pData, lcbSttbListNames );
+
+ pData += 0x382 - 0x37A;
+ Set_UInt32( pData, fcPlcfTch );
+ Set_UInt32( pData, lcbPlcfTch );
+
+ pData += 0x3FA - 0x38A;
+ Set_UInt16( pData, (sal_uInt16)0x0002);
+ Set_UInt16( pData, (sal_uInt16)0x00D9);
+
+ pData += 0x41A - 0x3FE;
+ Set_UInt32( pData, fcAtrdExtra );
+ Set_UInt32( pData, lcbAtrdExtra );
+
+ pData += 0x4DA - 0x422;
+ Set_UInt32( pData, fcHplxsdr );
+ Set_UInt32( pData, 0);
+ }
+
+ rStrm.Write( pDataPtr, fcMin - nUnencryptedHdr );
+ delete[] pDataPtr;
+ return 0 == rStrm.GetError();
+}
+
+rtl_TextEncoding WW8Fib::GetFIBCharset(sal_uInt16 chs)
+{
+ OSL_ENSURE(chs <= 0x100, "overflowed winword charset set");
+ rtl_TextEncoding eCharSet =
+ (0x0100 == chs)
+ ? RTL_TEXTENCODING_APPLE_ROMAN
+ : rtl_getTextEncodingFromWindowsCharset( static_cast<sal_uInt8>(chs) );
+ return eCharSet;
+}
+
+WW8Style::WW8Style(SvStream& rStream, WW8Fib& rFibPara)
+ : rFib(rFibPara), rSt(rStream), cstd(0), cbSTDBaseInFile(0),
+ stiMaxWhenSaved(0), istdMaxFixedWhenSaved(0), nVerBuiltInNamesWhenSaved(0),
+ ftcAsci(0), ftcFE(0), ftcOther(0), ftcBi(0)
+{
+ nStyleStart = rFib.fcStshf;
+ nStyleLen = rFib.lcbStshf;
+
+ rSt.Seek(nStyleStart);
+
+ sal_uInt16 cbStshi = 0; // 2 bytes size of the following STSHI structure
+
+ if (rFib.GetFIBVersion() <= ww::eWW2)
+ {
+ cbStshi = 0;
+ cstd = 256;
+ }
+ else if (rFib.nFib < 67) // old Version ? (need to find this again to fix)
+ cbStshi = 4; // -> Laengenfeld fehlt
+ else // neue Version:
+ // lies die Laenge der in der Datei gespeicherten Struktur
+ rSt >> cbStshi;
+
+ sal_uInt16 nRead = cbStshi;
+ do
+ {
+ sal_uInt16 a16Bit;
+
+ if( 2 > nRead ) break;
+ rSt >> cstd;
+
+ if( 4 > nRead ) break;
+ rSt >> cbSTDBaseInFile;
+
+ if( 6 > nRead ) break;
+ rSt >> a16Bit;
+ fStdStylenamesWritten = a16Bit & 0x0001;
+
+ if( 8 > nRead ) break;
+ rSt >> stiMaxWhenSaved;
+
+ if( 10 > nRead ) break;
+ rSt >> istdMaxFixedWhenSaved;
+
+ if( 12 > nRead ) break;
+ rSt >> nVerBuiltInNamesWhenSaved;
+
+ if( 14 > nRead ) break;
+ rSt >> ftcAsci;
+
+ if( 16 > nRead ) break;
+ rSt >> ftcFE;
+
+ if ( 18 > nRead ) break;
+ rSt >> ftcOther;
+
+ ftcBi = ftcOther;
+
+ if ( 20 > nRead ) break;
+ rSt >> ftcBi;
+
+ // ggfs. den Rest ueberlesen
+ if( 20 < nRead )
+ rSt.SeekRel( nRead-20 );
+ }
+ while( !this ); // Trick: obiger Block wird genau einmal durchlaufen
+ // und kann vorzeitig per "break" verlassen werden.
+
+ if( 0 != rSt.GetError() )
+ {
+ // wie denn nun den Error melden?
+ }
+}
+
+// Read1STDFixed() liest ein Style ein. Wenn der Style vollstaendig vorhanden
+// ist, d.h. kein leerer Slot, dann wird Speicher alloziert und ein Pointer auf
+// die ( evtl. mit Nullen aufgefuellten ) STD geliefert. Ist es ein leerer
+// Slot, dann wird ein Nullpointer zurueckgeliefert.
+WW8_STD* WW8Style::Read1STDFixed( short& rSkip, short* pcbStd )
+{
+ WW8_STD* pStd = 0;
+
+ sal_uInt16 cbStd;
+ rSt >> cbStd; // lies Laenge
+
+ sal_uInt16 nRead = cbSTDBaseInFile;
+ if( cbStd >= cbSTDBaseInFile )
+ {
+ // Fixed part vollst. vorhanden
+
+ // read fixed part of STD
+ pStd = new WW8_STD;
+ memset( pStd, 0, sizeof( *pStd ) );
+
+ do
+ {
+ sal_uInt16 a16Bit;
+
+ if( 2 > nRead ) break;
+ rSt >> a16Bit;
+ pStd->sti = a16Bit & 0x0fff ;
+ pStd->fScratch = 0 != ( a16Bit & 0x1000 );
+ pStd->fInvalHeight = 0 != ( a16Bit & 0x2000 );
+ pStd->fHasUpe = 0 != ( a16Bit & 0x4000 );
+ pStd->fMassCopy = 0 != ( a16Bit & 0x8000 );
+
+ if( 4 > nRead ) break;
+ rSt >> a16Bit;
+ pStd->sgc = a16Bit & 0x000f ;
+ pStd->istdBase = ( a16Bit & 0xfff0 ) >> 4;
+
+ if( 6 > nRead ) break;
+ rSt >> a16Bit;
+ pStd->cupx = a16Bit & 0x000f ;
+ pStd->istdNext = ( a16Bit & 0xfff0 ) >> 4;
+
+ if( 8 > nRead ) break;
+ rSt >> pStd->bchUpe;
+
+ // ab Ver8 sollten diese beiden Felder dazukommen:
+ if(10 > nRead ) break;
+ rSt >> a16Bit;
+ pStd->fAutoRedef = a16Bit & 0x0001 ;
+ pStd->fHidden = ( a16Bit & 0x0002 ) >> 2;
+
+ // man kann nie wissen: vorsichtshalber ueberlesen
+ // wir eventuelle Fuellsel, die noch zum BASE-Part gehoeren...
+ if( 10 < nRead )
+ rSt.SeekRel( nRead-10 );
+ }
+ while( !this ); // Trick: obiger Block wird genau einmal durchlaufen
+ // und kann vorzeitig per "break" verlassen werden.
+
+ if( (0 != rSt.GetError()) || !nRead )
+ DELETEZ( pStd ); // per NULL den Error melden
+
+ rSkip = cbStd - cbSTDBaseInFile;
+ }
+ else
+ { // Fixed part zu kurz
+ if( cbStd )
+ rSt.SeekRel( cbStd ); // ueberlies Reste
+ rSkip = 0;
+ }
+ if( pcbStd )
+ *pcbStd = cbStd;
+ return pStd;
+}
+
+WW8_STD* WW8Style::Read1Style( short& rSkip, String* pString, short* pcbStd )
+{
+ // Attention: MacWord-Documents have their Stylenames
+ // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
+
+ WW8_STD* pStd = Read1STDFixed( rSkip, pcbStd ); // lese STD
+
+ // String gewuenscht ?
+ if( pString )
+ { // echter Style ?
+ if ( pStd )
+ {
+ switch( rFib.nVersion )
+ {
+ case 6:
+ case 7:
+ // lies Pascal-String
+ *pString = WW8ReadPString( rSt, RTL_TEXTENCODING_MS_1252 );
+ // leading len and trailing zero --> 2
+ rSkip -= 2+ pString->Len();
+ break;
+ case 8:
+ // handle Unicode-String with leading length short and
+ // trailing zero
+ if (ww8String::TestBeltAndBraces(rSt))
+ {
+ *pString = WW8Read_xstz(rSt, 0, true);
+ rSkip -= (pString->Len() + 2) * 2;
+ }
+ else
+ {
+ /*
+ #i8114#
+ This is supposed to be impossible, its just supposed
+ to be 16 bit count followed by the string and ending
+ in a 0 short. But "Lotus SmartSuite Product: Word Pro"
+ is creating invalid style names in ww7- format. So we
+ use the belt and braces of the ms strings to see if
+ they are not corrupt. If they are then we try them as
+ 8bit ones
+ */
+ *pString = WW8ReadPString(rSt,RTL_TEXTENCODING_MS_1252);
+ // leading len and trailing zero --> 2
+ rSkip -= 2+ pString->Len();
+ }
+ break;
+ default:
+ OSL_ENSURE(!this, "Es wurde vergessen, nVersion zu kodieren!");
+ break;
+ }
+ }
+ else
+ *pString = aEmptyStr; // Kann keinen Namen liefern
+ }
+ return pStd;
+}
+
+
+//-----------------------------------------
+
+
+struct WW8_FFN_Ver6 : public WW8_FFN_BASE
+{
+ // ab Ver6
+ sal_Char szFfn[65]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that
+ // records name of font.
+ // Maximal size of szFfn is 65 characters.
+ // Vorsicht: Dieses Array kann auch kleiner sein!!!
+ // Possibly followed by a second sz which records the
+ // name of an alternate font to use if the first named
+ // font does not exist on this system.
+};
+struct WW8_FFN_Ver8 : public WW8_FFN_BASE
+{
+ // ab Ver8 sind folgende beiden Felder eingeschoben,
+ // werden von uns ignoriert.
+ sal_Char panose[ 10 ]; // 0x6 PANOSE
+ sal_Char fs[ 24 ]; // 0x10 FONTSIGNATURE
+
+ // ab Ver8 als Unicode
+ sal_uInt16 szFfn[65]; // 0x6 bzw. 0x40 ab Ver8 zero terminated string that
+ // records name of font.
+ // Maximal size of szFfn is 65 characters.
+ // Vorsicht: Dieses Array kann auch kleiner sein!!!
+ // Possibly followed by a second sz which records the
+ // name of an alternate font to use if the first named
+ // font does not exist on this system.
+};
+
+// #i43762# check font name for illegal characters
+void lcl_checkFontname( String& sString )
+{
+ // for efficiency, we'd like to use String methods as far as possible.
+ // Hence, we will:
+ // 1) convert all invalid chars to \u0001
+ // 2) then erase all \u0001 chars (if any were found), and
+ // 3) erase leading/trailing ';', in case a font name was
+ // completely removed
+
+ // convert all invalid chars to \u0001
+ sal_Unicode* pBuffer = sString.GetBufferAccess();
+ xub_StrLen nLen = sString.Len();
+ bool bFound = false;
+ for( xub_StrLen n = 0; n < nLen; n++ )
+ {
+ if( pBuffer[n] < sal_Unicode( 0x20 ) )
+ {
+ pBuffer[n] = sal_Unicode( 1 );
+ bFound = true;
+ }
+ }
+ sString.ReleaseBufferAccess();
+
+ // if anything was found, remove \u0001 + leading/trailing ';'
+ if( bFound )
+ {
+ sString.EraseAllChars( sal_Unicode( 1 ) );
+ sString.EraseLeadingAndTrailingChars( sal_Unicode( ';' ) );
+ }
+}
+
+WW8Fonts::WW8Fonts( SvStream& rSt, WW8Fib& rFib )
+ : pFontA(0), nMax(0)
+{
+ // Attention: MacWord-Documents have their Fontnames
+ // always in ANSI, even if eStructCharSet == CHARSET_MAC !!
+ if( rFib.lcbSttbfffn <= 2 )
+ {
+ OSL_ENSURE( !this, "Fonttabelle kaputt! (rFib.lcbSttbfffn < 2)" );
+ pFontA = 0;
+ nMax = 0;
+ return;
+ }
+
+ rSt.Seek( rFib.fcSttbfffn );
+
+ sal_Int32 nFFn = rFib.lcbSttbfffn - 2;
+
+ // allocate Font Array
+ sal_uInt8* pA = new sal_uInt8[ nFFn ];
+ memset(pA, 0, nFFn);
+ WW8_FFN* p = (WW8_FFN*)pA;
+
+ ww::WordVersion eVersion = rFib.GetFIBVersion();
+
+ if( eVersion >= ww::eWW8 )
+ {
+ // bVer8: read the count of strings in nMax
+ rSt >> nMax;
+ }
+
+ // Ver8: skip undefined uint16
+ // Ver67: skip the herein stored total byte of structure
+ // - we already got that information in rFib.lcbSttbfffn
+ rSt.SeekRel( 2 );
+
+ // read all font information
+ nFFn = rSt.Read( pA, nFFn );
+
+ if( eVersion < ww::eWW8 )
+ {
+ // try to figure out how many fonts are defined here
+ nMax = 0;
+ long nLeft = nFFn;
+ for(;;)
+ {
+ short nNextSiz;
+
+ nNextSiz = p->cbFfnM1 + 1;
+ if( nNextSiz > nLeft )
+ break;
+ nMax++;
+ nLeft -= nNextSiz;
+ if( nLeft < 1 ) // can we read the given ammount of bytes ?
+ break;
+ // increase p by nNextSiz Bytes
+ p = (WW8_FFN *)( ( (sal_uInt8*)p ) + nNextSiz );
+ }
+ }
+
+ if( nMax )
+ {
+ // allocate Index Array
+ pFontA = new WW8_FFN[ nMax ];
+ p = pFontA;
+
+ if( eVersion <= ww::eWW2 )
+ {
+ WW8_FFN_BASE* pVer2 = (WW8_FFN_BASE*)pA;
+ for(sal_uInt16 i=0; i<nMax; ++i, ++p)
+ {
+ p->cbFfnM1 = pVer2->cbFfnM1;
+
+ p->prg = 0;
+ p->fTrueType = 0;
+ p->ff = 0;
+
+ p->wWeight = ( *(((sal_uInt8*)pVer2) + 1) );
+ p->chs = ( *(((sal_uInt8*)pVer2) + 2) );
+ /*
+ #i8726# 7- seems to encode the name in the same encoding as
+ the font, e.g load the doc in 97 and save to see the unicode
+ ver of the asian fontnames in that example to confirm.
+ */
+ rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(p->chs);
+ if ((eEnc == RTL_TEXTENCODING_SYMBOL) || (eEnc == RTL_TEXTENCODING_DONTKNOW))
+ eEnc = RTL_TEXTENCODING_MS_1252;
+
+ p->sFontname = String ( (((const sal_Char*)pVer2) + 1 + 2), eEnc);
+ pVer2 = (WW8_FFN_BASE*)( ((sal_uInt8*)pVer2) + pVer2->cbFfnM1 + 1 );
+ }
+ }
+ else if( eVersion < ww::eWW8 )
+ {
+ WW8_FFN_Ver6* pVer6 = (WW8_FFN_Ver6*)pA;
+ sal_uInt8 c2;
+ for(sal_uInt16 i=0; i<nMax; ++i, ++p)
+ {
+ p->cbFfnM1 = pVer6->cbFfnM1;
+ c2 = *(((sal_uInt8*)pVer6) + 1);
+
+ p->prg = c2 & 0x02;
+ p->fTrueType = (c2 & 0x04) >> 2;
+ // ein Reserve-Bit ueberspringen
+ p->ff = (c2 & 0x70) >> 4;
+
+ p->wWeight = SVBT16ToShort( *(SVBT16*)&pVer6->wWeight );
+ p->chs = pVer6->chs;
+ p->ibszAlt = pVer6->ibszAlt;
+ /*
+ #i8726# 7- seems to encode the name in the same encoding as
+ the font, e.g load the doc in 97 and save to see the unicode
+ ver of the asian fontnames in that example to confirm.
+ */
+ rtl_TextEncoding eEnc = WW8Fib::GetFIBCharset(p->chs);
+ if ((eEnc == RTL_TEXTENCODING_SYMBOL) || (eEnc == RTL_TEXTENCODING_DONTKNOW))
+ eEnc = RTL_TEXTENCODING_MS_1252;
+ p->sFontname = String(pVer6->szFfn, eEnc);
+ if (p->ibszAlt)
+ {
+ p->sFontname.Append(';');
+ p->sFontname += String(pVer6->szFfn+p->ibszAlt, eEnc);
+ }
+ else
+ {
+ //#i18369# if its a symbol font set Symbol as fallback
+ if (
+ RTL_TEXTENCODING_SYMBOL == WW8Fib::GetFIBCharset(p->chs)
+ && !p->sFontname.EqualsAscii("Symbol")
+ )
+ {
+ p->sFontname.APPEND_CONST_ASC(";Symbol");
+ }
+ }
+ pVer6 = (WW8_FFN_Ver6*)( ((sal_uInt8*)pVer6) + pVer6->cbFfnM1 + 1 );
+ }
+ }
+ else
+ {
+ WW8_FFN_Ver8* pVer8 = (WW8_FFN_Ver8*)pA;
+ sal_uInt8 c2;
+ for(sal_uInt16 i=0; i<nMax; ++i, ++p)
+ {
+ p->cbFfnM1 = pVer8->cbFfnM1;
+ c2 = *(((sal_uInt8*)pVer8) + 1);
+
+ p->prg = c2 & 0x02;
+ p->fTrueType = (c2 & 0x04) >> 2;
+ // ein Reserve-Bit ueberspringen
+ p->ff = (c2 & 0x70) >> 4;
+
+ p->wWeight = SVBT16ToShort( *(SVBT16*)&pVer8->wWeight );
+ p->chs = pVer8->chs;
+ p->ibszAlt = pVer8->ibszAlt;
+
+#ifdef __WW8_NEEDS_COPY
+ {
+ sal_uInt8 nLen = 0x28;
+ sal_uInt8 nLength = sizeof( pVer8->szFfn ) / sizeof( SVBT16 );
+ nLength = std::min( nLength, sal_uInt8( pVer8->cbFfnM1+1 ) );
+ for( sal_uInt16* pTmp = pVer8->szFfn;
+ nLen < nLength; ++pTmp, nLen+=2 )
+ {
+ *pTmp = SVBT16ToShort( *(SVBT16*)pTmp );
+ }
+ }
+#endif // defined __WW8_NEEDS_COPY
+
+ p->sFontname = pVer8->szFfn;
+ if (p->ibszAlt)
+ {
+ p->sFontname.Append(';');
+ p->sFontname.Append(pVer8->szFfn+p->ibszAlt);
+ }
+
+ // #i43762# check font name for illegal characters
+ lcl_checkFontname( p->sFontname );
+
+ // Zeiger auf Ursprungsarray einen Font nach hinten setzen
+ pVer8 = (WW8_FFN_Ver8*)( ((sal_uInt8*)pVer8) + pVer8->cbFfnM1 + 1 );
+ }
+ }
+ }
+ delete[] pA;
+}
+
+const WW8_FFN* WW8Fonts::GetFont( sal_uInt16 nNum ) const
+{
+ if( !pFontA || nNum >= nMax )
+ return 0;
+
+ return &pFontA[ nNum ];
+}
+
+
+
+//-----------------------------------------
+
+
+// Suche zu einem Header / Footer den Index in der WW-Liste von Headern / Footern
+//
+// Pferdefuesse bei WinWord6 und -7:
+// 1) Am Anfang des Einlesens muss WWPLCF_HdFt mit Fib und Dop konstruiert werden
+// 2) Der Haupttext muss sequentiell ueber alle Sections gelesen werden
+// 3) Fuer jedes vorkommende Header / Footer - Attribut des Haupttextes
+// ( Darf pro Section maximal eins sein ) muss UpdateIndex() genau einmal
+// mit dem Parameter des Attributes gerufen werden. Dieser Aufruf muss *nach*
+// dem letzten Aufruf von GetTextPos() passieren.
+// 4) GetTextPos() darf mit genau einem der obenstehen WW_... aufgerufen werden
+// ( nicht verodern ! )
+// -> dann liefert GetTextPos() vielleicht auch ein richtiges Ergebnis
+
+WW8PLCF_HdFt::WW8PLCF_HdFt( SvStream* pSt, WW8Fib& rFib, WW8Dop& rDop )
+ : aPLCF( pSt, rFib.fcPlcfhdd , rFib.lcbPlcfhdd , 0 )
+{
+ nIdxOffset = 0;
+
+ /*
+ cmc 23/02/2000: This dop.grpfIhdt has a bit set for each special
+ footnote *and endnote!!* seperator,continuation seperator, and
+ continuation notice entry, the documentation does not mention the
+ endnote seperators, the documentation also gets the index numbers
+ backwards when specifiying which bits to test. The bottom six bits
+ of this value must be tested and skipped over. Each section's
+ grpfIhdt is then tested for the existence of the appropiate headers
+ and footers, at the end of each section the nIdxOffset must be updated
+ to point to the beginning of the next section's group of headers and
+ footers in this PLCF, UpdateIndex does that task.
+ */
+ for( sal_uInt8 nI = 0x1; nI <= 0x20; nI <<= 1 )
+ if( nI & rDop.grpfIhdt ) // Bit gesetzt ?
+ nIdxOffset++;
+
+ nTextOfs = rFib.ccpText + rFib.ccpFtn; // Groesse des Haupttextes
+ // und der Fussnoten
+}
+
+bool WW8PLCF_HdFt::GetTextPos(sal_uInt8 grpfIhdt, sal_uInt8 nWhich, WW8_CP& rStart,
+ long& rLen)
+{
+ sal_uInt8 nI = 0x01;
+ short nIdx = nIdxOffset;
+ while (true)
+ {
+ if( nI & nWhich )
+ break; // found
+ if( grpfIhdt & nI )
+ nIdx++; // uninteresting Header / Footer
+ nI <<= 1; // text next bit
+ if( nI > 0x20 )
+ return false; // not found
+ }
+ // nIdx ist HdFt-Index
+ WW8_CP nEnd;
+ void* pData;
+
+ aPLCF.SetIdx( nIdx ); // Lookup suitable CP
+ aPLCF.Get( rStart, nEnd, pData );
+ rLen = nEnd - rStart;
+ aPLCF++;
+
+ return true;
+}
+
+bool WW8PLCF_HdFt::GetTextPosExact(short nIdx, WW8_CP& rStart, long& rLen)
+{
+ WW8_CP nEnd;
+ void* pData;
+
+ aPLCF.SetIdx( nIdx ); // Lookup suitable CP
+ aPLCF.Get( rStart, nEnd, pData );
+ rLen = nEnd - rStart;
+ return true;
+}
+
+void WW8PLCF_HdFt::UpdateIndex( sal_uInt8 grpfIhdt )
+{
+ // Caution: Description is not correct
+ for( sal_uInt8 nI = 0x01; nI <= 0x20; nI <<= 1 )
+ if( nI & grpfIhdt )
+ nIdxOffset++;
+}
+
+//-----------------------------------------
+// WW8Dop
+//-----------------------------------------
+
+WW8Dop::WW8Dop(SvStream& rSt, sal_Int16 nFib, sal_Int32 nPos, sal_uInt32 nSize) : bUseThaiLineBreakingRules(false)
+{
+ memset( &nDataStart, 0, (&nDataEnd - &nDataStart) );
+ fDontUseHTMLAutoSpacing = true; //default
+ fAcetateShowAtn = true; //default
+ const sal_uInt32 nMaxDopSize = 0x268;
+ sal_uInt8* pDataPtr = new sal_uInt8[ nMaxDopSize ];
+ sal_uInt8* pData = pDataPtr;
+
+ sal_uInt32 nRead = nMaxDopSize < nSize ? nMaxDopSize : nSize;
+ rSt.Seek( nPos );
+ if (2 > nSize || nRead != rSt.Read(pData, nRead))
+ nDopError = ERR_SWG_READ_ERROR; // Error melden
+ else
+ {
+ if (nMaxDopSize > nRead)
+ memset( pData + nRead, 0, nMaxDopSize - nRead );
+
+ // dann mal die Daten auswerten
+ sal_uInt32 a32Bit;
+ sal_uInt16 a16Bit;
+ sal_uInt8 a8Bit;
+
+ a16Bit = Get_UShort( pData ); // 0 0x00
+ fFacingPages = 0 != ( a16Bit & 0x0001 ) ;
+ fWidowControl = 0 != ( a16Bit & 0x0002 ) ;
+ fPMHMainDoc = 0 != ( a16Bit & 0x0004 ) ;
+ grfSuppression = ( a16Bit & 0x0018 ) >> 3;
+ fpc = ( a16Bit & 0x0060 ) >> 5;
+ grpfIhdt = ( a16Bit & 0xff00 ) >> 8;
+
+ a16Bit = Get_UShort( pData ); // 2 0x02
+ rncFtn = a16Bit & 0x0003 ;
+ nFtn = ( a16Bit & ~0x0003 ) >> 2 ;
+
+ a8Bit = Get_Byte( pData ); // 4 0x04
+ fOutlineDirtySave = 0 != ( a8Bit & 0x01 );
+
+ a8Bit = Get_Byte( pData ); // 5 0x05
+ fOnlyMacPics = 0 != ( a8Bit & 0x01 );
+ fOnlyWinPics = 0 != ( a8Bit & 0x02 );
+ fLabelDoc = 0 != ( a8Bit & 0x04 );
+ fHyphCapitals = 0 != ( a8Bit & 0x08 );
+ fAutoHyphen = 0 != ( a8Bit & 0x10 );
+ fFormNoFields = 0 != ( a8Bit & 0x20 );
+ fLinkStyles = 0 != ( a8Bit & 0x40 );
+ fRevMarking = 0 != ( a8Bit & 0x80 );
+
+ a8Bit = Get_Byte( pData ); // 6 0x06
+ fBackup = 0 != ( a8Bit & 0x01 );
+ fExactCWords = 0 != ( a8Bit & 0x02 );
+ fPagHidden = 0 != ( a8Bit & 0x04 );
+ fPagResults = 0 != ( a8Bit & 0x08 );
+ fLockAtn = 0 != ( a8Bit & 0x10 );
+ fMirrorMargins = 0 != ( a8Bit & 0x20 );
+ fReadOnlyRecommended = 0 != ( a8Bit & 0x40 );
+ fDfltTrueType = 0 != ( a8Bit & 0x80 );
+
+ a8Bit = Get_Byte( pData ); // 7 0x07
+ fPagSuppressTopSpacing = 0 != ( a8Bit & 0x01 );
+ fProtEnabled = 0 != ( a8Bit & 0x02 );
+ fDispFormFldSel = 0 != ( a8Bit & 0x04 );
+ fRMView = 0 != ( a8Bit & 0x08 );
+ fRMPrint = 0 != ( a8Bit & 0x10 );
+ fWriteReservation = 0 != ( a8Bit & 0x20 );
+ fLockRev = 0 != ( a8Bit & 0x40 );
+ fEmbedFonts = 0 != ( a8Bit & 0x80 );
+
+
+ a8Bit = Get_Byte( pData ); // 8 0x08
+ copts_fNoTabForInd = 0 != ( a8Bit & 0x01 );
+ copts_fNoSpaceRaiseLower = 0 != ( a8Bit & 0x02 );
+ copts_fSupressSpbfAfterPgBrk = 0 != ( a8Bit & 0x04 );
+ copts_fWrapTrailSpaces = 0 != ( a8Bit & 0x08 );
+ copts_fMapPrintTextColor = 0 != ( a8Bit & 0x10 );
+ copts_fNoColumnBalance = 0 != ( a8Bit & 0x20 );
+ copts_fConvMailMergeEsc = 0 != ( a8Bit & 0x40 );
+ copts_fSupressTopSpacing = 0 != ( a8Bit & 0x80 );
+
+ a8Bit = Get_Byte( pData ); // 9 0x09
+ copts_fOrigWordTableRules = 0 != ( a8Bit & 0x01 );
+ copts_fTransparentMetafiles = 0 != ( a8Bit & 0x02 );
+ copts_fShowBreaksInFrames = 0 != ( a8Bit & 0x04 );
+ copts_fSwapBordersFacingPgs = 0 != ( a8Bit & 0x08 );
+ copts_fExpShRtn = 0 != ( a8Bit & 0x20 ); // #i56856#
+
+ dxaTab = Get_Short( pData ); // 10 0x0a
+ wSpare = Get_UShort( pData ); // 12 0x0c
+ dxaHotZ = Get_UShort( pData ); // 14 0x0e
+ cConsecHypLim = Get_UShort( pData ); // 16 0x10
+ wSpare2 = Get_UShort( pData ); // 18 0x12
+ dttmCreated = Get_Long( pData ); // 20 0x14
+ dttmRevised = Get_Long( pData ); // 24 0x18
+ dttmLastPrint = Get_Long( pData ); // 28 0x1c
+ nRevision = Get_Short( pData ); // 32 0x20
+ tmEdited = Get_Long( pData ); // 34 0x22
+ cWords = Get_Long( pData ); // 38 0x26
+ cCh = Get_Long( pData ); // 42 0x2a
+ cPg = Get_Short( pData ); // 46 0x2e
+ cParas = Get_Long( pData ); // 48 0x30
+
+ a16Bit = Get_UShort( pData ); // 52 0x34
+ rncEdn = a16Bit & 0x0003 ;
+ nEdn = ( a16Bit & ~0x0003 ) >> 2;
+
+ a16Bit = Get_UShort( pData ); // 54 0x36
+ epc = a16Bit & 0x0003 ;
+ nfcFtnRef = ( a16Bit & 0x003c ) >> 2;
+ nfcEdnRef = ( a16Bit & 0x03c0 ) >> 6;
+ fPrintFormData = 0 != ( a16Bit & 0x0400 );
+ fSaveFormData = 0 != ( a16Bit & 0x0800 );
+ fShadeFormData = 0 != ( a16Bit & 0x1000 );
+ fWCFtnEdn = 0 != ( a16Bit & 0x8000 );
+
+ cLines = Get_Long( pData ); // 56 0x38
+ cWordsFtnEnd = Get_Long( pData ); // 60 0x3c
+ cChFtnEdn = Get_Long( pData ); // 64 0x40
+ cPgFtnEdn = Get_Short( pData ); // 68 0x44
+ cParasFtnEdn = Get_Long( pData ); // 70 0x46
+ cLinesFtnEdn = Get_Long( pData ); // 74 0x4a
+ lKeyProtDoc = Get_Long( pData ); // 78 0x4e
+
+ a16Bit = Get_UShort( pData ); // 82 0x52
+ wvkSaved = a16Bit & 0x0007 ;
+ wScaleSaved = ( a16Bit & 0x0ff8 ) >> 3 ;
+ zkSaved = ( a16Bit & 0x3000 ) >> 12;
+ fRotateFontW6 = ( a16Bit & 0x4000 ) >> 14;
+ iGutterPos = ( a16Bit & 0x8000 ) >> 15;
+ /*
+ bei nFib >= 103 gehts weiter:
+ */
+ if (nFib >= 103) // Word 6/32bit, 95, 97, 2000, 2002, 2003, 2007
+ {
+ a32Bit = Get_ULong( pData ); // 84 0x54
+ SetCompatabilityOptions(a32Bit);
+ }
+
+ //#i22436#, for all WW7- documents
+ if (nFib <= 104) // Word 95
+ fUsePrinterMetrics = 1;
+
+ /*
+ bei nFib > 105 gehts weiter:
+ */
+ if (nFib > 105) // Word 97, 2000, 2002, 2003, 2007
+ {
+ adt = Get_Short( pData ); // 88 0x58
+
+ doptypography.ReadFromMem(pData); // 90 0x5a
+
+ memcpy( &dogrid, pData, sizeof( WW8_DOGRID )); // 400 0x190
+ pData += sizeof( WW8_DOGRID );
+
+ a16Bit = Get_UShort( pData ); // 410 0x19a
+ // die untersten 9 Bit sind uninteressant
+ fHtmlDoc = ( a16Bit & 0x0200 ) >> 9 ;
+ fSnapBorder = ( a16Bit & 0x0800 ) >> 11 ;
+ fIncludeHeader = ( a16Bit & 0x1000 ) >> 12 ;
+ fIncludeFooter = ( a16Bit & 0x2000 ) >> 13 ;
+ fForcePageSizePag = ( a16Bit & 0x4000 ) >> 14 ;
+ fMinFontSizePag = ( a16Bit & 0x8000 ) >> 15 ;
+
+ a16Bit = Get_UShort( pData ); // 412 0x19c
+ fHaveVersions = 0 != ( a16Bit & 0x0001 );
+ fAutoVersion = 0 != ( a16Bit & 0x0002 );
+
+ pData += 12; // 414 0x19e
+
+ cChWS = Get_Long( pData ); // 426 0x1aa
+ cChWSFtnEdn = Get_Long( pData ); // 430 0x1ae
+ grfDocEvents = Get_Long( pData ); // 434 0x1b2
+
+ pData += 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
+
+ cDBC = Get_Long( pData ); // 480 0x1e0
+ cDBCFtnEdn = Get_Long( pData ); // 484 0x1e4
+
+ pData += 1 * sizeof( sal_Int32); // 488 0x1e8
+
+ nfcFtnRef = Get_Short( pData ); // 492 0x1ec
+ nfcEdnRef = Get_Short( pData ); // 494 0x1ee
+ hpsZoonFontPag = Get_Short( pData ); // 496 0x1f0
+ dywDispPag = Get_Short( pData ); // 498 0x1f2
+
+ if (nRead >= 516)
+ {
+ //500 -> 508, Appear to be repeated here in 2000+
+ pData += 8; // 500 0x1f4
+ a32Bit = Get_Long( pData ); // 508 0x1fc
+ SetCompatabilityOptions(a32Bit);
+ a32Bit = Get_Long( pData ); // 512 0x200
+
+ // i#78591#
+ SetCompatabilityOptions2(a32Bit);
+ }
+ if (nRead >= 550)
+ {
+ pData += 32;
+ a16Bit = Get_UShort( pData );
+ fDoNotEmbedSystemFont = ( a16Bit & 0x0001 );
+ fWordCompat = ( a16Bit & 0x0002 ) >> 1;
+ fLiveRecover = ( a16Bit & 0x0004 ) >> 2;
+ fEmbedFactoids = ( a16Bit & 0x0008 ) >> 3;
+ fFactoidXML = ( a16Bit & 0x00010 ) >> 4;
+ fFactoidAllDone = ( a16Bit & 0x0020 ) >> 5;
+ fFolioPrint = ( a16Bit & 0x0040 ) >> 6;
+ fReverseFolio = ( a16Bit & 0x0080 ) >> 7;
+ iTextLineEnding = ( a16Bit & 0x0700 ) >> 8;
+ fHideFcc = ( a16Bit & 0x0800 ) >> 11;
+ fAcetateShowMarkup = ( a16Bit & 0x1000 ) >> 12;
+ fAcetateShowAtn = ( a16Bit & 0x2000 ) >> 13;
+ fAcetateShowInsDel = ( a16Bit & 0x4000 ) >> 14;
+ fAcetateShowProps = ( a16Bit & 0x8000 ) >> 15;
+ }
+ if (nRead >= 600)
+ {
+ pData += 48;
+ a16Bit = Get_Short(pData);
+ fUseBackGroundInAllmodes = (a16Bit & 0x0080) >> 7;
+ }
+ }
+ }
+ delete[] pDataPtr;
+}
+
+WW8Dop::WW8Dop() : bUseThaiLineBreakingRules(false)
+{
+ // first set everything to a default of 0
+ memset( &nDataStart, 0, (&nDataEnd - &nDataStart) );
+
+ fWidowControl = 1;
+ fpc = 1;
+ nFtn = 1;
+ fOutlineDirtySave = 1;
+ fHyphCapitals = 1;
+ fBackup = 1;
+ fPagHidden = 1;
+ fPagResults = 1;
+ fDfltTrueType = 1;
+
+ /*
+ Writer acts like this all the time at the moment, ideally we need an
+ option for these two as well to import word docs that are not like
+ this by default
+ */
+ fNoLeading = 1;
+ fUsePrinterMetrics = 1;
+
+ fRMView = 1;
+ fRMPrint = 1;
+ dxaTab = 0x2d0;
+ dxaHotZ = 0x168;
+ nRevision = 1;
+ nEdn = 1;
+
+ epc = 3;
+ nfcEdnRef = 2;
+ fShadeFormData = 1;
+
+ wvkSaved = 2;
+ wScaleSaved = 100;
+ zkSaved = 0;
+
+ lvl = 9;
+ fIncludeHeader = 1;
+ fIncludeFooter = 1;
+
+ cChWS = /**!!**/ 0;
+ cChWSFtnEdn = /**!!**/ 0;
+
+ cDBC = /**!!**/ 0;
+ cDBCFtnEdn = /**!!**/ 0;
+
+ fAcetateShowAtn = true;
+}
+
+void WW8Dop::SetCompatabilityOptions(sal_uInt32 a32Bit)
+{
+ fNoTabForInd = ( a32Bit & 0x00000001 ) ;
+ fNoSpaceRaiseLower = ( a32Bit & 0x00000002 ) >> 1 ;
+ fSupressSpbfAfterPageBreak = ( a32Bit & 0x00000004 ) >> 2 ;
+ fWrapTrailSpaces = ( a32Bit & 0x00000008 ) >> 3 ;
+ fMapPrintTextColor = ( a32Bit & 0x00000010 ) >> 4 ;
+ fNoColumnBalance = ( a32Bit & 0x00000020 ) >> 5 ;
+ fConvMailMergeEsc = ( a32Bit & 0x00000040 ) >> 6 ;
+ fSupressTopSpacing = ( a32Bit & 0x00000080 ) >> 7 ;
+ fOrigWordTableRules = ( a32Bit & 0x00000100 ) >> 8 ;
+ fTransparentMetafiles = ( a32Bit & 0x00000200 ) >> 9 ;
+ fShowBreaksInFrames = ( a32Bit & 0x00000400 ) >> 10 ;
+ fSwapBordersFacingPgs = ( a32Bit & 0x00000800 ) >> 11 ;
+ fCompatabilityOptions_Unknown1_13 = ( a32Bit & 0x00001000 ) >> 12 ;
+ fExpShRtn = ( a32Bit & 0x00002000 ) >> 13 ; // #i56856#
+ fCompatabilityOptions_Unknown1_15 = ( a32Bit & 0x00004000 ) >> 14 ;
+ fCompatabilityOptions_Unknown1_16 = ( a32Bit & 0x00008000 ) >> 15 ;
+ fSuppressTopSpacingMac5 = ( a32Bit & 0x00010000 ) >> 16 ;
+ fTruncDxaExpand = ( a32Bit & 0x00020000 ) >> 17 ;
+ fPrintBodyBeforeHdr = ( a32Bit & 0x00040000 ) >> 18 ;
+ fNoLeading = ( a32Bit & 0x00080000 ) >> 19 ;
+ fCompatabilityOptions_Unknown1_21 = ( a32Bit & 0x00100000 ) >> 20 ;
+ fMWSmallCaps = ( a32Bit & 0x00200000 ) >> 21 ;
+ fCompatabilityOptions_Unknown1_23 = ( a32Bit & 0x00400000 ) >> 22 ;
+ fCompatabilityOptions_Unknown1_24 = ( a32Bit & 0x00800800 ) >> 23 ;
+ fCompatabilityOptions_Unknown1_25 = ( a32Bit & 0x01000000 ) >> 24 ;
+ fCompatabilityOptions_Unknown1_26 = ( a32Bit & 0x02000000 ) >> 25 ;
+ fCompatabilityOptions_Unknown1_27 = ( a32Bit & 0x04000000 ) >> 26 ;
+ fCompatabilityOptions_Unknown1_28 = ( a32Bit & 0x08000000 ) >> 27 ;
+ fCompatabilityOptions_Unknown1_29 = ( a32Bit & 0x10000000 ) >> 28 ;
+ fCompatabilityOptions_Unknown1_30 = ( a32Bit & 0x20000000 ) >> 29 ;
+ fCompatabilityOptions_Unknown1_31 = ( a32Bit & 0x40000000 ) >> 30 ;
+
+ fUsePrinterMetrics = ( a32Bit & 0x80000000 ) >> 31 ;
+}
+
+sal_uInt32 WW8Dop::GetCompatabilityOptions() const
+{
+ sal_uInt32 a32Bit = 0;
+ if (fNoTabForInd) a32Bit |= 0x00000001;
+ if (fNoSpaceRaiseLower) a32Bit |= 0x00000002;
+ if (fSupressSpbfAfterPageBreak) a32Bit |= 0x00000004;
+ if (fWrapTrailSpaces) a32Bit |= 0x00000008;
+ if (fMapPrintTextColor) a32Bit |= 0x00000010;
+ if (fNoColumnBalance) a32Bit |= 0x00000020;
+ if (fConvMailMergeEsc) a32Bit |= 0x00000040;
+ if (fSupressTopSpacing) a32Bit |= 0x00000080;
+ if (fOrigWordTableRules) a32Bit |= 0x00000100;
+ if (fTransparentMetafiles) a32Bit |= 0x00000200;
+ if (fShowBreaksInFrames) a32Bit |= 0x00000400;
+ if (fSwapBordersFacingPgs) a32Bit |= 0x00000800;
+ if (fCompatabilityOptions_Unknown1_13) a32Bit |= 0x00001000;
+ if (fExpShRtn) a32Bit |= 0x00002000; // #i56856#
+ if (fCompatabilityOptions_Unknown1_15) a32Bit |= 0x00004000;
+ if (fCompatabilityOptions_Unknown1_16) a32Bit |= 0x00008000;
+ if (fSuppressTopSpacingMac5) a32Bit |= 0x00010000;
+ if (fTruncDxaExpand) a32Bit |= 0x00020000;
+ if (fPrintBodyBeforeHdr) a32Bit |= 0x00040000;
+ if (fNoLeading) a32Bit |= 0x00080000;
+ if (fCompatabilityOptions_Unknown1_21) a32Bit |= 0x00100000;
+ if (fMWSmallCaps) a32Bit |= 0x00200000;
+ if (fCompatabilityOptions_Unknown1_23) a32Bit |= 0x00400000;
+ if (fCompatabilityOptions_Unknown1_24) a32Bit |= 0x00800000;
+ if (fCompatabilityOptions_Unknown1_25) a32Bit |= 0x01000000;
+ if (fCompatabilityOptions_Unknown1_26) a32Bit |= 0x02000000;
+ if (fCompatabilityOptions_Unknown1_27) a32Bit |= 0x04000000;
+ if (fCompatabilityOptions_Unknown1_28) a32Bit |= 0x08000000;
+ if (fCompatabilityOptions_Unknown1_29) a32Bit |= 0x10000000;
+ if (fCompatabilityOptions_Unknown1_30) a32Bit |= 0x20000000;
+ if (fCompatabilityOptions_Unknown1_31) a32Bit |= 0x40000000;
+ if (fUsePrinterMetrics) a32Bit |= 0x80000000;
+ return a32Bit;
+}
+
+// i#78591#
+void WW8Dop::SetCompatabilityOptions2(sal_uInt32 a32Bit)
+{
+ fCompatabilityOptions_Unknown2_1 = ( a32Bit & 0x00000001 );
+ fCompatabilityOptions_Unknown2_2 = ( a32Bit & 0x00000002 ) >> 1 ;
+ fDontUseHTMLAutoSpacing = ( a32Bit & 0x00000004 ) >> 2 ;
+ fCompatabilityOptions_Unknown2_4 = ( a32Bit & 0x00000008 ) >> 3 ;
+ fCompatabilityOptions_Unknown2_5 = ( a32Bit & 0x00000010 ) >> 4 ;
+ fCompatabilityOptions_Unknown2_6 = ( a32Bit & 0x00000020 ) >> 5 ;
+ fCompatabilityOptions_Unknown2_7 = ( a32Bit & 0x00000040 ) >> 6 ;
+ fCompatabilityOptions_Unknown2_8 = ( a32Bit & 0x00000080 ) >> 7 ;
+ fCompatabilityOptions_Unknown2_9 = ( a32Bit & 0x00000100 ) >> 8 ;
+ fCompatabilityOptions_Unknown2_10 = ( a32Bit & 0x00000200 ) >> 9 ;
+ fCompatabilityOptions_Unknown2_11 = ( a32Bit & 0x00000400 ) >> 10 ;
+ fCompatabilityOptions_Unknown2_12 = ( a32Bit & 0x00000800 ) >> 11 ;
+ fCompatabilityOptions_Unknown2_13 = ( a32Bit & 0x00001000 ) >> 12 ;
+ fCompatabilityOptions_Unknown2_14 = ( a32Bit & 0x00002000 ) >> 13 ;
+ fCompatabilityOptions_Unknown2_15 = ( a32Bit & 0x00004000 ) >> 14 ;
+ fCompatabilityOptions_Unknown2_16 = ( a32Bit & 0x00008000 ) >> 15 ;
+ fCompatabilityOptions_Unknown2_17 = ( a32Bit & 0x00010000 ) >> 16 ;
+ fCompatabilityOptions_Unknown2_18 = ( a32Bit & 0x00020000 ) >> 17 ;
+ fCompatabilityOptions_Unknown2_19 = ( a32Bit & 0x00040000 ) >> 18 ;
+ fCompatabilityOptions_Unknown2_20 = ( a32Bit & 0x00080000 ) >> 19 ;
+ fCompatabilityOptions_Unknown2_21 = ( a32Bit & 0x00100000 ) >> 20 ;
+ fCompatabilityOptions_Unknown2_22 = ( a32Bit & 0x00200000 ) >> 21 ;
+ fCompatabilityOptions_Unknown2_23 = ( a32Bit & 0x00400000 ) >> 22 ;
+ fCompatabilityOptions_Unknown2_24 = ( a32Bit & 0x00800800 ) >> 23 ;
+ fCompatabilityOptions_Unknown2_25 = ( a32Bit & 0x01000800 ) >> 24 ;
+ fCompatabilityOptions_Unknown2_26 = ( a32Bit & 0x02000800 ) >> 25 ;
+ fCompatabilityOptions_Unknown2_27 = ( a32Bit & 0x04000800 ) >> 26 ;
+ fCompatabilityOptions_Unknown2_28 = ( a32Bit & 0x08000800 ) >> 27 ;
+ fCompatabilityOptions_Unknown2_29 = ( a32Bit & 0x10000800 ) >> 28 ;
+ fCompatabilityOptions_Unknown2_30 = ( a32Bit & 0x20000800 ) >> 29 ;
+ fCompatabilityOptions_Unknown2_31 = ( a32Bit & 0x40000800 ) >> 30 ;
+ fCompatabilityOptions_Unknown2_32 = ( a32Bit & 0x80000000 ) >> 31 ;
+}
+
+sal_uInt32 WW8Dop::GetCompatabilityOptions2() const
+{
+ sal_uInt32 a32Bit = 0;
+ if (fCompatabilityOptions_Unknown2_1) a32Bit |= 0x00000001;
+ if (fCompatabilityOptions_Unknown2_2) a32Bit |= 0x00000002;
+ if (fDontUseHTMLAutoSpacing) a32Bit |= 0x00000004;
+ if (fCompatabilityOptions_Unknown2_4) a32Bit |= 0x00000008;
+ if (fCompatabilityOptions_Unknown2_5) a32Bit |= 0x00000010;
+ if (fCompatabilityOptions_Unknown2_6) a32Bit |= 0x00000020;
+ if (fCompatabilityOptions_Unknown2_7) a32Bit |= 0x00000040;
+ if (fCompatabilityOptions_Unknown2_8) a32Bit |= 0x00000080;
+ if (fCompatabilityOptions_Unknown2_9) a32Bit |= 0x00000100;
+ if (fCompatabilityOptions_Unknown2_10) a32Bit |= 0x00000200;
+ if (fCompatabilityOptions_Unknown2_11) a32Bit |= 0x00000400;
+ if (fCompatabilityOptions_Unknown2_12) a32Bit |= 0x00000800;
+ if (fCompatabilityOptions_Unknown2_13) a32Bit |= 0x00001000;
+ //#i42909# set thai "line breaking rules" compatibility option
+ // pflin, wonder whether bUseThaiLineBreakingRules is correct
+ // when importing word document.
+ if (bUseThaiLineBreakingRules) a32Bit |= 0x00002000;
+ else if (fCompatabilityOptions_Unknown2_14) a32Bit |= 0x00002000;
+ if (fCompatabilityOptions_Unknown2_15) a32Bit |= 0x00004000;
+ if (fCompatabilityOptions_Unknown2_16) a32Bit |= 0x00008000;
+ if (fCompatabilityOptions_Unknown2_17) a32Bit |= 0x00010000;
+ if (fCompatabilityOptions_Unknown2_18) a32Bit |= 0x00020000;
+ if (fCompatabilityOptions_Unknown2_19) a32Bit |= 0x00040000;
+ if (fCompatabilityOptions_Unknown2_20) a32Bit |= 0x00080000;
+ if (fCompatabilityOptions_Unknown2_21) a32Bit |= 0x00100000;
+ if (fCompatabilityOptions_Unknown2_22) a32Bit |= 0x00200000;
+ if (fCompatabilityOptions_Unknown2_23) a32Bit |= 0x00400000;
+ if (fCompatabilityOptions_Unknown2_24) a32Bit |= 0x00800000;
+ if (fCompatabilityOptions_Unknown2_25) a32Bit |= 0x01000000;
+ if (fCompatabilityOptions_Unknown2_26) a32Bit |= 0x02000000;
+ if (fCompatabilityOptions_Unknown2_27) a32Bit |= 0x04000000;
+ if (fCompatabilityOptions_Unknown2_28) a32Bit |= 0x08000000;
+ if (fCompatabilityOptions_Unknown2_29) a32Bit |= 0x10000000;
+ if (fCompatabilityOptions_Unknown2_30) a32Bit |= 0x20000000;
+ if (fCompatabilityOptions_Unknown2_31) a32Bit |= 0x40000000;
+ if (fCompatabilityOptions_Unknown2_32) a32Bit |= 0x80000000;
+ return a32Bit;
+}
+
+bool WW8Dop::Write(SvStream& rStrm, WW8Fib& rFib) const
+{
+ const int nMaxDopLen = 610;
+ sal_uInt32 nLen = 8 == rFib.nVersion ? nMaxDopLen : 84;
+ rFib.fcDop = rStrm.Tell();
+ rFib.lcbDop = nLen;
+
+ sal_uInt8 aData[ nMaxDopLen ];
+ memset( aData, 0, nMaxDopLen );
+ sal_uInt8* pData = aData;
+
+ // dann mal die Daten auswerten
+ sal_uInt16 a16Bit;
+ sal_uInt8 a8Bit;
+
+ a16Bit = 0; // 0 0x00
+ if (fFacingPages)
+ a16Bit |= 0x0001;
+ if (fWidowControl)
+ a16Bit |= 0x0002;
+ if (fPMHMainDoc)
+ a16Bit |= 0x0004;
+ a16Bit |= ( 0x0018 & (grfSuppression << 3));
+ a16Bit |= ( 0x0060 & (fpc << 5));
+ a16Bit |= ( 0xff00 & (grpfIhdt << 8));
+ Set_UInt16( pData, a16Bit );
+
+ a16Bit = 0; // 2 0x02
+ a16Bit |= ( 0x0003 & rncFtn );
+ a16Bit |= ( ~0x0003 & (nFtn << 2));
+ Set_UInt16( pData, a16Bit );
+
+ a8Bit = 0; // 4 0x04
+ if( fOutlineDirtySave ) a8Bit |= 0x01;
+ Set_UInt8( pData, a8Bit );
+
+ a8Bit = 0; // 5 0x05
+ if( fOnlyMacPics ) a8Bit |= 0x01;
+ if( fOnlyWinPics ) a8Bit |= 0x02;
+ if( fLabelDoc ) a8Bit |= 0x04;
+ if( fHyphCapitals ) a8Bit |= 0x08;
+ if( fAutoHyphen ) a8Bit |= 0x10;
+ if( fFormNoFields ) a8Bit |= 0x20;
+ if( fLinkStyles ) a8Bit |= 0x40;
+ if( fRevMarking ) a8Bit |= 0x80;
+ Set_UInt8( pData, a8Bit );
+
+ a8Bit = 0; // 6 0x06
+ if( fBackup ) a8Bit |= 0x01;
+ if( fExactCWords ) a8Bit |= 0x02;
+ if( fPagHidden ) a8Bit |= 0x04;
+ if( fPagResults ) a8Bit |= 0x08;
+ if( fLockAtn ) a8Bit |= 0x10;
+ if( fMirrorMargins ) a8Bit |= 0x20;
+ if( fReadOnlyRecommended ) a8Bit |= 0x40;
+ if( fDfltTrueType ) a8Bit |= 0x80;
+ Set_UInt8( pData, a8Bit );
+
+ a8Bit = 0; // 7 0x07
+ if( fPagSuppressTopSpacing ) a8Bit |= 0x01;
+ if( fProtEnabled ) a8Bit |= 0x02;
+ if( fDispFormFldSel ) a8Bit |= 0x04;
+ if( fRMView ) a8Bit |= 0x08;
+ if( fRMPrint ) a8Bit |= 0x10;
+ if( fWriteReservation ) a8Bit |= 0x20;
+ if( fLockRev ) a8Bit |= 0x40;
+ if( fEmbedFonts ) a8Bit |= 0x80;
+ Set_UInt8( pData, a8Bit );
+
+
+ a8Bit = 0; // 8 0x08
+ if( copts_fNoTabForInd ) a8Bit |= 0x01;
+ if( copts_fNoSpaceRaiseLower ) a8Bit |= 0x02;
+ if( copts_fSupressSpbfAfterPgBrk ) a8Bit |= 0x04;
+ if( copts_fWrapTrailSpaces ) a8Bit |= 0x08;
+ if( copts_fMapPrintTextColor ) a8Bit |= 0x10;
+ if( copts_fNoColumnBalance ) a8Bit |= 0x20;
+ if( copts_fConvMailMergeEsc ) a8Bit |= 0x40;
+ if( copts_fSupressTopSpacing ) a8Bit |= 0x80;
+ Set_UInt8( pData, a8Bit );
+
+ a8Bit = 0; // 9 0x09
+ if( copts_fOrigWordTableRules ) a8Bit |= 0x01;
+ if( copts_fTransparentMetafiles ) a8Bit |= 0x02;
+ if( copts_fShowBreaksInFrames ) a8Bit |= 0x04;
+ if( copts_fSwapBordersFacingPgs ) a8Bit |= 0x08;
+ if( copts_fExpShRtn ) a8Bit |= 0x20; // #i56856#
+ Set_UInt8( pData, a8Bit );
+
+ Set_UInt16( pData, dxaTab ); // 10 0x0a
+ Set_UInt16( pData, wSpare ); // 12 0x0c
+ Set_UInt16( pData, dxaHotZ ); // 14 0x0e
+ Set_UInt16( pData, cConsecHypLim ); // 16 0x10
+ Set_UInt16( pData, wSpare2 ); // 18 0x12
+ Set_UInt32( pData, dttmCreated ); // 20 0x14
+ Set_UInt32( pData, dttmRevised ); // 24 0x18
+ Set_UInt32( pData, dttmLastPrint ); // 28 0x1c
+ Set_UInt16( pData, nRevision ); // 32 0x20
+ Set_UInt32( pData, tmEdited ); // 34 0x22
+ Set_UInt32( pData, cWords ); // 38 0x26
+ Set_UInt32( pData, cCh ); // 42 0x2a
+ Set_UInt16( pData, cPg ); // 46 0x2e
+ Set_UInt32( pData, cParas ); // 48 0x30
+
+ a16Bit = 0; // 52 0x34
+ a16Bit |= ( 0x0003 & rncEdn );
+ a16Bit |= (~0x0003 & ( nEdn << 2));
+ Set_UInt16( pData, a16Bit );
+
+ a16Bit = 0; // 54 0x36
+ a16Bit |= (0x0003 & epc );
+ a16Bit |= (0x003c & (nfcFtnRef << 2));
+ a16Bit |= (0x03c0 & (nfcEdnRef << 6));
+ if( fPrintFormData ) a16Bit |= 0x0400;
+ if( fSaveFormData ) a16Bit |= 0x0800;
+ if( fShadeFormData ) a16Bit |= 0x1000;
+ if( fWCFtnEdn ) a16Bit |= 0x8000;
+ Set_UInt16( pData, a16Bit );
+
+ Set_UInt32( pData, cLines ); // 56 0x38
+ Set_UInt32( pData, cWordsFtnEnd ); // 60 0x3c
+ Set_UInt32( pData, cChFtnEdn ); // 64 0x40
+ Set_UInt16( pData, cPgFtnEdn ); // 68 0x44
+ Set_UInt32( pData, cParasFtnEdn ); // 70 0x46
+ Set_UInt32( pData, cLinesFtnEdn ); // 74 0x4a
+ Set_UInt32( pData, lKeyProtDoc ); // 78 0x4e
+
+ a16Bit = 0; // 82 0x52
+ if (wvkSaved)
+ a16Bit |= 0x0007;
+ a16Bit |= (0x0ff8 & (wScaleSaved << 3));
+ a16Bit |= (0x3000 & (zkSaved << 12));
+ Set_UInt16( pData, a16Bit );
+
+ if( 8 == rFib.nVersion )
+ {
+ Set_UInt32(pData, GetCompatabilityOptions()); // 84 0x54
+
+ Set_UInt16( pData, adt ); // 88 0x58
+
+ doptypography.WriteToMem(pData); // 400 0x190
+
+ memcpy( pData, &dogrid, sizeof( WW8_DOGRID ));
+ pData += sizeof( WW8_DOGRID );
+
+ a16Bit = 0x12; // lvl auf 9 setzen // 410 0x19a
+ if( fHtmlDoc ) a16Bit |= 0x0200;
+ if( fSnapBorder ) a16Bit |= 0x0800;
+ if( fIncludeHeader ) a16Bit |= 0x1000;
+ if( fIncludeFooter ) a16Bit |= 0x2000;
+ if( fForcePageSizePag ) a16Bit |= 0x4000;
+ if( fMinFontSizePag ) a16Bit |= 0x8000;
+ Set_UInt16( pData, a16Bit );
+
+ a16Bit = 0; // 412 0x19c
+ if( fHaveVersions ) a16Bit |= 0x0001;
+ if( fAutoVersion ) a16Bit |= 0x0002;
+ Set_UInt16( pData, a16Bit );
+
+ pData += 12; // 414 0x19e
+
+ Set_UInt32( pData, cChWS ); // 426 0x1aa
+ Set_UInt32( pData, cChWSFtnEdn ); // 430 0x1ae
+ Set_UInt32( pData, grfDocEvents ); // 434 0x1b2
+
+ pData += 4+30+8; // 438 0x1b6; 442 0x1ba; 472 0x1d8; 476 0x1dc
+
+ Set_UInt32( pData, cDBC ); // 480 0x1e0
+ Set_UInt32( pData, cDBCFtnEdn ); // 484 0x1e4
+
+ pData += 1 * sizeof( sal_Int32); // 488 0x1e8
+
+ Set_UInt16( pData, nfcFtnRef ); // 492 0x1ec
+ Set_UInt16( pData, nfcEdnRef ); // 494 0x1ee
+ Set_UInt16( pData, hpsZoonFontPag ); // 496 0x1f0
+ Set_UInt16( pData, dywDispPag ); // 498 0x1f2
+
+ //500 -> 508, Appear to be repeated here in 2000+
+ pData += 8;
+ Set_UInt32(pData, GetCompatabilityOptions());
+ Set_UInt32(pData, GetCompatabilityOptions2());
+ pData += 32;
+
+ a16Bit = 0;
+ if (fAcetateShowMarkup)
+ a16Bit |= 0x1000;
+ //Word XP at least requires fAcetateShowMarkup to honour fAcetateShowAtn
+ if (fAcetateShowAtn)
+ {
+ a16Bit |= 0x1000;
+ a16Bit |= 0x2000;
+ }
+ Set_UInt16(pData, a16Bit);
+
+ pData += 48;
+ a16Bit = 0x0080;
+ Set_UInt16(pData, a16Bit);
+ }
+ rStrm.Write( aData, nLen );
+ return 0 == rStrm.GetError();
+}
+
+void WW8DopTypography::ReadFromMem(sal_uInt8 *&pData)
+{
+ sal_uInt16 a16Bit = Get_UShort(pData);
+ fKerningPunct = (a16Bit & 0x0001);
+ iJustification = (a16Bit & 0x0006) >> 1;
+ iLevelOfKinsoku = (a16Bit & 0x0018) >> 3;
+ f2on1 = (a16Bit & 0x0020) >> 5;
+ reserved1 = (a16Bit & 0x03C0) >> 6;
+ reserved2 = (a16Bit & 0xFC00) >> 10;
+
+ cchFollowingPunct = Get_Short(pData);
+ cchLeadingPunct = Get_Short(pData);
+
+ sal_Int16 i;
+ for (i=0; i < nMaxFollowing; ++i)
+ rgxchFPunct[i] = Get_Short(pData);
+ for (i=0; i < nMaxLeading; ++i)
+ rgxchLPunct[i] = Get_Short(pData);
+
+ if (cchFollowingPunct >= 0 && cchFollowingPunct < nMaxFollowing)
+ rgxchFPunct[cchFollowingPunct]=0;
+ else
+ rgxchFPunct[nMaxFollowing - 1]=0;
+
+ if (cchLeadingPunct >= 0 && cchLeadingPunct < nMaxLeading)
+ rgxchLPunct[cchLeadingPunct]=0;
+ else
+ rgxchLPunct[nMaxLeading - 1]=0;
+
+}
+
+void WW8DopTypography::WriteToMem(sal_uInt8 *&pData) const
+{
+ sal_uInt16 a16Bit = fKerningPunct;
+ a16Bit |= (iJustification << 1) & 0x0006;
+ a16Bit |= (iLevelOfKinsoku << 3) & 0x0018;
+ a16Bit |= (f2on1 << 5) & 0x002;
+ a16Bit |= (reserved1 << 6) & 0x03C0;
+ a16Bit |= (reserved2 << 10) & 0xFC00;
+ Set_UInt16(pData,a16Bit);
+
+ Set_UInt16(pData,cchFollowingPunct);
+ Set_UInt16(pData,cchLeadingPunct);
+
+ sal_Int16 i;
+ for (i=0; i < nMaxFollowing; ++i)
+ Set_UInt16(pData,rgxchFPunct[i]);
+ for (i=0; i < nMaxLeading; ++i)
+ Set_UInt16(pData,rgxchLPunct[i]);
+}
+
+sal_uInt16 WW8DopTypography::GetConvertedLang() const
+{
+ sal_uInt16 nLang;
+ //I have assumed peoples republic/taiwan == simplified/traditional
+
+ //This isn't a documented issue, so we might have it all wrong,
+ //i.e. i.e. whats with the powers of two ?
+
+ /*
+ One example of 3 for reserved1 which was really Japanese, perhaps last bit
+ is for some other use ?, or redundant. If more examples trigger the assert
+ we might be able to figure it out.
+ */
+ switch(reserved1 & 0xE)
+ {
+ case 2: //Japan
+ nLang = LANGUAGE_JAPANESE;
+ break;
+ case 4: //Chinese (Peoples Republic)
+ nLang = LANGUAGE_CHINESE_SIMPLIFIED;
+ break;
+ case 6: //Korean
+ nLang = LANGUAGE_KOREAN;
+ break;
+ case 8: //Chinese (Taiwan)
+ nLang = LANGUAGE_CHINESE_TRADITIONAL;
+ break;
+ default:
+ OSL_ENSURE(!this, "Unknown MS Asian Typography language, report");
+ nLang = LANGUAGE_CHINESE;
+ break;
+ case 0:
+ //And here we have the possibility that it says 2, but its really
+ //a bug and only japanese level 2 has been selected after a custom
+ //version was chosen on last save!
+ nLang = LANGUAGE_JAPANESE;
+ break;
+ }
+ return nLang;
+}
+
+//-----------------------------------------
+// Sprms
+//-----------------------------------------
+sal_uInt16 wwSprmParser::GetSprmTailLen(sal_uInt16 nId, const sal_uInt8* pSprm)
+ const
+{
+ SprmInfo aSprm = GetSprmInfo(nId);
+ sal_uInt16 nL = 0; // number of Bytes to read
+
+ //sprmPChgTabs
+ switch( nId )
+ {
+ case 23:
+ case 0xC615:
+ if( pSprm[1 + mnDelta] != 255 )
+ nL = static_cast< sal_uInt16 >(pSprm[1 + mnDelta] + aSprm.nLen);
+ else
+ {
+ sal_uInt8 nDel = pSprm[2 + mnDelta];
+ sal_uInt8 nIns = pSprm[3 + mnDelta + 4 * nDel];
+
+ nL = 2 + 4 * nDel + 3 * nIns;
+ }
+ break;
+ case 0xD608:
+ nL = SVBT16ToShort( &pSprm[1 + mnDelta] );
+ break;
+ default:
+ switch (aSprm.nVari)
+ {
+ case L_FIX:
+ nL = aSprm.nLen; // Excl. Token
+ break;
+ case L_VAR:
+ // Variable 1-Byte Length?
+ // Excl. Token + Var-Lengthbyte
+ nL = static_cast< sal_uInt16 >(pSprm[1 + mnDelta] + aSprm.nLen);
+ break;
+ case L_VAR2:
+ // Variable 2-Byte Length?
+ // Excl. Token + Var-Lengthbyte
+ nL = static_cast< sal_uInt16 >(SVBT16ToShort( &pSprm[1 + mnDelta] ) + aSprm.nLen - 1);
+ break;
+ default:
+ OSL_ENSURE(!this, "Unknown sprm varient");
+ break;
+ }
+ break;
+ }
+ return nL;
+}
+
+// one or two bytes at the beginning at the sprm id
+sal_uInt16 wwSprmParser::GetSprmId(const sal_uInt8* pSp) const
+{
+ ASSERT_RET_ON_FAIL(pSp, "Why GetSprmId with pSp of 0", 0);
+
+ sal_uInt16 nId = 0;
+
+ if (ww::IsSevenMinus(meVersion))
+ {
+ nId = *pSp;
+ if (0x0100 < nId)
+ nId = 0;
+ }
+ else
+ {
+ nId = SVBT16ToShort(pSp);
+ if (0x0800 > nId)
+ nId = 0;
+ }
+
+ return nId;
+}
+
+// with tokens and length byte
+sal_uInt16 wwSprmParser::GetSprmSize(sal_uInt16 nId, const sal_uInt8* pSprm) const
+{
+ return GetSprmTailLen(nId, pSprm) + 1 + mnDelta + SprmDataOfs(nId);
+}
+
+sal_uInt8 wwSprmParser::SprmDataOfs(sal_uInt16 nId) const
+{
+ return GetSprmInfo(nId).nVari;
+}
+
+sal_uInt16 wwSprmParser::DistanceToData(sal_uInt16 nId) const
+{
+ return 1 + mnDelta + SprmDataOfs(nId);
+}
+
+SEPr::SEPr() :
+ bkc(2), fTitlePage(0), fAutoPgn(0), nfcPgn(0), fUnlocked(0), cnsPgn(0),
+ fPgnRestart(0), fEndNote(1), lnc(0), grpfIhdt(0), nLnnMod(0), dxaLnn(0),
+ dxaPgn(720), dyaPgn(720), fLBetween(0), vjc(0), dmBinFirst(0),
+ dmBinOther(0), dmPaperReq(0), fPropRMark(0), ibstPropRMark(0),
+ dttmPropRMark(0), dxtCharSpace(0), dyaLinePitch(0), clm(0), reserved1(0),
+ dmOrientPage(0), iHeadingPgn(0), pgnStart(1), lnnMin(0), wTextFlow(0),
+ reserved2(0), pgbApplyTo(0), pgbPageDepth(0), pgbOffsetFrom(0),
+ xaPage(lLetterWidth), yaPage(lLetterHeight), xaPageNUp(lLetterWidth), yaPageNUp(lLetterHeight),
+ dxaLeft(1800), dxaRight(1800), dyaTop(1440), dyaBottom(1440), dzaGutter(0),
+ dyaHdrTop(720), dyaHdrBottom(720), ccolM1(0), fEvenlySpaced(1),
+ reserved3(0), fBiDi(0), fFacingCol(0), fRTLGutter(0), fRTLAlignment(0),
+ dxaColumns(720), dxaColumnWidth(0), dmOrientFirst(0), fLayout(0),
+ reserved4(0)
+{
+ memset(rgdxaColumnWidthSpacing, 0, sizeof(rgdxaColumnWidthSpacing));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8scan.hxx b/sw/source/filter/ww8/ww8scan.hxx
new file mode 100644
index 000000000000..96300f4fbe5a
--- /dev/null
+++ b/sw/source/filter/ww8/ww8scan.hxx
@@ -0,0 +1,1785 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WW8SCAN_HXX
+#define _WW8SCAN_HXX
+
+#ifndef LONG_MAX
+#include <limits.h>
+#endif
+#include <stack>
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <tools/solar.h> // UINTXX
+#include <tools/datetime.hxx>
+#include <tools/stream.hxx>
+#include <tools/string.hxx>
+#include "hash_wrap.hxx"
+#include "sortedarray.hxx"
+
+#include "ww8struc.hxx" // FIB, STSHI, STD...
+#include <types.hxx>
+
+#include <unomid.h>
+
+#define APPEND_CONST_ASC(s) AppendAscii(RTL_CONSTASCII_STRINGPARAM(s))
+#define ASSIGN_CONST_ASC(s) AssignAscii(RTL_CONSTASCII_STRINGPARAM(s))
+#define CREATE_CONST_ASC(s) String::CreateFromAscii( \
+ RTL_CONSTASCII_STRINGPARAM(s))
+
+
+
+//--Line below which the code has meaningful comments
+
+//Commonly used string literals for stream and storage names in word docs
+namespace SL
+{
+# define DEFCONSTSTRINGARRAY(X) extern const char a##X[sizeof("" #X "")]
+ DEFCONSTSTRINGARRAY(ObjectPool);
+ DEFCONSTSTRINGARRAY(1Table);
+ DEFCONSTSTRINGARRAY(0Table);
+ DEFCONSTSTRINGARRAY(Data);
+ DEFCONSTSTRINGARRAY(CheckBox);
+ DEFCONSTSTRINGARRAY(ListBox);
+ DEFCONSTSTRINGARRAY(TextBox);
+ DEFCONSTSTRINGARRAY(TextField);
+ DEFCONSTSTRINGARRAY(MSMacroCmds);
+}
+
+/**
+ winword strings are typically Belt and Braces strings preceeded with a
+ pascal style count, and ending with a c style 0 terminator. 16bit chars
+ and count for ww8+ and 8bit chars and count for ww7-. The count and 0
+ can be checked for integrity to catch errors (e.g. lotus created documents)
+ where in error 8bit strings are used instead of 16bits strings for style
+ names.
+*/
+template<class C> class wwString
+{
+public:
+ static bool TestBeltAndBraces(const SvStream& rStrm);
+ //move the other string related code into this class as time goes by
+};
+
+typedef wwString<sal_uInt16> ww8String;
+
+struct SprmInfo
+{
+ sal_uInt16 nId; ///< A ww8 sprm is hardcoded as 16bits
+ unsigned int nLen : 6;
+ unsigned int nVari : 2;
+};
+
+struct SprmInfoHash
+{
+ size_t operator()(const SprmInfo &a) const
+ {
+ return a.nId;
+ }
+};
+
+typedef ww::WrappedHash<SprmInfo, SprmInfoHash> wwSprmSearcher;
+typedef ww::WrappedHash<sal_uInt16> wwSprmSequence;
+
+/**
+ wwSprmParser knows how to take a sequence of bytes and split it up into
+ sprms and their arguments
+*/
+class wwSprmParser
+{
+private:
+ ww::WordVersion meVersion;
+ sal_uInt8 mnDelta;
+ const wwSprmSearcher *mpKnownSprms;
+ static const wwSprmSearcher* GetWW8SprmSearcher();
+ static const wwSprmSearcher* GetWW6SprmSearcher();
+ static const wwSprmSearcher* GetWW2SprmSearcher();
+
+ SprmInfo GetSprmInfo(sal_uInt16 nId) const;
+
+ sal_uInt8 SprmDataOfs(sal_uInt16 nId) const;
+
+ enum SprmType {L_FIX=0, L_VAR=1, L_VAR2=2};
+public:
+ //7- ids are very different to 8+ ones
+ wwSprmParser(ww::WordVersion eVersion);
+ /// Return the SPRM id at the beginning of this byte sequence
+ sal_uInt16 GetSprmId(const sal_uInt8* pSp) const;
+
+ sal_uInt16 GetSprmSize(sal_uInt16 nId, const sal_uInt8* pSprm) const;
+
+ /// Get known len of a sprms head, the bytes of the sprm id + any bytes
+ /// reserved to hold a variable length
+ sal_uInt16 DistanceToData(sal_uInt16 nId) const;
+
+ /// Get len of a sprms data area, ignoring the bytes of the sprm id and
+ /// ignoring any len bytes. Reports the remaining data after those bytes
+ sal_uInt16 GetSprmTailLen(sal_uInt16 nId, const sal_uInt8 * pSprm) const;
+
+ /// The minimum acceptable sprm len possible for this type of parser
+ int MinSprmLen() const { return (IsSevenMinus(meVersion)) ? 2 : 3; }
+
+ inline int getVersion() const { return meVersion; } //cmc, I'm dubious about the usage of this, how can it be 0
+};
+
+//--Line abovewhich the code has meaningful comments
+
+class WW8Fib;
+class WW8ScannerBase;
+class WW8PLCFspecial;
+struct WW8PLCFxDesc;
+class WW8PLCFx_PCD;
+
+String WW8ReadPString( SvStream& rStrm, rtl_TextEncoding eEnc,
+ bool bAtEndSeekRel1 = true);
+
+/**
+ The following method reads a 2Byte unicode string. If bAtEndSeekRel1 is set,
+ exactly ONE byte is skipped If nChars is set then that number of characters
+ (not bytes) is read, if its not set, the first character read is the length
+*/
+String WW8Read_xstz(SvStream& rStrm, sal_uInt16 nChars, bool bAtEndSeekRel1);
+
+/**
+ reads array of strings (see MS documentation: STring TaBle stored in File)
+ returns NOT the original pascal strings but an array of converted char*
+
+ attention: the *extra data* of each string are SKIPPED and ignored
+ */
+void WW8ReadSTTBF(bool bVer8, SvStream& rStrm, sal_uInt32 nStart, sal_Int32 nLen,
+ sal_uInt16 nExtraLen, rtl_TextEncoding eCS, ::std::vector<String> &rArray,
+ ::std::vector<ww::bytes>* pExtraArray = 0, ::std::vector<String>* pValueArray = 0);
+
+struct WW8FieldDesc
+{
+ long nLen; ///< Gesamtlaenge ( zum Text ueberlesen )
+ WW8_CP nSCode; ///< Anfang Befehlscode
+ WW8_CP nLCode; ///< Laenge
+ WW8_CP nSRes; ///< Anfang Ergebnis
+ WW8_CP nLRes; ///< Laenge ( == 0, falls kein Ergebnis )
+ sal_uInt16 nId; ///< WW-Id fuer Felder
+ sal_uInt8 nOpt; ///< WW-Flags ( z.B.: vom User geaendert )
+ sal_uInt8 bCodeNest:1; ///< Befehl rekursiv verwendet
+ sal_uInt8 bResNest:1; ///< Befehl in Resultat eingefuegt
+};
+
+struct WW8PLCFxSave1
+{
+ sal_uLong nPLCFxPos;
+ sal_uLong nPLCFxPos2; ///< fuer PLCF_Cp_Fkp: PieceIter-Pos
+ long nPLCFxMemOfs;
+ WW8_CP nStartCp; ///< for cp based iterator like PAP and CHP
+ long nCpOfs;
+ WW8_FC nStartFC;
+ WW8_CP nAttrStart;
+ WW8_CP nAttrEnd;
+ bool bLineEnd;
+};
+
+/**
+ u.a. fuer Felder, also genausoviele Attr wie Positionen,
+ falls Ctor-Param bNoEnd = false
+*/
+class WW8PLCFspecial // Iterator fuer PLCFs
+{
+private:
+ sal_Int32* pPLCF_PosArray; ///< Pointer auf Pos-Array und auf ganze Struktur
+ sal_uInt8* pPLCF_Contents; ///< Pointer auf Inhalts-Array-Teil des Pos-Array
+ long nIMax; ///< Anzahl der Elemente
+ long nIdx; ///< Merker, wo wir gerade sind
+ long nStru;
+public:
+ WW8PLCFspecial( SvStream* pSt, long nFilePos, long nPLCF,
+ long nStruct, long nStartPos = -1 );
+ ~WW8PLCFspecial() { delete[] pPLCF_PosArray; }
+ long GetIdx() const { return nIdx; }
+ void SetIdx( long nI ) { nIdx = nI; }
+ long GetIMax() const { return nIMax; }
+ bool SeekPos(long nPos); // geht ueber FC- bzw. CP-Wert
+ // bzw. naechste groesseren Wert
+ bool SeekPosExact(long nPos);
+ sal_Int32 Where() const
+ { return ( nIdx >= nIMax ) ? SAL_MAX_INT32 : pPLCF_PosArray[nIdx]; }
+ bool Get(WW8_CP& rStart, void*& rpValue) const;
+ bool GetData(long nIdx, WW8_CP& rPos, void*& rpValue) const;
+
+ const void* GetData( long nInIdx ) const
+ {
+ return ( nInIdx >= nIMax ) ? 0
+ : (const void*)&pPLCF_Contents[nInIdx * nStru];
+ }
+ sal_Int32 GetPos( long nInIdx ) const
+ { return ( nInIdx >= nIMax ) ? SAL_MAX_INT32 : pPLCF_PosArray[nInIdx]; }
+
+ WW8PLCFspecial& operator ++( int ) { nIdx++; return *this; }
+ WW8PLCFspecial& operator --( int ) { nIdx--; return *this; }
+};
+
+/** simple Iterator for SPRMs */
+class WW8SprmIter
+{
+private:
+ const wwSprmParser &mrSprmParser;
+ // these members will be updated
+ const sal_uInt8* pSprms; // remaining part of the SPRMs ( == start of akt. SPRM)
+ const sal_uInt8* pAktParams; // start of akt. SPRM's parameters
+ sal_uInt16 nAktId;
+ sal_uInt16 nAktSize;
+
+ long nRemLen; // length of remaining SPRMs (including akt. SPRM)
+
+ void UpdateMyMembers();
+public:
+ explicit WW8SprmIter( const sal_uInt8* pSprms_, long nLen_,
+ const wwSprmParser &rSprmParser);
+ void SetSprms( const sal_uInt8* pSprms_, long nLen_ );
+ const sal_uInt8* FindSprm(sal_uInt16 nId);
+ void advance();
+ const sal_uInt8* GetSprms() const
+ { return ( pSprms && (0 < nRemLen) ) ? pSprms : 0; }
+ const sal_uInt8* GetAktParams() const { return pAktParams; }
+ sal_uInt16 GetAktId() const { return nAktId; }
+private:
+ //No copying
+ WW8SprmIter(const WW8SprmIter&);
+ WW8SprmIter& operator=(const WW8SprmIter&);
+};
+
+/* u.a. fuer FKPs auf normale Attr., also ein Attr weniger als Positionen */
+class WW8PLCF // Iterator fuer PLCFs
+{
+private:
+ WW8_CP* pPLCF_PosArray; // Pointer auf Pos-Array und auf ganze Struktur
+ sal_uInt8* pPLCF_Contents; // Pointer auf Inhalts-Array-Teil des Pos-Array
+ sal_Int32 nIMax; // Anzahl der Elemente
+ sal_Int32 nIdx;
+ int nStru;
+
+ void ReadPLCF( SvStream* pSt, WW8_FC nFilePos, sal_Int32 nPLCF );
+
+ /*
+ Falls im Dok ein PLC fehlt und die FKPs solo dastehen,
+ machen wir uns hiermit einen PLC:
+ */
+ void GeneratePLCF( SvStream* pSt, sal_Int32 nPN, sal_Int32 ncpN );
+
+ void MakeFailedPLCF();
+public:
+ WW8PLCF( SvStream* pSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
+ WW8_CP nStartPos = -1 );
+
+ /*
+ folgender Ctor generiert ggfs. einen PLC aus nPN und ncpN
+ */
+ WW8PLCF( SvStream* pSt, WW8_FC nFilePos, sal_Int32 nPLCF, int nStruct,
+ WW8_CP nStartPos, sal_Int32 nPN, sal_Int32 ncpN );
+
+ ~WW8PLCF(){ delete[] pPLCF_PosArray; }
+ sal_Int32 GetIdx() const { return nIdx; }
+ void SetIdx( sal_Int32 nI ) { nIdx = nI; }
+ sal_Int32 GetIMax() const { return nIMax; }
+ bool SeekPos(WW8_CP nPos);
+ WW8_CP Where() const;
+ bool Get(WW8_CP& rStart, WW8_CP& rEnd, void*& rpValue) const;
+ WW8PLCF& operator ++( int ) { if( nIdx < nIMax ) nIdx++; return *this; }
+
+ const void* GetData( sal_Int32 nInIdx ) const
+ {
+ return ( nInIdx >= nIMax ) ? 0 :
+ (const void*)&pPLCF_Contents[nInIdx * nStru];
+ }
+};
+
+/* for Piece Table (.i.e. FastSave Table) */
+class WW8PLCFpcd
+{
+friend class WW8PLCFpcd_Iter;
+ sal_Int32* pPLCF_PosArray; // Pointer auf Pos-Array und auf ganze Struktur
+ sal_uInt8* pPLCF_Contents; // Pointer auf Inhalts-Array-Teil des Pos-Array
+ long nIMax;
+ long nStru;
+public:
+ WW8PLCFpcd( SvStream* pSt, long nFilePos, long nPLCF, long nStruct );
+ ~WW8PLCFpcd(){ delete[] pPLCF_PosArray; }
+};
+
+/* mehrere WW8PLCFpcd_Iter koennen auf die gleiche WW8PLCFpcd zeigen !!! */
+class WW8PLCFpcd_Iter
+{
+private:
+ WW8PLCFpcd& rPLCF;
+ long nIdx;
+
+ //No copying
+ WW8PLCFpcd_Iter(const WW8PLCFpcd_Iter&);
+ WW8PLCFpcd_Iter& operator=(const WW8PLCFpcd_Iter&);
+public:
+ WW8PLCFpcd_Iter( WW8PLCFpcd& rPLCFpcd, long nStartPos = -1 );
+ long GetIdx() const { return nIdx; }
+ void SetIdx( long nI ) { nIdx = nI; }
+ long GetIMax() const { return rPLCF.nIMax; }
+ bool SeekPos(long nPos);
+ sal_Int32 Where() const;
+ bool Get(WW8_CP& rStart, WW8_CP& rEnd, void*& rpValue) const;
+ WW8PLCFpcd_Iter& operator ++( int )
+ {
+ if( nIdx < rPLCF.nIMax )
+ nIdx++;
+ return *this;
+ }
+};
+
+// PLCF-Typ:
+enum ePLCFT{ CHP=0, PAP, SEP, /*HED, FNR, ENR,*/ PLCF_END };
+
+//Its hardcoded that eFTN be the first one: A very poor hack, needs to be fixed
+enum eExtSprm { eFTN = 256, eEDN = 257, eFLD = 258, eBKN = 259, eAND = 260 };
+
+/*
+ pure virtual:
+*/
+class WW8PLCFx // virtueller Iterator fuer Piece Table Exceptions
+{
+private:
+ ww::WordVersion meVer; // Version number of FIB
+ bool bIsSprm; // PLCF von Sprms oder von anderem ( Footnote, ... )
+ WW8_FC nStartFc;
+ bool bDirty;
+
+ //No copying
+ WW8PLCFx(const WW8PLCFx&);
+ WW8PLCFx& operator=(const WW8PLCFx&);
+public:
+ WW8PLCFx(ww::WordVersion eVersion, bool bSprm)
+ : meVer(eVersion), bIsSprm(bSprm), bDirty(false) {}
+ virtual ~WW8PLCFx() {}
+ bool IsSprm() const { return bIsSprm; }
+ virtual sal_uLong GetIdx() const = 0;
+ virtual void SetIdx( sal_uLong nIdx ) = 0;
+ virtual sal_uLong GetIdx2() const;
+ virtual void SetIdx2( sal_uLong nIdx );
+ virtual bool SeekPos(WW8_CP nCpPos) = 0;
+ virtual WW8_FC Where() = 0;
+ virtual void GetSprms( WW8PLCFxDesc* p );
+ virtual long GetNoSprms( WW8_CP& rStart, WW8_CP&, sal_Int32& rLen );
+ virtual WW8PLCFx& operator ++( int ) = 0;
+ virtual sal_uInt16 GetIstd() const { return 0xffff; }
+ virtual void Save( WW8PLCFxSave1& rSave ) const;
+ virtual void Restore( const WW8PLCFxSave1& rSave );
+ ww::WordVersion GetFIBVersion() const { return meVer; }
+ void SetStartFc( WW8_FC nFc ) { nStartFc = nFc; }
+ WW8_FC GetStartFc() const { return nStartFc; }
+ void SetDirty(bool bIn) {bDirty=bIn;}
+ bool GetDirty() const {return bDirty;}
+};
+
+class WW8PLCFx_PCDAttrs : public WW8PLCFx
+{
+private:
+ WW8PLCFpcd_Iter* pPcdI;
+ WW8PLCFx_PCD* pPcd;
+ sal_uInt8** const pGrpprls; // Attribute an Piece-Table
+ SVBT32 aShortSprm; // mini storage: can contain ONE sprm with
+ // 1 byte param
+ sal_uInt16 nGrpprls; // Attribut Anzahl davon
+
+ //No copying
+ WW8PLCFx_PCDAttrs(const WW8PLCFx_PCDAttrs&);
+ WW8PLCFx_PCDAttrs& operator=(const WW8PLCFx_PCDAttrs&);
+public:
+ WW8PLCFx_PCDAttrs(ww::WordVersion eVersion, WW8PLCFx_PCD* pPLCFx_PCD,
+ const WW8ScannerBase* pBase );
+ virtual sal_uLong GetIdx() const;
+ virtual void SetIdx( sal_uLong nI );
+ virtual bool SeekPos(WW8_CP nCpPos);
+ virtual WW8_FC Where();
+ virtual void GetSprms( WW8PLCFxDesc* p );
+ virtual WW8PLCFx& operator ++( int );
+
+ WW8PLCFpcd_Iter* GetIter() const { return pPcdI; }
+};
+
+class WW8PLCFx_PCD : public WW8PLCFx // Iterator fuer Piece Table
+{
+private:
+ WW8PLCFpcd_Iter* pPcdI;
+ bool bVer67;
+ WW8_CP nClipStart;
+
+ //No copying
+ WW8PLCFx_PCD(const WW8PLCFx_PCD&);
+ WW8PLCFx_PCD& operator=(const WW8PLCFx_PCD&);
+public:
+ WW8PLCFx_PCD(ww::WordVersion eVersion, WW8PLCFpcd* pPLCFpcd,
+ WW8_CP nStartCp, bool bVer67P);
+ virtual ~WW8PLCFx_PCD();
+ virtual sal_uLong GetIMax() const;
+ virtual sal_uLong GetIdx() const;
+ virtual void SetIdx( sal_uLong nI );
+ virtual bool SeekPos(WW8_CP nCpPos);
+ virtual WW8_FC Where();
+ virtual long GetNoSprms( WW8_CP& rStart, WW8_CP&, sal_Int32& rLen );
+ virtual WW8PLCFx& operator ++( int );
+ WW8_CP AktPieceStartFc2Cp( WW8_FC nStartPos );
+ WW8_FC AktPieceStartCp2Fc( WW8_CP nCp );
+ void AktPieceFc2Cp(WW8_CP& rStartPos, WW8_CP& rEndPos,
+ const WW8ScannerBase *pSBase);
+ WW8PLCFpcd_Iter* GetPLCFIter() { return pPcdI; }
+ void SetClipStart(WW8_CP nIn) { nClipStart = nIn; }
+ WW8_CP GetClipStart() { return nClipStart; }
+
+ static sal_Int32 TransformPieceAddress(long nfc, bool& bIsUnicodeAddress)
+ {
+ bIsUnicodeAddress = 0 == (0x40000000 & nfc);
+ return bIsUnicodeAddress ? nfc : (nfc & 0x3fffFFFF) / 2;
+ }
+};
+
+/**
+ Iterator for Piece Table Exceptions of Fkps
+ works only with FCs, not with CPs ! ( Low-Level )
+*/
+class WW8PLCFx_Fc_FKP : public WW8PLCFx
+{
+public:
+ class WW8Fkp // Iterator for Formatted Disk Page
+ {
+ private:
+ class Entry
+ {
+ public:
+ WW8_FC mnFC;
+
+ sal_uInt8* mpData;
+ sal_uInt16 mnLen;
+ sal_uInt16 mnIStd; // only for Fkp.Papx (actualy Style-Nr)
+ bool mbMustDelete;
+
+ explicit Entry(WW8_FC nFC) : mnFC(nFC), mpData(0), mnLen(0),
+ mnIStd(0), mbMustDelete(false) {}
+ Entry(const Entry &rEntry);
+ ~Entry();
+ bool operator<(const Entry& rEntry) const;
+ Entry& operator=(const Entry& rEntry);
+ };
+
+ sal_uInt8 maRawData[512];
+ std::vector<Entry> maEntries;
+
+ long nItemSize; // entweder 1 Byte oder ein komplettes BX
+
+ // Offset in Stream where last read of 52 bytes took place
+ long nFilePos;
+ sal_uInt8 mnIdx; // Pos-Merker
+ ePLCFT ePLCF;
+ sal_uInt8 mnIMax; // Anzahl der Eintraege
+
+ wwSprmParser maSprmParser;
+ public:
+ WW8Fkp (ww::WordVersion eVersion, SvStream* pFKPStrm,
+ SvStream* pDataStrm, long _nFilePos, long nItemSiz, ePLCFT ePl,
+ WW8_FC nStartFc = -1);
+ void Reset(WW8_FC nPos);
+ long GetFilePos() const { return nFilePos; }
+ sal_uInt8 GetIdx() const { return mnIdx; }
+ bool SetIdx(sal_uInt8 nI);
+ bool SeekPos(WW8_FC nFc);
+ WW8_FC Where() const
+ {
+ return (mnIdx < mnIMax) ? maEntries[mnIdx].mnFC : WW8_FC_MAX;
+ }
+ WW8Fkp& operator ++( int )
+ {
+ if (mnIdx < mnIMax)
+ mnIdx++;
+ return *this;
+ }
+ sal_uInt8* Get( WW8_FC& rStart, WW8_FC& rEnd, sal_Int32& rLen ) const;
+ sal_uInt16 GetIstd() const { return maEntries[mnIdx].mnIStd; }
+
+ /*
+ liefert einen echten Pointer auf das Sprm vom Typ nId,
+ falls ein solches im Fkp drin ist.
+ */
+ sal_uInt8* GetLenAndIStdAndSprms(sal_Int32& rLen) const;
+
+ /*
+ ruft GetLenAndIStdAndSprms() auf...
+ */
+ const sal_uInt8* HasSprm( sal_uInt16 nId );
+ bool HasSprm(sal_uInt16 nId, std::vector<const sal_uInt8 *> &rResult);
+
+ const wwSprmParser &GetSprmParser() const { return maSprmParser; }
+ };
+private:
+ SvStream* pFKPStrm; // Input-File
+ SvStream* pDataStrm; // Input-File
+ WW8PLCF* pPLCF;
+ WW8Fkp* pFkp;
+
+ /*
+ Keep a cache of eMaxCache entries of previously seen pFkps, which
+ speeds up considerably table parsing and load save plcfs for what turn
+ out to be small text frames, which frames generally are
+
+ size : cache hits
+ cache all : 19168 pap, 48 chp
+ == 100 : 19166 pap, 48 chp
+ == 50 : 18918 pap, 48 chp
+ == 10 : 18549 pap, 47 chp
+ == 5 : 18515 pap, 47 chp
+ */
+ typedef std::list<WW8Fkp*>::iterator myiter;
+ std::list<WW8Fkp*> maFkpCache;
+ enum Limits {eMaxCache = 5};
+
+ bool NewFkp();
+
+ //No copying
+ WW8PLCFx_Fc_FKP(const WW8PLCFx_Fc_FKP&);
+ WW8PLCFx_Fc_FKP& operator=(const WW8PLCFx_Fc_FKP&);
+protected:
+ ePLCFT ePLCF;
+ WW8PLCFx_PCDAttrs* pPCDAttrs;
+public:
+ WW8PLCFx_Fc_FKP( SvStream* pSt, SvStream* pTblSt, SvStream* pDataSt,
+ const WW8Fib& rFib, ePLCFT ePl, WW8_FC nStartFcL );
+ virtual ~WW8PLCFx_Fc_FKP();
+ virtual sal_uLong GetIdx() const;
+ virtual void SetIdx( sal_uLong nIdx );
+ virtual bool SeekPos(WW8_FC nFcPos);
+ virtual WW8_FC Where();
+ sal_uInt8* GetSprmsAndPos( WW8_FC& rStart, WW8_FC& rEnd, sal_Int32& rLen );
+ virtual WW8PLCFx& operator ++( int );
+ virtual sal_uInt16 GetIstd() const;
+ void GetPCDSprms( WW8PLCFxDesc& rDesc );
+ const sal_uInt8* HasSprm( sal_uInt16 nId );
+ bool HasSprm(sal_uInt16 nId, std::vector<const sal_uInt8 *> &rResult);
+ bool HasFkp() const { return (0 != pFkp); }
+};
+
+/// Iterator fuer Piece Table Exceptions of Fkps arbeitet auf CPs (High-Level)
+class WW8PLCFx_Cp_FKP : public WW8PLCFx_Fc_FKP
+{
+private:
+ const WW8ScannerBase& rSBase;
+ WW8PLCFx_PCD* pPcd;
+ WW8PLCFpcd_Iter *pPieceIter;
+ WW8_CP nAttrStart, nAttrEnd;
+ sal_uInt8 bLineEnd : 1;
+ sal_uInt8 bComplex : 1;
+
+ //No copying
+ WW8PLCFx_Cp_FKP(const WW8PLCFx_Cp_FKP&);
+ WW8PLCFx_Cp_FKP& operator=(const WW8PLCFx_Cp_FKP&);
+public:
+ WW8PLCFx_Cp_FKP( SvStream* pSt, SvStream* pTblSt, SvStream* pDataSt,
+ const WW8ScannerBase& rBase, ePLCFT ePl );
+ virtual ~WW8PLCFx_Cp_FKP();
+ void ResetAttrStartEnd();
+ sal_uLong GetPCDIMax() const;
+ sal_uLong GetPCDIdx() const;
+ void SetPCDIdx( sal_uLong nIdx );
+ virtual sal_uLong GetIdx2() const;
+ virtual void SetIdx2( sal_uLong nIdx );
+ virtual bool SeekPos(WW8_CP nCpPos);
+ virtual WW8_CP Where();
+ virtual void GetSprms( WW8PLCFxDesc* p );
+ virtual WW8PLCFx& operator ++( int );
+ virtual void Save( WW8PLCFxSave1& rSave ) const;
+ virtual void Restore( const WW8PLCFxSave1& rSave );
+};
+
+/// Iterator for Piece Table Exceptions of Sepx
+class WW8PLCFx_SEPX : public WW8PLCFx
+{
+private:
+ wwSprmParser maSprmParser;
+ SvStream* pStrm;
+ WW8PLCF* pPLCF;
+ sal_uInt8* pSprms;
+ sal_uInt16 nArrMax;
+ sal_uInt16 nSprmSiz;
+
+ //no copying
+ WW8PLCFx_SEPX(const WW8PLCFx_SEPX&);
+ WW8PLCFx_SEPX& operator=(const WW8PLCFx_SEPX&);
+public:
+ WW8PLCFx_SEPX( SvStream* pSt, SvStream* pTblxySt, const WW8Fib& rFib,
+ WW8_CP nStartCp );
+ virtual ~WW8PLCFx_SEPX();
+ virtual sal_uLong GetIdx() const;
+ virtual void SetIdx( sal_uLong nIdx );
+ long GetIMax() const { return ( pPLCF ) ? pPLCF->GetIMax() : 0; }
+ virtual bool SeekPos(WW8_CP nCpPos);
+ virtual WW8_FC Where();
+ virtual void GetSprms( WW8PLCFxDesc* p );
+ virtual WW8PLCFx& operator ++( int );
+ const sal_uInt8* HasSprm( sal_uInt16 nId ) const;
+ const sal_uInt8* HasSprm( sal_uInt16 nId, sal_uInt8 n2nd ) const;
+ const sal_uInt8* HasSprm( sal_uInt16 nId, const sal_uInt8* pOtherSprms,
+ long nOtherSprmSiz ) const;
+ bool Find4Sprms(sal_uInt16 nId1, sal_uInt16 nId2, sal_uInt16 nId3, sal_uInt16 nId4,
+ sal_uInt8*& p1, sal_uInt8*& p2, sal_uInt8*& p3, sal_uInt8*& p4 ) const;
+};
+
+/// Iterator fuer Fuss-/Endnoten und Anmerkungen
+class WW8PLCFx_SubDoc : public WW8PLCFx
+{
+private:
+ WW8PLCF* pRef;
+ WW8PLCF* pTxt;
+
+ //No copying
+ WW8PLCFx_SubDoc(const WW8PLCFx_SubDoc&);
+ WW8PLCFx_SubDoc& operator=(const WW8PLCFx_SubDoc&);
+public:
+ WW8PLCFx_SubDoc(SvStream* pSt, ww::WordVersion eVersion, WW8_CP nStartCp,
+ long nFcRef, long nLenRef, long nFcTxt, long nLenTxt, long nStruc = 0);
+ virtual ~WW8PLCFx_SubDoc();
+ virtual sal_uLong GetIdx() const;
+ virtual void SetIdx( sal_uLong nIdx );
+ virtual bool SeekPos(WW8_CP nCpPos);
+ virtual WW8_FC Where();
+
+ // liefert Reference Descriptoren
+ const void* GetData( long nIdx = -1 ) const
+ {
+ return pRef ? pRef->GetData( -1L == nIdx ? pRef->GetIdx() : nIdx ) : 0;
+ }
+
+ //liefert Angabe, wo Kopf und Fusszeilen-Text zu finden ist
+ bool Get(long& rStart, void*& rpValue) const;
+ virtual void GetSprms(WW8PLCFxDesc* p);
+ virtual WW8PLCFx& operator ++( int );
+ long Count() const { return ( pRef ) ? pRef->GetIMax() : 0; }
+};
+
+/// Iterator for fields
+class WW8PLCFx_FLD : public WW8PLCFx
+{
+private:
+ WW8PLCFspecial* pPLCF;
+ const WW8Fib& rFib;
+ //No copying
+ WW8PLCFx_FLD(const WW8PLCFx_FLD&);
+ WW8PLCFx_FLD& operator=(const WW8PLCFx_FLD &);
+public:
+ WW8PLCFx_FLD(SvStream* pSt, const WW8Fib& rMyFib, short nType);
+ virtual ~WW8PLCFx_FLD();
+ virtual sal_uLong GetIdx() const;
+ virtual void SetIdx( sal_uLong nIdx );
+ virtual bool SeekPos(WW8_CP nCpPos);
+ virtual WW8_FC Where();
+ virtual void GetSprms(WW8PLCFxDesc* p);
+ virtual WW8PLCFx& operator ++( int );
+ bool StartPosIsFieldStart();
+ bool EndPosIsFieldEnd();
+ bool GetPara(long nIdx, WW8FieldDesc& rF);
+};
+
+enum eBookStatus { BOOK_NORMAL = 0, BOOK_IGNORE = 0x1, BOOK_FIELD = 0x2 };
+
+/// Iterator for Booknotes
+class WW8PLCFx_Book : public WW8PLCFx
+{
+private:
+ WW8PLCFspecial* pBook[2]; // Start and End Position
+ ::std::vector<String> aBookNames; // Name
+ eBookStatus* pStatus;
+ long nIMax; // Number of Booknotes
+ sal_uInt16 nIsEnd;
+ int nBookmarkId; // counter incremented by GetUniqueBookmarkName.
+
+ //No copying
+ WW8PLCFx_Book(const WW8PLCFx_Book&);
+ WW8PLCFx_Book& operator=(const WW8PLCFx_Book&);
+public:
+ WW8PLCFx_Book(SvStream* pTblSt,const WW8Fib& rFib);
+ virtual ~WW8PLCFx_Book();
+ long GetIMax() const { return nIMax; }
+ virtual sal_uLong GetIdx() const;
+ virtual void SetIdx( sal_uLong nI );
+ virtual sal_uLong GetIdx2() const;
+ virtual void SetIdx2( sal_uLong nIdx );
+ virtual bool SeekPos(WW8_CP nCpPos);
+ virtual WW8_FC Where();
+ virtual long GetNoSprms( WW8_CP& rStart, WW8_CP& rEnd, sal_Int32& rLen );
+ virtual WW8PLCFx& operator ++( int );
+ const String* GetName() const;
+ WW8_CP GetStartPos() const
+ { return ( nIsEnd ) ? WW8_CP_MAX : pBook[0]->Where(); }
+ long GetLen() const;
+ bool GetIsEnd() const { return nIsEnd ? true : false; }
+ long GetHandle() const;
+ void SetStatus( sal_uInt16 nIndex, eBookStatus eStat );
+ bool MapName(String& rName);
+ String GetBookmark(long nStart,long nEnd, sal_uInt16 &nIndex);
+ eBookStatus GetStatus() const;
+ String GetUniqueBookmarkName(String &suggestedName);
+};
+
+/*
+ hiermit arbeiten wir draussen:
+*/
+struct WW8PLCFManResult
+{
+ WW8_CP nCpPos; // Attribut-Anfangsposition
+ long nMemLen; // Laenge dazu
+ long nCp2OrIdx; // footnote-textpos oder Index in PLCF
+ WW8_CP nAktCp; // wird nur vom Aufrufer benutzt
+ const sal_uInt8* pMemPos;// Mem-Pos fuer Sprms
+ sal_uInt16 nSprmId; // Sprm-Id ( 0 = ungueltige Id -> ueberspringen! )
+ // (2..255) oder Pseudo-Sprm-Id (256..260)
+ // bzw. ab Winword-Ver8 die Sprm-Id (800..)
+ sal_uInt8 nFlags; // Absatz- oder Section-Anfang
+};
+
+enum ManMaskTypes
+{
+ MAN_MASK_NEW_PAP = 1, // neue Zeile
+ MAN_MASK_NEW_SEP = 2 // neue Section
+};
+
+enum ManTypes // enums for PLCFMan-ctor
+{
+ MAN_MAINTEXT = 0, MAN_FTN = 1, MAN_EDN = 2, MAN_HDFT = 3, MAN_AND = 4,
+ MAN_TXBX = 5, MAN_TXBX_HDFT = 6
+};
+
+/*
+ hiermit arbeitet der Manager drinnen:
+*/
+struct WW8PLCFxDesc
+{
+ WW8PLCFx* pPLCFx;
+ ::std::stack<sal_uInt16>* pIdStk; // Speicher fuer Attr-Id fuer Attr-Ende(n)
+ const sal_uInt8* pMemPos;// wo liegen die Sprm(s)
+ long nOrigSprmsLen;
+
+ WW8_CP nStartPos;
+ WW8_CP nEndPos;
+
+ WW8_CP nOrigStartPos;
+ WW8_CP nOrigEndPos; // The ending character position of a paragraph is
+ // always one before the end reported in the FKP,
+ // also a character run that ends on the same location
+ // as the paragraph mark is adjusted to end just before
+ // the paragraph mark so as to handle their close
+ // first. The value being used to determing where the
+ // properties end is in nEndPos, but the original
+ // unadjusted end character position is important as
+ // it can be used as the beginning cp of the next set
+ // of properties
+
+ WW8_CP nCp2OrIdx; // wo liegen die NoSprm(s)
+ sal_Int32 nSprmsLen; // wie viele Bytes fuer weitere Sprms / Laenge Fussnote
+ long nCpOfs; // fuer Offset Header .. Footnote
+ bool bFirstSprm; // fuer Erkennung erster Sprm einer Gruppe
+ bool bRealLineEnd; // false bei Pap-Piece-Ende
+ void Save( WW8PLCFxSave1& rSave ) const;
+ void Restore( const WW8PLCFxSave1& rSave );
+ //With nStartPos set to WW8_CP_MAX then in the case of a pap or chp
+ //GetSprms will not search for the sprms, but instead take the
+ //existing ones.
+ WW8PLCFxDesc() : pIdStk(0), nStartPos(WW8_CP_MAX) {}
+ void ReduceByOffset();
+};
+
+#ifndef DUMP
+
+struct WW8PLCFxSaveAll;
+class WW8PLCFMan
+{
+public:
+ enum WW8PLCFManLimits {MAN_ANZ_PLCF = 10};
+private:
+ wwSprmParser maSprmParser;
+ long nCpO; // Origin Cp -- the basis for nNewCp
+
+ WW8_CP nLineEnd; // zeigt *hinter* das <CR>
+ long nLastWhereIdxCp; // last result of WhereIdx()
+ sal_uInt16 nPLCF; // so viele PLCFe werden verwaltet
+ ManTypes nManType;
+ bool mbDoingDrawTextBox; //Normally we adjust the end of attributes
+ //so that the end of a paragraph occurs
+ //before the para end mark, but for
+ //drawboxes we want the true offsets
+
+ WW8PLCFxDesc aD[MAN_ANZ_PLCF];
+ WW8PLCFxDesc *pChp, *pPap, *pSep, *pFld, *pFtn, *pEdn, *pBkm, *pPcd,
+ *pPcdA, *pAnd;
+ WW8PLCFspecial *pFdoa, *pTxbx, *pTxbxBkd,*pMagicTables, *pSubdocs;
+ sal_uInt8* pExtendedAtrds;
+
+ const WW8Fib* pWwFib;
+
+ sal_uInt16 WhereIdx(bool* pbStart=0, long* pPos=0) const;
+ void AdjustEnds(WW8PLCFxDesc& rDesc);
+ void GetNewSprms(WW8PLCFxDesc& rDesc);
+ void GetNewNoSprms(WW8PLCFxDesc& rDesc);
+ void GetSprmStart(short nIdx, WW8PLCFManResult* pRes) const;
+ void GetSprmEnd(short nIdx, WW8PLCFManResult* pRes) const;
+ void GetNoSprmStart(short nIdx, WW8PLCFManResult* pRes) const;
+ void GetNoSprmEnd(short nIdx, WW8PLCFManResult* pRes) const;
+ void AdvSprm(short nIdx, bool bStart);
+ void AdvNoSprm(short nIdx, bool bStart);
+ sal_uInt16 GetId(const WW8PLCFxDesc* p ) const;
+public:
+ WW8PLCFMan(WW8ScannerBase* pBase, ManTypes nType, long nStartCp,
+ bool bDoingDrawTextBox = false);
+ ~WW8PLCFMan();
+
+ /*
+ Where fragt, an welcher naechsten Position sich irgendein
+ Attr aendert...
+ */
+ WW8_CP Where() const;
+
+ bool Get(WW8PLCFManResult* pResult) const;
+ WW8PLCFMan& operator ++( int );
+ sal_uInt16 GetColl() const; // index of actual Style
+ WW8PLCFx_FLD* GetFld() const;
+ WW8PLCFx_SubDoc* GetEdn() const { return (WW8PLCFx_SubDoc*)pEdn->pPLCFx; }
+ WW8PLCFx_SubDoc* GetFtn() const { return (WW8PLCFx_SubDoc*)pFtn->pPLCFx; }
+ WW8PLCFx_SubDoc* GetAtn() const { return (WW8PLCFx_SubDoc*)pAnd->pPLCFx; }
+ WW8PLCFx_Book* GetBook() const { return (WW8PLCFx_Book*)pBkm->pPLCFx; }
+ long GetCpOfs() const { return pChp->nCpOfs; } // for Header/Footer...
+
+ /* fragt, ob *aktueller Absatz* einen Sprm diesen Typs hat */
+ const sal_uInt8* HasParaSprm( sal_uInt16 nId ) const;
+
+ /* fragt, ob *aktueller Textrun* einen Sprm diesen Typs hat */
+ const sal_uInt8* HasCharSprm( sal_uInt16 nId ) const;
+ bool HasCharSprm(sal_uInt16 nId, std::vector<const sal_uInt8 *> &rResult) const;
+
+ WW8PLCFx_Cp_FKP* GetChpPLCF() const
+ { return (WW8PLCFx_Cp_FKP*)pChp->pPLCFx; }
+ WW8PLCFx_Cp_FKP* GetPapPLCF() const
+ { return (WW8PLCFx_Cp_FKP*)pPap->pPLCFx; }
+ WW8PLCFx_SEPX* GetSepPLCF() const
+ { return (WW8PLCFx_SEPX*)pSep->pPLCFx; }
+ WW8PLCFxDesc* GetPap() const { return pPap; }
+ bool TransferOpenSprms(std::stack<sal_uInt16> &rStack);
+ void SeekPos( long nNewCp );
+ void SaveAllPLCFx( WW8PLCFxSaveAll& rSave ) const;
+ void RestoreAllPLCFx( const WW8PLCFxSaveAll& rSave );
+ WW8PLCFspecial* GetFdoa() const { return pFdoa; }
+ WW8PLCFspecial* GetTxbx() const { return pTxbx; }
+ WW8PLCFspecial* GetTxbxBkd() const { return pTxbxBkd; }
+ WW8PLCFspecial* GetMagicTables() const { return pMagicTables; }
+ WW8PLCFspecial* GetWkbPLCF() const { return pSubdocs; }
+ sal_uInt8* GetExtendedAtrds() const { return pExtendedAtrds; }
+ ManTypes GetManType() const { return nManType; }
+ bool GetDoingDrawTextBox() const { return mbDoingDrawTextBox; }
+};
+
+struct WW8PLCFxSaveAll
+{
+ WW8PLCFxSave1 aS[WW8PLCFMan::MAN_ANZ_PLCF];
+};
+
+#endif // !DUMP
+
+class WW8ScannerBase
+{
+friend WW8PLCFx_PCDAttrs::WW8PLCFx_PCDAttrs(ww::WordVersion eVersion,
+ WW8PLCFx_PCD* pPLCFx_PCD, const WW8ScannerBase* pBase );
+friend WW8PLCFx_Cp_FKP::WW8PLCFx_Cp_FKP( SvStream*, SvStream*, SvStream*,
+ const WW8ScannerBase&, ePLCFT );
+
+#ifndef DUMP
+friend WW8PLCFMan::WW8PLCFMan(WW8ScannerBase*, ManTypes, long, bool);
+friend class SwWw8ImplReader;
+friend class SwWW8FltControlStack;
+#endif
+
+private:
+ const WW8Fib* pWw8Fib;
+ WW8PLCFx_Cp_FKP* pChpPLCF; // Character-Attrs
+ WW8PLCFx_Cp_FKP* pPapPLCF; // Para-Attrs
+ WW8PLCFx_SEPX* pSepPLCF; // Section-Attrs
+ WW8PLCFx_SubDoc* pFtnPLCF; // Footnotes
+ WW8PLCFx_SubDoc* pEdnPLCF; // EndNotes
+ WW8PLCFx_SubDoc* pAndPLCF; // Anmerkungen
+ WW8PLCFx_FLD* pFldPLCF; // Fields in Main Text
+ WW8PLCFx_FLD* pFldHdFtPLCF; // Fields in Header / Footer
+ WW8PLCFx_FLD* pFldTxbxPLCF; // Fields in Textboxes in Main Text
+ WW8PLCFx_FLD* pFldTxbxHdFtPLCF; // Fields in Textboxes in Header / Footer
+ WW8PLCFx_FLD* pFldFtnPLCF; // Fields in Footnotes
+ WW8PLCFx_FLD* pFldEdnPLCF; // Fields in Endnotes
+ WW8PLCFx_FLD* pFldAndPLCF; // Fields in Anmerkungen
+ WW8PLCFspecial* pMainFdoa; // Graphic Primitives in Main Text
+ WW8PLCFspecial* pHdFtFdoa; // Graphic Primitives in Header / Footer
+ WW8PLCFspecial* pMainTxbx; // Textboxen in Main Text
+ WW8PLCFspecial* pMainTxbxBkd; // Break-Deskriptoren fuer diese
+ WW8PLCFspecial* pHdFtTxbx; // TextBoxen in Header / Footer
+ WW8PLCFspecial* pHdFtTxbxBkd; // Break-Deskriptoren fuer diese
+ WW8PLCFspecial* pMagicTables; // Break-Deskriptoren fuer diese
+ WW8PLCFspecial* pSubdocs; // subdoc references in master document
+ sal_uInt8* pExtendedAtrds; // Extended ATRDs
+ WW8PLCFx_Book* pBook; // Bookmarks
+
+ WW8PLCFpcd* pPiecePLCF; // fuer FastSave ( Basis-PLCF ohne Iterator )
+ WW8PLCFpcd_Iter* pPieceIter; // fuer FastSave ( Iterator dazu )
+ WW8PLCFx_PCD* pPLCFx_PCD; // dito
+ WW8PLCFx_PCDAttrs* pPLCFx_PCDAttrs;
+ sal_uInt8** pPieceGrpprls; // Attribute an Piece-Table
+ sal_uInt16 nPieceGrpprls; // Anzahl davon
+
+ WW8PLCFpcd* OpenPieceTable( SvStream* pStr, const WW8Fib* pWwF );
+ void DeletePieceTable();
+public:
+ WW8ScannerBase( SvStream* pSt, SvStream* pTblSt, SvStream* pDataSt,
+ const WW8Fib* pWwF );
+ ~WW8ScannerBase();
+ bool AreThereFootnotes() const { return pFtnPLCF->Count() > 0; };
+ bool AreThereEndnotes() const { return pEdnPLCF->Count() > 0; };
+
+ //If you use WW8Fc2Cp you are almost certainly doing the wrong thing
+ //when it comes to fastsaved files, avoid like the plague. For export
+ //given that we never write fastsaved files you can use it, otherwise
+ //I will beat you with a stick
+ WW8_CP WW8Fc2Cp(WW8_FC nFcPos) const ;
+ WW8_FC WW8Cp2Fc(WW8_CP nCpPos, bool* pIsUnicode = 0,
+ WW8_CP* pNextPieceCp = 0, bool* pTestFlag = 0) const;
+
+ xub_StrLen WW8ReadString(SvStream& rStrm, String& rStr, WW8_CP nAktStartCp,
+ long nTotalLen, rtl_TextEncoding eEnc ) const;
+
+};
+
+/** FIB - the File Information Block
+
+ The FIB contains a "magic word" and pointers to the various other parts of
+ the file, as well as information about the length of the file.
+ The FIB starts at the beginning of the file.
+*/
+class WW8Fib
+{
+private:
+ sal_Unicode nNumDecimalSep;
+
+public:
+ /**
+ Program-Version asked for by us:
+ in Ctor we check if it matches the value of nFib
+
+ 6 == "WinWord 6 or WinWord 95",
+ 7 == "only WinWord 95"
+ 8 == "WinWord 97 or newer"
+ */
+ sal_uInt8 nVersion;
+ /*
+ error status
+ */
+ sal_uLong nFibError;
+ /*
+ vom Ctor aus dem FIB gelesene Daten
+ (entspricht nur ungefaehr der tatsaechlichen Struktur
+ des Winword-FIB)
+ */
+ sal_uInt16 wIdent; // 0x0 int magic number
+ /*
+ File Information Block (FIB) values:
+ WinWord 1.0 = 33
+ WinWord 2.0 = 45
+ WinWord 6.0c for 16bit = 101
+ Word 6/32 bit = 104
+ Word 95 = 104
+ Word 97 = 193
+ Word 2000 = 217
+ Word 2002 = 257
+ Word 2003 = 268
+ Word 2007 = 274
+ */
+ sal_uInt16 nFib; // 0x2 FIB version written
+ sal_uInt16 nProduct; // 0x4 product version written by
+ sal_Int16 lid; // 0x6 language stamp---localized version;
+ WW8_PN pnNext; // 0x8
+
+ sal_uInt16 fDot :1; // 0xa 0001
+ sal_uInt16 fGlsy :1;
+ sal_uInt16 fComplex :1; // 0004 when 1, file is in complex, fast-saved format.
+ sal_uInt16 fHasPic :1; // 0008 file contains 1 or more pictures
+ sal_uInt16 cQuickSaves :4; // 00F0 count of times file was quicksaved
+ sal_uInt16 fEncrypted :1; //0100 1 if file is encrypted, 0 if not
+ sal_uInt16 fWhichTblStm :1; //0200 When 0, this fib refers to the table stream
+ sal_uInt16 fReadOnlyRecommended :1;
+ sal_uInt16 fWriteReservation :1;
+ // named "0Table", when 1, this fib refers to the
+ // table stream named "1Table". Normally, a file
+ // will have only one table stream, but under unusual
+ // circumstances a file may have table streams with
+ // both names. In that case, this flag must be used
+ // to decide which table stream is valid.
+
+ sal_uInt16 fExtChar :1; // 1000 =1, when using extended character set in file
+ sal_uInt16 fFarEast :1; // 4000 =1, probably, when far-East language vaiants of Word is used to create a file #i90932#
+
+ sal_uInt16 fObfuscated :1; // 8000=1. specifies whether the document is obfuscated using XOR obfuscation. otherwise this bit MUST be ignored.
+
+ sal_uInt16 nFibBack; // 0xc
+ sal_uInt16 nHash; // 0xe file encrypted hash
+ sal_uInt16 nKey; // 0x10 file encrypted key
+ sal_uInt8 envr; // 0x12 environment in which file was created
+ // 0 created by Win Word / 1 created by Mac Word
+ sal_uInt8 fMac :1; // 0x13 when 1, this file was last saved in the Mac environment
+ sal_uInt8 fEmptySpecial :1;
+ sal_uInt8 fLoadOverridePage :1;
+ sal_uInt8 fFuturesavedUndo :1;
+ sal_uInt8 fWord97Saved :1;
+ sal_uInt8 fWord2000Saved :1;
+ sal_uInt8 :2;
+
+ sal_uInt16 chse; // 0x14 default extended character set id for text in document stream. (overidden by chp.chse)
+ // 0 = ANSI / 256 Macintosh character set.
+ sal_uInt16 chseTables; // 0x16 default extended character set id for text in
+ // internal data structures: 0 = ANSI, 256 = Macintosh
+ WW8_FC fcMin; // 0x18 file offset of first character of text
+ WW8_FC fcMac; // 0x1c file offset of last character of text + 1
+
+ // Einschub fuer WW8 *****************************************************
+ sal_uInt16 csw; // Count of fields in the array of "shorts"
+
+ // Marke: "rgsw" Beginning of the array of shorts
+ sal_uInt16 wMagicCreated; // unique number Identifying the File's creator
+ // 0x6A62 is the creator ID for Word and is reserved.
+ // Other creators should choose a different value.
+ sal_uInt16 wMagicRevised; // identifies the File's last modifier
+ sal_uInt16 wMagicCreatedPrivate; // private data
+ sal_uInt16 wMagicRevisedPrivate; // private data
+ /*
+ sal_Int16 pnFbpChpFirst_W6; // not used
+ sal_Int16 pnChpFirst_W6; // not used
+ sal_Int16 cpnBteChp_W6; // not used
+ sal_Int16 pnFbpPapFirst_W6; // not used
+ sal_Int16 pnPapFirst_W6; // not used
+ sal_Int16 cpnBtePap_W6; // not used
+ sal_Int16 pnFbpLvcFirst_W6; // not used
+ sal_Int16 pnLvcFirst_W6; // not used
+ sal_Int16 cpnBteLvc_W6; // not used
+ */
+ sal_Int16 lidFE; // Language id if document was written by Far East version
+ // of Word (i.e. FIB.fFarEast is on)
+ sal_uInt16 clw; // Number of fields in the array of longs
+
+ // Ende des Einschubs fuer WW8 *******************************************
+
+ // Marke: "rglw" Beginning of the array of longs
+ WW8_FC cbMac; // 0x20 file offset of last byte written to file + 1.
+
+ // WW8_FC u4[4]; // 0x24
+ WW8_CP ccpText; // 0x34 length of main document text stream
+ WW8_CP ccpFtn; // 0x38 length of footnote subdocument text stream
+ WW8_CP ccpHdr; // 0x3c length of header subdocument text stream
+ WW8_CP ccpMcr; // 0x40 length of macro subdocument text stream
+ WW8_CP ccpAtn; // 0x44 length of annotation subdocument text stream
+ WW8_CP ccpEdn; // 0x48 length of endnote subdocument text stream
+ WW8_CP ccpTxbx; // 0x4c length of textbox subdocument text stream
+ WW8_CP ccpHdrTxbx; // 0x50 length of header textbox subdocument text stream
+
+ // Einschub fuer WW8 *****************************************************
+ sal_Int32 pnFbpChpFirst; // when there was insufficient memory for Word to expand
+ // the PLCFbte at save time, the PLCFbte is written
+ // to the file in a linked list of 512-byte pieces
+ // starting with this pn.
+ /*
+ // folgende Felder existieren zwar so in der Datei,
+ // wir benutzen jedoch unten deklarierte General-Variablen
+ // fuer Ver67 und Ver8 gemeinsam.
+ sal_Int32 pnChpFirst; // the page number of the lowest numbered page in the
+ // document that records CHPX FKP information
+ sal_Int32 cpnBteChp; // count of CHPX FKPs recorded in file. In non-complex
+ // files if the number of entries in the PLCFbteChpx
+ // is less than this, the PLCFbteChpx is incomplete.
+ */
+ sal_Int32 pnFbpPapFirst; // when there was insufficient memory for Word to expand
+ // the PLCFbte at save time, the PLCFbte is written to
+ // the file in a linked list of 512-byte pieces
+ // starting with this pn
+ /*
+ // folgende Felder existieren zwar so in der Datei,
+ // wir benutzen jedoch unten deklarierte General-Variablen
+ // fuer Ver67 und Ver8 gemeinsam.
+ sal_Int32 pnPapFirst; // the page number of the lowest numbered page in the
+ // document that records PAPX FKP information
+ sal_Int32 cpnBtePap; // count of PAPX FKPs recorded in file. In non-complex
+ // files if the number of entries in the PLCFbtePapx is
+ // less than this, the PLCFbtePapx is incomplete.
+ */
+ sal_Int32 pnFbpLvcFirst; // when there was insufficient memory for Word to expand
+ // the PLCFbte at save time, the PLCFbte is written to
+ // the file in a linked list of 512-byte pieces
+ // starting with this pn
+ sal_Int32 pnLvcFirst; // the page number of the lowest numbered page in the
+ // document that records LVC FKP information
+ sal_Int32 cpnBteLvc; // count of LVC FKPs recorded in file. In non-complex
+ // files if the number of entries in the PLCFbtePapx is
+ // less than this, the PLCFbtePapx is incomplete.
+ sal_Int32 fcIslandFirst; // ?
+ sal_Int32 fcIslandLim; // ?
+ sal_uInt16 cfclcb; // Number of fields in the array of FC/LCB pairs.
+
+ // Ende des Einschubs fuer WW8 *******************************************
+
+ // Marke: "rgfclcb" Beginning of array of FC/LCB pairs.
+ WW8_FC fcStshfOrig; // file offset of original allocation for STSH in table
+ // stream. During fast save Word will attempt to reuse
+ // this allocation if STSH is small enough to fit.
+ sal_Int32 lcbStshfOrig; // 0x5c count of bytes of original STSH allocation
+ WW8_FC fcStshf; // 0x60 file offset of STSH in file.
+ sal_Int32 lcbStshf; // 0x64 count of bytes of current STSH allocation
+ WW8_FC fcPlcffndRef; // 0x68 file offset of footnote reference PLCF.
+ sal_Int32 lcbPlcffndRef; // 0x6c count of bytes of footnote reference PLCF
+ // == 0 if no footnotes defined in document.
+
+ WW8_FC fcPlcffndTxt; // 0x70 file offset of footnote text PLCF.
+ sal_Int32 lcbPlcffndTxt; // 0x74 count of bytes of footnote text PLCF.
+ // == 0 if no footnotes defined in document
+
+ WW8_FC fcPlcfandRef; // 0x78 file offset of annotation reference PLCF.
+ sal_Int32 lcbPlcfandRef; // 0x7c count of bytes of annotation reference PLCF.
+
+ WW8_FC fcPlcfandTxt; // 0x80 file offset of annotation text PLCF.
+ sal_Int32 lcbPlcfandTxt; // 0x84 count of bytes of the annotation text PLCF
+
+ WW8_FC fcPlcfsed; // 8x88 file offset of section descriptor PLCF.
+ sal_Int32 lcbPlcfsed; // 0x8c count of bytes of section descriptor PLCF.
+
+ WW8_FC fcPlcfpad; // 0x90 file offset of paragraph descriptor PLCF
+ sal_Int32 lcbPlcfpad; // 0x94 count of bytes of paragraph descriptor PLCF.
+ // ==0 if file was never viewed in Outline view.
+ // Should not be written by third party creators
+
+ WW8_FC fcPlcfphe; // 0x98 file offset of PLCF of paragraph heights.
+ sal_Int32 lcbPlcfphe; // 0x9c count of bytes of paragraph height PLCF.
+ // ==0 when file is non-complex.
+
+ WW8_FC fcSttbfglsy; // 0xa0 file offset of glossary string table.
+ sal_Int32 lcbSttbfglsy; // 0xa4 count of bytes of glossary string table.
+ // == 0 for non-glossary documents.
+ // !=0 for glossary documents.
+
+ WW8_FC fcPlcfglsy; // 0xa8 file offset of glossary PLCF.
+ sal_Int32 lcbPlcfglsy; // 0xac count of bytes of glossary PLCF.
+ // == 0 for non-glossary documents.
+ // !=0 for glossary documents.
+
+ WW8_FC fcPlcfhdd; // 0xb0 byte offset of header PLCF.
+ sal_Int32 lcbPlcfhdd; // 0xb4 count of bytes of header PLCF.
+ // == 0 if document contains no headers
+
+ WW8_FC fcPlcfbteChpx; // 0xb8 file offset of character property bin table.PLCF.
+ sal_Int32 lcbPlcfbteChpx;// 0xbc count of bytes of character property bin table PLCF.
+
+ WW8_FC fcPlcfbtePapx; // 0xc0 file offset of paragraph property bin table.PLCF.
+ sal_Int32 lcbPlcfbtePapx;// 0xc4 count of bytes of paragraph property bin table PLCF.
+
+ WW8_FC fcPlcfsea; // 0xc8 file offset of PLCF reserved for private use. The SEA is 6 bytes long.
+ sal_Int32 lcbPlcfsea; // 0xcc count of bytes of private use PLCF.
+
+ WW8_FC fcSttbfffn; // 0xd0 file offset of font information STTBF. See the FFN file structure definition.
+ sal_Int32 lcbSttbfffn; // 0xd4 count of bytes in sttbfffn.
+
+ WW8_FC fcPlcffldMom; // 0xd8 offset in doc stream to the PLCF of field positions in the main document.
+ sal_Int32 lcbPlcffldMom; // 0xdc
+
+ WW8_FC fcPlcffldHdr; // 0xe0 offset in doc stream to the PLCF of field positions in the header subdocument.
+ sal_Int32 lcbPlcffldHdr; // 0xe4
+
+ WW8_FC fcPlcffldFtn; // 0xe8 offset in doc stream to the PLCF of field positions in the footnote subdocument.
+ sal_Int32 lcbPlcffldFtn; // 0xec
+
+ WW8_FC fcPlcffldAtn; // 0xf0 offset in doc stream to the PLCF of field positions in the annotation subdocument.
+ sal_Int32 lcbPlcffldAtn; // 0xf4
+
+ WW8_FC fcPlcffldMcr; // 0xf8 offset in doc stream to the PLCF of field positions in the macro subdocument.
+ sal_Int32 lcbPlcffldMcr; // 9xfc
+
+ WW8_FC fcSttbfbkmk; // 0x100 offset in document stream of the STTBF that records bookmark names in the main document
+ sal_Int32 lcbSttbfbkmk; // 0x104
+
+ WW8_FC fcPlcfbkf; // 0x108 offset in document stream of the PLCF that records the beginning CP offsets of bookmarks in the main document. See BKF
+ sal_Int32 lcbPlcfbkf; // 0x10c
+
+ WW8_FC fcPlcfbkl; // 0x110 offset in document stream of the PLCF that records the ending CP offsets of bookmarks recorded in the main document. See the BKL structure definition.
+ sal_Int32 lcbPlcfbkl; // 0x114 sal_Int32
+
+ WW8_FC fcCmds; // 0x118 FC
+ sal_Int32 lcbCmds; // 0x11c
+
+ WW8_FC fcPlcfmcr; // 0x120 FC
+ sal_Int32 lcbPlcfmcr; // 0x124
+
+ WW8_FC fcSttbfmcr; // 0x128 FC
+ sal_Int32 lcbSttbfmcr; // 0x12c
+
+ WW8_FC fcPrDrvr; // 0x130 file offset of the printer driver information (names of drivers, port etc...)
+ sal_Int32 lcbPrDrvr; // 0x134 count of bytes of the printer driver information (names of drivers, port etc...)
+
+ WW8_FC fcPrEnvPort; // 0x138 file offset of the print environment in portrait mode.
+ sal_Int32 lcbPrEnvPort; // 0x13c count of bytes of the print environment in portrait mode.
+
+ WW8_FC fcPrEnvLand; // 0x140 file offset of the print environment in landscape mode.
+ sal_Int32 lcbPrEnvLand; // 0x144 count of bytes of the print environment in landscape mode.
+
+ WW8_FC fcWss; // 0x148 file offset of Window Save State data structure. See WSS.
+ sal_Int32 lcbWss; // 0x14c count of bytes of WSS. ==0 if unable to store the window state.
+
+ WW8_FC fcDop; // 0x150 file offset of document property data structure.
+ sal_uInt32 lcbDop; // 0x154 count of bytes of document properties.
+ // cbDOP is 84 when nFib < 103
+
+
+ WW8_FC fcSttbfAssoc; // 0x158 offset to STTBF of associated strings. See STTBFASSOC.
+ sal_Int32 lcbSttbfAssoc; // 0x15C
+
+ WW8_FC fcClx; // 0x160 file offset of beginning of information for complex files.
+ sal_Int32 lcbClx; // 0x164 count of bytes of complex file information. 0 if file is non-complex.
+
+ WW8_FC fcPlcfpgdFtn; // 0x168 file offset of page descriptor PLCF for footnote subdocument.
+ sal_Int32 lcbPlcfpgdFtn; // 0x16C count of bytes of page descriptor PLCF for footnote subdocument.
+ // ==0 if document has not been paginated. The length of the PGD is 8 bytes.
+
+ WW8_FC fcAutosaveSource; // 0x170 file offset of the name of the original file.
+ sal_Int32 lcbAutosaveSource; // 0x174 count of bytes of the name of the original file.
+
+ WW8_FC fcGrpStAtnOwners; // 0x178 group of strings recording the names of the owners of annotations
+ sal_Int32 lcbGrpStAtnOwners; // 0x17C count of bytes of the group of strings
+
+ WW8_FC fcSttbfAtnbkmk; // 0x180 file offset of the sttbf that records names of bookmarks in the annotation subdocument
+ sal_Int32 lcbSttbfAtnbkmk; // 0x184 length in bytes of the sttbf that records names of bookmarks in the annotation subdocument
+
+ // Einschubs fuer WW67 ***************************************************
+
+ // sal_Int16 wSpare4Fib; // Reserve, muss hier nicht deklariert werden
+
+ /*
+ // folgende Felder existieren zwar so in der Datei,
+ // wir benutzen jedoch unten deklarierte General-Variablen
+ // fuer Ver67 und Ver8 gemeinsam.
+ WW8_PN pnChpFirst; // the page number of the lowest numbered page in
+ // the document that records CHPX FKP information
+ WW8_PN pnPapFirst; // the page number of the lowest numbered page in
+ // the document that records PAPX FKP information
+
+ WW8_PN cpnBteChp; // count of CHPX FKPs recorded in file. In non-complex
+ // files if the number of entries in the PLCFbteChpx is
+ // less than this, the PLCFbteChpx is incomplete.
+ WW8_PN cpnBtePap; // count of PAPX FKPs recorded in file. In non-complex
+ // files if the number of entries in the PLCFbtePapx is
+ // less than this, the PLCFbtePapx is incomplete.
+ */
+
+ // Ende des Einschubs fuer WW67 ******************************************
+
+ WW8_FC fcPlcfdoaMom; // 0x192 file offset of the FDOA (drawn object) PLCF for main document.
+ // ==0 if document has no drawn objects. The length of the FDOA is 6 bytes.
+ // ab Ver8 unused
+ sal_Int32 lcbPlcfdoaMom; // 0x196 length in bytes of the FDOA PLCF of the main document
+ // ab Ver8 unused
+ WW8_FC fcPlcfdoaHdr; // 0x19A file offset of the FDOA (drawn object) PLCF for the header document.
+ // ==0 if document has no drawn objects. The length of the FDOA is 6 bytes.
+ // ab Ver8 unused
+ sal_Int32 lcbPlcfdoaHdr; // 0x19E length in bytes of the FDOA PLCF of the header document
+ // ab Ver8 unused
+
+ WW8_FC fcPlcfspaMom; // offset in table stream of the FSPA PLCF for main document.
+ // == 0 if document has no office art objects
+ // war in Ver67 nur leere Reserve
+ sal_Int32 lcbPlcfspaMom; // length in bytes of the FSPA PLCF of the main document
+ // war in Ver67 nur leere Reserve
+ WW8_FC fcPlcfspaHdr; // offset in table stream of the FSPA PLCF for header document.
+ // == 0 if document has no office art objects
+ // war in Ver67 nur leere Reserve
+ sal_Int32 lcbPlcfspaHdr; // length in bytes of the FSPA PLCF of the header document
+ // war in Ver67 nur leere Reserve
+
+ WW8_FC fcPlcfAtnbkf; // 0x1B2 file offset of BKF (bookmark first) PLCF of the annotation subdocument
+ sal_Int32 lcbPlcfAtnbkf; // 0x1B6 length in bytes of BKF (bookmark first) PLCF of the annotation subdocument
+
+ WW8_FC fcPlcfAtnbkl; // 0x1BA file offset of BKL (bookmark last) PLCF of the annotation subdocument
+ sal_Int32 lcbPlcfAtnbkl; // 0x1BE length in bytes of BKL (bookmark first) PLCF of the annotation subdocument
+
+ WW8_FC fcPms; // 0x1C2 file offset of PMS (Print Merge State) information block
+ sal_Int32 lcbPMS; // 0x1C6 length in bytes of PMS
+
+ WW8_FC fcFormFldSttbf; // 0x1CA file offset of form field Sttbf which contains strings used in form field dropdown controls
+ sal_Int32 lcbFormFldSttbf; // 0x1CE length in bytes of form field Sttbf
+
+ WW8_FC fcPlcfendRef; // 0x1D2 file offset of PLCFendRef which points to endnote references in the main document stream
+ sal_Int32 lcbPlcfendRef; // 0x1D6
+
+ WW8_FC fcPlcfendTxt; // 0x1DA file offset of PLCFendRef which points to endnote text in the endnote document
+ // stream which corresponds with the PLCFendRef
+ sal_Int32 lcbPlcfendTxt; // 0x1DE
+
+ WW8_FC fcPlcffldEdn; // 0x1E2 offset to PLCF of field positions in the endnote subdoc
+ sal_Int32 lcbPlcffldEdn; // 0x1E6
+
+ WW8_FC fcPlcfpgdEdn; // 0x1EA offset to PLCF of page boundaries in the endnote subdoc.
+ sal_Int32 lcbPlcfpgdEdn; // 0x1EE
+
+
+ WW8_FC fcDggInfo; // offset in table stream of the office art object table data.
+ // The format of office art object table data is found in a separate document.
+ // war in Ver67 nur leere Reserve
+ sal_Int32 lcbDggInfo; // length in bytes of the office art object table data
+ // war in Ver67 nur leere Reserve
+
+ WW8_FC fcSttbfRMark; // 0x1fa offset to STTBF that records the author abbreviations...
+ sal_Int32 lcbSttbfRMark; // 0x1fe
+ WW8_FC fcSttbfCaption; // 0x202 offset to STTBF that records caption titles...
+ sal_Int32 lcbSttbfCaption; // 0x206
+ WW8_FC fcSttbAutoCaption; // offset in table stream to the STTBF that records the object names and
+ // indices into the caption STTBF for objects which get auto captions.
+ sal_Int32 lcbSttbAutoCaption; // 0x20e
+
+ WW8_FC fcPlcfwkb; // 0x212 offset to PLCF that describes the boundaries of contributing documents...
+ sal_Int32 lcbPlcfwkb; // 0x216
+
+ WW8_FC fcPlcfspl; // offset in table stream of PLCF (of SPLS structures) that records spell check state
+ // war in Ver67 nur leere Reserve
+ sal_Int32 lcbPlcfspl; // war in Ver67 nur leere Reserve
+
+ WW8_FC fcPlcftxbxTxt; // 0x222 ...PLCF of beginning CP in the text box subdoc
+ sal_Int32 lcbPlcftxbxTxt; // 0x226
+ WW8_FC fcPlcffldTxbx; // 0x22a ...PLCF of field boundaries recorded in the textbox subdoc.
+ sal_Int32 lcbPlcffldTxbx; // 0x22e
+ WW8_FC fcPlcfHdrtxbxTxt;// 0x232 ...PLCF of beginning CP in the header text box subdoc
+ sal_Int32 lcbPlcfHdrtxbxTxt;// 0x236
+ WW8_FC fcPlcffldHdrTxbx;// 0x23a ...PLCF of field boundaries recorded in the header textbox subdoc.
+ sal_Int32 lcbPlcffldHdrTxbx;// 0x23e
+ WW8_FC fcStwUser;
+ sal_uInt32 lcbStwUser;
+ WW8_FC fcSttbttmbd;
+ sal_uInt32 lcbSttbttmbd;
+
+ WW8_FC fcSttbFnm; // 0x02da offset in the table stream of masters subdocument names
+ sal_Int32 lcbSttbFnm; // 0x02de length
+
+ /*
+ spezielle Listenverwaltung fuer WW8
+ */
+ WW8_FC fcPlcfLst; // 0x02e2 offset in the table stream of list format information.
+ sal_Int32 lcbPlcfLst; // 0x02e6 length
+ WW8_FC fcPlfLfo; // 0x02ea offset in the table stream of list format override information.
+ sal_Int32 lcbPlfLfo; // 0x02ee length
+ /*
+ spezielle Break-Verwaltung fuer Text-Box-Stories in WW8
+ */
+ WW8_FC fcPlcftxbxBkd; // 0x02f2 PLCF fuer TextBox-Break-Deskriptoren im Maintext
+ sal_Int32 lcbPlcftxbxBkd; // 0x02f6
+ WW8_FC fcPlcfHdrtxbxBkd;// 0x02fa PLCF fuer TextBox-Break-Deskriptoren im Header-/Footer-Bereich
+ sal_Int32 lcbPlcfHdrtxbxBkd;// 0x02fe
+
+ // 0x302 - 372 == ignore
+ /*
+ ListNames (skip to here!)
+ */
+ WW8_FC fcSttbListNames;// 0x0372 PLCF for Listname Table
+ sal_Int32 lcbSttbListNames;// 0x0376
+
+ WW8_FC fcPlcfTch;
+ sal_Int32 lcbPlcfTch;
+
+ // 0x38A - 41A == ignore
+ WW8_FC fcAtrdExtra;
+ sal_uInt32 lcbAtrdExtra;
+
+ // 0x422 - 0x4D4 == ignore
+ WW8_FC fcHplxsdr; //bizarrely, word xp seems to require this set to shows dates from AtrdExtra
+ sal_uInt32 lcbHplxsdr;
+
+ /*
+ General-Varaiblen, die fuer Ver67 und Ver8 verwendet werden,
+ obwohl sie in der jeweiligen DATEI verschiedene Groesse haben:
+ */
+ sal_Int32 pnChpFirst;
+ sal_Int32 pnPapFirst;
+ sal_Int32 cpnBteChp;
+ sal_Int32 cpnBtePap;
+ /*
+ The actual nFib, moved here because some readers assumed
+ they couldn't read any format with nFib > some constant
+ */
+ sal_uInt16 nFib_actual; // 0x05bc #i56856#
+ /*
+ nun wird lediglich noch ein Ctor benoetigt
+ */
+ WW8Fib( SvStream& rStrm, sal_uInt8 nWantedVersion,sal_uInt32 nOffset=0 );
+
+ /* leider falsch, man braucht auch noch einen fuer den Export */
+ WW8Fib( sal_uInt8 nVersion = 6 );
+ bool WriteHeader(SvStream& rStrm);
+ bool Write(SvStream& rStrm);
+ static rtl_TextEncoding GetFIBCharset(sal_uInt16 chs);
+ ww::WordVersion GetFIBVersion() const;
+ WW8_CP GetBaseCp(ManTypes nType) const;
+ sal_Unicode getNumDecimalSep() const;
+};
+
+class WW8Style
+{
+protected:
+ WW8Fib& rFib;
+ SvStream& rSt;
+ long nStyleStart;
+ long nStyleLen;
+
+ sal_uInt16 cstd; // Count of styles in stylesheet
+ sal_uInt16 cbSTDBaseInFile; // Length of STD Base as stored in a file
+ sal_uInt16 fStdStylenamesWritten : 1; // Are built-in stylenames stored?
+ sal_uInt16 : 15; // Spare flags
+ sal_uInt16 stiMaxWhenSaved; // Max sti known when file was written
+ sal_uInt16 istdMaxFixedWhenSaved; // How many fixed-index istds are there?
+ sal_uInt16 nVerBuiltInNamesWhenSaved; // Current version of built-in stylenames
+ // ftc used by StandardChpStsh for this document
+ sal_uInt16 ftcAsci;
+ // CJK ftc used by StandardChpStsh for this document
+ sal_uInt16 ftcFE;
+ // CTL/Other ftc used by StandardChpStsh for this document
+ sal_uInt16 ftcOther;
+ // CTL ftc used by StandardChpStsh for this document
+ sal_uInt16 ftcBi;
+
+ //No copying
+ WW8Style(const WW8Style&);
+ WW8Style& operator=(const WW8Style&);
+public:
+ WW8Style( SvStream& rSt, WW8Fib& rFibPara );
+ WW8_STD* Read1STDFixed( short& rSkip, short* pcbStd );
+ WW8_STD* Read1Style( short& rSkip, String* pString, short* pcbStd );
+ sal_uInt16 GetCount() const { return cstd; }
+};
+
+class WW8Fonts
+{
+protected:
+ WW8_FFN* pFontA; // Array of Pointers to Font Description
+ sal_uInt16 nMax; // Array-Size
+public:
+ WW8Fonts( SvStream& rSt, WW8Fib& rFib );
+ ~WW8Fonts() { delete[] pFontA; }
+ const WW8_FFN* GetFont( sal_uInt16 nNum ) const;
+ sal_uInt16 GetMax() const { return nMax; }
+};
+
+typedef sal_uInt8 HdFtFlags;
+namespace nsHdFtFlags
+{
+ const HdFtFlags WW8_HEADER_EVEN = 0x01;
+ const HdFtFlags WW8_HEADER_ODD = 0x02;
+ const HdFtFlags WW8_FOOTER_EVEN = 0x04;
+ const HdFtFlags WW8_FOOTER_ODD = 0x08;
+ const HdFtFlags WW8_HEADER_FIRST = 0x10;
+ const HdFtFlags WW8_FOOTER_FIRST = 0x20;
+}
+
+/// Document Properties
+class WW8Dop
+{
+public:
+ /* Error Status */
+ sal_uLong nDopError;
+ /*
+ Corresponds only roughly to the actual structure of the Winword DOP,
+ the winword FIB version matters to what exists.
+ */
+ // Initialisier-Dummy:
+ sal_uInt8 nDataStart;
+ //-------------------------
+ sal_uInt16 fFacingPages : 1; // 1 when facing pages should be printed
+ sal_uInt16 fWidowControl : 1; // 1 when widow control is in effect. 0 when widow control disabled.
+ sal_uInt16 fPMHMainDoc : 1; // 1 when doc is a main doc for Print Merge Helper, 0 when not; default=0
+ sal_uInt16 grfSuppression : 2; // 0 Default line suppression storage; 0= form letter line suppression; 1= no line suppression; default=0
+ sal_uInt16 fpc : 2; // 1 footnote position code: 0 as endnotes, 1 at bottom of page, 2 immediately beneath text
+ sal_uInt16 : 1; // 0 unused
+ //-------------------------
+ sal_uInt16 grpfIhdt : 8; // 0 specification of document headers and footers. See explanation under Headers and Footers topic.
+ //-------------------------
+ sal_uInt16 rncFtn : 2; // 0 restart index for footnotes, 0 don't restart note numbering, 1 section, 2 page
+ sal_uInt16 nFtn : 14; // 1 initial footnote number for document
+ sal_uInt16 fOutlineDirtySave : 1; // when 1, indicates that information in the hPLCFpad should be refreshed since outline has been dirtied
+ sal_uInt16 : 7; // reserved
+ sal_uInt16 fOnlyMacPics : 1; // when 1, Word believes all pictures recorded in the document were created on a Macintosh
+ sal_uInt16 fOnlyWinPics : 1; // when 1, Word believes all pictures recorded in the document were created in Windows
+ sal_uInt16 fLabelDoc : 1; // when 1, document was created as a print merge labels document
+ sal_uInt16 fHyphCapitals : 1; // when 1, Word is allowed to hyphenate words that are capitalized. When 0, capitalized may not be hyphenated
+ sal_uInt16 fAutoHyphen : 1; // when 1, Word will hyphenate newly typed text as a background task
+ sal_uInt16 fFormNoFields : 1;
+ sal_uInt16 fLinkStyles : 1; // when 1, Word will merge styles from its template
+ sal_uInt16 fRevMarking : 1; // when 1, Word will mark revisions as the document is edited
+ sal_uInt16 fBackup : 1; // always make backup when document saved when 1.
+ sal_uInt16 fExactCWords : 1;
+ sal_uInt16 fPagHidden : 1; //
+ sal_uInt16 fPagResults : 1;
+ sal_uInt16 fLockAtn : 1; // when 1, annotations are locked for editing
+ sal_uInt16 fMirrorMargins : 1; // swap margins on left/right pages when 1.
+ sal_uInt16 fReadOnlyRecommended : 1;// user has recommended that this doc be opened read-only when 1
+ sal_uInt16 fDfltTrueType : 1; // when 1, use TrueType fonts by default (flag obeyed only when doc was created by WinWord 2.x)
+ sal_uInt16 fPagSuppressTopSpacing : 1;//when 1, file created with SUPPRESSTOPSPACING=YES in win.ini. (flag obeyed only when doc was created by WinWord 2.x).
+ sal_uInt16 fProtEnabled : 1; // when 1, document is protected from edit operations
+ sal_uInt16 fDispFormFldSel : 1;// when 1, restrict selections to occur only within form fields
+ sal_uInt16 fRMView : 1; // when 1, show revision markings on screen
+ sal_uInt16 fRMPrint : 1; // when 1, print revision marks when document is printed
+ sal_uInt16 fWriteReservation : 1;
+ sal_uInt16 fLockRev : 1; // when 1, the current revision marking state is locked
+ sal_uInt16 fEmbedFonts : 1; // when 1, document contains embedded True Type fonts
+ // compatability options
+ sal_uInt16 copts_fNoTabForInd : 1; // when 1, don�t add automatic tab stops for hanging indent
+ sal_uInt16 copts_fNoSpaceRaiseLower : 1; // when 1, don�t add extra space for raised or lowered characters
+ sal_uInt16 copts_fSupressSpbfAfterPgBrk : 1; // when 1, supress the paragraph Space Before and Space After options after a page break
+ sal_uInt16 copts_fWrapTrailSpaces : 1; // when 1, wrap trailing spaces at the end of a line to the next line
+ sal_uInt16 copts_fMapPrintTextColor : 1; // when 1, print colors as black on non-color printers
+ sal_uInt16 copts_fNoColumnBalance : 1; // when 1, don�t balance columns for Continuous Section starts
+ sal_uInt16 copts_fConvMailMergeEsc : 1;
+ sal_uInt16 copts_fSupressTopSpacing : 1; // when 1, supress extra line spacing at top of page
+ sal_uInt16 copts_fOrigWordTableRules : 1; // when 1, combine table borders like Word 5.x for the Macintosh
+ sal_uInt16 copts_fTransparentMetafiles : 1; // when 1, don�t blank area between metafile pictures
+ sal_uInt16 copts_fShowBreaksInFrames : 1; // when 1, show hard page or column breaks in frames
+ sal_uInt16 copts_fSwapBordersFacingPgs : 1; // when 1, swap left and right pages on odd facing pages
+ sal_uInt16 copts_fExpShRtn : 1; // when 1, expand character spaces on the line ending SHIFT+RETURN // #i56856#
+
+ sal_Int16 dxaTab; // 720 twips default tab width
+ sal_uInt16 wSpare; //
+ sal_uInt16 dxaHotZ; // width of hyphenation hot zone measured in twips
+ sal_uInt16 cConsecHypLim; // number of lines allowed to have consecutive hyphens
+ sal_uInt16 wSpare2; // reserved
+ sal_Int32 dttmCreated; // DTTM date and time document was created
+ sal_Int32 dttmRevised; // DTTM date and time document was last revised
+ sal_Int32 dttmLastPrint; // DTTM date and time document was last printed
+ sal_Int16 nRevision; // number of times document has been revised since its creation
+ sal_Int32 tmEdited; // time document was last edited
+ sal_Int32 cWords; // count of words tallied by last Word Count execution
+ sal_Int32 cCh; // count of characters tallied by last Word Count execution
+ sal_Int16 cPg; // count of pages tallied by last Word Count execution
+ sal_Int32 cParas; // count of paragraphs tallied by last Word Count execution
+ sal_uInt16 rncEdn : 2; // restart endnote number code: 0 don�t restart endnote numbering, 1 section, 2 page
+ sal_uInt16 nEdn : 14; // beginning endnote number
+ sal_uInt16 epc : 2; // endnote position code: 0 at end of section, 3 at end of document
+ // sal_uInt16 nfcFtnRef : 4; // number format code for auto footnotes: 0 Arabic, 1 Upper case Roman, 2 Lower case Roman
+ // 3 Upper case Letter, 4 Lower case Letter
+ // ersetzt durch gleichlautendes Feld unten
+ // sal_uInt16 nfcEdnRef : 4; // number format code for auto endnotes: 0 Arabic, 1 Upper case Roman, 2 Lower case Roman
+ // 3 Upper case Letter, 4 Lower case Letter
+ // ersetzt durch gleichlautendes Feld unten
+ sal_uInt16 fPrintFormData : 1; // only print data inside of form fields
+ sal_uInt16 fSaveFormData : 1; // only save document data that is inside of a form field.
+ sal_uInt16 fShadeFormData : 1; // shade form fields
+ sal_uInt16 : 2; // reserved
+ sal_uInt16 fWCFtnEdn : 1; // when 1, include footnotes and endnotes in word count
+ sal_Int32 cLines; // count of lines tallied by last Word Count operation
+ sal_Int32 cWordsFtnEnd; // count of words in footnotes and endnotes tallied by last Word Count operation
+ sal_Int32 cChFtnEdn; // count of characters in footnotes and endnotes tallied by last Word Count operation
+ sal_Int16 cPgFtnEdn; // count of pages in footnotes and endnotes tallied by last Word Count operation
+ sal_Int32 cParasFtnEdn; // count of paragraphs in footnotes and endnotes tallied by last Word Count operation
+ sal_Int32 cLinesFtnEdn; // count of paragraphs in footnotes and endnotes tallied by last Word Count operation
+ sal_Int32 lKeyProtDoc; // document protection password key, only valid if dop.fProtEnabled, dop.fLockAtn or dop.fLockRev are 1.
+ sal_uInt16 wvkSaved : 3; // document view kind: 0 Normal view, 1 Outline view, 2 Page View
+ sal_uInt16 wScaleSaved : 9; //
+ sal_uInt16 zkSaved : 2;
+ sal_uInt16 fRotateFontW6 : 1;
+ sal_uInt16 iGutterPos : 1 ;
+
+ // hier sollte bei nFib < 103 Schluss sein, sonst ist Datei fehlerhaft!
+
+ /*
+ bei nFib >= 103 gehts weiter:
+ */
+ sal_uInt32 fNoTabForInd :1; // see above in compatability options
+ sal_uInt32 fNoSpaceRaiseLower :1; // see above
+ sal_uInt32 fSupressSpbfAfterPageBreak :1; // see above
+ sal_uInt32 fWrapTrailSpaces :1; // see above
+ sal_uInt32 fMapPrintTextColor :1; // see above
+ sal_uInt32 fNoColumnBalance :1; // see above
+ sal_uInt32 fConvMailMergeEsc :1; // see above
+ sal_uInt32 fSupressTopSpacing :1; // see above
+ sal_uInt32 fOrigWordTableRules :1; // see above
+ sal_uInt32 fTransparentMetafiles :1; // see above
+ sal_uInt32 fShowBreaksInFrames :1; // see above
+ sal_uInt32 fSwapBordersFacingPgs :1; // see above
+ sal_uInt32 fCompatabilityOptions_Unknown1_13 :1; // #i78591#
+ sal_uInt32 fExpShRtn :1; // #i78591# and #i56856#
+ sal_uInt32 fCompatabilityOptions_Unknown1_15 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown1_16 :1; // #i78591#
+ sal_uInt32 fSuppressTopSpacingMac5 :1; // Suppress extra line spacing at top
+ // of page like MacWord 5.x
+ sal_uInt32 fTruncDxaExpand :1; // Expand/Condense by whole number of points
+ sal_uInt32 fPrintBodyBeforeHdr :1; // Print body text before header/footer
+ sal_uInt32 fNoLeading :1; // Don't add extra spacebetween rows of text
+ sal_uInt32 fCompatabilityOptions_Unknown1_21 :1; // #i78591#
+ sal_uInt32 fMWSmallCaps : 1; // Use larger small caps like MacWord 5.x
+ sal_uInt32 fCompatabilityOptions_Unknown1_23 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown1_24 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown1_25 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown1_26 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown1_27 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown1_28 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown1_29 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown1_30 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown1_31 :1; // #i78591#
+ sal_uInt32 fUsePrinterMetrics : 1; //The magic option
+
+ // hier sollte bei nFib <= 105 Schluss sein, sonst ist Datei fehlerhaft!
+
+ /*
+ bei nFib > 105 gehts weiter:
+ */
+ sal_Int16 adt; // Autoformat Document Type:
+ // 0 for normal.
+ // 1 for letter, and
+ // 2 for email.
+ WW8DopTypography doptypography; // see WW8STRUC.HXX
+ WW8_DOGRID dogrid; // see WW8STRUC.HXX
+ sal_uInt16 :1; // reserved
+ sal_uInt16 lvl :4; // Which outline levels are showing in outline view
+ sal_uInt16 :4; // reserved
+ sal_uInt16 fHtmlDoc :1; // This file is based upon an HTML file
+ sal_uInt16 :1; // reserved
+ sal_uInt16 fSnapBorder :1; // Snap table and page borders to page border
+ sal_uInt16 fIncludeHeader :1; // Place header inside page border
+ sal_uInt16 fIncludeFooter :1; // Place footer inside page border
+ sal_uInt16 fForcePageSizePag :1; // Are we in online view
+ sal_uInt16 fMinFontSizePag :1; // Are we auto-promoting fonts to >= hpsZoonFontPag?
+ sal_uInt16 fHaveVersions :1; // versioning is turned on
+ sal_uInt16 fAutoVersion :1; // autoversioning is enabled
+ sal_uInt16 : 14; // reserved
+ // Skip 12 Bytes here: ASUMI
+ sal_Int32 cChWS;
+ sal_Int32 cChWSFtnEdn;
+ sal_Int32 grfDocEvents;
+ // Skip 4+30+8 Bytes here
+ sal_Int32 cDBC;
+ sal_Int32 cDBCFtnEdn;
+ // Skip 4 Bytes here
+ sal_Int16 nfcFtnRef;
+ sal_Int16 nfcEdnRef;
+ sal_Int16 hpsZoonFontPag;
+ sal_Int16 dywDispPag;
+
+ sal_uInt32 fCompatabilityOptions_Unknown2_1 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_2 :1; // #i78591#
+ sal_uInt32 fDontUseHTMLAutoSpacing:1;
+ sal_uInt32 fCompatabilityOptions_Unknown2_4 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_5 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_6 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_7 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_8 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_9 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_10 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_11 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_12 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_13 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_14 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_15 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_16 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_17 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_18 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_19 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_20 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_21 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_22 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_23 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_24 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_25 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_26 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_27 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_28 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_29 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_30 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_31 :1; // #i78591#
+ sal_uInt32 fCompatabilityOptions_Unknown2_32 :1; // #i78591#
+
+ sal_uInt16 fUnknown3:15;
+ sal_uInt16 fUseBackGroundInAllmodes:1;
+
+ sal_uInt16 fDoNotEmbedSystemFont:1;
+ sal_uInt16 fWordCompat:1;
+ sal_uInt16 fLiveRecover:1;
+ sal_uInt16 fEmbedFactoids:1;
+ sal_uInt16 fFactoidXML:1;
+ sal_uInt16 fFactoidAllDone:1;
+ sal_uInt16 fFolioPrint:1;
+ sal_uInt16 fReverseFolio:1;
+ sal_uInt16 iTextLineEnding:3;
+ sal_uInt16 fHideFcc:1;
+ sal_uInt16 fAcetateShowMarkup:1;
+ sal_uInt16 fAcetateShowAtn:1;
+ sal_uInt16 fAcetateShowInsDel:1;
+ sal_uInt16 fAcetateShowProps:1;
+
+ // 2. Initialisier-Dummy:
+ sal_uInt8 nDataEnd;
+
+ bool bUseThaiLineBreakingRules;
+
+ /* Constructor for importing, needs to know the version of word used */
+ WW8Dop(SvStream& rSt, sal_Int16 nFib, sal_Int32 nPos, sal_uInt32 nSize);
+
+ /* Constructs default DOP suitable for exporting */
+ WW8Dop();
+ bool Write(SvStream& rStrm, WW8Fib& rFib) const;
+public:
+ sal_uInt32 GetCompatabilityOptions() const;
+ void SetCompatabilityOptions(sal_uInt32 a32Bit);
+ // i#78591#
+ sal_uInt32 GetCompatabilityOptions2() const;
+ void SetCompatabilityOptions2(sal_uInt32 a32Bit);
+};
+
+class WW8PLCF_HdFt
+{
+private:
+ WW8PLCF aPLCF;
+ long nTextOfs;
+ short nIdxOffset;
+public:
+ WW8PLCF_HdFt( SvStream* pSt, WW8Fib& rFib, WW8Dop& rDop );
+ bool GetTextPos(sal_uInt8 grpfIhdt, sal_uInt8 nWhich, WW8_CP& rStart, long& rLen);
+ bool GetTextPosExact(short nIdx, WW8_CP& rStart, long& rLen);
+ void UpdateIndex( sal_uInt8 grpfIhdt );
+};
+
+void SwapQuotesInField(String &rFmt);
+
+Word2CHPX ReadWord2Chpx(SvStream &rSt, sal_Size nOffset, sal_uInt8 nSize);
+std::vector<sal_uInt8> ChpxToSprms(const Word2CHPX &rChpx);
+
+sal_uLong SafeReadString(ByteString &rStr,sal_uInt16 nLen,SvStream &rStrm);
+
+//MS has a (slightly) inaccurate view of how many twips
+//are in the default letter size of a page
+const sal_uInt16 lLetterWidth = 12242;
+const sal_uInt16 lLetterHeight = 15842;
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8struc.hxx b/sw/source/filter/ww8/ww8struc.hxx
new file mode 100644
index 000000000000..6ac5461c9c56
--- /dev/null
+++ b/sw/source/filter/ww8/ww8struc.hxx
@@ -0,0 +1,991 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org 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 Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+#ifndef _WW8STRUC_HXX
+#define _WW8STRUC_HXX
+
+#include <osl/endian.h>
+#include <tools/string.hxx>
+#include <sal/config.h>
+
+#include <editeng/borderline.hxx>
+
+#if defined OSL_BIGENDIAN || SAL_TYPES_ALIGNMENT4 > 2 || defined UNX
+# define __WW8_NEEDS_COPY
+#endif
+
+#ifdef SAL_W32
+# pragma pack(push, 2)
+#elif defined(SAL_OS2)
+# pragma pack(2)
+#endif
+
+inline void Set_UInt8( sal_uInt8 *& p, sal_uInt8 n )
+{
+ ByteToSVBT8( n, *(SVBT8*)p );
+ p+= 1;
+}
+
+inline void Set_UInt16( sal_uInt8 *& p, sal_uInt16 n )
+{
+ ShortToSVBT16( n, *(SVBT16*)p );
+ p+= 2;
+}
+
+inline void Set_UInt32( sal_uInt8 *& p, sal_uInt32 n )
+{
+ UInt32ToSVBT32( n, *(SVBT32*)p );
+ p+= 4;
+}
+
+struct Word2CHPX
+{
+ sal_uInt16 fBold:1;
+ sal_uInt16 fItalic:1;
+ sal_uInt16 fRMarkDel:1;
+ sal_uInt16 fOutline:1;
+ sal_uInt16 fFldVanish:1;
+ sal_uInt16 fSmallCaps:1;
+ sal_uInt16 fCaps:1;
+ sal_uInt16 fVanish:1;
+ sal_uInt16 fRMark:1;
+ sal_uInt16 fSpec:1;
+ sal_uInt16 fStrike:1;
+ sal_uInt16 fObj:1;
+ sal_uInt16 fBoldBi:1;
+ sal_uInt16 fItalicBi:1;
+ sal_uInt16 fBiDi:1;
+ sal_uInt16 fDiacUSico:1;
+ sal_uInt16 fsIco:1;
+ sal_uInt16 fsFtc:1;
+ sal_uInt16 fsHps:1;
+ sal_uInt16 fsKul:1;
+ sal_uInt16 fsPos:1;
+ sal_uInt16 fsSpace:1;
+ sal_uInt16 fsLid:1;
+ sal_uInt16 fsIcoBi:1;
+ sal_uInt16 fsFtcBi:1;
+ sal_uInt16 fsHpsBi:1;
+ sal_uInt16 fsLidBi:1;
+
+ sal_uInt16 ftc;
+ sal_uInt16 hps;
+ sal_uInt8 qpsSpace:6;
+ sal_uInt8 fSysVanish:1;
+ sal_uInt8 fNumRun:1;
+ sal_uInt8 ico:5;
+ sal_uInt8 kul:3;
+ sal_uInt8 hpsPos;
+ sal_uInt8 icoBi;
+ sal_uInt16 lid;
+ sal_uInt16 ftcBi;
+ sal_uInt16 hpsBi;
+ sal_uInt16 lidBi;
+ sal_uInt32 fcPic;
+
+ Word2CHPX()
+ {
+ fBold = 0;
+ fItalic = 0;
+ fRMarkDel = 0;
+ fOutline = 0;
+ fFldVanish = 0;
+ fSmallCaps = 0;
+ fCaps = 0;
+ fVanish = 0;
+ fRMark = 0;
+ fSpec = 0;
+ fStrike = 0;
+ fObj = 0;
+ fBoldBi = 0;
+ fItalicBi = 0;
+ fBiDi = 0;
+ fDiacUSico = 0;
+ fsIco = 0;
+ fsFtc = 0;
+ fsHps = 0;
+ fsKul = 0;
+ fsPos = 0;
+ fsSpace = 0;
+ fsLid = 0;
+ fsIcoBi = 0;
+ fsFtcBi = 0;
+ fsHpsBi = 0;
+ fsLidBi = 0;
+
+ ftc = 0;
+ hps = 0;
+ qpsSpace = 0;
+ fSysVanish = 0;
+ fNumRun = 0;
+ ico = 0;
+ kul = 0;
+ hpsPos = 0;
+ icoBi = 0;
+ lid = 0;
+ ftcBi = 0;
+ hpsBi = 0;
+ lidBi = 0;
+ fcPic = 0;
+ }
+};
+
+
+typedef sal_Int16 WW8_PN;
+typedef sal_Int32 WW8_FC;
+typedef sal_Int32 WW8_CP;
+
+const WW8_FC WW8_FC_MAX = SAL_MAX_INT32;
+const WW8_CP WW8_CP_MAX = SAL_MAX_INT32;
+
+/** STD - STyle Definition
+
+ The STD contains the entire definition of a style.
+ It has two parts, a fixed-length base (cbSTDBase bytes long)
+ and a variable length remainder holding the name, and the upx and upe
+ arrays (a upx and upe for each type stored in the style, std.cupx)
+ Note that new fields can be added to the BASE of the STD without
+ invalidating the file format, because the STSHI contains the length
+ that is stored in the file. When reading STDs from an older version,
+ new fields will be zero.
+*/
+struct WW8_STD
+{
+ // Base part of STD:
+ sal_uInt16 sti : 12; // invariant style identifier
+ sal_uInt16 fScratch : 1; // spare field for any temporary use,
+ // always reset back to zero!
+ sal_uInt16 fInvalHeight : 1; // PHEs of all text with this style are wrong
+ sal_uInt16 fHasUpe : 1; // UPEs have been generated
+ sal_uInt16 fMassCopy : 1; // std has been mass-copied; if unused at
+ // save time, style should be deleted
+ sal_uInt16 sgc : 4; // style type code
+ sal_uInt16 istdBase : 12; // base style
+ sal_uInt16 cupx : 4; // # of UPXs (and UPEs)
+ sal_uInt16 istdNext : 12; // next style
+ sal_uInt16 bchUpe; // offset to end of upx's, start of upe's
+ //-------- jetzt neu:
+ // ab Ver8 gibts zwei Felder mehr:
+ sal_uInt16 fAutoRedef : 1; /* auto redefine style when appropriate */
+ sal_uInt16 fHidden : 1; /* hidden from UI? */
+ sal_uInt16 : 14; /* unused bits */
+
+ // Variable length part of STD:
+ // sal_uInt8 stzName[2]; /* sub-names are separated by chDelimStyle
+ // char grupx[];
+ // the UPEs are not stored on the file; they are a cache of the based-on
+ // chain
+ // char grupe[];
+};
+
+/** Basis zum Einlesen UND zum Arbeiten (wird jeweils unter schiedlich beerbt)
+*/
+struct WW8_FFN_BASE // Font Descriptor
+{
+ // ab Ver6
+ sal_uInt8 cbFfnM1; // 0x0 total length of FFN - 1.
+
+ sal_uInt8 prg: 2; // 0x1:03 pitch request
+ sal_uInt8 fTrueType : 1; // 0x1:04 when 1, font is a TrueType font
+ // 0x1:08 reserved
+ sal_uInt8 ff : 3; // 0x1:70 font family id
+ // 0x1:80 reserved
+
+ short wWeight; // 0x2 base weight of font
+ sal_uInt8 chs; // 0x4 character set identifier
+ sal_uInt8 ibszAlt; // 0x5 index into ffn.szFfn to the name of the alternate font
+};
+
+/** Hiermit arbeiten wir im Parser (und Dumper)
+*/
+struct WW8_FFN : public WW8_FFN_BASE
+{
+ // ab Ver8 als Unicode
+ String sFontname;// 0x6 bzw. 0x40 ab Ver8 zero terminated string that
+ // records name of font.
+ // Maximal size of szFfn is 65 characters.
+ // Vorsicht: Dieses Array kann auch kleiner sein!!!
+ // Possibly followed by a second sz which records the
+ // name of an alternate font to use if the first named
+ // font does not exist on this system.
+};
+
+
+
+struct WW8_BRCVer6 // alter Border Code
+{
+ SVBT16 aBits1;
+// sal_uInt16 dxpLineWidth : 3;// 0007 When dxpLineWidth is 0, 1, 2, 3, 4, or 5, this field is the width of
+ // a single line of border in units of 0.75 points
+ // Must be nonzero when brcType is nonzero.
+ // 6 == dotted, 7 == dashed.
+// sal_uInt16 brcType : 2; // 0018 border type code: 0 == none, 1 == single, 2 == thick, 3 == double
+// sal_uInt16 fShadow : 1; // 0020 when 1, border is drawn with shadow. Must be 0 when BRC is a substructure of the TC
+// sal_uInt16 ico : 5; // 07C0 color code (see chp.ico)
+// sal_uInt16 dxpSpace : 5; // F800 width of space to maintain between border and text within border.
+ // Must be 0 when BRC is a substructure of the TC. Stored in points for Windows.
+};
+
+class WW8_BRC // Border Code
+{
+public:
+ SVBT16 aBits1;
+ SVBT16 aBits2;
+// sal_uInt16 dxpLineWidth : 3;// 0007 When dxpLineWidth is 0, 1, 2, 3, 4, or 5, this field is the width of
+ // a single line of border in units of 0.75 points
+ // Must be nonzero when brcType is nonzero.
+ // 6 == dotted, 7 == dashed.
+// sal_uInt16 brcType : 2; // 0018 border type code: 0 == none, 1 == single, 2 == thick, 3 == double
+// sal_uInt16 fShadow : 1; // 0020 when 1, border is drawn with shadow. Must be 0 when BRC is a substructure of the TC
+// sal_uInt16 ico : 5; // 07C0 color code (see chp.ico)
+// sal_uInt16 dxpSpace : 5; // F800 width of space to maintain between border and text within border.
+ // Must be 0 when BRC is a substructure of the TC. Stored in points for Windows.
+ WW8_BRC()
+ {
+ memset(aBits1, 0, sizeof(aBits1));
+ memset(aBits2, 0, sizeof(aBits2));
+ }
+ short DetermineBorderProperties (bool bVer67, short *pSpace=0,
+ sal_uInt8 *pCol=0, short *pIdx=0) const;
+ bool IsEmpty(bool bVer67) const;
+ bool IsZeroed(bool bVer67) const;
+ bool IsBlank() const;
+};
+
+typedef WW8_BRC WW8_BRC5[5]; // 5 * Border Code
+
+enum BRC_Sides
+{
+ WW8_TOP = 0, WW8_LEFT = 1, WW8_BOT = 2, WW8_RIGHT = 3, WW8_BETW = 4
+};
+
+/*
+Document Typography Info (DOPTYPOGRAPHY) These options are Far East only,
+and are accessible through the Typography tab of the Tools/Options dialog.
+*/
+class WW8DopTypography
+{
+public:
+ void ReadFromMem(sal_uInt8 *&pData);
+ void WriteToMem(sal_uInt8 *&pData) const;
+
+ //Maps what I think is the language this is to affect to the OOo language
+ sal_uInt16 GetConvertedLang() const;
+
+ sal_uInt16 fKerningPunct : 1; // true if we're kerning punctuation
+ sal_uInt16 iJustification : 2; // Kinsoku method of justification:
+ // 0 = always expand
+ // 1 = compress punctuation
+ // 2 = compress punctuation and kana.
+ sal_uInt16 iLevelOfKinsoku : 2; // Level of Kinsoku:
+ // 0 = Level 1
+ // 1 = Level 2
+ // 2 = Custom
+ sal_uInt16 f2on1 : 1; // 2-page-on-1 feature is turned on.
+ sal_uInt16 reserved1 : 4; // in 97 its marked as reserved BUT
+ sal_uInt16 reserved2 : 6; // reserved ?
+ //we find that the following applies,
+ //2 == Japanese
+ //4 == Chinese (VR...
+ //6 == Korean
+ //8 == Chinese (Ta...
+ //perhaps a bit field where the DOP can possibly relate to more than
+ //one language at a time, nevertheless MS seems to have painted
+ //themselves into a small corner with one DopTypography for the
+ //full document, might not matter all that much though ?
+
+ enum RuleLengths {nMaxFollowing = 101, nMaxLeading = 51};
+ static const sal_Unicode * GetJapanNotBeginLevel1();
+ static const sal_Unicode * GetJapanNotEndLevel1();
+
+ sal_Int16 cchFollowingPunct; // length of rgxchFPunct
+ sal_Int16 cchLeadingPunct; // length of rgxchLPunct
+
+ // array of characters that should never appear at the start of a line
+ sal_Unicode rgxchFPunct[nMaxFollowing];
+ // array of characters that should never appear at the end of a line
+ sal_Unicode rgxchLPunct[nMaxLeading];
+};
+
+struct WW8_DOGRID
+{
+ short xaGrid; // x-coord of the upper left-hand corner of the grid
+ short yaGrid; // y-coord of the upper left-hand corner of the grid
+ short dxaGrid; // width of each grid square
+ short dyaGrid; // height of each grid square
+
+
+
+ /* a c h t u n g : es duerfen keine solchen Bitfelder ueber einen eingelesenes Byte-Array
+ gelegt werden!!
+ stattdessen ist ein aBits1 darueber zu legen, das mit & auszulesen ist
+ GRUND: Compiler auf Intel und Sparc sortieren die Bits unterschiedlich
+ */
+
+
+
+ short dyGridDisplay:7; // the number of grid squares (in the y direction)
+ // between each gridline drawn on the screen. 0 means
+ // don't display any gridlines in the y direction.
+ short fTurnItOff :1; // suppress display of gridlines
+ short dxGridDisplay:7; // the number of grid squares (in the x direction)
+ // between each gridline drawn on the screen. 0 means
+ // don't display any gridlines in the y direction.
+ short fFollowMargins:1; // if true, the grid will start at the left and top
+ // margins and ignore xaGrid and yaGrid.
+};
+
+struct WW8_PIC
+{
+ sal_Int32 lcb; // 0x0 number of bytes in the PIC structure plus size of following picture data which may be a Window's metafile, a bitmap, or the filename of a TIFF file.
+ sal_uInt16 cbHeader; // 0x4 number of bytes in the PIC (to allow for future expansion).
+ struct {
+ sal_Int16 mm; // 0x6 int
+ sal_Int16 xExt; // 0x8 int
+ sal_Int16 yExt; // 0xa int
+ sal_Int16 hMF; // 0xc int
+ }MFP;
+// sal_uInt8 bm[14]; // 0xe BITMAP(14 bytes) Window's bitmap structure when PIC describes a BITMAP.
+ sal_uInt8 rcWinMF[14]; // 0xe rc (rectangle - 8 bytes) rect for window origin
+ // and extents when metafile is stored -- ignored if 0
+ sal_Int16 dxaGoal; // 0x1c horizontal measurement in twips of the rectangle the picture should be imaged within.
+ sal_Int16 dyaGoal; // 0x1e vertical measurement in twips of the rectangle the picture should be imaged within.
+ sal_uInt16 mx; // 0x20 horizontal scaling factor supplied by user in .1% units.
+ sal_uInt16 my; // 0x22 vertical scaling factor supplied by user in .1% units.
+ sal_Int16 dxaCropLeft; // 0x24 the amount the picture has been cropped on the left in twips.
+ sal_Int16 dyaCropTop; // 0x26 the amount the picture has been cropped on the top in twips.
+ sal_Int16 dxaCropRight; // 0x28 the amount the picture has been cropped on the right in twips.
+ sal_Int16 dyaCropBottom;// 0x2a the amount the picture has been cropped on the bottom in twips.
+ sal_Int16 brcl : 4; // 000F Obsolete, superseded by brcTop, etc. In
+ sal_Int16 fFrameEmpty : 1; // 0010 picture consists of a single frame
+ sal_Int16 fBitmap : 1; // 0020 ==1, when picture is just a bitmap
+ sal_Int16 fDrawHatch : 1; // 0040 ==1, when picture is an active OLE object
+ sal_Int16 fError : 1; // 0080 ==1, when picture is just an error message
+ sal_Int16 bpp : 8; // FF00 bits per pixel, 0 = unknown
+ WW8_BRC rgbrc[4];
+// BRC brcTop; // 0x2e specification for border above picture
+// BRC brcLeft; // 0x30 specification for border to the left
+// BRC brcBottom; // 0x32 specification for border below picture
+// BRC brcRight; // 0x34 specification for border to the right
+ sal_Int16 dxaOrigin; // 0x36 horizontal offset of hand annotation origin
+ sal_Int16 dyaOrigin; // 0x38 vertical offset of hand annotation origin
+// sal_uInt8 rgb[]; // 0x3a variable array of bytes containing Window's metafile, bitmap or TIFF file filename.
+};
+
+struct WW8_PIC_SHADOW
+{
+ SVBT32 lcb; // 0x0 number of bytes in the PIC structure plus size of following picture data which may be a Window's metafile, a bitmap, or the filename of a TIFF file.
+ SVBT16 cbHeader; // 0x4 number of bytes in the PIC (to allow for future expansion).
+ struct {
+ SVBT16 mm; // 0x6 int
+ SVBT16 xExt; // 0x8 int
+ SVBT16 yExt; // 0xa int
+ SVBT16 hMF; // 0xc int
+ }MFP;
+// SVBT8 bm[14]; // 0xe BITMAP(14 bytes) Window's bitmap structure when PIC describes a BITMAP.
+ SVBT8 rcWinMF[14]; // 0xe rc (rectangle - 8 bytes) rect for window origin
+ // and extents when metafile is stored -- ignored if 0
+ SVBT16 dxaGoal; // 0x1c horizontal measurement in twips of the rectangle the picture should be imaged within.
+ SVBT16 dyaGoal; // 0x1e vertical measurement in twips of the rectangle the picture should be imaged within.
+ SVBT16 mx; // 0x20 horizontal scaling factor supplied by user in .1% units.
+ SVBT16 my; // 0x22 vertical scaling factor supplied by user in .1% units.
+ SVBT16 dxaCropLeft; // 0x24 the amount the picture has been cropped on the left in twips.
+ SVBT16 dyaCropTop; // 0x26 the amount the picture has been cropped on the top in twips.
+ SVBT16 dxaCropRight; // 0x28 the amount the picture has been cropped on the right in twips.
+ SVBT16 dyaCropBottom;// 0x2a the amount the picture has been cropped on the bottom in twips.
+ SVBT8 aBits1; //0x2c
+ SVBT8 aBits2;
+// WW8_BRC rgbrc[4];
+// BRC brcTop; // 0x2e specification for border above picture
+// BRC brcLeft; // 0x30 specification for border to the left
+// BRC brcBottom; // 0x32 specification for border below picture
+// BRC brcRight; // 0x34 specification for border to the right
+// SVBT16 dxaOrigin; // 0x36 horizontal offset of hand annotation origin
+// SVBT16 dyaOrigin; // 0x38 vertical offset of hand annotation origin
+// SVBT8 rgb[]; // 0x3a variable array of bytes containing Window's metafile, bitmap or TIFF file filename.
+};
+
+
+struct WW8_TBD
+{
+ SVBT8 aBits1;
+// sal_uInt8 jc : 3; // 0x07 justification code: 0=left tab, 1=centered tab, 2=right tab, 3=decimal tab, 4=bar
+// sal_uInt8 tlc : 3; // 0x38 tab leader code: 0=no leader, 1=dotted leader,
+ // 2=hyphenated leader, 3=single line leader, 4=heavy line leader
+// * int :2 C0 reserved
+};
+
+struct WW8_TCell // hiermit wird weitergearbeitet (entspricht weitestgehend dem Ver8-Format)
+{
+ sal_uInt8 bFirstMerged : 1;// 0001 set to 1 when cell is first cell of a range of cells that have been merged.
+ sal_uInt8 bMerged : 1;// 0002 set to 1 when cell has been merged with preceding cell.
+ sal_uInt8 bVertical : 1;// set to 1 when cell has vertical text flow
+ sal_uInt8 bBackward : 1;// for a vertical table cell, text flow is bottom to top when 1 and is bottom to top when 0.
+ sal_uInt8 bRotateFont : 1;// set to 1 when cell has rotated characters (i.e. uses @font)
+ sal_uInt8 bVertMerge : 1;// set to 1 when cell is vertically merged with the cell(s) above and/or below. When cells are vertically merged, the display area of the merged cells are consolidated. The consolidated area is used to display the contents of the first vertically merged cell (the cell with fVertRestart set to 1), and all other vertically merged cells (those with fVertRestart set to 0) must be empty. Cells can only be merged vertically if their left and right boundaries are (nearly) identical (i.e. if corresponding entries in rgdxaCenter of the table rows differ by at most 3).
+ sal_uInt8 bVertRestart : 1;// set to 1 when the cell is the first of a set of vertically merged cells. The contents of a cell with fVertStart set to 1 are displayed in the consolidated area belonging to the entire set of vertically merged cells. Vertically merged cells with fVertRestart set to 0 must be empty.
+ sal_uInt8 nVertAlign : 2;// specifies the alignment of the cell contents relative to text flow (e.g. in a cell with bottom to top text flow and bottom vertical alignment, the text is shifted horizontally to match the cell's right boundary):
+ // 0 top
+ // 1 center
+ // 2 bottom
+ sal_uInt16 fUnused : 7;// reserved - nicht loeschen: macht das sal_uInt16 voll !!
+
+ WW8_BRC rgbrc[4]; // border codes
+//notational convenience for referring to brcTop, brcLeft, etc fields.
+// BRC brcTop; // specification of the top border of a table cell
+// BRC brcLeft; // specification of left border of table row
+// BRC brcBottom; // specification of bottom border of table row
+// BRC brcRight; // specification of right border of table row.
+};
+// cbTC (count of bytes of a TC) is 18(decimal), 12(hex).
+
+
+struct WW8_TCellVer6 // wird aus der Datei gelesen
+{
+ SVBT8 aBits1Ver6;
+ SVBT8 aBits2Ver6;
+// sal_uInt16 fFirstMerged : 1;// 0001 set to 1 when cell is first cell of a range of cells that have been merged.
+// sal_uInt16 fMerged : 1; // 0002 set to 1 when cell has been merged with preceding cell.
+// sal_uInt16 fUnused : 14; // FFFC reserved
+ WW8_BRCVer6 rgbrcVer6[4];
+// notational convenience for referring to brcTop, brcLeft, etc fields:
+// BRC brcTop; // specification of the top border of a table cell
+// BRC brcLeft; // specification of left border of table row
+// BRC brcBottom; // specification of bottom border of table row
+// BRC brcRight; // specification of right border of table row.
+};
+// cbTC (count of bytes of a TC) is 10(decimal), A(hex).
+
+struct WW8_TCellVer8 // wird aus der Datei gelesen
+{
+ SVBT16 aBits1Ver8; // Dokumentation siehe oben unter WW8_TCell
+ SVBT16 aUnused; // reserve
+ WW8_BRC rgbrcVer8[4]; // Dokumentation siehe oben unter WW8_TCell
+};
+// cbTC (count of bytes of a TC) is 20(decimal), 14(hex).
+
+
+struct WW8_SHD // struct SHD fehlt in der Beschreibung
+{
+private:
+ sal_uInt16 maBits;
+// sal_uInt16 nFore : 5; // 0x001f ForegroundColor
+// sal_uInt16 nBack : 5; // 0x03e0 BackgroundColor
+// sal_uInt16 nStyle : 5; // 0x7c00 Percentage and Style
+// sal_uInt16 nDontKnow : 1; // 0x8000 ??? ab Ver8: ebenfalls fuer Style
+
+public:
+ WW8_SHD() : maBits(0) {}
+
+ sal_uInt8 GetFore() const { return (sal_uInt8)( maBits & 0x1f); }
+ sal_uInt8 GetBack() const { return (sal_uInt8)((maBits >> 5 ) & 0x1f); }
+ sal_uInt8 GetStyle(bool bVer67) const
+ { return (sal_uInt8)((maBits >> 10) & ( bVer67 ? 0x1f : 0x3f ) ); }
+
+ sal_uInt16 GetValue() const { return maBits; }
+
+ void SetValue(sal_uInt16 nVal) { maBits = nVal; }
+ void SetWWValue(SVBT16 nVal) { maBits = SVBT16ToShort(nVal); }
+
+ void SetFore(sal_uInt8 nVal)
+ {
+ maBits &= 0xffe0;
+ maBits |= (nVal & 0x1f);
+ }
+ void SetBack(sal_uInt8 nVal)
+ {
+ maBits &= 0xfc1f;
+ maBits |= (nVal & 0x1f) << 5;
+ }
+ void SetStyle(bool bVer67, sal_uInt8 nVal)
+ {
+ if (bVer67)
+ {
+ maBits &= 0x83ff;
+ maBits |= (nVal & 0x1f) << 10;
+ }
+ else
+ {
+ maBits &= 0x03ff;
+ maBits |= (nVal & 0x2f) << 10;
+ }
+ }
+};
+
+struct WW8_ANLV
+{
+ SVBT8 nfc; // 0 number format code, 0=Arabic, 1=Upper case Roman, 2=Lower case Roman
+ // 3=Upper case Letter, 4=Lower case letter, 5=Ordinal
+ SVBT8 cbTextBefore; // 1 offset into anld.rgch limit of prefix text
+ SVBT8 cbTextAfter; // 2
+ SVBT8 aBits1;
+// sal_uInt8 jc : 2; // 3 : 0x03 justification code, 0=left, 1=center, 2=right, 3=left and right justify
+// sal_uInt8 fPrev : 1; // 0x04 when ==1, include previous levels
+// sal_uInt8 fHang : 1; // 0x08 when ==1, number will be displayed using a hanging indent
+// sal_uInt8 fSetBold : 1; // 0x10 when ==1, boldness of number will be determined by anld.fBold.
+// sal_uInt8 fSetItalic : 1;// 0x20 when ==1, italicness of number will be determined by anld.fItalic
+// sal_uInt8 fSetSmallCaps : 1;// 0x40 when ==1, anld.fSmallCaps will determine whether number will be displayed in small caps or not.
+// sal_uInt8 fSetCaps : 1; // 0x80 when ==1, anld.fCaps will determine whether number will be displayed capitalized or not
+ SVBT8 aBits2;
+// sal_uInt8 fSetStrike : 1;// 4 : 0x01 when ==1, anld.fStrike will determine whether the number will be displayed using strikethrough or not.
+// sal_uInt8 fSetKul : 1; // 0x02 when ==1, anld.kul will determine the underlining state of the autonumber.
+// sal_uInt8 fPrevSpace : 1;// 0x04 when ==1, autonumber will be displayed with a single prefixing space character
+// sal_uInt8 fBold : 1; // 0x08 determines boldness of autonumber when anld.fSetBold == 1.
+// sal_uInt8 fItalic : 1; // 0x10 determines italicness of autonumber when anld.fSetItalic == 1.
+// sal_uInt8 fSmallCaps : 1;// 0x20 determines whether autonumber will be displayed using small caps when anld.fSetSmallCaps == 1.
+// sal_uInt8 fCaps : 1; // 0x40 determines whether autonumber will be displayed using caps when anld.fSetCaps == 1.
+// sal_uInt8 fStrike : 1; // 0x80 determines whether autonumber will be displayed using caps when anld.fSetStrike == 1.
+ SVBT8 aBits3;
+// sal_uInt8 kul : 3; // 5 : 0x07 determines whether autonumber will be displayed with underlining when anld.fSetKul == 1.
+// sal_uInt8 ico : 5; // 0xF1 color of autonumber
+ SVBT16 ftc; // 6 font code of autonumber
+ SVBT16 hps; // 8 font half point size (or 0=auto)
+ SVBT16 iStartAt; // 0x0a starting value (0 to 65535)
+ SVBT16 dxaIndent; // 0x0c *short?* *sal_uInt16?* width of prefix text (same as indent)
+ SVBT16 dxaSpace; // 0x0e minimum space between number and paragraph
+};
+// *cbANLV (count of bytes of ANLV) is 16 (decimal), 10(hex).
+
+struct WW8_ANLD
+{
+ WW8_ANLV eAnlv; // 0
+ SVBT8 fNumber1; // 0x10 number only 1 item per table cell
+ SVBT8 fNumberAcross; // 0x11 number across cells in table rows(instead of down)
+ SVBT8 fRestartHdn; // 0x12 restart heading number on section boundary
+ SVBT8 fSpareX; // 0x13 unused( should be 0)
+ sal_uInt8 rgchAnld[32]; // 0x14 characters displayed before/after autonumber
+};
+
+struct WW8_OLST
+{
+ WW8_ANLV rganlv[9]; // 0 an array of 9 ANLV structures (heading levels)
+ SVBT8 fRestartHdr; // 0x90 when ==1, restart heading on section break
+ SVBT8 fSpareOlst2; // 0x91 reserved
+ SVBT8 fSpareOlst3; // 0x92 reserved
+ SVBT8 fSpareOlst4; // 0x93 reserved
+ sal_uInt8 rgch[64]; // 0x94 array of 64 chars text before/after number
+};
+// cbOLST is 212(decimal), D4(hex).
+
+struct WW8_FDOA
+{
+ SVBT32 fc; // 0 FC pointing to drawing object data
+ SVBT16 ctxbx; // 4 count of textboxes in the drawing object
+};
+
+struct WW8_DO
+{
+ SVBT16 dok; // 0 Drawn Object Kind, currently this is always 0
+ SVBT16 cb; // 2 size (count of bytes) of the entire DO
+ SVBT8 bx; // 4 x position relative to anchor CP
+ SVBT8 by; // 5 y position relative to anchor CP
+ SVBT16 dhgt; // 6 height of DO
+ SVBT16 aBits1;
+// sal_uInt16 fAnchorLock : 1; // 8 1 if the DO anchor is locked
+// sal_uInt8[] rgdp; // 0xa variable length array of drawing primitives
+};
+
+struct WW8_DPHEAD
+{
+ SVBT16 dpk; // 0 Drawn Primitive Kind REVIEW davebu
+ // 0=start of grouping, 1=line, 2=textbox, 3=rectangle,
+ // 4=arc, 5=elipse, 6=polyline, 7=callout textbox,
+ // 8=end of grouping, 9=sample primitve holding default values
+ SVBT16 cb; // 2 size (count of bytes) of this DP
+ SVBT16 xa; // 4 These 2 points describe the rectangle
+ SVBT16 ya; // 6 enclosing this DP relative to the origin of
+ SVBT16 dxa; // 8 the DO
+ SVBT16 dya; // 0xa
+};
+
+
+struct WW8_DP_LINETYPE
+{
+ SVBT32 lnpc; // LiNe Property Color -- RGB color value
+ SVBT16 lnpw; // line property weight in twips
+ SVBT16 lnps; // line property style : 0=Solid, 1=Dashed
+ // 2=Dotted, 3=Dash Dot, 4=Dash Dot Dot, 5=Hollow
+};
+
+struct WW8_DP_SHADOW // Schattierung!
+{
+ SVBT16 shdwpi; // Shadow Property Intensity
+ SVBT16 xaOffset; // x offset of shadow
+ SVBT16 yaOffset; // y offset of shadow
+};
+
+struct WW8_DP_FILL
+{
+ SVBT32 dlpcFg; // FiLl Property Color ForeGround -- RGB color value
+ SVBT32 dlpcBg; // Property Color BackGround -- RGB color value
+ SVBT16 flpp; // FiLl Property Pattern REVIEW davebu
+};
+
+struct WW8_DP_LINEEND
+{
+ SVBT16 aStartBits;
+// sal_uInt16 eppsStart : 2; // Start EndPoint Property Style
+ // 0=None, 1=Hollow, 2=Filled
+// sal_uInt16 eppwStart : 2; // Start EndPoint Property Weight
+// sal_uInt16 epplStart : 2; // Start EndPoint Property length
+// sal_uInt16 dummyStart : 10; // Alignment
+ SVBT16 aEndBits;
+// sal_uInt16 eppsEnd : 2; // End EndPoint Property Style
+// sal_uInt16 eppwEnd : 2; // End EndPoint Property Weight
+// sal_uInt16 epplEnd : 2; // End EndPoint Property length
+// sal_uInt16 dummyEnd : 10; // Alignment
+};
+
+struct WW8_DP_LINE
+{
+// WW8_DPHEAD dphead; // 0 Common header for a drawing primitive
+ SVBT16 xaStart; // starting point for line
+ SVBT16 yaStart; //
+ SVBT16 xaEnd; // ending point for line
+ SVBT16 yaEnd;
+ WW8_DP_LINETYPE aLnt;
+ WW8_DP_LINEEND aEpp;
+ WW8_DP_SHADOW aShd;
+};
+
+struct WW8_DP_TXTBOX
+{
+ WW8_DP_LINETYPE aLnt;
+ WW8_DP_FILL aFill;
+ WW8_DP_SHADOW aShd;
+ SVBT16 aBits1;
+// sal_uInt16 fRoundCorners : 1; //0x24 0001 1 if the textbox has rounded corners
+// sal_uInt16 zaShape : 15; // 0x24 000e REVIEW davebu
+ SVBT16 dzaInternalMargin; // 0x26 REVIEW davebu
+};
+
+struct WW8_DP_RECT
+{
+ WW8_DP_LINETYPE aLnt;
+ WW8_DP_FILL aFill;
+ WW8_DP_SHADOW aShd;
+ SVBT16 aBits1;
+// sal_uInt16 fRoundCorners : 1; // 0x24 0001 1 if the textbox has rounded corners
+// sal_uInt16 zaShape : 15; // 0x24 000e REVIEW davebu
+};
+
+struct WW8_DP_ARC
+{
+ WW8_DP_LINETYPE aLnt;
+ WW8_DP_FILL aFill;
+ WW8_DP_SHADOW aShd;
+ SVBT8 fLeft; // 0x24 00ff REVIEW davebu
+ SVBT8 fUp; // 0x24 ff00 REVIEW davebu
+// sal_uInt16 fLeft : 8; // 0x24 00ff REVIEW davebu
+// sal_uInt16 fUp : 8; // 0x24 ff00 REVIEW davebu
+};
+
+struct WW8_DP_ELIPSE
+{
+ WW8_DP_LINETYPE aLnt;
+ WW8_DP_FILL aFill;
+ WW8_DP_SHADOW aShd;
+};
+
+struct WW8_DP_POLYLINE
+{
+ WW8_DP_LINETYPE aLnt;
+ WW8_DP_FILL aFill;
+ WW8_DP_LINEEND aEpp;
+ WW8_DP_SHADOW aShd;
+ SVBT16 aBits1;
+// sal_uInt16 fPolygon : 1; // 0x28 0001 1 if this is a polygon
+// sal_uInt16 cpt : 15; // 0x28 00fe count of points
+// short xaFirst; // 0x2a These are the endpoints of the first line.
+// short yaFirst; // 0x2c
+// short xaEnd; // 0x2e
+// short yaEnd; // 0x30
+// short rgpta[]; // 0x32 An array of xa,ya pairs for the remaining points
+};
+
+struct WW8_DP_CALLOUT_TXTBOX
+{
+ SVBT16 flags; // 0x0c REVIEW davebu flags
+ SVBT16 dzaOffset; // 0x0e REVIEW davebu
+ SVBT16 dzaDescent; // 0x10 REVIEW davebu
+ SVBT16 dzaLength; // 0x12 REVIEW davebu
+ WW8_DPHEAD dpheadTxbx; // 0x14 DPHEAD for a textbox
+ WW8_DP_TXTBOX dptxbx; // 0x20 DP for a textbox
+ WW8_DPHEAD dpheadPolyLine; // 0x4c DPHEAD for a Polyline
+ WW8_DP_POLYLINE dpPolyLine; // 0x48 DP for a polyline
+};
+
+struct WW8_PCD
+{
+ SVBT8 aBits1;
+// sal_uInt8 fNoParaLast : 1; // when 1, means that piece contains no end of paragraph marks.
+// sal_uInt8 fPaphNil : 1; // used internally by Word
+// sal_uInt8 fCopied : 1; // used internally by Word
+// * int :5
+ SVBT8 aBits2; // fn int:8, used internally by Word
+ SVBT32 fc; // file offset of beginning of piece. The size of the
+ // ithpiece can be determined by subtracting rgcp[i] of
+ // the containing plcfpcd from its rgcp[i+1].
+ SVBT16 prm; // PRM contains either a single sprm or else an index number
+ // of the grpprl which contains the sprms that modify the
+ // properties of the piece.
+};
+
+// AnnoTation Refernce Descriptor (ATRD)
+struct WW8_ATRD // fuer die 8-Version
+{
+ SVBT16 xstUsrInitl[ 10 ]; // pascal-style String holding initials
+ // of annotation author
+ SVBT16 ibst; // index into GrpXstAtnOwners
+ SVBT16 ak; // not used
+ SVBT16 grfbmc; // not used
+ SVBT32 ITagBkmk; // when not -1, this tag identifies the
+ // annotation bookmark that locates the
+ // range of CPs in the main document which
+ // this annotation references.
+};
+
+struct WW8_ATRDEXTRA
+{
+ // --- Extended bit since Word 2002 --- //
+
+ SVBT32 dttm;
+ SVBT16 bf;
+ SVBT32 cDepth;
+ SVBT32 diatrdParent;
+ SVBT32 Discussitem;
+};
+
+struct WW67_ATRD // fuer die 6/7-Version
+{
+ sal_Char xstUsrInitl[ 10 ]; // pascal-style String holding initials
+ // of annotation author
+ SVBT16 ibst; // index into GrpXstAtnOwners
+ SVBT16 ak; // not used
+ SVBT16 grfbmc; // not used
+ SVBT32 ITagBkmk; // when not -1, this tag identifies the
+ // annotation bookmark that locates the
+ // range of CPs in the main document which
+ // this annotation references.
+};
+
+struct WW8_TablePos
+{
+ sal_Int16 nSp26;
+ sal_Int16 nSp27;
+ sal_Int16 nLeMgn;
+ sal_Int16 nRiMgn;
+ sal_Int16 nUpMgn;
+ sal_Int16 nLoMgn;
+ sal_uInt8 nSp29;
+ sal_uInt8 nSp37;
+};
+
+struct WW8_FSPA
+{
+public:
+ sal_Int32 nSpId; //Shape Identifier. Used in conjunction with the office art data (found via fcDggInfo in the FIB) to find the actual data for this shape.
+ sal_Int32 nXaLeft; //left of rectangle enclosing shape relative to the origin of the shape
+ sal_Int32 nYaTop; //top of rectangle enclosing shape relative to the origin of the shape
+ sal_Int32 nXaRight; //right of rectangle enclosing shape relative to the origin of the shape
+ sal_Int32 nYaBottom;//bottom of the rectangle enclosing shape relative to the origin of the shape
+ sal_uInt16 bHdr:1;
+ //0001 1 in the undo doc when shape is from the header doc, 0 otherwise (undefined when not in the undo doc)
+ sal_uInt16 nbx:2;
+ //0006 x position of shape relative to anchor CP
+ //0 relative to page margin
+ //1 relative to top of page
+ //2 relative to text (column for horizontal text; paragraph for vertical text)
+ //3 reserved for future use
+ sal_uInt16 nby:2;
+ //0018 y position of shape relative to anchor CP
+ //0 relative to page margin
+ //1 relative to top of page
+ //2 relative to text (paragraph for horizontal text; column for vertical text)
+ sal_uInt16 nwr:4;
+ //01E0 text wrapping mode
+ //0 like 2, but doesn't require absolute object
+ //1 no text next to shape
+ //2 wrap around absolute object
+ //3 wrap as if no object present
+ //4 wrap tightly around object
+ //5 wrap tightly, but allow holes
+ //6-15 reserved for future use
+ sal_uInt16 nwrk:4;
+ //1E00 text wrapping mode type (valid only for wrapping modes 2 and 4
+ //0 wrap both sides
+ //1 wrap only on left
+ //2 wrap only on right
+ //3 wrap only on largest side
+ sal_uInt16 bRcaSimple:1;
+ //2000 when set, temporarily overrides bx, by, forcing the xaLeft, xaRight, yaTop, and yaBottom fields to all be page relative.
+ sal_uInt16 bBelowText:1;
+ //4000
+ //1 shape is below text
+ //0 shape is above text
+ sal_uInt16 bAnchorLock:1;
+ //8000 1 anchor is locked
+ // 0 anchor is not locked
+ sal_Int32 nTxbx; //count of textboxes in shape (undo doc only)
+public:
+ enum FSPAOrient {RelPgMargin, RelPageBorder, RelText};
+};
+
+
+struct WW8_FSPA_SHADOW // alle Member an gleicher Position und Groesse,
+{ // wegen: pF = (WW8_FSPA*)pFS;
+ SVBT32 nSpId;
+ SVBT32 nXaLeft;
+ SVBT32 nYaTop;
+ SVBT32 nXaRight;
+ SVBT32 nYaBottom;
+ SVBT16 aBits1;
+ SVBT32 nTxbx;
+};
+
+struct WW8_TXBXS
+{
+ SVBT32 cTxbx_iNextReuse;
+ SVBT32 cReusable;
+ SVBT16 fReusable;
+ SVBT32 reserved;
+ SVBT32 ShapeId;
+ SVBT32 txidUndo;
+};
+
+struct WW8_STRINGID
+{
+ // M.M. This is the extra data stored in the SttbfFnm
+ // For now I only need the String Id
+ SVBT16 nStringId;
+ SVBT16 reserved1;
+ SVBT16 reserved2;
+ SVBT16 reserved3;
+};
+
+struct WW8_WKB
+{
+ // M.M. This is the WkbPLCF struct
+ // For now I only need the Link Id
+ SVBT16 reserved1;
+ SVBT16 reserved2;
+ SVBT16 reserved3;
+ SVBT16 nLinkId;
+ SVBT16 reserved4;
+ SVBT16 reserved5;
+};
+
+#ifdef SAL_W32
+# pragma pack(pop)
+#elif defined(SAL_OS2)
+# pragma pack()
+#endif
+
+struct SEPr
+{
+ SEPr();
+ sal_uInt8 bkc;
+ sal_uInt8 fTitlePage;
+ sal_Int8 fAutoPgn;
+ sal_uInt8 nfcPgn;
+ sal_uInt8 fUnlocked;
+ sal_uInt8 cnsPgn;
+ sal_uInt8 fPgnRestart;
+ sal_uInt8 fEndNote;
+ sal_Int8 lnc;
+ sal_Int8 grpfIhdt;
+ sal_uInt16 nLnnMod;
+ sal_Int32 dxaLnn;
+ sal_Int16 dxaPgn;
+ sal_Int16 dyaPgn;
+ sal_Int8 fLBetween;
+ sal_Int8 vjc;
+ sal_uInt16 dmBinFirst;
+ sal_uInt16 dmBinOther;
+ sal_uInt16 dmPaperReq;
+/*
+ 28 1C brcTop BRC top page border
+
+ 32 20 brcLeft BRC left page border
+
+ 36 24 brcBottom BRC bottom page border
+
+ 40 28 brcRight BRC right page border
+*/
+ sal_Int16 fPropRMark;
+ sal_Int16 ibstPropRMark;
+ sal_Int32 dttmPropRMark; //DTTM
+ sal_Int32 dxtCharSpace;
+ sal_Int32 dyaLinePitch;
+ sal_uInt16 clm;
+ sal_Int16 reserved1;
+ sal_uInt8 dmOrientPage;
+ sal_uInt8 iHeadingPgn;
+ sal_uInt16 pgnStart;
+ sal_Int16 lnnMin;
+ sal_uInt16 wTextFlow;
+ sal_Int16 reserved2;
+ sal_uInt16 pgbApplyTo:3;
+ sal_uInt16 pgbPageDepth:2;
+ sal_Int16 pgbOffsetFrom:3;
+ sal_Int16 :8;
+ sal_uInt32 xaPage;
+ sal_uInt32 yaPage;
+ sal_uInt32 xaPageNUp;
+ sal_uInt32 yaPageNUp;
+ sal_uInt32 dxaLeft;
+ sal_uInt32 dxaRight;
+ sal_Int32 dyaTop;
+ sal_Int32 dyaBottom;
+ sal_uInt32 dzaGutter;
+ sal_uInt32 dyaHdrTop;
+ sal_uInt32 dyaHdrBottom;
+ sal_Int16 ccolM1;
+ sal_Int8 fEvenlySpaced;
+ sal_Int8 reserved3;
+ sal_uInt8 fBiDi;
+ sal_uInt8 fFacingCol;
+ sal_uInt8 fRTLGutter;
+ sal_uInt8 fRTLAlignment;
+ sal_Int32 dxaColumns;
+ sal_Int32 rgdxaColumnWidthSpacing[89];
+ sal_Int32 dxaColumnWidth;
+ sal_uInt8 dmOrientFirst;
+ sal_uInt8 fLayout;
+ sal_Int16 reserved4;
+};
+
+namespace wwUtility
+{
+ sal_uInt32 BGRToRGB(sal_uInt32 nColour);
+ inline sal_uInt32 RGBToBGR(sal_uInt32 nColour) { return BGRToRGB(nColour); }
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8toolbar.cxx b/sw/source/filter/ww8/ww8toolbar.cxx
new file mode 100644
index 000000000000..0f4a644989e8
--- /dev/null
+++ b/sw/source/filter/ww8/ww8toolbar.cxx
@@ -0,0 +1,1332 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Initial Developer of the Original Code is
+ * Noel Power <noel.power@novell.com>
+ * Portions created by the Initial Developer are Copyright (C) 2010 the
+ * Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Noel Power <noel.power@novell.com>
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+#include "ww8toolbar.hxx"
+#include <rtl/ustrbuf.hxx>
+#include <stdarg.h>
+#include <com/sun/star/ui/XUIConfigurationPersistence.hpp>
+#include <com/sun/star/ui/XModuleUIConfigurationManagerSupplier.hpp>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleComponentFactory.hpp>
+#include <com/sun/star/lang/XMultiComponentFactory.hpp>
+#include <com/sun/star/ui/XImageManager.hpp>
+#include <com/sun/star/ui/ItemType.hpp>
+#include <fstream>
+#include <comphelper/processfactory.hxx>
+#include <vcl/graph.hxx>
+#include <map>
+using namespace com::sun::star;
+
+// no. of visual data elements in a CTB ( fixed )
+const short nVisualData = 5;
+
+typedef std::map< sal_Int16, rtl::OUString > IdToString;
+
+class MSOWordCommandConvertor : public MSOCommandConvertor
+{
+ IdToString msoToOOcmd;
+ IdToString tcidToOOcmd;
+public:
+ MSOWordCommandConvertor();
+ virtual rtl::OUString MSOCommandToOOCommand( sal_Int16 msoCmd );
+ virtual rtl::OUString MSOTCIDToOOCommand( sal_Int16 key );
+};
+
+MSOWordCommandConvertor::MSOWordCommandConvertor()
+{
+ // mso command id to ooo command string
+ // #FIXME and *HUNDREDS* of id's to added here
+ msoToOOcmd[ 0x20b ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".uno:CloseDoc") );
+ msoToOOcmd[ 0x50 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".uno:Open") );
+
+ // mso tcid to ooo command string
+ // #FIXME and *HUNDREDS* of id's to added here
+ tcidToOOcmd[ 0x9d9 ] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(".uno:Print") );
+}
+
+rtl::OUString MSOWordCommandConvertor::MSOCommandToOOCommand( sal_Int16 key )
+{
+ rtl::OUString sResult;
+ IdToString::iterator it = msoToOOcmd.find( key );
+ if ( it != msoToOOcmd.end() )
+ sResult = it->second;
+ return sResult;
+}
+
+rtl::OUString MSOWordCommandConvertor::MSOTCIDToOOCommand( sal_Int16 key )
+{
+ rtl::OUString sResult;
+ IdToString::iterator it = tcidToOOcmd.find( key );
+ if ( it != tcidToOOcmd.end() )
+ sResult = it->second;
+ return sResult;
+}
+
+
+CTBWrapper::CTBWrapper( bool bReadId ) : Tcg255SubStruct( bReadId )
+,reserved2(0)
+,reserved3(0)
+,reserved4(0)
+,reserved5(0)
+,cbTBD(0)
+,cCust(0)
+,cbDTBC(0)
+,rtbdc(0)
+{
+}
+
+CTBWrapper::~CTBWrapper()
+{
+}
+
+Customization* CTBWrapper::GetCustomizaton( sal_Int16 index )
+{
+ if ( index < 0 || index >= static_cast<sal_Int16>( rCustomizations.size() ) )
+ return NULL;
+ return &rCustomizations[ index ];
+}
+
+CTB* CTBWrapper::GetCustomizationData( const rtl::OUString& sTBName )
+{
+ CTB* pCTB = NULL;
+ for ( std::vector< Customization >::iterator it = rCustomizations.begin(); it != rCustomizations.end(); ++it )
+ {
+ if ( it->GetCustomizationData() && it->GetCustomizationData()->GetName().equals( sTBName ) )
+ {
+ pCTB = it->GetCustomizationData();
+ break;
+ }
+ }
+ return pCTB;
+}
+
+bool CTBWrapper::Read( SvStream* pS )
+{
+ OSL_TRACE("CTBWrapper::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ Tcg255SubStruct::Read( pS );
+ *pS >> reserved2 >> reserved3 >> reserved4 >> reserved5;
+ *pS >> cbTBD >> cCust >> cbDTBC;
+ long nExpectedPos = pS->Tell() + cbDTBC;
+ if ( cbDTBC )
+ {
+ // cbDTBC is the size in bytes of the TBC array
+ // but the size of a TBC element is dynamic ( and this relates to TBDelta's
+ int nStart = pS->Tell();
+
+ int bytesRead = 0;
+ int bytesToRead = cbDTBC - bytesRead;
+ // cbDTBC specifies the size ( in bytes ) taken by an array ( of unspecified size )
+ // of TBC records ( TBC records have dynamic length, so we need to check our position
+ // after each read )
+ do
+ {
+ TBC aTBC;
+ if ( !aTBC.Read( pS ) )
+ return false;
+ rtbdc.push_back( aTBC );
+ bytesToRead = cbDTBC - ( pS->Tell() - nStart );
+ } while ( bytesToRead > 0 );
+ }
+ if ( static_cast< long >( pS->Tell() ) != nExpectedPos )
+ {
+ // Strange error condition, shouldn't happen ( but does in at least
+ // one test document ) In the case where it happens the TBC &
+ // TBCHeader records seem blank??? ( and incorrect )
+ OSL_ENSURE( static_cast< long >(pS->Tell()) == nExpectedPos, "### Error: Expected pos not equal to actual pos after reading rtbdc");
+ OSL_TRACE("\tPos now is 0x%x should be 0x%x", pS->Tell(), nExpectedPos );
+ // seek to correct position after rtbdc
+ pS->Seek( nExpectedPos );
+ }
+ if ( cCust )
+ {
+ for ( sal_Int32 index = 0; index < cCust; ++index )
+ {
+ Customization aCust( this );
+ if ( !aCust.Read( pS ) )
+ return false;
+ rCustomizations.push_back( aCust );
+ }
+ }
+ std::vector< sal_Int16 >::iterator it_end = dropDownMenuIndices.end();
+ for ( std::vector< sal_Int16 >::iterator it = dropDownMenuIndices.begin(); it != it_end; ++it )
+ {
+ rCustomizations[ *it ].bIsDroppedMenuTB = true;
+ }
+ return true;
+}
+
+TBC* CTBWrapper::GetTBCAtOffset( sal_uInt32 nStreamOffset )
+{
+ for ( std::vector< TBC >::iterator it = rtbdc.begin(); it != rtbdc.end(); ++it )
+ {
+ if ( (*it).GetOffset() == nStreamOffset )
+ return &(*it);
+ }
+ return NULL;
+}
+
+void CTBWrapper::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp,"[ 0x%x ] CTBWrapper - dump\n", nOffSet );
+ bool bRes = ( ch == 0x12 && reserved2 == 0x0 && reserved3 == 0x7 && reserved4 == 0x6 && reserved5 == 0xC );
+ if ( bRes )
+ indent_printf(fp," sanity check ( first 8 bytes conform )\n");
+ else
+ {
+ indent_printf(fp," reserved1(0x%x)\n",ch);
+ indent_printf(fp," reserved2(0x%x)\n",reserved2);
+ indent_printf(fp," reserved3(0x%x)\n",reserved3);
+ indent_printf(fp," reserved4(0x%x)\n",reserved4);
+ indent_printf(fp," reserved5(0x%x)\n",reserved5);
+ indent_printf(fp,"Quiting dump");
+ return;
+ }
+ indent_printf(fp," size of TBDelta structures 0x%x\n", cbTBD );
+ indent_printf(fp," cCust: no. of cCust structures 0x%x\n",cCust);
+ indent_printf(fp," cbDTBC: no. of bytes in rtbdc array 0x%x\n", static_cast< unsigned int >( cbDTBC ));
+
+ sal_Int32 index = 0;
+
+ for ( std::vector< TBC >::iterator it = rtbdc.begin(); it != rtbdc.end(); ++it, ++index )
+ {
+ indent_printf(fp," Dumping rtbdc[%d]\n", static_cast< int >( index ));
+ Indent b;
+ it->Print( fp );
+ }
+
+ index = 0;
+
+ for ( std::vector< Customization >::iterator it = rCustomizations.begin(); it != rCustomizations.end(); ++it, ++index )
+ {
+ indent_printf(fp," Dumping custimization [%d]\n", static_cast< int >( index ));
+ Indent c;
+ it->Print(fp);
+ }
+}
+
+bool CTBWrapper::ImportCustomToolBar( SfxObjectShell& rDocSh )
+{
+ for ( std::vector< Customization >::iterator it = rCustomizations.begin(); it != rCustomizations.end(); ++it )
+ {
+ uno::Reference< lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
+ uno::Reference< ui::XModuleUIConfigurationManagerSupplier > xAppCfgSupp( xMSF->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.ModuleUIConfigurationManagerSupplier" ) ) ), uno::UNO_QUERY_THROW );
+ CustomToolBarImportHelper helper( rDocSh, xAppCfgSupp->getUIConfigurationManager( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextDocument" ) ) ) );
+ helper.setMSOCommandMap( new MSOWordCommandConvertor() );
+
+ if ( !(*it).ImportCustomToolBar( *this, helper ) )
+ return false;
+ }
+ return false;
+}
+
+Customization::Customization( CTBWrapper* wrapper ) : tbidForTBD( 0 )
+,reserved1( 0 )
+, ctbds( 0 )
+, pWrapper( wrapper )
+, bIsDroppedMenuTB( false )
+{
+}
+
+Customization::~Customization()
+{
+}
+
+bool Customization::Read( SvStream *pS)
+{
+ OSL_TRACE("Custimization::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ *pS >> tbidForTBD >> reserved1 >> ctbds;
+ if ( tbidForTBD )
+ {
+ for ( sal_Int32 index = 0; index < ctbds; ++index )
+ {
+ TBDelta aTBDelta;
+ if (!aTBDelta.Read( pS ) )
+ return false;
+ customizationDataTBDelta.push_back( aTBDelta );
+ // Only set the drop down for menu's associated with standard toolbar
+ if ( aTBDelta.ControlDropsToolBar() && tbidForTBD == 0x25 )
+ pWrapper->InsertDropIndex( aTBDelta.CustomizationIndex() );
+ }
+ }
+ else
+ {
+ customizationDataCTB.reset( new CTB() );
+ if ( !customizationDataCTB->Read( pS ) )
+ return false;
+ }
+ return true;
+}
+
+void Customization::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp,"[ 0x%x ] Customization -- dump \n", nOffSet );
+ indent_printf( fp," tbidForTBD 0x%x ( should be 0 for CTBs )\n", static_cast< unsigned int >( tbidForTBD ));
+ indent_printf( fp," reserved1 0x%x \n", reserved1);
+ indent_printf( fp," ctbds - number of customisations %d(0x%x) \n", ctbds, ctbds );
+ if ( !tbidForTBD && !ctbds )
+ customizationDataCTB->Print( fp );
+ else
+ {
+ const char* pToolBar = NULL;
+ switch ( tbidForTBD )
+ {
+ case 0x9:
+ pToolBar = "Standard";
+ break;
+ case 0x25:
+ pToolBar = "Builtin-Menu";
+ break;
+ default:
+ pToolBar = "Unknown toolbar";
+ break;
+ }
+
+ indent_printf( fp," TBDelta(s) are associated with %s toolbar.\n", pToolBar);
+ std::vector< TBDelta >::iterator it = customizationDataTBDelta.begin();
+ for ( sal_Int32 index = 0; index < ctbds; ++it,++index )
+ it->Print( fp );
+ }
+
+}
+
+bool Customization::ImportMenu( CTBWrapper& rWrapper, CustomToolBarImportHelper& helper )
+{
+ if ( tbidForTBD == 0x25 ) // we can handle in a limited way additions the built-in menu bar
+ {
+ for ( std::vector< TBDelta >::iterator it = customizationDataTBDelta.begin(); it != customizationDataTBDelta.end(); ++it )
+ {
+ // for each new menu ( control that drops a toolbar )
+ // import a toolbar
+ if ( it->ControlIsInserted() && it->ControlDropsToolBar() )
+ {
+ Customization* pCust = pWrapper->GetCustomizaton( it->CustomizationIndex() );
+ if ( pCust )
+ {
+ // currently only support built-in menu
+ rtl::OUString sMenuBar( RTL_CONSTASCII_USTRINGPARAM("private:resource/menubar/") );
+
+ sMenuBar = sMenuBar.concat( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("menubar") ) );
+ // Get menu name
+ TBC* pTBC = pWrapper->GetTBCAtOffset( it->TBCStreamOffset() );
+ if ( !pTBC )
+ return false;
+ rtl::OUString sMenuName = pTBC->GetCustomText();
+ sMenuName = sMenuName.replace('&','~');
+
+ // see if the document has already setting for the menubar
+
+ uno::Reference< container::XIndexContainer > xIndexContainer;
+ bool bHasSettings = false;
+ if ( helper.getCfgManager()->hasSettings( sMenuBar ) )
+ {
+ xIndexContainer.set( helper.getCfgManager()->getSettings( sMenuBar, sal_True ), uno::UNO_QUERY_THROW );
+ bHasSettings = true;
+ }
+ else
+ {
+ if ( helper.getAppCfgManager()->hasSettings( sMenuBar ) )
+ xIndexContainer.set( helper.getAppCfgManager()->getSettings( sMenuBar, sal_True ), uno::UNO_QUERY_THROW );
+ else
+ xIndexContainer.set( helper.getAppCfgManager()->createSettings(), uno::UNO_QUERY_THROW );
+ }
+
+ uno::Reference< lang::XSingleComponentFactory > xSCF( xIndexContainer, uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
+ uno::Reference< uno::XComponentContext > xContext( xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ))), uno::UNO_QUERY_THROW );
+ // create the popup menu
+ uno::Sequence< beans::PropertyValue > aPopupMenu( 4 );
+ aPopupMenu[0].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("CommandURL") );
+ aPopupMenu[0].Value = uno::makeAny( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("vnd.openoffice.org:") ) + sMenuName );
+ aPopupMenu[1].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Label") );
+ aPopupMenu[1].Value <<= sMenuName;
+ aPopupMenu[2].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Type" ) );
+ aPopupMenu[2].Value <<= sal_Int32( 0 );
+ aPopupMenu[3].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ItemDescriptorContainer") );
+ uno::Reference< container::XIndexContainer > xMenuContainer( xSCF->createInstanceWithContext( xContext ), uno::UNO_QUERY_THROW );
+ aPopupMenu[3].Value <<= xMenuContainer;
+ if ( pCust->customizationDataCTB.get() && !pCust->customizationDataCTB->ImportMenuTB( rWrapper, xMenuContainer, helper ) )
+ return false;
+ OSL_TRACE("** there are %d menu items on the bar, inserting after that", xIndexContainer->getCount() );
+ xIndexContainer->insertByIndex( xIndexContainer->getCount(), uno::makeAny( aPopupMenu ) );
+
+ if ( bHasSettings )
+ helper.getCfgManager()->replaceSettings( sMenuBar, uno::Reference< container::XIndexAccess >( xIndexContainer, uno::UNO_QUERY_THROW ) );
+ else
+ helper.getCfgManager()->insertSettings( sMenuBar, uno::Reference< container::XIndexAccess >( xIndexContainer, uno::UNO_QUERY_THROW ) );
+ uno::Reference< ui::XUIConfigurationPersistence > xPersistence( helper.getCfgManager(), uno::UNO_QUERY_THROW );
+ xPersistence->store();
+ }
+ }
+ }
+ return true;
+ }
+ return true;
+}
+
+bool Customization::ImportCustomToolBar( CTBWrapper& rWrapper, CustomToolBarImportHelper& helper )
+{
+ if ( GetTBIDForTB() == 0x25 )
+ return ImportMenu( rWrapper, helper );
+ if ( !customizationDataCTB.get() )
+ return false;
+ if ( !customizationDataCTB->IsMenuToolbar() )
+ {
+ if ( !customizationDataCTB->ImportCustomToolBar( rWrapper, helper ) )
+ return false;
+ }
+ return true;
+}
+
+TBDelta::TBDelta() : doprfatendFlags(0)
+,ibts(0)
+,cidNext(0)
+,cid(0)
+,fc(0)
+,cbTBC(0)
+{
+}
+
+bool TBDelta::ControlIsModified()
+{
+ return ( ( doprfatendFlags & 0x3 ) == 0x2 );
+}
+
+bool TBDelta::ControlIsInserted()
+{
+ return ( ( doprfatendFlags & 0x3 ) == 0x1 );
+}
+
+bool TBDelta::ControlIsChanged()
+{
+ return ( ( doprfatendFlags & 0x3 ) == 0x1 );
+}
+
+bool TBDelta::ControlDropsToolBar()
+{
+ return !( CiTBDE & 0x8000 );
+}
+
+sal_Int32 TBDelta::TBCStreamOffset()
+{
+ return fc;
+}
+
+sal_Int16 TBDelta::CustomizationIndex()
+{
+ sal_Int16 nIndex = CiTBDE;
+ nIndex = nIndex >> 1;
+ nIndex &= 0x1ff; // only 13 bits are relevant
+ return nIndex;
+}
+
+bool TBDelta::Read(SvStream *pS)
+{
+ OSL_TRACE("TBDelta::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ *pS >> doprfatendFlags >> ibts >> cidNext >> cid >> fc ;
+ *pS >> CiTBDE >> cbTBC;
+ return true;
+}
+
+void TBDelta::Print( FILE* fp )
+{
+ // Like most of the debug output, it's raw and little ( no )
+ // interpretation of the data is output ( e.g. flag values etc. )
+ indent_printf( fp, "[ 0x%x ] TBDelta -- dump\n", nOffSet );
+ indent_printf( fp, " doprfatendFlags 0x%x\n",doprfatendFlags );
+
+ indent_printf( fp, " ibts 0x%x\n",ibts );
+ indent_printf( fp, " cidNext 0x%x\n", static_cast< unsigned int >( cidNext ) );
+ indent_printf( fp, " cid 0x%x\n", static_cast< unsigned int >( cid ) );
+ indent_printf( fp, " fc 0x%x\n", static_cast< unsigned int >( fc ) );
+ indent_printf( fp, " CiTBDE 0x%x\n",CiTBDE );
+ indent_printf( fp, " cbTBC 0x%x\n", cbTBC );
+ if ( ControlDropsToolBar() )
+ {
+ indent_printf( fp, " this delta is associated with a control that drops a menu toolbar\n", cbTBC );
+ indent_printf( fp, " the menu toolbar drops the toolbar defined at index[%d] in the rCustomizations array of the CTBWRAPPER that contains this TBDelta\n", CustomizationIndex() );
+ }
+}
+
+CTB::CTB() : cbTBData( 0 )
+,iWCTBl( 0 )
+,reserved( 0 )
+,unused( 0 )
+,cCtls( 0 )
+{
+}
+
+CTB::~CTB()
+{
+}
+
+bool CTB::IsMenuToolbar()
+{
+ return tb.IsMenuToolbar();
+}
+
+
+bool CTB::Read( SvStream *pS)
+{
+ OSL_TRACE("CTB::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ if ( !name.Read( pS ) )
+ return false;
+ *pS >> cbTBData;
+ if ( !tb.Read( pS ) )
+ return false;
+ for ( short index = 0; index < nVisualData; ++index )
+ {
+ TBVisualData aVisData;
+ aVisData.Read( pS );
+ rVisualData.push_back( aVisData );
+ }
+
+ *pS >> iWCTBl >> reserved >> unused >> cCtls;
+
+ if ( cCtls )
+ {
+ for ( sal_Int32 index = 0; index < cCtls; ++index )
+ {
+ TBC aTBC;
+ if ( !aTBC.Read( pS ) )
+ return false;
+ rTBC.push_back( aTBC );
+ }
+ }
+ return true;
+}
+
+void
+CTB::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp, "[ 0x%x ] CTB - dump\n", nOffSet );
+ indent_printf(fp, " name %s\n", rtl::OUStringToOString( name.getString(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ indent_printf(fp, " cbTBData size, in bytes, of this structure excluding the name, cCtls, and rTBC fields. %x\n", static_cast< unsigned int >( cbTBData ) );
+
+ tb.Print(fp);
+ for ( short counter = 0; counter < nVisualData; ++counter )
+ {
+ indent_printf( fp, " TBVisualData [%d]\n", counter);
+ Indent b;
+ rVisualData[ counter ].Print( fp );
+ }
+ indent_printf(fp, " iWCTBl 0x%x reserved 0x%x unused 0x%x cCtls( toolbar controls ) 0x%x \n", static_cast< unsigned int >( iWCTBl ), reserved, unused, static_cast< unsigned int >( cCtls ) );
+ if ( cCtls )
+ {
+ for ( sal_Int32 index = 0; index < cCtls; ++index )
+ {
+
+ indent_printf(fp, " dumping toolbar control 0x%x\n", static_cast< unsigned int >( index ) );
+ rTBC[ index ].Print( fp );
+ }
+ }
+}
+
+bool CTB::ImportCustomToolBar( CTBWrapper& rWrapper, CustomToolBarImportHelper& helper )
+{
+ static rtl::OUString sToolbarPrefix( RTL_CONSTASCII_USTRINGPARAM( "private:resource/toolbar/custom_" ) );
+ bool bRes = false;
+ try
+ {
+ if ( !tb.IsEnabled() )
+ return true; // didn't fail, just ignoring
+ // Create default setting
+ uno::Reference< container::XIndexContainer > xIndexContainer( helper.getCfgManager()->createSettings(), uno::UNO_QUERY_THROW );
+ uno::Reference< container::XIndexAccess > xIndexAccess( xIndexContainer, uno::UNO_QUERY_THROW );
+ uno::Reference< beans::XPropertySet > xProps( xIndexContainer, uno::UNO_QUERY_THROW );
+
+ // set UI name for toolbar
+ xProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("UIName") ), uno::makeAny( name.getString() ) );
+
+ rtl::OUString sToolBarName = sToolbarPrefix.concat( name.getString() );
+ for ( std::vector< TBC >::iterator it = rTBC.begin(); it != rTBC.end(); ++it )
+ {
+ // createToolBar item for control
+ if ( !it->ImportToolBarControl( rWrapper, xIndexContainer, helper, IsMenuToolbar() ) )
+ return false;
+ }
+
+ OSL_TRACE("Name of toolbar :-/ %s", rtl::OUStringToOString( sToolBarName, RTL_TEXTENCODING_UTF8 ).getStr() );
+
+ helper.getCfgManager()->insertSettings( sToolBarName, xIndexAccess );
+ helper.applyIcons();
+#if 1 // don't think this is necessary
+ uno::Reference< ui::XUIConfigurationPersistence > xPersistence( helper.getCfgManager()->getImageManager(), uno::UNO_QUERY_THROW );
+ xPersistence->store();
+
+ xPersistence.set( helper.getCfgManager(), uno::UNO_QUERY_THROW );
+ xPersistence->store();
+#endif
+ bRes = true;
+ }
+ catch( uno::Exception& e )
+ {
+ OSL_TRACE("***** For some reason we have an exception %s", rtl::OUStringToOString( e.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
+ bRes = false;
+ }
+ return bRes;
+}
+
+bool CTB::ImportMenuTB( CTBWrapper& rWrapper, const css::uno::Reference< css::container::XIndexContainer >& xIndexContainer, CustomToolBarImportHelper& rHelper )
+{
+ for ( std::vector< TBC >::iterator it = rTBC.begin(); it != rTBC.end(); ++it )
+ {
+ // createToolBar item for control
+ if ( !it->ImportToolBarControl( rWrapper, xIndexContainer, rHelper, true ) )
+ return false;
+ }
+ return true;
+}
+
+TBC::TBC()
+{
+}
+
+TBC::~TBC()
+{
+}
+
+bool TBC::Read( SvStream *pS )
+{
+ OSL_TRACE("TBC::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ if ( !tbch.Read( pS ) )
+ return false;
+ if ( tbch.getTcID() != 0x1 && tbch.getTcID() != 0x1051 )
+ {
+ cid.reset( new sal_uInt32 );
+ *pS >> *cid;
+ }
+ // MUST exist if tbch.tct is not equal to 0x16
+ if ( tbch.getTct() != 0x16 )
+ {
+ tbcd.reset( new TBCData( tbch ) );
+ if ( !tbcd->Read( pS ) )
+ return false;
+ }
+ return true;
+}
+
+void TBC::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp,"[ 0x%x ] TBC -- dump\n", nOffSet );
+ indent_printf(fp," dumping header ( TBCHeader )\n");
+ tbch.Print( fp );
+ if ( cid.get() )
+ indent_printf(fp," cid = 0x%x\n", static_cast< unsigned int >( *cid ) );
+ if ( tbcd.get() )
+ {
+ indent_printf(fp," dumping toolbar data TBCData \n");
+ tbcd->Print(fp);
+ }
+}
+
+bool
+TBC::ImportToolBarControl( CTBWrapper& rWrapper, const css::uno::Reference< css::container::XIndexContainer >& toolbarcontainer, CustomToolBarImportHelper& helper, bool bIsMenuBar )
+{
+ // cmtFci 0x1 Command based on a built-in command. See CidFci.
+ // cmtMacro 0x2 Macro command. See CidMacro.
+ // cmtAllocated 0x3 Allocated command. See CidAllocated.
+ // cmtNil 0x7 No command. See Cid.
+ bool bBuiltin = false;
+ sal_uInt16 cmdId = 0;
+ if ( cid.get() )
+ {
+ sal_uInt16 arg2 = ( *( cid.get() ) & 0xFFFF );
+
+ sal_uInt8 cmt = ( arg2 & 0x7 );
+ arg2 = ( arg2 >> 3 );
+
+ switch ( cmt )
+ {
+ case 1:
+ OSL_TRACE("cmt is cmtFci builtin command 0x%x", arg2);
+ bBuiltin = true;
+ cmdId = arg2;
+ break;
+ case 2:
+ OSL_TRACE("cmt is cmtMacro macro 0x%x", arg2);
+ break;
+ case 3:
+ OSL_TRACE("cmt is cmtAllocated [???] 0x%x", arg2);
+ break;
+ case 7:
+ OSL_TRACE("cmt is cmNill no-phing 0x%x", arg2);
+ break;
+ default:
+ OSL_TRACE("illegal 0x%x", cmt);
+ break;
+ }
+ }
+
+ if ( tbcd.get() )
+ {
+ std::vector< css::beans::PropertyValue > props;
+ if ( bBuiltin )
+ {
+ rtl::OUString sCommand = helper.MSOCommandToOOCommand( cmdId );
+ if ( sCommand.getLength() > 0 )
+ {
+ beans::PropertyValue aProp;
+
+ aProp.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("CommandURL") );
+ aProp.Value <<= sCommand;
+ props.push_back( aProp );
+ }
+ }
+ bool bBeginGroup = false;
+ if ( ! tbcd->ImportToolBarControl( helper, props, bBeginGroup, bIsMenuBar ) )
+ return false;
+
+ TBCMenuSpecific* pMenu = tbcd->getMenuSpecific();
+ if ( pMenu )
+ {
+ OSL_TRACE("** control has a menu, name of toolbar with menu items is %s", rtl::OUStringToOString( pMenu->Name(), RTL_TEXTENCODING_UTF8 ).getStr() );
+ // search for CTB with the appropriate name ( it contains the
+ // menu items, although we cannot import ( or create ) a menu on
+ // a custom toolbar we can import the menu items in a separate
+ // toolbar ( better than nothing )
+ CTB* pCustTB = rWrapper.GetCustomizationData( pMenu->Name() );
+ if ( pCustTB )
+ {
+ uno::Reference< container::XIndexContainer > xMenuDesc;
+ uno::Reference< lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY_THROW );
+ xMenuDesc.set( xMSF->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.document.IndexedPropertyValues" ) ) ), uno::UNO_QUERY_THROW );
+ if ( !pCustTB->ImportMenuTB( rWrapper,xMenuDesc, helper ) )
+ return false;
+ if ( !bIsMenuBar )
+ {
+ if ( !helper.createMenu( pMenu->Name(), uno::Reference< container::XIndexAccess >( xMenuDesc, uno::UNO_QUERY ), true ) )
+ return false;
+ }
+ else
+ {
+ beans::PropertyValue aProp;
+ aProp.Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ItemDescriptorContainer") );
+ aProp.Value <<= xMenuDesc;
+ props.push_back( aProp );
+ }
+ }
+ }
+
+ if ( bBeginGroup )
+ {
+ // insert spacer
+ uno::Sequence< beans::PropertyValue > sProps( 1 );
+ sProps[ 0 ].Name = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Type") );
+ sProps[ 0 ].Value = uno::makeAny( ui::ItemType::SEPARATOR_LINE );
+ toolbarcontainer->insertByIndex( toolbarcontainer->getCount(), uno::makeAny( sProps ) );
+ }
+
+ uno::Sequence< beans::PropertyValue > sProps( props.size() );
+ beans::PropertyValue* pProp = sProps.getArray();
+
+ for ( std::vector< css::beans::PropertyValue >::iterator it = props.begin(); it != props.end(); ++it, ++pProp )
+ *pProp = *it;
+
+ toolbarcontainer->insertByIndex( toolbarcontainer->getCount(), uno::makeAny( sProps ) );
+ }
+ return true;
+}
+
+rtl::OUString
+TBC::GetCustomText()
+{
+ rtl::OUString sCustomText;
+ if ( tbcd.get() )
+ sCustomText = tbcd->getGeneralInfo().CustomText();
+ return sCustomText;
+
+
+}
+
+bool
+Xst::Read( SvStream* pS )
+{
+ OSL_TRACE("Xst::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ sal_Int16 nChars = 0;
+ *pS >> nChars;
+ sString = readUnicodeString( pS, static_cast< sal_Int32 >( nChars ) );
+ return true;
+}
+
+void
+Xst::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp, "[ 0x%x ] Xst -- dump\n", nOffSet );
+ indent_printf( fp, " %s", rtl::OUStringToOString( sString, RTL_TEXTENCODING_UTF8 ).getStr() );
+}
+
+Tcg::Tcg() : nTcgVer( 255 )
+{
+}
+
+bool Tcg::Read(SvStream *pS)
+{
+ OSL_TRACE("Tcg::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ *pS >> nTcgVer;
+ if ( nTcgVer != (sal_Int8)255 )
+ return false;
+ tcg.reset( new Tcg255() );
+ return tcg->Read( pS );
+}
+
+void Tcg::Print( FILE* fp )
+{
+ Indent a(true);
+ indent_printf(fp, "[ 0x%x ] Tcg - dump %d\n", nOffSet, nTcgVer);
+ indent_printf(fp," nTcgVer %d\n", nTcgVer);
+ if ( tcg.get() )
+ tcg->Print( fp );
+}
+
+bool Tcg::ImportCustomToolBar( SfxObjectShell& rDocSh )
+{
+ if ( tcg.get() )
+ return tcg->ImportCustomToolBar( rDocSh );
+ return false;
+}
+
+Tcg255::Tcg255()
+{
+}
+
+Tcg255::~Tcg255()
+{
+ std::vector< Tcg255SubStruct* >::iterator it = rgtcgData.begin();
+ for ( ; it != rgtcgData.end(); ++it )
+ delete *it;
+}
+
+bool Tcg255::processSubStruct( sal_uInt8 nId, SvStream *pS )
+{
+ Tcg255SubStruct* pSubStruct = NULL;
+ switch ( nId )
+ {
+ case 0x1:
+ {
+ pSubStruct = new PlfMcd( false ); // don't read the id
+ break;
+ }
+ case 0x2:
+ {
+ pSubStruct = new PlfAcd( false );
+ break;
+ }
+ case 0x3:
+ case 0x4:
+ {
+ pSubStruct = new PlfKme( false );
+ break;
+ }
+ case 0x10:
+ {
+ pSubStruct = new TcgSttbf( false );
+ break;
+ }
+ case 0x11:
+ {
+ pSubStruct = new MacroNames( false );
+ break;
+ }
+ case 0x12:
+ {
+ pSubStruct = new CTBWrapper( false );
+ break;
+ }
+ default:
+ OSL_TRACE("Unknown id 0x%x",nId);
+ return false;
+ }
+ pSubStruct->ch = nId;
+ if ( !pSubStruct->Read( pS ) )
+ return false;
+ rgtcgData.push_back( pSubStruct );
+ return true;
+}
+
+bool Tcg255::ImportCustomToolBar( SfxObjectShell& rDocSh )
+{
+ // Find the CTBWrapper
+ for ( std::vector< Tcg255SubStruct* >::const_iterator it = rgtcgData.begin(); it != rgtcgData.end(); ++it )
+ {
+ if ( (*it)->id() == 0x12 )
+ {
+ // not so great, shouldn't really have to do a horror casting
+ CTBWrapper* pCTBWrapper = dynamic_cast< CTBWrapper* > ( *it );
+ if ( pCTBWrapper )
+ {
+ if ( !pCTBWrapper->ImportCustomToolBar( rDocSh ) )
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+
+bool Tcg255::Read(SvStream *pS)
+{
+ OSL_TRACE("Tcg255::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ sal_uInt8 nId = 0; //
+ *pS >> nId;
+ while ( nId != 0x40 )
+ {
+ if ( !processSubStruct( nId, pS ) )
+ return false;
+ *pS >> nId;
+ }
+ return true;
+ // Peek at
+}
+
+void Tcg255::Print( FILE* fp)
+{
+ Indent a;
+ indent_printf(fp, "[ 0x%x ] Tcg255 - dump\n", nOffSet );
+ indent_printf(fp, " contains %d sub records\n", rgtcgData.size() );
+ std::vector< Tcg255SubStruct* >::iterator it = rgtcgData.begin();
+ std::vector< Tcg255SubStruct* >::iterator it_end = rgtcgData.end();
+
+ for( sal_Int32 count = 1; it != it_end ; ++it, ++count )
+ {
+ Indent b;
+ indent_printf(fp, " [%d] Tcg255SubStruct \n", static_cast< unsigned int >( count ) );
+ (*it)->Print(fp);
+ }
+}
+
+
+Tcg255SubStruct::Tcg255SubStruct( bool bReadId ) : mbReadId( bReadId ), ch(0)
+{
+}
+
+bool Tcg255SubStruct::Read(SvStream *pS)
+{
+ OSL_TRACE("Tcg255SubStruct::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ if ( mbReadId )
+ *pS >> ch;
+ return true;
+}
+
+PlfMcd::PlfMcd( bool bReadId ): Tcg255SubStruct( bReadId ), rgmcd( NULL )
+{
+}
+PlfMcd::~PlfMcd()
+{
+ if ( rgmcd )
+ delete[] rgmcd;
+}
+
+bool PlfMcd::Read(SvStream *pS)
+{
+ OSL_TRACE("PffMcd::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ Tcg255SubStruct::Read( pS );
+ *pS >> iMac;
+ if ( iMac )
+ {
+ rgmcd = new MCD[ iMac ];
+ for ( sal_Int32 index = 0; index < iMac; ++index )
+ {
+ if ( !rgmcd[ index ].Read( pS ) )
+ return false;
+ }
+ }
+ return true;
+}
+
+void PlfMcd::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp, "[ 0x%x ] PlfMcd ( Tcg255SubStruct ) - dump\n", nOffSet );
+ indent_printf(fp, " contains %d MCD records\n", static_cast<int>( iMac ) );
+ for ( sal_Int32 count=0; count < iMac; ++count )
+ {
+ Indent b;
+ indent_printf(fp, "[%d] MCD\n", static_cast< int >( count ) );
+ rgmcd[ count ].Print( fp );
+ }
+
+}
+
+PlfAcd::PlfAcd( bool bReadId ) : Tcg255SubStruct( bReadId )
+,iMac(0)
+,rgacd(NULL)
+{
+}
+
+
+PlfAcd::~PlfAcd()
+{
+ if ( rgacd )
+ delete[] rgacd;
+}
+
+bool PlfAcd::Read( SvStream *pS)
+{
+ OSL_TRACE("PffAcd::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ Tcg255SubStruct::Read( pS );
+ *pS >> iMac;
+ if ( iMac )
+ {
+ rgacd = new Acd[ iMac ];
+ for ( sal_Int32 index = 0; index < iMac; ++index )
+ {
+ if ( !rgacd[ index ].Read( pS ) )
+ return false;
+ }
+ }
+ return true;
+}
+void PlfAcd::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp, "[ 0x%x ] PlfAcd ( Tcg255SubStruct ) - dump\n", nOffSet );
+ indent_printf(fp, " contains %d ACD records\n", static_cast< int >( iMac ) );
+ for ( sal_Int32 count=0; count < iMac; ++count )
+ {
+ Indent b;
+ indent_printf(fp, "[%d] ACD\n", static_cast< int >( count ) );
+ rgacd[ count ].Print( fp );
+ }
+
+}
+
+PlfKme::PlfKme( bool bReadId ) : Tcg255SubStruct( bReadId )
+,iMac( 0 )
+,rgkme( NULL )
+{
+}
+
+PlfKme::~PlfKme()
+{
+ if ( rgkme )
+ delete[] rgkme;
+}
+
+bool PlfKme::Read(SvStream *pS)
+{
+ OSL_TRACE("PlfKme::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ Tcg255SubStruct::Read( pS );
+ *pS >> iMac;
+ if ( iMac )
+ {
+ rgkme = new Kme[ iMac ];
+ for( sal_Int32 index=0; index<iMac; ++index )
+ {
+ if ( !rgkme[ index ].Read( pS ) )
+ return false;
+ }
+ }
+ return true;
+}
+
+void PlfKme::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp, "[ 0x%x ] PlfKme ( Tcg255SubStruct ) - dump\n", nOffSet );
+ indent_printf(fp, " contains %d Kme records\n", static_cast< int >( iMac ) );
+ for ( sal_Int32 count=0; count < iMac; ++count )
+ {
+ Indent b;
+ indent_printf(fp, "[%d] Kme\n", static_cast< int >( count ) );
+ rgkme[ count ].Print( fp );
+ }
+
+}
+
+TcgSttbf::TcgSttbf( bool bReadId ) : Tcg255SubStruct( bReadId )
+{
+}
+
+bool TcgSttbf::Read( SvStream *pS)
+{
+ OSL_TRACE("TcgSttbf::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ Tcg255SubStruct::Read( pS );
+ return sttbf.Read( pS );
+}
+
+void TcgSttbf::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp,"[ 0x%x ] TcgSttbf - dump\n", nOffSet );
+ sttbf.Print( fp );
+}
+
+TcgSttbfCore::TcgSttbfCore() : fExtend( 0 )
+,cData( 0 )
+,cbExtra( 0 )
+,dataItems( NULL )
+{
+}
+
+TcgSttbfCore::~TcgSttbfCore()
+{
+ if ( dataItems )
+ delete[] dataItems;
+}
+
+bool TcgSttbfCore::Read( SvStream* pS )
+{
+ OSL_TRACE("TcgSttbfCore::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ *pS >> fExtend >> cData >> cbExtra;
+ if ( cData )
+ {
+ dataItems = new SBBItem[ cData ];
+ for ( sal_Int32 index = 0; index < cData; ++index )
+ {
+ *pS >> dataItems[ index ].cchData;
+ dataItems[ index ].data = readUnicodeString( pS, dataItems[ index ].cchData );
+ *pS >> dataItems[ index ].extraData;
+ }
+ }
+ return true;
+}
+
+void TcgSttbfCore::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp, "[ 0x%x ] TcgSttbfCore - dump\n");
+ indent_printf( fp, " fExtend 0x%x [expected 0xFFFF ]\n", fExtend );
+ indent_printf( fp, " cbExtra 0x%x [expected 0x02 ]\n", cbExtra );
+ indent_printf( fp, " cData no. or string data items %d (0x%x)\n", cData, cData );
+
+ if ( cData )
+ {
+ for ( sal_Int32 index = 0; index < cData; ++index )
+ indent_printf(fp," string dataItem[ %d(0x%x) ] has name %s and if referenced %d times.\n", static_cast< int >( index ), static_cast< unsigned int >( index ), rtl::OUStringToOString( dataItems[ index ].data, RTL_TEXTENCODING_UTF8 ).getStr(), dataItems[ index ].extraData );
+ }
+
+}
+MacroNames::MacroNames( bool bReadId ) : Tcg255SubStruct( bReadId )
+,iMac( 0 )
+,rgNames( NULL )
+{
+}
+
+MacroNames::~MacroNames()
+{
+ if ( rgNames )
+ delete[] rgNames;
+}
+
+bool MacroNames::Read( SvStream *pS)
+{
+ OSL_TRACE("MacroNames::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ Tcg255SubStruct::Read( pS );
+ *pS >> iMac;
+ if ( iMac )
+ {
+ rgNames = new MacroName[ iMac ];
+ for ( sal_Int32 index = 0; index < iMac; ++index )
+ {
+ if ( !rgNames[ index ].Read( pS ) )
+ return false;
+ }
+ }
+ return true;
+}
+
+void MacroNames::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp, "[ 0x%x ] MacroNames ( Tcg255SubStruct ) - dump\n");
+ indent_printf(fp, " contains %d MacroName records\n", iMac );
+ for ( sal_Int32 count=0; count < iMac; ++count )
+ {
+ Indent b;
+ indent_printf(fp, "[%d] MacroName\n", static_cast<int>( count ) );
+ rgNames[ count ].Print( fp );
+ }
+
+}
+
+MacroName::MacroName():ibst(0)
+{
+}
+
+
+bool MacroName::Read(SvStream *pS)
+{
+ OSL_TRACE("MacroName::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ *pS >> ibst;
+ return xstz.Read( pS );
+}
+
+void MacroName::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp, "[ 0x%x ] MacroName - dump");
+ indent_printf( fp," index - 0x%x has associated following record\n", ibst );
+ xstz.Print( fp );
+}
+
+
+
+Xstz::Xstz():chTerm(0)
+{
+}
+
+bool
+Xstz::Read(SvStream *pS)
+{
+ OSL_TRACE("Xstz::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ if ( !xst.Read( pS ) )
+ return false;
+ *pS >> chTerm;
+ if ( chTerm != 0 ) // should be an assert
+ return false;
+ return true;
+}
+
+void Xstz::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf(fp,"[ 0x%x ] Xstz -- dump\n", nOffSet );
+ indent_printf(fp," Xst\n");
+ xst.Print( fp );
+ indent_printf(fp," chterm 0x%x ( should be zero )\n", chTerm);
+}
+
+Kme::Kme() : reserved1(0)
+,reserved2(0)
+,kcm1(0)
+,kcm2(0)
+,kt(0)
+,param(0)
+{
+}
+
+Kme::~Kme()
+{
+}
+
+bool
+Kme::Read(SvStream *pS)
+{
+ OSL_TRACE("Kme::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ *pS >> reserved1 >> reserved2 >> kcm1 >> kcm2 >> kt >> param;
+ return true;
+}
+
+void Kme::Print( FILE* fp )
+{
+ Indent a;
+
+ indent_printf( fp, "[ 0x%x ] Kme - dump\n", nOffSet );
+ indent_printf( fp, " reserved1 0x%x [expected 0x0 ]\n", reserved1 );
+ indent_printf( fp, " reserved2 0x%x [expected 0x0 ]\n", reserved2 );
+ indent_printf( fp, " kcm1 0x%x [shortcut key]\n", kcm1 );
+ indent_printf( fp, " kcm2 0x%x [shortcut key]\n", kcm2 );
+ indent_printf( fp, " kt 0x%x \n", kt );
+ indent_printf( fp, " param 0x%x \n", static_cast< unsigned int >( param ) );
+}
+
+Acd::Acd() : ibst( 0 )
+, fciBasedOnABC( 0 )
+{
+}
+
+bool Acd::Read(SvStream *pS)
+{
+ OSL_TRACE("Acd::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ *pS >> ibst >> fciBasedOnABC;
+ return true;
+}
+
+void Acd::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp,"[ 0x%x ] ACD - dump\n", nOffSet );
+ // #TODO flesh out interpretation of these values
+ indent_printf( fp," ibst 0x%x\n", ibst);
+ indent_printf( fp," fciBaseObABC 0x%x\n", fciBasedOnABC);
+}
+
+MCD::MCD() : reserved1(0x56)
+,reserved2( 0 )
+,ibst( 0 )
+,ibstName( 0 )
+,reserved3( 0xFFFF )
+,reserved4( 0 )
+,reserved5( 0 )
+,reserved6( 0 )
+,reserved7( 0 )
+{
+}
+
+bool MCD::Read(SvStream *pS)
+{
+ OSL_TRACE("MCD::Read() stream pos 0x%x", pS->Tell() );
+ nOffSet = pS->Tell();
+ *pS >> reserved1 >> reserved2 >> ibst >> ibstName >> reserved3;
+ *pS >> reserved4 >> reserved5 >> reserved6 >> reserved7;
+ return true;
+}
+
+void MCD::Print( FILE* fp )
+{
+ Indent a;
+ indent_printf( fp, "[ 0x%x ] MCD - dump\n", nOffSet );
+ indent_printf( fp, " reserved1 0x%x [expected 0x56 ]\n", reserved1 );
+ indent_printf( fp, " reserved2 0x%x [expected 0x0 ]\n", reserved2 );
+ indent_printf( fp, " ibst 0x%x specifies macro with MacroName.xstz = 0x%x\n", ibst, ibst );
+ indent_printf( fp, " ibstName 0x%x index into command string table ( TcgSttbf.sttbf )\n", ibstName );
+
+ indent_printf( fp, " reserved3 0x%x [expected 0xFFFF ]\n", reserved3 );
+ indent_printf( fp, " reserved4 0x%x\n", static_cast< unsigned int >( reserved4 ) );
+ indent_printf( fp, " reserved5 0x%x [expected 0x0 ]\n", static_cast< unsigned int >( reserved5 ) );
+ indent_printf( fp, " reserved6 0x%x\n", static_cast< unsigned int >( reserved6 ) );
+ indent_printf( fp, " reserved7 0x%x\n", static_cast< unsigned int >( reserved7 ) );
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/filter/ww8/ww8toolbar.hxx b/sw/source/filter/ww8/ww8toolbar.hxx
new file mode 100644
index 000000000000..b983eaff0c53
--- /dev/null
+++ b/sw/source/filter/ww8/ww8toolbar.hxx
@@ -0,0 +1,379 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * Version: MPL 1.1 / GPLv3+ / LGPLv3+
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License or as specified alternatively below. You may obtain a copy of
+ * the License at http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Initial Developer of the Original Code is
+ * Noel Power <noel.power@novell.com>
+ * Portions created by the Initial Developer are Copyright (C) 2010 the
+ * Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Noel Power <noel.power@novell.com>
+ *
+ * For minor contributions see the git repository.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
+ * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
+ * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
+ * instead of those above.
+ */
+#ifndef _WW8TOOLBAR_HXX
+#define _WW8TOOLBAR_HXX
+
+#include <filter/msfilter/mstoolbar.hxx>
+
+namespace css = ::com::sun::star;
+
+class Xst : public TBBase
+{
+ rtl::OUString sString;
+public:
+ Xst(){}
+ bool Read(SvStream *pS);
+ rtl::OUString getString() { return sString; }
+ void Print( FILE* fp );
+};
+
+class CTBWrapper;
+class TBC : public TBBase
+{
+ TBCHeader tbch;
+ boost::shared_ptr< sal_uInt32 > cid; // optional
+ boost::shared_ptr<TBCData> tbcd;
+public:
+ TBC();
+ ~TBC();
+ bool Read(SvStream *pS);
+ void Print( FILE* );
+ bool ImportToolBarControl( CTBWrapper&, const css::uno::Reference< css::container::XIndexContainer >&, CustomToolBarImportHelper&, bool );
+ rtl::OUString GetCustomText();
+};
+
+class CTB : public TBBase
+{
+ Xst name;
+ sal_Int32 cbTBData;
+ TB tb;
+ std::vector<TBVisualData> rVisualData;
+ sal_Int32 iWCTBl;
+ sal_uInt16 reserved;
+ sal_uInt16 unused;
+ sal_Int32 cCtls;
+ std::vector< TBC > rTBC;
+
+ CTB(const CTB&);
+ CTB& operator = ( const CTB&);
+public:
+ CTB();
+ ~CTB();
+ bool Read(SvStream *pS);
+ void Print( FILE* fp );
+ bool IsMenuToolbar();
+ bool ImportCustomToolBar( CTBWrapper&, CustomToolBarImportHelper& );
+ bool ImportMenuTB( CTBWrapper&, const css::uno::Reference< css::container::XIndexContainer >&, CustomToolBarImportHelper& );
+ rtl::OUString GetName() { return tb.getName().getString(); }
+};
+
+class TBDelta : public TBBase
+{
+ sal_uInt8 doprfatendFlags;
+
+ sal_uInt8 ibts;
+ sal_Int32 cidNext;
+ sal_Int32 cid;
+ sal_Int32 fc;
+ sal_uInt16 CiTBDE; // careful of this ( endian matters etc. )
+ sal_uInt16 cbTBC;
+public:
+ TBDelta();
+ ~TBDelta(){}
+ bool Read(SvStream *pS);
+ void Print( FILE* );
+ bool ControlIsModified();
+ bool ControlIsInserted();
+ bool ControlIsChanged();
+ bool ControlDropsToolBar();
+ sal_Int32 TBCStreamOffset();
+ sal_Int16 CustomizationIndex();
+
+};
+
+class Tcg255SubStruct : public TBBase
+{
+friend class Tcg255;
+ bool mbReadId;
+ Tcg255SubStruct(const Tcg255SubStruct&);
+ Tcg255SubStruct& operator = ( const Tcg255SubStruct&);
+protected:
+ sal_uInt8 ch;
+public:
+ Tcg255SubStruct( bool bReadId );
+ ~Tcg255SubStruct(){}
+ virtual sal_uInt8 id() const { return ch; }
+ bool Read(SvStream *pS);
+};
+
+class CTBWrapper;
+class Customization : public TBBase
+{
+friend class CTBWrapper;
+ sal_Int32 tbidForTBD;
+ sal_uInt16 reserved1;
+ sal_Int16 ctbds;
+ CTBWrapper* pWrapper;
+ boost::shared_ptr< CTB > customizationDataCTB;
+ std::vector< TBDelta > customizationDataTBDelta;
+ bool bIsDroppedMenuTB;
+ bool ImportMenu( CTBWrapper&, const css::uno::Reference< css::container::XIndexContainer >&, CustomToolBarImportHelper& );
+public:
+ Customization( CTBWrapper* rapper );
+ ~Customization();
+ bool Read(SvStream *pS);
+ bool ImportCustomToolBar( CTBWrapper&, CustomToolBarImportHelper& );
+ bool ImportMenu( CTBWrapper&, CustomToolBarImportHelper& );
+ void Print( FILE* );
+ sal_Int32 GetTBIDForTB(){ return tbidForTBD; }
+ CTB* GetCustomizationData() { return customizationDataCTB.get(); };
+};
+
+class SfxObjectShell;
+
+class CTBWrapper : public Tcg255SubStruct
+{
+ // reserved1 is the ch field of Tcg255SubStruct
+ sal_uInt16 reserved2;
+ sal_uInt8 reserved3;
+ sal_uInt16 reserved4;
+ sal_uInt16 reserved5;
+
+ sal_Int16 cbTBD;
+ sal_Int16 cCust;
+
+ sal_Int32 cbDTBC;
+
+ std::vector< TBC > rtbdc; //
+ std::vector< Customization > rCustomizations; // array of Customizations
+ std::vector< sal_Int16 > dropDownMenuIndices; // array of indexes of Customization toolbars that are dropped by a menu
+ CTBWrapper(const CTBWrapper&);
+ CTBWrapper& operator = ( const CTBWrapper&);
+public:
+ CTBWrapper( bool bReadId = true );
+ ~CTBWrapper();
+ void InsertDropIndex( sal_Int32 aIndex ) { dropDownMenuIndices.push_back( aIndex ); }
+ TBC* GetTBCAtOffset( sal_uInt32 nStreamOffset );
+ bool Read(SvStream *pS);
+ bool ImportCustomToolBar( SfxObjectShell& rDocSh );
+
+ Customization* GetCustomizaton( sal_Int16 index );
+ CTB* GetCustomizationData( const rtl::OUString& name );
+ void Print( FILE* );
+};
+
+class MCD : public TBBase
+{
+ sal_Int8 reserved1; // A signed integer that MUST be 0x56.
+ sal_uInt8 reserved2; // MUST be 0.
+ sal_uInt16 ibst; // Unsigned integer that specifies the name of the macro. Macro name is specified by MacroName.xstz of the MacroName entry in the MacroNames such that MacroName.ibst equals ibst. MacroNames MUST contain such an entry.
+ sal_uInt16 ibstName; // An unsigned integer that specifies the index into the Command String Table (TcgSttbf.sttbf) where the macro‘s name and arguments are specified.
+ sal_uInt16 reserved3; // An unsigned integer that MUST be 0xFFFF.
+ sal_uInt32 reserved4; //MUST be ignored.
+ sal_uInt32 reserved5; //MUST be 0.
+ sal_uInt32 reserved6; //MUST be ignored.
+ sal_uInt32 reserved7; //MUST be ignored
+
+ MCD(const MCD&);
+ MCD& operator = ( const MCD&);
+public:
+ MCD();
+ ~MCD(){}
+ bool Read(SvStream *pS);
+ void Print( FILE* );
+};
+
+class PlfMcd : public Tcg255SubStruct
+{
+ sal_Int32 iMac;
+ MCD* rgmcd; // array of MCD's
+ PlfMcd(const PlfMcd&);
+ PlfMcd& operator = ( const PlfMcd&);
+public:
+ PlfMcd( bool bReadId = true );
+ ~PlfMcd();
+ bool Read(SvStream *pS);
+ void Print( FILE* );
+};
+
+class Acd : public TBBase
+{
+ sal_Int16 ibst;
+ sal_uInt16 fciBasedOnABC; // fciBasedOn(13 bits) A(1bit)B(1bit)C(1Bit)
+ Acd(const Acd&);
+ Acd& operator = ( const Acd&);
+public:
+ Acd();
+ ~Acd(){}
+ bool Read(SvStream *pS);
+ void Print( FILE* );
+};
+
+class PlfAcd: public Tcg255SubStruct
+{
+ sal_Int32 iMac;
+ Acd* rgacd;
+ PlfAcd(const PlfAcd&);
+ PlfAcd& operator = ( const PlfAcd&);
+public:
+ PlfAcd( bool bReadId = true );
+ ~PlfAcd();
+ bool Read(SvStream *pS);
+ void Print(FILE*);
+};
+
+class Kme : public TBBase
+{
+ sal_Int16 reserved1; //MUST be zero.
+ sal_Int16 reserved2; //MUST be zero.
+ sal_uInt16 kcm1; //A Kcm that specifies the primary shortcut key.
+ sal_uInt16 kcm2; //A Kcm that specifies the secondary shortcut key, or 0x00FF if there is no secondary shortcut key.
+ sal_uInt16 kt; //A Kt that specifies the type of action to be taken when the key combination is pressed.
+ sal_uInt32 param; //The meaning of this field depends on the value of kt
+
+ Kme(const Kme&);
+ Kme& operator = ( const Kme&);
+public:
+ Kme();
+ ~Kme();
+ bool Read(SvStream *pS);
+ void Print( FILE* );
+};
+
+class PlfKme : public Tcg255SubStruct
+{
+ sal_Int32 iMac;
+ Kme* rgkme;
+ PlfKme(const PlfKme&);
+ PlfKme& operator = ( const PlfKme&);
+public:
+ PlfKme( bool bReadId = true );
+ ~PlfKme();
+ bool Read(SvStream *pS);
+ void Print( FILE* );
+};
+
+class TcgSttbfCore : public TBBase
+{
+struct SBBItem
+{
+ sal_uInt16 cchData;
+ rtl::OUString data;
+ sal_uInt16 extraData;
+ SBBItem() : cchData(0), extraData(0){}
+};
+ sal_uInt16 fExtend;
+ sal_uInt16 cData;
+ sal_uInt16 cbExtra;
+ SBBItem* dataItems;
+ TcgSttbfCore(const TcgSttbfCore&);
+ TcgSttbfCore& operator = ( const TcgSttbfCore&);
+public:
+ TcgSttbfCore();
+ ~TcgSttbfCore();
+ bool Read(SvStream *pS);
+ void Print( FILE* fp );
+};
+
+class TcgSttbf : public Tcg255SubStruct
+{
+ TcgSttbfCore sttbf;
+ TcgSttbf(const TcgSttbf&);
+ TcgSttbf& operator = ( const TcgSttbf&);
+public:
+ TcgSttbf( bool bReadId = true );
+ ~TcgSttbf(){}
+ bool Read(SvStream *pS);
+ void Print( FILE* fp );
+};
+
+class Xstz : public TBBase
+{
+ Xst xst; //An Xst specifying the string with its pre-pended length.
+ sal_uInt16 chTerm;
+
+ Xstz(const Xstz&);
+ Xstz& operator = ( const Xstz&);
+public:
+ Xstz();
+ ~Xstz(){}
+ bool Read(SvStream *pS);
+ void Print( FILE* fp );
+};
+
+class MacroName : public TBBase
+{
+ sal_uInt16 ibst; //An unsigned integer that specifies the index of the current entry in the macro name table. MUST NOT be the same as the index of any other entry.
+ Xstz xstz;
+ MacroName(const MacroName&);
+ MacroName& operator = ( const MacroName&);
+public:
+ MacroName();
+ ~MacroName(){}
+ bool Read(SvStream *pS);
+ void Print( FILE* );
+};
+
+class MacroNames : public Tcg255SubStruct
+{
+ sal_uInt16 iMac; //An unsigned integer that specifies the number of MacroName structures in rgNames.
+ MacroName* rgNames;
+
+ MacroNames(const MacroNames&);
+ MacroNames& operator = ( const MacroNames&);
+public:
+ MacroNames( bool bReadId = true );
+ ~MacroNames();
+ bool Read(SvStream *pS);
+ void Print( FILE* );
+};
+
+class Tcg255 : public TBBase
+{
+ std::vector< Tcg255SubStruct* > rgtcgData; // array of sub structures
+ Tcg255(const Tcg255&);
+ Tcg255& operator = ( const Tcg255&);
+ bool processSubStruct( sal_uInt8 nId, SvStream* );
+public:
+ Tcg255();
+ ~Tcg255();
+ bool Read(SvStream *pS);
+ void Print( FILE* );
+ bool ImportCustomToolBar( SfxObjectShell& rDocSh );
+};
+
+class Tcg: public TBBase
+{
+ sal_Int8 nTcgVer;
+ std::auto_ptr< Tcg255 > tcg;
+ Tcg(const Tcg&);
+ Tcg& operator = ( const Tcg&);
+public:
+ Tcg();
+ ~Tcg(){}
+ bool Read(SvStream *pS);
+ bool ImportCustomToolBar( SfxObjectShell& rDocSh );
+ void Print( FILE* );
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */