summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8/ww8par3.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/ww8/ww8par3.cxx')
-rw-r--r--sw/source/filter/ww8/ww8par3.cxx2613
1 files changed, 2613 insertions, 0 deletions
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: */