summaryrefslogtreecommitdiff
path: root/sw/source/filter/ww8/ww8par.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sw/source/filter/ww8/ww8par.cxx')
-rw-r--r--sw/source/filter/ww8/ww8par.cxx5054
1 files changed, 5054 insertions, 0 deletions
diff --git a/sw/source/filter/ww8/ww8par.cxx b/sw/source/filter/ww8/ww8par.cxx
new file mode 100644
index 000000000000..599c6b3ea1b6
--- /dev/null
+++ b/sw/source/filter/ww8/ww8par.cxx
@@ -0,0 +1,5054 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2008 by Sun Microsystems, Inc.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * $RCSfile: ww8par.cxx,v $
+ * $Revision: 1.199.12.6 $
+ *
+ * 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"
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+
+#include <hash_set>
+#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 <sot/storage.hxx>
+#include <sfx2/docinf.hxx>
+#include <sfx2/docfile.hxx>
+#include <tools/urlobj.hxx>
+#include <unotools/tempfile.hxx>
+#include <svtools/sfxecode.hxx>
+
+#include <comphelper/docpasswordrequest.hxx>
+#include <hintids.hxx>
+
+#include <svx/tstpitem.hxx>
+#include <svx/cscoitem.hxx>
+#include <svx/svdobj.hxx>
+#include <svx/svdpage.hxx>
+#include <svx/paperinf.hxx>
+#include <svx/lrspitem.hxx> // SvxLRSpaceItem
+#include <svx/ulspitem.hxx>
+#include <svx/langitem.hxx>
+// --> OD 2005-02-28 #i43427#
+#include <svx/opaqitem.hxx>
+// <--
+#include <svx/svxmsbas.hxx>
+#include <svx/unoapi.hxx>
+#include <svx/svdoole2.hxx>
+#include <svx/msdffimp.hxx>
+#include <svx/svdoashp.hxx>
+#include <svx/svxerr.hxx>
+#include <svx/mscodec.hxx>
+#include <svx/svdmodel.hxx>
+#include <svx/svdogrp.hxx>
+#include <svx/xflclit.hxx>
+
+#include <svtools/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 <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 <svtools/itemiter.hxx> //SfxItemIter
+
+#include <stdio.h>
+
+#ifdef DEBUG
+#include <iostream>
+#include <dbgoutsw.hxx>
+#endif
+
+#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;
+
+
+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();
+}
+
+UINT32 SwMSDffManager::GetFilterFlags()
+{
+ 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
+ */
+// --> OD 2004-12-14 #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
+{
+ // --> OD 2004-12-14 #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 );
+ ASSERT(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()
+{
+ ASSERT(!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;
+}
+
+USHORT SwWW8ImplReader::GetToggleAttrFlags() const
+{
+ return pCtrlStck ? pCtrlStck->GetToggleAttrFlags() : 0;
+}
+
+USHORT SwWW8ImplReader::GetToggleBiDiAttrFlags() const
+{
+ return pCtrlStck ? pCtrlStck->GetToggleBiDiAttrFlags() : 0;
+}
+
+void SwWW8ImplReader::SetToggleAttrFlags(USHORT nFlags)
+{
+ if (pCtrlStck)
+ pCtrlStck->SetToggleAttrFlags(nFlags);
+}
+
+void SwWW8ImplReader::SetToggleBiDiAttrFlags(USHORT 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
+ // --> OD 2008-04-10 #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 )
+ {
+ UINT32 nBytesLeft = maShapeRecords.Current()->nRecLen;
+ UINT32 nUDData;
+ UINT16 nPID;
+ while( 5 < nBytesLeft )
+ {
+ rSt >> nPID;
+ if ( rSt.GetError() != 0 )
+ break;
+ rSt >> nUDData;
+ switch( nPID )
+ {
+ case 0x038F: pImpRec->nXAlign = nUDData; break;
+ case 0x0390: pImpRec->nXRelTo = nUDData; break;
+ case 0x0391: pImpRec->nYAlign = nUDData; break;
+ case 0x0392: pImpRec->nYRelTo = nUDData; break;
+ case 0x03BF: pImpRec->nLayoutInTableCell = nUDData; break;
+ }
+ if ( rSt.GetError() != 0 )
+ break;
+ pImpRec->bHasUDefProp = TRUE;
+ nBytesLeft -= 6;
+ }
+ }
+
+ // Textrahmen, auch Title oder Outline
+ 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.
+ 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)
+ // && (eWrapMode == mso_wrapSquare)
+ && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() )
+ )
+ );
+ }
+
+ // Distance of Textbox to it's surrounding Autoshape
+ INT32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 91440L);
+ INT32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 91440L );
+ INT32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 45720L );
+ INT32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 45720L );
+
+ ScaleEmu( nTextLeft );
+ ScaleEmu( nTextRight );
+ ScaleEmu( nTextTop );
+ ScaleEmu( nTextBottom );
+
+ 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;
+
+ INT32 nOldTextLeft = nTextLeft;
+ INT32 nOldTextRight = nTextRight;
+ INT32 nOldTextTop = nTextTop;
+ 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;
+
+ INT32 nOldTextLeft = nTextLeft;
+ INT32 nOldTextRight = nTextRight;
+ INT32 nOldTextTop = nTextTop;
+ 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 = TRUE;
+
+ USHORT 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 );
+
+ bool bFitText = false;
+ if (GetPropertyValue(DFF_Prop_FitTextToShape) & 2)
+ {
+ aSet.Put( SdrTextAutoGrowHeightItem( TRUE ) );
+ aSet.Put( SdrTextMinFrameHeightItem(
+ aNewRect.Bottom() - aNewRect.Top() ) );
+ aSet.Put( SdrTextMinFrameWidthItem(
+ aNewRect.Right() - aNewRect.Left() ) );
+ bFitText = true;
+ }
+ else
+ {
+ aSet.Put( SdrTextAutoGrowHeightItem( FALSE ) );
+ aSet.Put( SdrTextAutoGrowWidthItem( FALSE ) );
+ }
+
+ switch ( (MSO_WrapMode)
+ GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) )
+ {
+ case mso_wrapNone :
+ aSet.Put( SdrTextAutoGrowWidthItem( TRUE ) );
+ pImpRec->bAutoWidth = true;
+ break;
+ case mso_wrapByPoints :
+ aSet.Put( SdrTextContourFrameItem( 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;
+
+ // --> SJ 2009-03-06 : 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;
+/*
+ case mso_anchorTopBaseline:
+ case mso_anchorBottomBaseline:
+ case mso_anchorTopCenteredBaseline:
+ case mso_anchorBottomCenteredBaseline:
+ break;
+*/
+ default:
+ ;
+ }
+
+ aSet.Put( SdrTextVertAdjustItem( eTVA ) );
+ aSet.Put( SdrTextHorzAdjustItem( eTHA ) );
+
+ 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,
+ 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 = TRUE;
+ else
+ pImpRec->bDrawHell = FALSE;
+ if (GetPropertyValue(DFF_Prop_fPrint) & 0x02)
+ pImpRec->bHidden = TRUE;
+ pImpRec->nNextShapeId = GetPropertyValue( DFF_Prop_hspNext, 0 );
+
+ if ( nTextId )
+ {
+ pImpRec->aTextId.nTxBxS = (UINT16)( nTextId >> 16 );
+ pImpRec->aTextId.nSequence = (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 );
+
+ UINT32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash );
+ // --> OD 2008-06-16 #156765#
+ 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->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,
+ ( ( (ULONG)pImpRec->aTextId.nTxBxS ) << 16 )
+ + pImpRec->aTextId.nSequence, pObj );
+ }
+ else
+ delete pImpRec;
+ }
+
+ return pObj;
+}
+
+/***************************************************************************
+# Spezial FastSave - Attribute
+#**************************************************************************/
+
+void SwWW8ImplReader::Read_StyleCode( USHORT, const BYTE* pData, short nLen )
+{
+ if (nLen < 0)
+ {
+ bCpxStyle = false;
+ return;
+ }
+ USHORT 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( USHORT, const BYTE* , short )
+{
+}
+
+//-----------------------------------------
+// Stack
+//-----------------------------------------
+void SwWW8FltControlStack::NewAttr(const SwPosition& rPos,
+ const SfxPoolItem& rAttr)
+{
+ ASSERT(RES_TXTATR_FIELD != rAttr.Which(), "probably don't want to put"
+ "fields into the control stack");
+ ASSERT(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, USHORT nAttrId,
+ BOOL bTstEnde, long nHand, 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())
+ {
+ USHORT nCnt = static_cast< USHORT >(Count());
+ for (USHORT 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)
+{
+ ASSERT( 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)
+{
+ ASSERT( 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;
+}
+
+void SyncIndentWithList(SvxLRSpaceItem &rLR, const SwNumFmt &rFmt)
+{
+ long nWantedFirstLinePos;
+ long nExtraListIndent = lcl_GetTrueMargin(rLR, rFmt, nWantedFirstLinePos);
+ rLR.SetTxtLeft(nWantedFirstLinePos - nExtraListIndent);
+ rLR.SetTxtFirstLineOfst(0);
+}
+
+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);
+ BYTE nLvl = static_cast< BYTE >(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 );
+ ULONG nStart = aRegion.Start()->nNode.GetIndex();
+ 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);
+
+ // --> OD 2008-06-03 #i86652#
+// if (pNum)
+ if ( pNum &&
+ pNum->GetPositionAndSpaceMode() ==
+ SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
+ // <--
+ {
+ SyncIndentWithList(aNewLR, *pNum);
+ }
+
+ if (aNewLR == aOldLR)
+ continue;
+
+ pNd->SetAttr(aNewLR);
+
+ }
+ }
+ }
+ break;
+ case RES_TXTATR_FIELD:
+ ASSERT(!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,
+ USHORT nWhich)
+{
+ const SfxPoolItem *pItem = GetStackAttr(rPos, nWhich);
+ if (!pItem)
+ {
+ const SwCntntNode *pNd = pDoc->GetNodes()[ rPos.nNode ]->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)
+ pItem = &(rReader.pCollA[rReader.nAktColl].maWordLR);
+ }
+
+ if (!pItem)
+ pItem = &pNd->GetAttr(nWhich);
+ }
+ }
+ return pItem;
+}
+
+const SfxPoolItem* SwWW8FltControlStack::GetStackAttr(const SwPosition& rPos,
+ USHORT nWhich)
+{
+ SwNodeIndex aNode( rPos.nNode, -1 );
+ USHORT nIdx = rPos.nContent.GetIndex();
+
+ USHORT nSize = static_cast< USHORT >(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) ) )
+ {
+ return (const SfxPoolItem*)pEntry->pAttr;
+ }
+ }
+ }
+ return 0;
+}
+
+bool SwWW8FltRefStack::IsFtnEdnBkmField(const SwFmtFld& rFmtFld, USHORT& rBkmNo)
+{
+ const SwField* pFld = rFmtFld.GetFld();
+ USHORT 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();
+
+ // OD 2004-03-19 - <NOT> got lost from revision 1.128 to 1.129
+ if (!RefToVar(pFld,pEntry))
+ {
+ USHORT 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 )
+ {
+ USHORT 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:
+ ASSERT(!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(USHORT , const BYTE* pData, short nLen)
+{
+ if (nLen < 0)
+ {
+ pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_TABSTOP);
+ return;
+ }
+
+ short i;
+ const BYTE* pDel = pData + 1; // Del - Array
+ BYTE nDel = pData[0];
+ const BYTE* pIns = pData + 2*nDel + 2; // Ins - Array
+ BYTE 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;
+ USHORT 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;
+ ::std::hash_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
+ {
+
+ USHORT 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)
+ {
+ USHORT 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;
+ }
+
+ USHORT 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);
+ // OD 14.10.2003 #i18732# - adjust default of option 'FollowTextFlow'
+ rDoc.SetDefault( SwFmtFollowTextFlow( FALSE ) );
+
+ // Import Default-Tabs
+ long nDefTabSiz = pWDop->dxaTab;
+ if( nDefTabSiz < 56 )
+ nDefTabSiz = 709;
+
+ // wir wollen genau einen DefaultTab
+ SvxTabStopItem aNewTab( 1, USHORT(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);
+
+ // -> #111955#
+ rDoc.set(IDocumentSettingAccess::OLD_NUMBERING, false);
+ // <- #111955#
+
+ // --> FME 2005-05-27 #i47448#
+ rDoc.set(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, false);
+ // <--
+
+ // --> FME 2005-06-08 #i49277#
+ rDoc.set(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, !pWDop->fExpShRtn); // #i56856#
+ // --> FME 2005-08-11 #i53199#
+ rDoc.set(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, false);
+
+ rDoc.set(IDocumentSettingAccess::OLD_LINE_SPACING, false);
+
+ // OD, MMAHER 2004-03-01 #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);
+
+ // OD 2004-03-17 #i11860# - set new compatibility option
+ // 'Use former object positioning' to <FALSE>
+ rDoc.set(IDocumentSettingAccess::USE_FORMER_OBJECT_POS, false);
+
+ // OD 2004-05-10 #i27767# - set new compatibility option
+ // 'Conder Wrapping mode when positioning object' to <TRUE>
+ rDoc.set(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION, true);
+
+ // --> FME 2004-04-22 # #108724#, #i13832#, #i24135#
+ rDoc.set(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING, false);
+ // <--
+
+ // --> FME 2006-02-10 #131283#
+ rDoc.set(IDocumentSettingAccess::TABLE_ROW_KEEP, true); //SetTableRowKeep( true );
+ // <--
+
+ // --> FME 2006-03-01 #i3952#
+ rDoc.set(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, 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);
+
+ // #110055# disable form design mode to be able to use imported controls directly
+ // #i31239# always disable form design mode, not only in protected docs
+// if (pWDop->fProtEnabled)
+ {
+ 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() &&
+ xInfo->hasPropertyByName(C2U("ApplyFormDesignMode")))
+ {
+ xDocProps->setPropertyValue(C2U("ApplyFormDesignMode"),
+ cppu::bool2any(bValue));
+ }
+ }
+ }
+ 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);
+ maFieldCtxStack.swap(pRdr->maNewFieldCtxStack);
+}
+
+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);
+ pRdr->maNewFieldCtxStack.swap(maFieldCtxStack);
+}
+
+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 (BYTE * pExtended = pPlcxMan->GetExtendedAtrds()) // Word < 2002 has no date data for comments
+ {
+ 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);
+
+ rDoc.InsertPoolItem(*pPaM, SwFmtFld(aPostIt), 0);
+
+ return 0;
+}
+
+void SwWW8ImplReader::Read_HdFtTextAsHackedFrame(long nStart, long nLen,
+ SwFrmFmt &rHdFtFmt, sal_uInt16 nPageWidth)
+{
+ const SwNodeIndex* pSttIdx = rHdFtFmt.GetCntnt().GetCntntIdx();
+ ASSERT(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_CNTNT, pPaM->GetPoint());
+
+ pFrame->SetFmtAttr(SwFmtFrmSize(ATT_MIN_SIZE, nPageWidth, MINLAY));
+ pFrame->SetFmtAttr(SwFmtSurround(SURROUND_THROUGHT));
+ pFrame->SetFmtAttr(SwFmtHoriOrient(0, text::HoriOrientation::RIGHT)); //iFOO
+ // --> OD 2005-02-28 #i43427# - send frame for header/footer into background.
+ pFrame->SetFmtAttr( SvxOpaqueItem( RES_OPAQUE, false ) );
+ SdrObject* pFrmObj = CreateContactObject( pFrame );
+ ASSERT( 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::HasOwnHeaderFooter(BYTE nWhichItems, BYTE grpfIhdt,
+ int nSect)
+{
+ if (pHdFt)
+ {
+ WW8_CP start;
+ long nLen;
+ BYTE nNumber = 5;
+
+ for( BYTE 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 );
+ }
+
+ if (bOk)
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect,
+ const SwPageDesc *pPrev, const wwSection &rSection)
+{
+ BYTE nWhichItems = 0;
+ SwPageDesc *pPD = 0;
+ if (!bIsTitle)
+ {
+ nWhichItems =
+ rSection.maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST);
+ pPD = rSection.mpPage;
+ }
+ else
+ {
+ // --> OD 2008-08-06 #150965#
+ // Always read title page header/footer data - it could be used by following sections
+// nWhichItems =
+// rSection.maSep.grpfIhdt & (WW8_HEADER_FIRST | WW8_FOOTER_FIRST),
+ nWhichItems = ( WW8_HEADER_FIRST | WW8_FOOTER_FIRST );
+ // <--
+ pPD = rSection.mpTitlePage;
+ }
+
+ BYTE grpfIhdt = rSection.maSep.grpfIhdt;
+
+
+ if( pHdFt )
+ {
+ WW8_CP start;
+ long nLen;
+ BYTE nNumber = 5;
+
+ for( BYTE 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 );
+ }
+
+ 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* pFmt = 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 = (SwFrmFmt*)pFmt->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 = (SwFrmFmt*)pFmt->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.pWDop->fProtEnabled && !rSection.IsNotProtected());
+}
+
+void wwSectionManager::SetHdFt(wwSection &rSection, int nSect,
+ const wwSection *pPrevious)
+{
+ // Header / Footer nicht da
+ if (!rSection.maSep.grpfIhdt)
+ return;
+
+ ASSERT(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< USHORT >(nSpace) );
+ else
+ aUL.SetLower( static_cast< USHORT >(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);
+}
+
+USHORT 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();
+
+ ASSERT(!nInTable, "unclosed table!");
+}
+
+bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync, WW8_CP nStartCp)
+{
+ // Frame / Table / Anl
+ if (bInHyperlink)
+ return false;
+
+ rbReSync = false;
+
+ ASSERT(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
+ BYTE 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 BYTE *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< BYTE >(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 BYTE* pSprm13 = pPlcxMan->HasParaSprm( 13 );
+ if( pSprm13 )
+ { // Noch Anl ?
+ BYTE nT = static_cast< BYTE >(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)
+ 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 ((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);
+
+ ASSERT(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(USHORT 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;
+ ASSERT(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
+ BYTE nBCode = 0;
+ UINT16 nUCode;
+ xub_StrLen nL2;
+
+ USHORT 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 );
+ 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);
+ ASSERT(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 );
+
+ AddTextToParagraph(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;
+}
+
+bool SwWW8ImplReader::AddTextToParagraph(const String& rAddString)
+{
+ const SwTxtNode* pNd = pPaM->GetCntntNode()->GetTxtNode();
+ if (rAddString.Len())
+ {
+/*
+#ifdef DEBUG
+//!! does not compile with debug=t -> unresolved external (dbg_out),
+//!! sommeone who knows what he wants to get should fix this
+// ::std::clog << "<addTextToParagraph>" << dbg_out(rAddString)
+// << "</addTextToParagraph>" << ::std::endl;
+#endif
+*/
+ 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;
+ }
+
+ return true;
+}
+
+// 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(USHORT 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)
+ {
+ bPgSecBreak = true;
+ pCtrlStck->KillUnlockedAttrs(*pPaM->GetPoint());
+ /*
+ #74468#
+ 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.
+ */
+ if (!bWasParaEnd)
+ {
+ 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) );
+
+ BYTE nBCode;
+ 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;
+ 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:
+ //#108817# 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. ##
+ 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';
+ else
+ {
+ // 0x15 is special --> so it's our field end mark...;
+ // hmmm what about field marks not handled by us??, maybe a problem with nested fields;
+ // probably an area of bugs... [well release quick and release often....]
+ if (!maNewFieldCtxStack.empty() && pPaM!=NULL && pPaM->GetPoint()!=NULL)
+ {
+ ::boost::scoped_ptr<WW8NewFieldCtx> pFieldCtx(maNewFieldCtxStack.back());
+ maNewFieldCtxStack.pop_back();
+ SwPosition aEndPos = *pPaM->GetPoint();
+ SwPaM aFldPam(pFieldCtx->GetPtNode(), pFieldCtx->GetPtCntnt(), aEndPos.nNode, aEndPos.nContent.GetIndex());
+ IDocumentMarkAccess* const pMarkAccess = rDoc.getIDocumentMarkAccess();
+ ::sw::mark::IFieldmark* pFieldmark =
+ dynamic_cast< ::sw::mark::IFieldmark*>(pMarkAccess->makeMark(
+ aFldPam,
+ pFieldCtx->GetBookmarkName(),
+ IDocumentMarkAccess::TEXT_FIELDMARK));
+ OSL_ENSURE(pFieldmark!=NULL,
+ "hmmm; why was the bookmark not created?");
+ if (pFieldmark)
+ pFieldCtx->SetCurrentFieldParamsTo(pFieldmark);
+ }
+ }
+ 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();
+
+ //#102160# If we have a bad 0x1 insert a space instead.
+ if (!pResult)
+ {
+ cInsert = ' ';
+ ASSERT(!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 );
+ AddTextToParagraph(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)
+{
+ USHORT 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;
+
+ ASSERT(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
+ {
+ ASSERT(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
+ ASSERT(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;
+ USHORT 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<USHORT> aStack;
+ pPlcxMan->TransferOpenSprms(aStack);
+
+ while (!aStack.empty())
+ {
+ USHORT 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;
+ BYTE 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
+ ASSERT(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<BYTE>(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 BYTE *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 BYTE *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 = (USHORT)( 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))
+ {
+ // --> OD 2005-01-07 #i39251# - insert text node for page break,
+ // if no one inserted.
+ // --> OD 2005-02-28 #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);
+ 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(BYTE 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),
+ 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;
+ bParaAutoBefore = false;
+ bParaAutoAfter = false;
+ nProgress = 0;
+ nSwNumLevel = nWwNumType = 0xff;
+ pTableDesc = 0;
+ pNumOlst = 0;
+ pNode_FLY_AT_CNTNT = 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
+ {
+ ASSERT( !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_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);
+
+ ASSERT(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();
+ ASSERT(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;
+ // --> OD 2008-08-06 #150965#
+ // Always read title page header/footer data - it could be used by following sections
+// if (rIter->HasTitlePage())
+ // <--
+ {
+ if (IsNewDoc() && rIter == rStart)
+ {
+ rIter->mpTitlePage =
+ mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_FIRST);
+ }
+ else
+ {
+ USHORT nPos = mrReader.rDoc.MakePageDesc(
+ ViewShell::GetShellRes()->GetPageDescName(mnDesc)
+ , 0, false);
+ rIter->mpTitlePage = &mrReader.rDoc._GetPageDesc(nPos);
+ }
+ ASSERT(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
+ {
+ USHORT nPos = mrReader.rDoc.MakePageDesc(
+ ViewShell::GetShellRes()->GetPageDescName(mnDesc,
+ false, rIter->HasTitlePage()),
+ rIter->mpTitlePage, false);
+ rIter->mpPage = &mrReader.rDoc._GetPageDesc(nPos);
+ }
+ ASSERT(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)
+ {
+ 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 = !bUseEnhFields && SectionIsProtected(*aIter); // do we really need this ?? I guess I have a different logic in editshell which disales this...
+ 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;
+ 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();
+ const SwTxtNode* pSttNd =
+ mrReader.rDoc.GetNodes()[ pPos->nNode ]->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;
+ /*
+ #112027# #110379#
+ 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())
+ {
+ ULONG nStart = aSectPaM.Start()->nNode.GetIndex();
+ 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());
+ 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()) {
+ sfx2::LoadOlePropertySet(xDocProps, pStg);
+ }
+ }
+}
+
+ULONG SwWW8ImplReader::CoreLoad(WW8Glossary *pGloss, const SwPosition &rPos)
+{
+ 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);
+
+ USHORT 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);
+
+#ifdef DEBUGDUMP
+ //experimental embedded ttf dumper
+ if (pWwFib->lcbSttbttmbd && (7 < pWwFib->nVersion))
+ {
+ pTableStream->Seek(pWwFib->fcSttbttmbd);
+ sal_uInt16 nZeros;
+ *pTableStream >> nZeros;
+ sal_uInt16 nNoEntries;
+ *pTableStream >> nNoEntries;
+ sal_uInt32 nUnknown1;
+ *pTableStream >> nUnknown1;
+ sal_uInt16 nUnknown2;
+ *pTableStream >> nUnknown2;
+ std::vector<sal_uInt32> aOffsets;
+ for (sal_uInt16 nI = 0; nI < nNoEntries; ++nI)
+ {
+ sal_uInt32 nOffset;
+ *pTableStream >> nOffset;
+ aOffsets.push_back(nOffset);
+ sal_uInt32 nUnknown3;
+ *pTableStream >> nUnknown3;
+ sal_uInt32 nUnknown4;
+ *pTableStream >> nUnknown4;
+ }
+ typedef std::vector<sal_uInt32>::iterator myIter;
+ myIter aEnd = aOffsets.end();
+ myIter aIter = aOffsets.begin();
+ while (aIter != aEnd)
+ {
+ sal_uInt32 nOffset = *aIter;
+ sal_uInt32 nLen = STREAM_SEEK_TO_END;
+ ++aIter;
+ pStrm->Seek(nOffset);
+ if (aIter != aEnd)
+ nLen = *aIter - nOffset;
+ SvStream *pDbg = sw::hack::CreateDebuggingStream(CREATE_CONST_ASC(".ttf.dump"));
+ sw::hack::DumpStream(*pStrm, *pDbg, nLen);
+ delete pDbg;
+ }
+ }
+#endif
+
+ // 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(); // #129053# 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
+
+ // Ich kann nicht setzen, wann neu nummerieren...
+ // aInfo.eNum = eNumA[pWDop->pDop->rncEdn];
+ 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();
+ const SwTxtNode* pSttNd =
+ rDoc.GetNodes()[ pPos->nNode ]->GetTxtNode();
+
+ USHORT 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
+ 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
+ {
+ 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
+ USHORT nShapeCount = pMSDffManager->GetShapeOrders()->Count();
+
+ for (USHORT 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
+ USHORT nTxBxCount = aTxBxSort.Count();
+ if( nTxBxCount )
+ {
+ SwFmtChain aChain;
+ for (USHORT 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;
+ if (pStg && !pGloss) /*meaningless for a glossary, cmc*/
+ {
+ const SvtFilterOptions* pVBAFlags = SvtFilterOptions::Get();
+ maTracer.EnterEnvironment(sw::log::eMacros);
+ SvxImportMSVBasic aVBasic(*mpDocShell, *pStg,
+ pVBAFlags->IsLoadWordBasicCode(),
+ pVBAFlags->IsLoadWordBasicStorage() );
+ String s1(CREATE_CONST_ASC("Macros"));
+ String s2(CREATE_CONST_ASC("VBA"));
+ int nRet = aVBasic.Import( s1, s2 );
+ if( 2 & nRet )
+ {
+ maTracer.Log(sw::log::eContainsVisualBasic);
+ rDoc.SetContainsMSVBasic(true);
+ }
+
+ StoreMacroCmds();
+
+ maTracer.LeaveEnvironment(sw::log::eMacros);
+ }
+ }
+
+ 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;
+}
+
+ULONG SwWW8ImplReader::SetSubStreams(SvStorageStreamRef &rTableStream,
+ SvStorageStreamRef &rDataStream)
+{
+ 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)
+ {
+ ASSERT( 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!
+ ASSERT( !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(svx::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
+ {
+ rIn.Seek(STREAM_SEEK_TO_END);
+ ULONG nLen = rIn.Tell();
+ rIn.Seek(0);
+
+ sal_uInt8 in[WW_BLOCKSIZE];
+ for (ULONG nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
+ {
+ ULONG 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(svx::MSCodec_XorWord95 &rCtx, SvStream &rIn, SvStream &rOut)
+ {
+ ULONG nSt = rIn.Tell();
+ rIn.Seek(STREAM_SEEK_TO_END);
+ ULONG nLen = rIn.Tell();
+ rIn.Seek(nSt);
+
+ rCtx.InitCipher();
+ rCtx.Skip(nSt);
+
+ sal_uInt8 in[0x4096];
+ for (ULONG nI = nSt; nI < nLen; nI += 0x4096)
+ {
+ 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, 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;
+ }
+
+}
+
+ULONG SwWW8ImplReader::LoadThroughDecryption(SwPaM& rPaM ,WW8Glossary *pGloss)
+{
+ 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;
+ switch (eAlgo)
+ {
+ default:
+ nErrRet = ERRCODE_SVX_READ_FILTER_CRYPT;
+ break;
+ case XOR:
+ {
+ String sUniPassword =
+ QueryPasswordForMedium(*(mpDocShell->GetMedium()));
+
+ ByteString sPassword(sUniPassword,
+ WW8Fib::GetFIBCharset(pWwFib->chseTables));
+
+ xub_StrLen nLen = sPassword.Len();
+ // DR: do not cut a wrong (too long) password
+ if( nLen <= 15 )
+ {
+ sal_uInt8 aPassword[16] = {0};
+
+ for (xub_StrLen nChar = 0; nChar < sPassword.Len(); ++nChar )
+ aPassword[nChar] = sPassword.GetChar(nChar);
+
+ svx::MSCodec_XorWord95 aCtx;
+ aCtx.InitKey(aPassword);
+ if (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;
+ }
+ }
+ }
+ }
+ break;
+ case RC4:
+ {
+ String sUniPassword =
+ QueryPasswordForMedium(*(mpDocShell->GetMedium()));
+
+ xub_StrLen nLen = sUniPassword.Len();
+ // DR: do not cut a wrong (too long) password
+ if (nLen <= 15)
+ {
+ sal_Unicode aPassword[16] = {0};
+ for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
+ aPassword[nChar] = sUniPassword.GetChar(nChar);
+
+ sal_uInt8 aDocId[ 16 ];
+ pTableStream->Read(aDocId, 16);
+ sal_uInt8 aSaltData[ 16 ];
+ pTableStream->Read(aSaltData, 16);
+ sal_uInt8 aSaltHash[ 16 ];
+ pTableStream->Read(aSaltHash, 16);
+
+ svx::MSCodec_Std97 aCtx;
+ aCtx.InitKey(aPassword, aDocId);
+ if (aCtx.VerifyKey(aSaltData, aSaltHash))
+ {
+ nErrRet = 0;
+
+ pTempTable = MakeTemp(aDecryptTable);
+ DecryptRC4(aCtx, *pTableStream, aDecryptTable);
+ pTableStream = &aDecryptTable;
+
+ pTempMain = MakeTemp(aDecryptMain);
+ DecryptRC4(aCtx, *pStrm, aDecryptMain);
+
+ if (!pDataStream || pDataStream == pStrm)
+ pDataStream = &aDecryptMain;
+ else
+ {
+ pTempData = MakeTemp(aDecryptData);
+ DecryptRC4(aCtx, *pDataStream, aDecryptData);
+ pDataStream = &aDecryptData;
+ }
+ SfxMedium* pMedium = mpDocShell->GetMedium();
+ if ( pMedium )
+ {
+ SfxItemSet* pSet = pMedium->GetItemSet();
+ if ( pSet )
+ pSet->Put( SfxStringItem(SID_PASSWORD, sUniPassword) );
+ }
+ }
+ }
+ }
+ 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:
+ BYTE mnNum;
+public:
+ outlineeq(BYTE nNum) : mnNum(nNum) {}
+ bool operator()(const SwTxtFmtColl *pTest) const
+ {
+ //return pTest->GetOutlineLevel() == mnNum; //#outline level,zhaojianwei
+ return pTest->IsAssignedToListLevelOfOutlineStyle() && pTest->GetAssignedOutlineStyleLevel() == mnNum; //<-end,zhaojianwei
+ }
+};
+
+void SwWW8ImplReader::SetOutLineStyles()
+{
+ /*
+ #i3674# & #101291# Load new document and insert document cases.
+ */
+ SwNumRule aOutlineRule(*rDoc.GetOutlineNumRule());
+ // --> OD 2005-10-14 #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 = rDoc.GetOutlineNumRule();
+ mpChosenOutlineNumRule = &aOutlineRule;
+ // <--
+
+ sw::ParaStyles aOutLined(sw::util::GetParaStyles(rDoc));
+ // --> OD 2009-02-04 #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.
+ */
+ USHORT nFlagsStyleOutlLevel = 0;
+ if (!mbNewDoc)
+ {
+ // --> OD 2008-12-16 #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)->GetOutlineLevel() < MAXLEVEL) //#outline level,zhaojianwei,
+ //nFlagsStyleOutlLevel |= 1 << (*aIter)->GetOutlineLevel();
+ if ((*aIter)->IsAssignedToListLevelOfOutlineStyle())
+ nFlagsStyleOutlLevel |= 1 << (*aIter)->GetAssignedOutlineStyleLevel();//<-end,zhaojianwei
+ else
+ break;
+ }
+ }
+ else
+ {
+ /*
+ #111955#
+ 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.
+ */
+ // --> OD 2005-11-07 #127520# - 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<USHORT, int>aRuleMap;
+ typedef std::map<USHORT, int>::iterator myIter;
+ for (USHORT nI = 0; nI < nColls; ++nI)
+ {
+ SwWW8StyInf& rSI = pCollA[ nI ];
+ if (
+ (MAXLEVEL > rSI.nOutlineLevel) && rSI.pOutlineNumrule &&
+ rSI.pFmt
+ )
+ {
+ // --> OD 2005-11-07 #127520#
+ myIter aIter = aRuleMap.find(nI);
+ // <--
+ if (aIter == aRuleMap.end())
+ {
+ // --> OD 2005-11-07 #127520#
+ 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;
+ // --> OD 2005-11-07 #127520#
+ mpChosenOutlineNumRule = pCollA[ aIter->first ].pOutlineNumrule;
+ // <--
+ }
+ }
+ // <--
+
+ ASSERT(mpChosenOutlineNumRule, "Impossible");
+ if (mpChosenOutlineNumRule)
+ aOutlineRule = *mpChosenOutlineNumRule;
+
+ if (mpChosenOutlineNumRule != &aOutlineRule)
+ {
+ // --> OD 2008-12-16 #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)->GetOutlineLevel() < MAXLEVEL)//#outline level,zhaojianwei
+ // (*aIter)->SetOutlineLevel(NO_NUMBERING);
+ if((*aIter)->IsAssignedToListLevelOfOutlineStyle())
+ (*aIter)->DeleteAssignmentToListLevelOfOutlineStyle(); //<-end
+
+ else
+ break;
+ }
+ }
+ }
+
+ USHORT nOldFlags = nFlagsStyleOutlLevel;
+
+ for (USHORT nI = 0; nI < nColls; ++nI)
+ {
+ SwWW8StyInf& rSI = pCollA[nI];
+
+ if (rSI.IsOutlineNumbered())
+ {
+ USHORT 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)->SetOutlineLevel(NO_NUMBERING);
+ ((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)->SetOutlineLevel(NO_NUMBERING);//#outline level,zhaojianwei
+ (*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.
+ */
+ BYTE nFromLevel = rSI.nListLevel;
+ BYTE nToLevel = rSI.nOutlineLevel;
+ const SwNumFmt& rRule=rSI.pOutlineNumrule->Get(nFromLevel);
+ aOutlineRule.Set(nToLevel, rRule);
+ // Set my outline level
+ //((SwTxtFmtColl*)rSI.pFmt)->SetOutlineLevel(nToLevel);//#outline level,zhaojianwei
+ ((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);
+ // --> OD 2005-10-14 #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 + BYTE Count
+ }
+ else
+ {
+ mpAtnNames->push_back(WW8Read_xstz(rStrm, 0, false));
+ // UNICode: doppelte Laenge + USHORT Count
+ nRead += mpAtnNames->rbegin()->Len() * 2 + 2;
+ }
+ }
+ rStrm.Seek( nOldPos );
+ }
+
+ const String *pRet = 0;
+ if (mpAtnNames && nIdx < mpAtnNames->size())
+ pRet = &((*mpAtnNames)[nIdx]);
+ return pRet;
+}
+
+ULONG SwWW8ImplReader::LoadDoc( SwPaM& rPaM,WW8Glossary *pGloss)
+{
+ 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;
+ }
+
+ 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)
+ )
+ {
+ //JP 06.05.99: teste auf eigenen 97-Fake!
+ if (pStg && 0xa5ec == nMagic)
+ {
+ ULONG nCurPos = pStrm->Tell();
+ if (pStrm->Seek(nCurPos + 22))
+ {
+ 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;
+ ASSERT( !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();
+}
+
+ULONG WW8Reader::Read(SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & /* FileName */)
+{
+ USHORT nOldBuffSize = 32768;
+ bool bNew = !bInsertMode; // Neues Doc ( kein Einfuegen )
+
+
+ SvStorageStreamRef refStrm; // damit uns keiner den Stream klaut
+ SvStream* pIn = pStrm;
+
+ ULONG nRet = 0;
+ BYTE nVersion = 8;
+
+ String sFltName = GetFltName();
+ if( sFltName.EqualsAscii( "WW6" ) )
+ {
+ if (pStrm)
+ nVersion = 6;
+ else
+ {
+ ASSERT(!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
+ {
+ ASSERT(!this, "WinWord 95/97 Reader-Read ohne Storage");
+ nRet = ERR_SWG_READ_ERROR;
+ }
+ }
+
+ if( !nRet )
+ {
+ //JP 18.01.96: 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);
+ nRet = pRdr->LoadDoc( rPam );
+ 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;
+}
+
+BOOL WW8Reader::HasGlossaries() const
+{
+ return true;
+}
+
+BOOL WW8Reader::ReadGlossaries(SwTextBlocks& rBlocks, BOOL bSaveRelFiles) const
+{
+ bool bRet=false;
+
+ WW8Reader *pThis = const_cast<WW8Reader *>(this);
+
+ USHORT 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;
+}
+
+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();
+ {
+ // --> OD 2004-12-08 #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 BYTE* pSprm = aDesc.pMemPos;
+
+ while (nLen >= 2 && !nPictureId)
+ {
+ USHORT nId = aSprmParser.GetSprmId(pSprm);
+ USHORT 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;
+}
+
+BOOL SwMSDffManager::ShapeHasText(ULONG, 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;
+ // --> OD 2006-01-19 #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;
+ }
+ }
+}
+
+/* vi:set tabstop=4 shiftwidth=4 expandtab: */