1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <com/sun/star/embed/ElementModes.hpp>
23 #include <i18nlangtag/languagetag.hxx>
25 #include <unotools/ucbstreamhelper.hxx>
26 #include <rtl/random.h>
28 #include <sfx2/docinf.hxx>
29 #include <sfx2/request.hxx>
30 #include <sfx2/frame.hxx>
31 #include <tools/urlobj.hxx>
32 #include <unotools/tempfile.hxx>
34 #include <comphelper/docpasswordrequest.hxx>
35 #include <comphelper/string.hxx>
37 #include <editeng/brushitem.hxx>
38 #include <editeng/tstpitem.hxx>
39 #include <editeng/ulspitem.hxx>
40 #include <editeng/langitem.hxx>
41 #include <editeng/opaqitem.hxx>
42 #include <editeng/charhiddenitem.hxx>
43 #include <editeng/fontitem.hxx>
44 #include <svx/unoapi.hxx>
45 #include <svx/svdoole2.hxx>
46 #include <svx/svdoashp.hxx>
47 #include <svx/svxerr.hxx>
48 #include <filter/msfilter/mscodec.hxx>
49 #include <svx/svdmodel.hxx>
50 #include <svx/xflclit.hxx>
52 #include <unotools/fltrcfg.hxx>
55 #include <fmtinfmt.hxx>
57 #include <fmthdft.hxx>
58 #include <fmtcntnt.hxx>
59 #include <fmtcnct.hxx>
60 #include <fmtanchr.hxx>
61 #include <fmtpdsc.hxx>
62 #include <ftninfo.hxx>
65 #include <ndtxt.hxx> // class SwTxtNode
66 #include <pagedesc.hxx> // class SwPageDesc
68 #include <fmtclbl.hxx>
69 #include <section.hxx>
71 #include <docufld.hxx>
72 #include <swfltopt.hxx>
74 #include <shellres.hxx>
75 #include <mdiexp.hxx> // Progress
76 #include <statstr.hrc> // ResId fuer Statusleiste
77 #include <swerror.h> // ERR_WW8_...
78 #include <swtable.hxx> // class SwTableLines, ...
79 #include <fchrfmt.hxx>
80 #include <charfmt.hxx>
83 #include <comphelper/extract.hxx>
86 #include "writerwordglue.hxx"
89 #include <editeng/editids.hrc>
90 #include <txtflcnt.hxx>
91 #include <fmtflcnt.hxx>
92 #include <txatbase.hxx>
94 #include "ww8par2.hxx" // class WW8RStyle, class WW8AnchorPara
96 #include <com/sun/star/beans/PropertyAttribute.hpp>
97 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
98 #include <com/sun/star/document/XViewDataSupplier.hpp>
99 #include <com/sun/star/document/IndexedPropertyValues.hpp>
100 #include <svl/itemiter.hxx> //SfxItemIter
102 #include <comphelper/processfactory.hxx>
103 #include <basic/basmgr.hxx>
105 #include "ww8toolbar.hxx"
106 #include <osl/file.hxx>
108 #include <breakit.hxx>
110 #if OSL_DEBUG_LEVEL > 1
112 #include <dbgoutsw.hxx>
114 #include <unotools/localfilehelper.hxx>
116 #include "WW8Sttbf.hxx"
117 #include "WW8FibData.hxx"
119 using namespace ::com::sun::star
;
120 using namespace sw::util
;
121 using namespace sw::types
;
122 using namespace nsHdFtFlags
;
124 #include <com/sun/star/i18n/ScriptType.hpp>
125 #include <unotools/pathoptions.hxx>
126 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
128 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
129 #include <comphelper/mediadescriptor.hxx>
130 #include <oox/ole/vbaproject.hxx>
131 #include <oox/ole/olestorage.hxx>
133 using ::comphelper::MediaDescriptor
;
135 class BasicProjImportHelper
137 SwDocShell
& mrDocShell
;
138 uno::Reference
< uno::XComponentContext
> mxCtx
;
140 BasicProjImportHelper( SwDocShell
& rShell
) : mrDocShell( rShell
)
142 mxCtx
= comphelper::getProcessComponentContext();
144 bool import( const uno::Reference
< io::XInputStream
>& rxIn
);
145 OUString
getProjectName();
148 bool BasicProjImportHelper::import( const uno::Reference
< io::XInputStream
>& rxIn
)
153 oox::ole::OleStorage
root( mxCtx
, rxIn
, false );
154 oox::StorageRef vbaStg
= root
.openSubStorage( "Macros" , false );
157 oox::ole::VbaProject
aVbaPrj( mxCtx
, mrDocShell
.GetModel(), OUString("Writer") );
158 bRet
= aVbaPrj
.importVbaProject( *vbaStg
);
161 catch( const uno::Exception
& )
168 OUString
BasicProjImportHelper::getProjectName()
170 OUString
sProjName( "Standard" );
171 uno::Reference
< beans::XPropertySet
> xProps( mrDocShell
.GetModel(), uno::UNO_QUERY
);
176 uno::Reference
< script::vba::XVBACompatibility
> xVBA( xProps
->getPropertyValue( "BasicLibraries" ), uno::UNO_QUERY_THROW
);
177 sProjName
= xVBA
->getProjectName();
180 catch( const uno::Exception
& )
194 SBBItem() : cchData(0){}
200 std::vector
< SBBItem
> dataItems
;
203 Sttb
& operator = ( const Sttb
&);
207 bool Read(SvStream
&rS
);
208 void Print( FILE* fp
);
209 OUString
getStringAtIndex( sal_uInt32
);
212 Sttb::Sttb() : fExtend( 0 )
222 bool Sttb::Read( SvStream
& rS
)
224 OSL_TRACE("Sttb::Read() stream pos 0x%x", rS
.Tell() );
226 rS
>> fExtend
>> cData
>> cbExtra
;
229 for ( sal_Int32 index
= 0; index
< cData
; ++index
)
233 aItem
.data
= read_uInt16s_ToOUString(rS
, aItem
.cchData
);
234 dataItems
.push_back( aItem
);
240 void Sttb::Print( FILE* fp
)
242 fprintf( fp
, "[ 0x%" SAL_PRIxUINT32
" ] Sttb - dump\n", nOffSet
);
243 fprintf( fp
, " fExtend 0x%x [expected 0xFFFF ]\n", fExtend
);
244 fprintf( fp
, " cData no. or string data items %d (0x%x)\n", cData
, cData
);
248 for ( sal_Int32 index
= 0; index
< cData
; ++index
)
249 fprintf(fp
," string dataItem[ %d(0x%x) ] has name %s\n", static_cast< int >( index
), static_cast< unsigned int >( index
), OUStringToOString( dataItems
[ index
].data
, RTL_TEXTENCODING_UTF8
).getStr() );
255 Sttb::getStringAtIndex( sal_uInt32 index
)
258 if ( index
< dataItems
.size() )
259 aRet
= dataItems
[ index
].data
;
263 SwMSDffManager::SwMSDffManager( SwWW8ImplReader
& rRdr
)
264 : SvxMSDffManager(*rRdr
.pTableStream
, rRdr
.GetBaseURL(), rRdr
.pWwFib
->fcDggInfo
,
265 rRdr
.pDataStream
, 0, 0, COL_WHITE
, 12, rRdr
.pStrm
),
266 rReader(rRdr
), pFallbackStream(0)
268 SetSvxMSDffSettings( GetSvxMSDffSettings() );
269 nSvxMSDffOLEConvFlags
= SwMSDffManager::GetFilterFlags();
272 sal_uInt32
SwMSDffManager::GetFilterFlags()
274 sal_uInt32
nFlags(0);
275 const SvtFilterOptions
& rOpt
= SvtFilterOptions::Get();
276 if (rOpt
.IsMathType2Math())
277 nFlags
|= OLE_MATHTYPE_2_STARMATH
;
278 if (rOpt
.IsExcel2Calc())
279 nFlags
|= OLE_EXCEL_2_STARCALC
;
280 if (rOpt
.IsPowerPoint2Impress())
281 nFlags
|= OLE_POWERPOINT_2_STARIMPRESS
;
282 if (rOpt
.IsWinWord2Writer())
283 nFlags
|= OLE_WINWORD_2_STARWRITER
;
288 * I would like to override the default OLE importing to add a test
289 * and conversion of OCX controls from their native OLE type into our
290 * native nonOLE Form Control Objects.
294 // #i32596# - consider new parameter <_nCalledByGroup>
295 SdrObject
* SwMSDffManager::ImportOLE( long nOLEId
,
297 const Rectangle
& rBoundRect
,
298 const Rectangle
& rVisArea
,
299 const int _nCalledByGroup
,
300 sal_Int64 nAspect
) const
302 // #i32596# - no import of OLE object, if it's inside a group.
303 // NOTE: This can be undone, if grouping of Writer fly frames is possible or
304 // if drawing OLE objects are allowed in Writer.
305 if ( _nCalledByGroup
> 0 )
311 OUString sStorageName
;
312 SotStorageRef xSrcStg
;
313 uno::Reference
< embed::XStorage
> xDstStg
;
314 if( GetOLEStorageName( nOLEId
, sStorageName
, xSrcStg
, xDstStg
))
316 SvStorageRef xSrc
= xSrcStg
->OpenSotStorage( sStorageName
,
317 STREAM_READWRITE
| STREAM_SHARE_DENYALL
);
318 OSL_ENSURE(rReader
.pFormImpl
, "No Form Implementation!");
319 ::com::sun::star::uno::Reference
< ::com::sun::star::drawing::XShape
> xShape
;
320 if ( (!(rReader
.bIsHeader
|| rReader
.bIsFooter
)) &&
321 rReader
.pFormImpl
->ReadOCXStream(xSrc
,&xShape
,true))
323 pRet
= GetSdrObjectFromXShape(xShape
);
327 ErrCode nError
= ERRCODE_NONE
;
328 pRet
= CreateSdrOLEFromStorage( sStorageName
, xSrcStg
, xDstStg
,
329 rGrf
, rBoundRect
, rVisArea
, pStData
, nError
, nSvxMSDffOLEConvFlags
, nAspect
);
335 void SwMSDffManager::DisableFallbackStream()
337 OSL_ENSURE(!pFallbackStream
,
338 "if you're recursive, you're broken");
339 pFallbackStream
= pStData2
;
340 aOldEscherBlipCache
= aEscherBlipCache
;
341 aEscherBlipCache
.clear();
345 void SwMSDffManager::EnableFallbackStream()
347 pStData2
= pFallbackStream
;
348 aEscherBlipCache
= aOldEscherBlipCache
;
349 aOldEscherBlipCache
.clear();
353 sal_uInt16
SwWW8ImplReader::GetToggleAttrFlags() const
355 return pCtrlStck
? pCtrlStck
->GetToggleAttrFlags() : 0;
358 sal_uInt16
SwWW8ImplReader::GetToggleBiDiAttrFlags() const
360 return pCtrlStck
? pCtrlStck
->GetToggleBiDiAttrFlags() : 0;
363 void SwWW8ImplReader::SetToggleAttrFlags(sal_uInt16 nFlags
)
366 pCtrlStck
->SetToggleAttrFlags(nFlags
);
369 void SwWW8ImplReader::SetToggleBiDiAttrFlags(sal_uInt16 nFlags
)
372 pCtrlStck
->SetToggleBiDiAttrFlags(nFlags
);
376 SdrObject
* SwMSDffManager::ProcessObj(SvStream
& rSt
,
377 DffObjData
& rObjData
,
379 Rectangle
& rTextRect
,
383 if( !rTextRect
.IsEmpty() )
385 SvxMSDffImportData
& rImportData
= *(SvxMSDffImportData
*)pData
;
386 SvxMSDffImportRec
* pImpRec
= new SvxMSDffImportRec
;
388 // fill Import Record with data
389 pImpRec
->nShapeId
= rObjData
.nShapeId
;
390 pImpRec
->eShapeType
= rObjData
.eShapeType
;
392 rObjData
.bClientAnchor
= maShapeRecords
.SeekToContent( rSt
,
393 DFF_msofbtClientAnchor
,
394 SEEK_FROM_CURRENT_AND_RESTART
);
395 if( rObjData
.bClientAnchor
)
396 ProcessClientAnchor( rSt
,
397 maShapeRecords
.Current()->nRecLen
,
398 pImpRec
->pClientAnchorBuffer
, pImpRec
->nClientAnchorLen
);
400 rObjData
.bClientData
= maShapeRecords
.SeekToContent( rSt
,
401 DFF_msofbtClientData
,
402 SEEK_FROM_CURRENT_AND_RESTART
);
403 if( rObjData
.bClientData
)
404 ProcessClientData( rSt
,
405 maShapeRecords
.Current()->nRecLen
,
406 pImpRec
->pClientDataBuffer
, pImpRec
->nClientDataLen
);
409 // process user (== Winword) defined parameters in 0xF122 record
410 // #i84783# - set special value to determine, if property is provided or not.
411 pImpRec
->nLayoutInTableCell
= 0xFFFFFFFF;
413 if( maShapeRecords
.SeekToContent( rSt
,
415 SEEK_FROM_CURRENT_AND_RESTART
)
416 && maShapeRecords
.Current()->nRecLen
)
418 sal_uInt32 nBytesLeft
= maShapeRecords
.Current()->nRecLen
;
421 while( 5 < nBytesLeft
)
424 if ( rSt
.GetError() != 0 )
429 case 0x038F: pImpRec
->nXAlign
= nUDData
; break;
431 delete pImpRec
->pXRelTo
;
432 pImpRec
->pXRelTo
= new sal_uInt32
;
433 *(pImpRec
->pXRelTo
) = nUDData
;
435 case 0x0391: pImpRec
->nYAlign
= nUDData
; break;
437 delete pImpRec
->pYRelTo
;
438 pImpRec
->pYRelTo
= new sal_uInt32
;
439 *(pImpRec
->pYRelTo
) = nUDData
;
441 case 0x03BF: pImpRec
->nLayoutInTableCell
= nUDData
; break;
443 // This seems to correspond to o:hrpct from .docx (even including
444 // the difference that it's in 0.1% even though the .docx spec
446 pImpRec
->relativeHorizontalWidth
= nUDData
;
449 // And this is really just a guess, but a mere presence of this
450 // flag makes a horizontal rule be as wide as the page (unless
451 // overriden by something), so it probably matches o:hr from .docx.
452 pImpRec
->isHorizontalRule
= true;
455 if ( rSt
.GetError() != 0 )
457 pImpRec
->bHasUDefProp
= sal_True
;
462 // Textrahmen, auch Title oder Outline
463 sal_uInt32 nTextId
= GetPropertyValue( DFF_Prop_lTxid
, 0 );
466 SfxItemSet
aSet( pSdrModel
->GetItemPool() );
468 //Originally anything that as a mso_sptTextBox was created as a
469 //textbox, this was changed for #88277# to be created as a simple
470 //rect to keep impress happy. For the rest of us we'd like to turn
471 //it back into a textbox again.
472 bool bIsSimpleDrawingTextBox
= (pImpRec
->eShapeType
== mso_sptTextBox
);
473 if (!bIsSimpleDrawingTextBox
)
476 //a) its a simple text object or
477 //b) its a rectangle with text and square wrapping.
478 bIsSimpleDrawingTextBox
=
480 (pImpRec
->eShapeType
== mso_sptTextSimple
) ||
482 (pImpRec
->eShapeType
== mso_sptRectangle
)
483 && ShapeHasText(pImpRec
->nShapeId
, rObjData
.rSpHd
.GetRecBegFilePos() )
488 // Distance of Textbox to it's surrounding Autoshape
489 sal_Int32 nTextLeft
= GetPropertyValue( DFF_Prop_dxTextLeft
, 91440L);
490 sal_Int32 nTextRight
= GetPropertyValue( DFF_Prop_dxTextRight
, 91440L );
491 sal_Int32 nTextTop
= GetPropertyValue( DFF_Prop_dyTextTop
, 45720L );
492 sal_Int32 nTextBottom
= GetPropertyValue( DFF_Prop_dyTextBottom
, 45720L );
494 ScaleEmu( nTextLeft
);
495 ScaleEmu( nTextRight
);
496 ScaleEmu( nTextTop
);
497 ScaleEmu( nTextBottom
);
499 sal_Int32 nTextRotationAngle
=0;
500 bool bVerticalText
= false;
501 if ( IsProperty( DFF_Prop_txflTextFlow
) )
503 MSO_TextFlow eTextFlow
= (MSO_TextFlow
)(GetPropertyValue(
504 DFF_Prop_txflTextFlow
) & 0xFFFF);
508 nTextRotationAngle
= 9000;
512 nTextRotationAngle
= 27000;
515 bVerticalText
= true;
518 bVerticalText
= true;
519 nTextRotationAngle
= 9000;
526 if (nTextRotationAngle
)
528 while (nTextRotationAngle
> 360000)
529 nTextRotationAngle
-=9000;
530 switch (nTextRotationAngle
)
534 long nWidth
= rTextRect
.GetWidth();
535 rTextRect
.Right() = rTextRect
.Left() + rTextRect
.GetHeight();
536 rTextRect
.Bottom() = rTextRect
.Top() + nWidth
;
538 sal_Int32 nOldTextLeft
= nTextLeft
;
539 sal_Int32 nOldTextRight
= nTextRight
;
540 sal_Int32 nOldTextTop
= nTextTop
;
541 sal_Int32 nOldTextBottom
= nTextBottom
;
543 nTextLeft
= nOldTextBottom
;
544 nTextRight
= nOldTextTop
;
545 nTextTop
= nOldTextLeft
;
546 nTextBottom
= nOldTextRight
;
551 long nWidth
= rTextRect
.GetWidth();
552 rTextRect
.Right() = rTextRect
.Left() + rTextRect
.GetHeight();
553 rTextRect
.Bottom() = rTextRect
.Top() + nWidth
;
555 sal_Int32 nOldTextLeft
= nTextLeft
;
556 sal_Int32 nOldTextRight
= nTextRight
;
557 sal_Int32 nOldTextTop
= nTextTop
;
558 sal_Int32 nOldTextBottom
= nTextBottom
;
560 nTextLeft
= nOldTextTop
;
561 nTextRight
= nOldTextBottom
;
562 nTextTop
= nOldTextRight
;
563 nTextBottom
= nOldTextLeft
;
571 if (bIsSimpleDrawingTextBox
)
573 SdrObject::Free( pObj
);
574 pObj
= new SdrRectObj(OBJ_TEXT
, rTextRect
);
577 // Die vertikalen Absatzeinrueckungen sind im BoundRect mit drin,
579 Rectangle
aNewRect(rTextRect
);
580 aNewRect
.Bottom() -= nTextTop
+ nTextBottom
;
581 aNewRect
.Right() -= nTextLeft
+ nTextRight
;
583 // Nur falls es eine einfache Textbox ist, darf der Writer
584 // das Objekt durch einen Rahmen ersetzen, ansonsten
585 if( bIsSimpleDrawingTextBox
)
587 ::boost::shared_ptr
<SvxMSDffShapeInfo
> const pTmpRec(
588 new SvxMSDffShapeInfo(0, pImpRec
->nShapeId
));
590 SvxMSDffShapeInfos_ById::const_iterator
const it
=
591 GetShapeInfos()->find(pTmpRec
);
592 if (it
!= GetShapeInfos()->end())
594 SvxMSDffShapeInfo
& rInfo
= **it
;
595 pImpRec
->bReplaceByFly
= rInfo
.bReplaceByFly
;
596 pImpRec
->bLastBoxInChain
= rInfo
.bLastBoxInChain
;
600 if( bIsSimpleDrawingTextBox
)
601 ApplyAttributes( rSt
, aSet
, rObjData
);
603 if (GetPropertyValue(DFF_Prop_FitTextToShape
) & 2)
605 aSet
.Put( SdrTextAutoGrowHeightItem( sal_True
) );
606 aSet
.Put( SdrTextMinFrameHeightItem(
607 aNewRect
.Bottom() - aNewRect
.Top() ) );
608 aSet
.Put( SdrTextMinFrameWidthItem(
609 aNewRect
.Right() - aNewRect
.Left() ) );
613 aSet
.Put( SdrTextAutoGrowHeightItem( sal_False
) );
614 aSet
.Put( SdrTextAutoGrowWidthItem( sal_False
) );
617 switch ( (MSO_WrapMode
)
618 GetPropertyValue( DFF_Prop_WrapText
, mso_wrapSquare
) )
621 aSet
.Put( SdrTextAutoGrowWidthItem( sal_True
) );
622 pImpRec
->bAutoWidth
= true;
624 case mso_wrapByPoints
:
625 aSet
.Put( SdrTextContourFrameItem( sal_True
) );
631 // Abstaende an den Raendern der Textbox setzen
632 aSet
.Put( SdrTextLeftDistItem( nTextLeft
) );
633 aSet
.Put( SdrTextRightDistItem( nTextRight
) );
634 aSet
.Put( SdrTextUpperDistItem( nTextTop
) );
635 aSet
.Put( SdrTextLowerDistItem( nTextBottom
) );
636 pImpRec
->nDxTextLeft
= nTextLeft
;
637 pImpRec
->nDyTextTop
= nTextTop
;
638 pImpRec
->nDxTextRight
= nTextRight
;
639 pImpRec
->nDyTextBottom
= nTextBottom
;
641 // taking the correct default (which is mso_anchorTop)
642 MSO_Anchor eTextAnchor
=
643 (MSO_Anchor
)GetPropertyValue( DFF_Prop_anchorText
, mso_anchorTop
);
645 SdrTextVertAdjust eTVA
= bVerticalText
646 ? SDRTEXTVERTADJUST_BLOCK
647 : SDRTEXTVERTADJUST_CENTER
;
648 SdrTextHorzAdjust eTHA
= bVerticalText
649 ? SDRTEXTHORZADJUST_CENTER
650 : SDRTEXTHORZADJUST_BLOCK
;
652 switch( eTextAnchor
)
657 eTHA
= SDRTEXTHORZADJUST_RIGHT
;
659 eTVA
= SDRTEXTVERTADJUST_TOP
;
662 case mso_anchorTopCentered
:
665 eTHA
= SDRTEXTHORZADJUST_RIGHT
;
667 eTVA
= SDRTEXTVERTADJUST_TOP
;
670 case mso_anchorMiddle
:
672 case mso_anchorMiddleCentered
:
674 case mso_anchorBottom
:
677 eTHA
= SDRTEXTHORZADJUST_LEFT
;
679 eTVA
= SDRTEXTVERTADJUST_BOTTOM
;
682 case mso_anchorBottomCentered
:
685 eTHA
= SDRTEXTHORZADJUST_LEFT
;
687 eTVA
= SDRTEXTVERTADJUST_BOTTOM
;
694 aSet
.Put( SdrTextVertAdjustItem( eTVA
) );
695 aSet
.Put( SdrTextHorzAdjustItem( eTHA
) );
699 pObj
->SetMergedItemSet(aSet
);
700 pObj
->SetModel(pSdrModel
);
702 if (bVerticalText
&& dynamic_cast< SdrTextObj
* >( pObj
) )
703 dynamic_cast< SdrTextObj
* >( pObj
)->SetVerticalWriting(sal_True
);
705 if ( bIsSimpleDrawingTextBox
)
707 if ( nTextRotationAngle
)
709 long nMinWH
= rTextRect
.GetWidth() < rTextRect
.GetHeight() ?
710 rTextRect
.GetWidth() : rTextRect
.GetHeight();
712 Point
aPivot(rTextRect
.TopLeft());
713 aPivot
.X() += nMinWH
;
714 aPivot
.Y() += nMinWH
;
715 double a
= nTextRotationAngle
* nPi180
;
716 pObj
->NbcRotate(aPivot
, nTextRotationAngle
, sin(a
), cos(a
));
720 if ( ( ( rObjData
.nSpFlags
& SP_FFLIPV
) || mnFix16Angle
|| nTextRotationAngle
) && dynamic_cast< SdrObjCustomShape
* >( pObj
) )
722 SdrObjCustomShape
* pCustomShape
= dynamic_cast< SdrObjCustomShape
* >( pObj
);
724 double fExtraTextRotation
= 0.0;
725 if ( mnFix16Angle
&& !( GetPropertyValue( DFF_Prop_FitTextToShape
) & 4 ) )
726 { // text is already rotated, we have to take back the object rotation if DFF_Prop_RotateText is false
727 fExtraTextRotation
= -mnFix16Angle
;
729 if ( rObjData
.nSpFlags
& SP_FFLIPV
) // sj: in ppt the text is flipped, whereas in word the text
730 { // remains unchanged, so we have to take back the flipping here
731 fExtraTextRotation
+= 18000.0; // because our core will flip text if the shape is flipped.
733 fExtraTextRotation
+= nTextRotationAngle
;
734 if ( !::basegfx::fTools::equalZero( fExtraTextRotation
) )
736 fExtraTextRotation
/= 100.0;
737 SdrCustomShapeGeometryItem
aGeometryItem( (SdrCustomShapeGeometryItem
&)pCustomShape
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
) );
738 const OUString
sTextRotateAngle( "TextRotateAngle" );
739 com::sun::star::beans::PropertyValue aPropVal
;
740 aPropVal
.Name
= sTextRotateAngle
;
741 aPropVal
.Value
<<= fExtraTextRotation
;
742 aGeometryItem
.SetPropertyValue( aPropVal
);
743 pCustomShape
->SetMergedItem( aGeometryItem
);
746 else if ( mnFix16Angle
)
748 // rotate text with shape ?
749 double a
= mnFix16Angle
* nPi180
;
750 pObj
->NbcRotate( rObjData
.aBoundRect
.Center(), mnFix16Angle
,
751 sin( a
), cos( a
) );
757 // simple rectangular objects are ignored by ImportObj() :-(
758 // this is OK for Draw but not for Calc and Writer
759 // cause here these objects have a default border
760 pObj
= new SdrRectObj(rTextRect
);
761 pObj
->SetModel( pSdrModel
);
762 SfxItemSet
aSet( pSdrModel
->GetItemPool() );
763 ApplyAttributes( rSt
, aSet
, rObjData
);
765 const SfxPoolItem
* pPoolItem
=NULL
;
766 SfxItemState eState
= aSet
.GetItemState( XATTR_FILLCOLOR
,
767 sal_False
, &pPoolItem
);
768 if( SFX_ITEM_DEFAULT
== eState
)
769 aSet
.Put( XFillColorItem( String(),
770 Color( mnDefaultColor
) ) );
771 pObj
->SetMergedItemSet(aSet
);
774 //Means that fBehindDocument is set
775 if (GetPropertyValue(DFF_Prop_fPrint
) & 0x20)
776 pImpRec
->bDrawHell
= sal_True
;
778 pImpRec
->bDrawHell
= sal_False
;
779 if (GetPropertyValue(DFF_Prop_fPrint
) & 0x02)
780 pImpRec
->bHidden
= sal_True
;
781 pImpRec
->nNextShapeId
= GetPropertyValue( DFF_Prop_hspNext
, 0 );
785 pImpRec
->aTextId
.nTxBxS
= (sal_uInt16
)( nTextId
>> 16 );
786 pImpRec
->aTextId
.nSequence
= (sal_uInt16
)nTextId
;
789 pImpRec
->nDxWrapDistLeft
= GetPropertyValue(
790 DFF_Prop_dxWrapDistLeft
, 114935L ) / 635L;
791 pImpRec
->nDyWrapDistTop
= GetPropertyValue(
792 DFF_Prop_dyWrapDistTop
, 0 ) / 635L;
793 pImpRec
->nDxWrapDistRight
= GetPropertyValue(
794 DFF_Prop_dxWrapDistRight
, 114935L ) / 635L;
795 pImpRec
->nDyWrapDistBottom
= GetPropertyValue(
796 DFF_Prop_dyWrapDistBottom
, 0 ) / 635L;
797 // 16.16 fraction times total image width or height, as appropriate.
799 if (SeekToContent(DFF_Prop_pWrapPolygonVertices
, rSt
))
801 delete pImpRec
->pWrapPolygon
;
802 pImpRec
->pWrapPolygon
= NULL
;
804 sal_uInt16 nNumElemVert
, nNumElemMemVert
, nElemSizeVert
;
805 rSt
>> nNumElemVert
>> nNumElemMemVert
>> nElemSizeVert
;
806 if (nNumElemVert
&& ((nElemSizeVert
== 8) || (nElemSizeVert
== 4)))
808 pImpRec
->pWrapPolygon
= new Polygon(nNumElemVert
);
809 for (sal_uInt16 i
= 0; i
< nNumElemVert
; ++i
)
812 if (nElemSizeVert
== 8)
816 sal_Int16 nSmallX
, nSmallY
;
817 rSt
>> nSmallX
>> nSmallY
;
821 (*(pImpRec
->pWrapPolygon
))[i
].X() = nX
;
822 (*(pImpRec
->pWrapPolygon
))[i
].Y() = nY
;
827 pImpRec
->nCropFromTop
= GetPropertyValue(
828 DFF_Prop_cropFromTop
, 0 );
829 pImpRec
->nCropFromBottom
= GetPropertyValue(
830 DFF_Prop_cropFromBottom
, 0 );
831 pImpRec
->nCropFromLeft
= GetPropertyValue(
832 DFF_Prop_cropFromLeft
, 0 );
833 pImpRec
->nCropFromRight
= GetPropertyValue(
834 DFF_Prop_cropFromRight
, 0 );
836 sal_uInt32 nLineFlags
= GetPropertyValue( DFF_Prop_fNoLineDrawDash
);
838 if ( !IsHardAttribute( DFF_Prop_fLine
) &&
839 pImpRec
->eShapeType
== mso_sptPictureFrame
)
844 pImpRec
->eLineStyle
= (nLineFlags
& 8)
845 ? (MSO_LineStyle
)GetPropertyValue(
848 : (MSO_LineStyle
)USHRT_MAX
;
849 pImpRec
->eLineDashing
= (MSO_LineDashing
)GetPropertyValue(
850 DFF_Prop_lineDashing
, mso_lineSolid
);
852 pImpRec
->nFlags
= rObjData
.nSpFlags
;
854 if( pImpRec
->nShapeId
)
856 // Import-Record-Liste ergaenzen
857 pImpRec
->pObj
= pObj
;
858 rImportData
.aRecords
.insert( pImpRec
);
860 // Eintrag in Z-Order-Liste um Zeiger auf dieses Objekt ergaenzen
861 /*Only store objects which are not deep inside the tree*/
862 if( ( rObjData
.nCalledByGroup
== 0 )
864 ( (rObjData
.nSpFlags
& SP_FGROUP
)
865 && (rObjData
.nCalledByGroup
< 2) )
867 StoreShapeOrder( pImpRec
->nShapeId
,
868 ( ( (sal_uLong
)pImpRec
->aTextId
.nTxBxS
) << 16 )
869 + pImpRec
->aTextId
.nSequence
, pObj
);
878 /***************************************************************************
879 # Spezial FastSave - Attribute
880 #**************************************************************************/
882 void SwWW8ImplReader::Read_StyleCode( sal_uInt16
, const sal_uInt8
* pData
, short nLen
)
889 sal_uInt16 nColl
= 0;
890 if (pWwFib
->GetFIBVersion() <= ww::eWW2
)
893 nColl
= SVBT16ToShort(pData
);
894 if (nColl
< vColl
.size())
896 SetTxtFmtCollAndListLevel( *pPaM
, vColl
[nColl
] );
901 // Read_Majority ist fuer Majority ( 103 ) und Majority50 ( 108 )
902 void SwWW8ImplReader::Read_Majority( sal_uInt16
, const sal_uInt8
* , short )
906 //-----------------------------------------
908 //-----------------------------------------
909 void SwWW8FltControlStack::NewAttr(const SwPosition
& rPos
,
910 const SfxPoolItem
& rAttr
)
912 OSL_ENSURE(RES_TXTATR_FIELD
!= rAttr
.Which(), "probably don't want to put"
913 "fields into the control stack");
914 OSL_ENSURE(RES_FLTR_REDLINE
!= rAttr
.Which(), "probably don't want to put"
915 "redlines into the control stack");
916 SwFltControlStack::NewAttr(rPos
, rAttr
);
919 SwFltStackEntry
* SwWW8FltControlStack::SetAttr(const SwPosition
& rPos
, sal_uInt16 nAttrId
,
920 sal_Bool bTstEnde
, long nHand
, sal_Bool
)
922 SwFltStackEntry
*pRet
= NULL
;
923 //Doing a textbox, and using the control stack only as a temporary
924 //collection point for properties which will are not to be set into
926 if (rReader
.pPlcxMan
&& rReader
.pPlcxMan
->GetDoingDrawTextBox())
928 size_t nCnt
= size();
929 for (size_t i
=0; i
< nCnt
; ++i
)
931 SwFltStackEntry
& rEntry
= (*this)[i
];
932 if (nAttrId
== rEntry
.pAttr
->Which())
934 DeleteAndDestroy(i
--);
939 else //Normal case, set the attribute into the document
940 pRet
= SwFltControlStack::SetAttr(rPos
, nAttrId
, bTstEnde
, nHand
);
944 long GetListFirstLineIndent(const SwNumFmt
&rFmt
)
946 OSL_ENSURE( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
,
947 "<GetListFirstLineIndent> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
949 SvxAdjust eAdj
= rFmt
.GetNumAdjust();
950 long nReverseListIndented
;
951 if (eAdj
== SVX_ADJUST_RIGHT
)
952 nReverseListIndented
= -rFmt
.GetCharTextDistance();
953 else if (eAdj
== SVX_ADJUST_CENTER
)
954 nReverseListIndented
= rFmt
.GetFirstLineOffset()/2;
956 nReverseListIndented
= rFmt
.GetFirstLineOffset();
957 return nReverseListIndented
;
960 static long lcl_GetTrueMargin(const SvxLRSpaceItem
&rLR
, const SwNumFmt
&rFmt
,
963 OSL_ENSURE( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
,
964 "<lcl_GetTrueMargin> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
966 const long nBodyIndent
= rLR
.GetTxtLeft();
967 const long nFirstLineDiff
= rLR
.GetTxtFirstLineOfst();
968 rFirstLinePos
= nBodyIndent
+ nFirstLineDiff
;
970 const long nPseudoListBodyIndent
= rFmt
.GetAbsLSpace();
971 const long nReverseListIndented
= GetListFirstLineIndent(rFmt
);
972 long nExtraListIndent
= nPseudoListBodyIndent
+ nReverseListIndented
;
974 return nExtraListIndent
> 0 ? nExtraListIndent
: 0;
979 void SyncIndentWithList( SvxLRSpaceItem
&rLR
,
980 const SwNumFmt
&rFmt
,
981 const bool bFirstLineOfstSet
,
982 const bool bLeftIndentSet
)
984 if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
986 long nWantedFirstLinePos
;
987 long nExtraListIndent
= lcl_GetTrueMargin(rLR
, rFmt
, nWantedFirstLinePos
);
988 rLR
.SetTxtLeft(nWantedFirstLinePos
- nExtraListIndent
);
989 rLR
.SetTxtFirstLineOfst(0);
991 else if ( rFmt
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
)
993 if ( !bFirstLineOfstSet
&& bLeftIndentSet
&&
994 rFmt
.GetFirstLineIndent() != 0 )
996 rLR
.SetTxtFirstLineOfst( rFmt
.GetFirstLineIndent() );
998 else if ( bFirstLineOfstSet
&& !bLeftIndentSet
&&
999 rFmt
.GetIndentAt() != 0 )
1001 rLR
.SetTxtLeft( rFmt
.GetIndentAt() );
1006 const SwNumFmt
* SwWW8FltControlStack::GetNumFmtFromStack(const SwPosition
&rPos
,
1007 const SwTxtNode
&rTxtNode
)
1009 const SwNumFmt
*pRet
= 0;
1010 const SfxPoolItem
*pItem
= GetStackAttr(rPos
, RES_FLTR_NUMRULE
);
1011 if (pItem
&& rTxtNode
.GetNumRule())
1013 String
sName(((SfxStringItem
*)pItem
)->GetValue());
1014 if (rTxtNode
.IsCountedInList())
1016 const SwNumRule
*pRule
= pDoc
->FindNumRulePtr(sName
);
1018 pRet
= GetNumFmtFromSwNumRuleLevel(*pRule
, rTxtNode
.GetActualListLevel());
1024 sal_Int32
SwWW8FltControlStack::GetCurrAttrCP() const
1026 return rReader
.GetCurrAttrCP();
1029 bool SwWW8FltControlStack::IsParaEndInCPs(sal_Int32 nStart
,sal_Int32 nEnd
,bool bSdOD
) const
1031 return rReader
.IsParaEndInCPs(nStart
,nEnd
,bSdOD
);
1034 //Clear the para end position recorded in reader intermittently for the least impact on loading performance
1035 void SwWW8FltControlStack::ClearParaEndPosition()
1040 rReader
.ClearParaEndPosition();
1043 bool SwWW8FltControlStack::CheckSdOD(sal_Int32 nStart
,sal_Int32 nEnd
)
1045 return rReader
.IsParaEndInCPs(nStart
,nEnd
);
1048 void SwWW8FltControlStack::SetAttrInDoc(const SwPosition
& rTmpPos
,
1049 SwFltStackEntry
& rEntry
)
1051 switch (rEntry
.pAttr
->Which())
1056 Loop over the affect nodes and
1057 a) convert the word style absolute indent to indent relative
1058 to any numbering indent active on the nodes
1059 b) adjust the writer style tabstops relative to the old
1060 paragraph indent to be relative to the new paragraph indent
1062 using namespace sw::util
;
1063 SwPaM
aRegion(rTmpPos
);
1064 if (rEntry
.MakeRegion(pDoc
, aRegion
, false))
1066 SvxLRSpaceItem
aNewLR( *(SvxLRSpaceItem
*)rEntry
.pAttr
);
1067 sal_uLong nStart
= aRegion
.Start()->nNode
.GetIndex();
1068 sal_uLong nEnd
= aRegion
.End()->nNode
.GetIndex();
1069 for(; nStart
<= nEnd
; ++nStart
)
1071 SwNode
* pNode
= pDoc
->GetNodes()[ nStart
];
1072 if (!pNode
|| !pNode
->IsTxtNode())
1075 SwCntntNode
* pNd
= (SwCntntNode
*)pNode
;
1076 SvxLRSpaceItem aOldLR
= (const SvxLRSpaceItem
&)
1077 pNd
->GetAttr(RES_LR_SPACE
);
1079 SwTxtNode
*pTxtNode
= (SwTxtNode
*)pNode
;
1081 const SwNumFmt
*pNum
= 0;
1082 pNum
= GetNumFmtFromStack(*aRegion
.GetPoint(),
1086 pNum
= GetNumFmtFromTxtNode(*pTxtNode
);
1092 const bool bFirstLineIndentSet
=
1093 ( rReader
.maTxtNodesHavingFirstLineOfstSet
.end() !=
1094 rReader
.maTxtNodesHavingFirstLineOfstSet
.find( pNode
) );
1096 const bool bLeftIndentSet
=
1097 ( rReader
.maTxtNodesHavingLeftIndentSet
.end() !=
1098 rReader
.maTxtNodesHavingLeftIndentSet
.find( pNode
) );
1099 SyncIndentWithList( aNewLR
, *pNum
,
1100 bFirstLineIndentSet
,
1104 if (aNewLR
== aOldLR
)
1107 pNd
->SetAttr(aNewLR
);
1113 case RES_TXTATR_FIELD
:
1114 OSL_ENSURE(!this, "What is a field doing in the control stack,"
1115 "probably should have been in the endstack");
1117 case RES_TXTATR_INETFMT
:
1119 SwPaM
aRegion(rTmpPos
);
1120 if (rEntry
.MakeRegion(pDoc
, aRegion
, false))
1123 //If we have just one single inline graphic then
1124 //don't insert a field for the single frame, set
1125 //the frames hyperlink field attribute directly.
1126 if (0 != (pFrm
= rReader
.ContainsSingleInlineGraphic(aRegion
)))
1128 const SwFmtINetFmt
*pAttr
= (const SwFmtINetFmt
*)
1131 aURL
.SetURL(pAttr
->GetValue(), false);
1132 aURL
.SetTargetFrameName(pAttr
->GetTargetFrame());
1133 pFrm
->SetFmtAttr(aURL
);
1137 pDoc
->InsertPoolItem(aRegion
, *rEntry
.pAttr
, 0);
1143 SwFltControlStack::SetAttrInDoc(rTmpPos
, rEntry
);
1148 const SfxPoolItem
* SwWW8FltControlStack::GetFmtAttr(const SwPosition
& rPos
,
1151 const SfxPoolItem
*pItem
= GetStackAttr(rPos
, nWhich
);
1154 SwCntntNode
const*const pNd
= rPos
.nNode
.GetNode().GetCntntNode();
1156 pItem
= &pDoc
->GetAttrPool().GetDefaultItem(nWhich
);
1160 If we're hunting for the indent on a paragraph and need to use the
1161 parent style indent, then return the indent in msword format, and
1162 not writer format, because that's the style that the filter works
1165 if (nWhich
== RES_LR_SPACE
)
1167 SfxItemState eState
= SFX_ITEM_DEFAULT
;
1168 if (const SfxItemSet
*pSet
= pNd
->GetpSwAttrSet())
1169 eState
= pSet
->GetItemState(RES_LR_SPACE
, false);
1170 if (eState
!= SFX_ITEM_SET
&& rReader
.nAktColl
< rReader
.vColl
.size())
1171 pItem
= &(rReader
.vColl
[rReader
.nAktColl
].maWordLR
);
1175 If we're hunting for a character property, try and exact position
1176 within the text node for lookup
1178 if (pNd
->IsTxtNode())
1180 xub_StrLen nPos
= rPos
.nContent
.GetIndex();
1181 SfxItemSet
aSet(pDoc
->GetAttrPool(), nWhich
, nWhich
);
1182 if (static_cast<const SwTxtNode
*>(pNd
)->GetAttr(aSet
, nPos
, nPos
))
1183 pItem
= aSet
.GetItem(nWhich
);
1187 pItem
= &pNd
->GetAttr(nWhich
);
1193 const SfxPoolItem
* SwWW8FltControlStack::GetStackAttr(const SwPosition
& rPos
,
1196 SwFltPosition
aFltPos(rPos
);
1198 size_t nSize
= size();
1201 const SwFltStackEntry
& rEntry
= (*this)[ --nSize
];
1202 if (rEntry
.pAttr
->Which() == nWhich
)
1204 if ( (rEntry
.bOpen
) ||
1206 (rEntry
.m_aMkPos
.m_nNode
<= aFltPos
.m_nNode
) &&
1207 (rEntry
.m_aPtPos
.m_nNode
>= aFltPos
.m_nNode
) &&
1208 (rEntry
.m_aMkPos
.m_nCntnt
<= aFltPos
.m_nCntnt
) &&
1209 (rEntry
.m_aPtPos
.m_nCntnt
> aFltPos
.m_nCntnt
)
1213 * e.g. half-open range [0-3) so asking for properties at 3
1214 * means props that end at 3 are not included
1217 return rEntry
.pAttr
;
1224 bool SwWW8FltRefStack::IsFtnEdnBkmField(const SwFmtFld
& rFmtFld
, sal_uInt16
& rBkmNo
)
1226 const SwField
* pFld
= rFmtFld
.GetFld();
1227 sal_uInt16 nSubType
;
1228 if(pFld
&& (RES_GETREFFLD
== pFld
->Which())
1229 && ((REF_FOOTNOTE
== (nSubType
= pFld
->GetSubType())) || (REF_ENDNOTE
== nSubType
))
1230 && !((SwGetRefField
*)pFld
)->GetSetRefName().isEmpty())
1232 const IDocumentMarkAccess
* const pMarkAccess
= pDoc
->getIDocumentMarkAccess();
1233 IDocumentMarkAccess::const_iterator_t ppBkmk
= pMarkAccess
->findMark(
1234 ((SwGetRefField
*)pFld
)->GetSetRefName());
1235 if(ppBkmk
!= pMarkAccess
->getMarksEnd())
1237 // find Sequence No of corresponding Foot-/Endnote
1238 rBkmNo
= ppBkmk
- pMarkAccess
->getMarksBegin();
1245 void SwWW8FltRefStack::SetAttrInDoc(const SwPosition
& rTmpPos
,
1246 SwFltStackEntry
& rEntry
)
1248 switch (rEntry
.pAttr
->Which())
1251 Look up these in our lists of bookmarks that were changed to
1252 variables, and replace the ref field with a var field, otherwise
1253 do normal (?) strange stuff
1255 case RES_TXTATR_FIELD
:
1257 SwNodeIndex
aIdx(rEntry
.m_aMkPos
.m_nNode
, 1);
1258 SwPaM
aPaM(aIdx
, rEntry
.m_aMkPos
.m_nCntnt
);
1260 SwFmtFld
& rFmtFld
= *(SwFmtFld
*)rEntry
.pAttr
;
1261 SwField
* pFld
= rFmtFld
.GetFld();
1263 // <NOT> got lost from revision 1.128 to 1.129
1264 if (!RefToVar(pFld
, rEntry
))
1267 if( IsFtnEdnBkmField(rFmtFld
, nBkmNo
) )
1269 ::sw::mark::IMark
const * const pMark
= (pDoc
->getIDocumentMarkAccess()->getMarksBegin() + nBkmNo
)->get();
1271 const SwPosition
& rBkMrkPos
= pMark
->GetMarkPos();
1273 SwTxtNode
* pTxt
= rBkMrkPos
.nNode
.GetNode().GetTxtNode();
1274 if( pTxt
&& rBkMrkPos
.nContent
.GetIndex() )
1276 SwTxtAttr
* const pFtn
= pTxt
->GetTxtAttrForCharAt(
1277 rBkMrkPos
.nContent
.GetIndex()-1, RES_TXTATR_FTN
);
1280 sal_uInt16 nRefNo
= ((SwTxtFtn
*)pFtn
)->GetSeqRefNo();
1282 ((SwGetRefField
*)pFld
)->SetSeqNo( nRefNo
);
1284 if( pFtn
->GetFtn().IsEndNote() )
1285 ((SwGetRefField
*)pFld
)->SetSubType(REF_ENDNOTE
);
1291 pDoc
->InsertPoolItem(aPaM
, *rEntry
.pAttr
, 0);
1292 MoveAttrs(*aPaM
.GetPoint());
1296 SwFltEndStack::SetAttrInDoc(rTmpPos
, rEntry
);
1299 case RES_FLTR_BOOKMARK
:
1300 OSL_ENSURE(!this, "EndStck used with non field, not what we want");
1301 SwFltEndStack::SetAttrInDoc(rTmpPos
, rEntry
);
1307 For styles we will do our tabstop arithmetic in word style and adjust them to
1308 writer style after all the styles have been finished and the dust settles as
1309 to what affects what.
1311 For explicit attributes we turn the adjusted writer tabstops back into 0 based
1312 word indexes and we'll turn them back into writer indexes when setting them
1313 into the document. If explicit left indent exist which affects them, then this
1314 is handled when the explicit left indent is set into the document
1316 void SwWW8ImplReader::Read_Tab(sal_uInt16
, const sal_uInt8
* pData
, short nLen
)
1320 pCtrlStck
->SetAttr(*pPaM
->GetPoint(), RES_PARATR_TABSTOP
);
1324 sal_uInt8 nDel
= (nLen
> 0) ? pData
[0] : 0;
1325 const sal_uInt8
* pDel
= pData
+ 1; // Del - Array
1327 sal_uInt8 nIns
= (nLen
> nDel
*2+1) ? pData
[nDel
*2+1] : 0;
1328 const sal_uInt8
* pIns
= pData
+ 2*nDel
+ 2; // Ins - Array
1330 short nRequiredLength
= 2 + 2*nDel
+ 2*nIns
+ 1*nIns
;
1331 if (nRequiredLength
> nLen
)
1333 //would require more data than available to describe!, discard invalid
1339 WW8_TBD
* pTyp
= (WW8_TBD
*)(pData
+ 2*nDel
+ 2*nIns
+ 2);// Typ - Array
1341 SvxTabStopItem
aAttr(0, 0, SVX_TAB_ADJUST_DEFAULT
, RES_PARATR_TABSTOP
);
1343 const SwTxtFmtColl
* pSty
= 0;
1344 sal_uInt16 nTabBase
;
1345 if (pAktColl
&& nAktColl
< vColl
.size()) // StyleDef
1347 nTabBase
= vColl
[nAktColl
].nBase
;
1348 if (nTabBase
< vColl
.size()) // Based On
1349 pSty
= (const SwTxtFmtColl
*)vColl
[nTabBase
].pFmt
;
1353 nTabBase
= nAktColl
;
1354 if (nAktColl
< vColl
.size())
1355 pSty
= (const SwTxtFmtColl
*)vColl
[nAktColl
].pFmt
;
1356 //TODO figure else here
1359 bool bFound
= false;
1360 ::boost::unordered_set
<size_t> aLoopWatch
;
1361 while (pSty
&& !bFound
)
1363 const SfxPoolItem
* pTabs
;
1364 bFound
= pSty
->GetAttrSet().GetItemState(RES_PARATR_TABSTOP
, false,
1365 &pTabs
) == SFX_ITEM_SET
;
1367 aAttr
= *((const SvxTabStopItem
*)pTabs
);
1370 sal_uInt16 nOldTabBase
= nTabBase
;
1371 // If based on another
1372 if (nTabBase
< vColl
.size())
1373 nTabBase
= vColl
[nTabBase
].nBase
;
1376 nTabBase
< vColl
.size() &&
1377 nOldTabBase
!= nTabBase
&&
1378 nTabBase
!= ww::stiNil
1381 // #i61789: Stop searching when next style is the same as the
1382 // current one (prevent loop)
1383 aLoopWatch
.insert(reinterpret_cast<size_t>(pSty
));
1384 if (nTabBase
< vColl
.size())
1385 pSty
= (const SwTxtFmtColl
*)vColl
[nTabBase
].pFmt
;
1386 //TODO figure out the else branch
1388 if (aLoopWatch
.find(reinterpret_cast<size_t>(pSty
)) !=
1393 pSty
= 0; // gib die Suche auf
1397 SvxTabStop aTabStop
;
1398 for (short i
=0; i
< nDel
; ++i
)
1400 sal_uInt16 nPos
= aAttr
.GetPos(SVBT16ToShort(pDel
+ i
*2));
1401 if( nPos
!= SVX_TAB_NOTFOUND
)
1402 aAttr
.Remove( nPos
, 1 );
1405 for (short i
=0; i
< nIns
; ++i
)
1407 short nPos
= SVBT16ToShort(pIns
+ i
*2);
1408 aTabStop
.GetTabPos() = nPos
;
1409 switch( SVBT8ToByte( pTyp
[i
].aBits1
) & 0x7 ) // pTyp[i].jc
1412 aTabStop
.GetAdjustment() = SVX_TAB_ADJUST_LEFT
;
1415 aTabStop
.GetAdjustment() = SVX_TAB_ADJUST_CENTER
;
1418 aTabStop
.GetAdjustment() = SVX_TAB_ADJUST_RIGHT
;
1421 aTabStop
.GetAdjustment() = SVX_TAB_ADJUST_DECIMAL
;
1424 continue; // ignoriere Bar
1427 switch( SVBT8ToByte( pTyp
[i
].aBits1
) >> 3 & 0x7 )
1430 aTabStop
.GetFill() = ' ';
1433 aTabStop
.GetFill() = '.';
1436 aTabStop
.GetFill() = '-';
1440 aTabStop
.GetFill() = '_';
1444 sal_uInt16 nPos2
= aAttr
.GetPos( nPos
);
1445 if (nPos2
!= SVX_TAB_NOTFOUND
)
1446 aAttr
.Remove(nPos2
, 1); // sonst weigert sich das Insert()
1447 aAttr
.Insert(aTabStop
);
1454 //Here we have a tab definition which inserts no extra tabs, or deletes
1455 //no existing tabs. An older version of writer is probably the creater
1456 //of the document :-( . So if we are importing a style we can just
1457 //ignore it. But if we are importing into text we cannot as during
1458 //text SwWW8ImplReader::Read_Tab is called at the begin and end of
1459 //the range the attrib affects, and ignoring it would upset the
1461 if (!pAktColl
) //not importing into a style
1463 using namespace sw::util
;
1464 SvxTabStopItem aOrig
= pSty
?
1465 ItemGet
<SvxTabStopItem
>(*pSty
, RES_PARATR_TABSTOP
) :
1466 DefaultItemGet
<SvxTabStopItem
>(rDoc
, RES_PARATR_TABSTOP
);
1472 //-----------------------------------------
1474 //-----------------------------------------
1476 void SwWW8ImplReader::ImportDop()
1478 // correct the LastPrinted date in DocumentProperties
1479 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
1480 mpDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
1481 uno::Reference
<document::XDocumentProperties
> xDocuProps(
1482 xDPS
->getDocumentProperties());
1483 OSL_ENSURE(xDocuProps
.is(), "DocumentProperties is null");
1484 if (xDocuProps
.is())
1486 DateTime
aLastPrinted(
1487 msfilter::util::DTTM2DateTime(pWDop
->dttmLastPrint
));
1488 ::util::DateTime
uDT(aLastPrinted
.GetNanoSec(),
1489 aLastPrinted
.GetSec(), aLastPrinted
.GetMin(),
1490 aLastPrinted
.GetHour(), aLastPrinted
.GetDay(),
1491 aLastPrinted
.GetMonth(), aLastPrinted
.GetYear(), false);
1492 xDocuProps
->setPrintDate(uDT
);
1496 // COMPATIBILITY FLAGS START
1499 // i#78951, remember the unknown compatability options
1500 // so as to export them out
1501 rDoc
.Setn32DummyCompatabilityOptions1( pWDop
->GetCompatabilityOptions());
1502 rDoc
.Setn32DummyCompatabilityOptions2( pWDop
->GetCompatabilityOptions2());
1504 // Abstand zwischen zwei Absaetzen ist die SUMME von unterem
1505 // Abst. des ersten und oberem Abst. des zweiten
1506 rDoc
.set(IDocumentSettingAccess::PARA_SPACE_MAX
, pWDop
->fDontUseHTMLAutoSpacing
);
1507 rDoc
.set(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES
, true );
1508 // move tabs on alignment
1509 rDoc
.set(IDocumentSettingAccess::TAB_COMPAT
, true);
1510 // #i24363# tab stops relative to indent
1511 rDoc
.set(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT
, false);
1513 // Import Default-Tabs
1514 long nDefTabSiz
= pWDop
->dxaTab
;
1515 if( nDefTabSiz
< 56 )
1518 // wir wollen genau einen DefaultTab
1519 SvxTabStopItem
aNewTab( 1, sal_uInt16(nDefTabSiz
), SVX_TAB_ADJUST_DEFAULT
, RES_PARATR_TABSTOP
);
1520 ((SvxTabStop
&)aNewTab
[0]).GetAdjustment() = SVX_TAB_ADJUST_DEFAULT
;
1522 rDoc
.GetAttrPool().SetPoolDefaultItem( aNewTab
);
1524 // Import zoom factor.
1525 if (pWDop
->wScaleSaved
)
1527 uno::Sequence
<beans::PropertyValue
> aViewProps(3);
1528 aViewProps
[0].Name
= "ZoomFactor";
1529 aViewProps
[0].Value
<<= sal_Int16(pWDop
->wScaleSaved
);
1530 aViewProps
[1].Name
= "VisibleBottom";
1531 aViewProps
[1].Value
<<= sal_Int32(0);
1532 aViewProps
[2].Name
= "ZoomType";
1533 aViewProps
[2].Value
<<= sal_Int16(0);
1535 uno::Reference
< uno::XComponentContext
> xComponentContext(comphelper::getProcessComponentContext());
1536 uno::Reference
<container::XIndexContainer
> xBox
= document::IndexedPropertyValues::create(xComponentContext
);
1537 xBox
->insertByIndex(sal_Int32(0), uno::makeAny(aViewProps
));
1538 uno::Reference
<container::XIndexAccess
> xIndexAccess(xBox
, uno::UNO_QUERY
);
1539 uno::Reference
<document::XViewDataSupplier
> xViewDataSupplier(mpDocShell
->GetModel(), uno::UNO_QUERY
);
1540 xViewDataSupplier
->setViewData(xIndexAccess
);
1543 rDoc
.set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE
, !pWDop
->fUsePrinterMetrics
);
1544 rDoc
.set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE
, true);
1545 rDoc
.set(IDocumentSettingAccess::ADD_FLY_OFFSETS
, true );
1546 rDoc
.set(IDocumentSettingAccess::ADD_EXT_LEADING
, !pWDop
->fNoLeading
);
1547 rDoc
.set(IDocumentSettingAccess::OLD_NUMBERING
, false);
1548 rDoc
.set(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING
, false); // #i47448#
1549 rDoc
.set(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK
, !pWDop
->fExpShRtn
); // #i49277#, #i56856#
1550 rDoc
.set(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT
, false); // #i53199#
1551 rDoc
.set(IDocumentSettingAccess::OLD_LINE_SPACING
, false);
1553 // #i25901# - set new compatibility option
1554 // 'Add paragraph and table spacing at bottom of table cells'
1555 rDoc
.set(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS
, true);
1557 // #i11860# - set new compatibility option
1558 // 'Use former object positioning' to <sal_False>
1559 rDoc
.set(IDocumentSettingAccess::USE_FORMER_OBJECT_POS
, false);
1561 // #i27767# - set new compatibility option
1562 // 'Conder Wrapping mode when positioning object' to <sal_True>
1563 rDoc
.set(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION
, true);
1565 rDoc
.set(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING
, false); // #i13832#, #i24135#
1567 rDoc
.set(IDocumentSettingAccess::TABLE_ROW_KEEP
, true); //SetTableRowKeep( true );
1569 rDoc
.set(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION
, true); // #i3952#
1571 rDoc
.set(IDocumentSettingAccess::INVERT_BORDER_SPACING
, true);
1572 rDoc
.set(IDocumentSettingAccess::COLLAPSE_EMPTY_CELL_PARA
, true);
1573 rDoc
.set(IDocumentSettingAccess::TAB_OVERFLOW
, true);
1574 rDoc
.set(IDocumentSettingAccess::UNBREAKABLE_NUMBERINGS
, true);
1575 rDoc
.set(IDocumentSettingAccess::CLIPPED_PICTURES
, true);
1576 rDoc
.set(IDocumentSettingAccess::TAB_OVER_MARGIN
, true);
1579 // COMPATIBILITY FLAGS END
1582 //import magic doptypography information, if its there
1583 if (pWwFib
->nFib
> 105)
1584 ImportDopTypography(pWDop
->doptypography
);
1586 // disable form design mode to be able to use imported controls directly
1587 // #i31239# always disable form design mode, not only in protected docs
1589 using namespace com::sun::star
;
1591 uno::Reference
<lang::XComponent
> xModelComp(mpDocShell
->GetModel(),
1593 uno::Reference
<beans::XPropertySet
> xDocProps(xModelComp
,
1597 uno::Reference
<beans::XPropertySetInfo
> xInfo
=
1598 xDocProps
->getPropertySetInfo();
1599 sal_Bool bValue
= false;
1602 if (xInfo
->hasPropertyByName("ApplyFormDesignMode"))
1604 xDocProps
->setPropertyValue("ApplyFormDesignMode", cppu::bool2any(bValue
));
1610 mpDocShell
->SetModifyPasswordHash(pWDop
->lKeyProtDoc
);
1612 const SvtFilterOptions
& rOpt
= SvtFilterOptions::Get();
1613 if (rOpt
.IsUseEnhancedFields())
1614 rDoc
.set(IDocumentSettingAccess::PROTECT_FORM
, pWDop
->fProtEnabled
);
1617 void SwWW8ImplReader::ImportDopTypography(const WW8DopTypography
&rTypo
)
1619 using namespace com::sun::star
;
1620 switch (rTypo
.iLevelOfKinsoku
)
1624 i18n::ForbiddenCharacters
aForbidden(rTypo
.rgxchFPunct
,
1626 rDoc
.setForbiddenCharacters(rTypo
.GetConvertedLang(),
1628 //Obviously cannot set the standard level 1 for japanese, so
1629 //bail out now while we can.
1630 if (rTypo
.GetConvertedLang() == LANGUAGE_JAPANESE
)
1639 This MS hack means that level 2 of japanese is not in operation, so we put
1640 in what we know are the MS defaults, there is a complementary reverse
1641 hack in the writer. Its our default as well, but we can set it anyway
1642 as a flag for later.
1644 if (!rTypo
.reserved2
)
1646 i18n::ForbiddenCharacters
aForbidden(rTypo
.GetJapanNotBeginLevel1(),
1647 rTypo
.GetJapanNotEndLevel1());
1648 rDoc
.setForbiddenCharacters(LANGUAGE_JAPANESE
,aForbidden
);
1651 rDoc
.set(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION
, rTypo
.fKerningPunct
);
1652 rDoc
.setCharacterCompressionType(static_cast<SwCharCompressType
>(rTypo
.iJustification
));
1655 //-----------------------------------------
1656 // Fuss- und Endnoten
1658 //-----------------------------------------
1660 WW8ReaderSave::WW8ReaderSave(SwWW8ImplReader
* pRdr
,WW8_CP nStartCp
) :
1661 maTmpPos(*pRdr
->pPaM
->GetPoint()),
1662 mpOldStck(pRdr
->pCtrlStck
),
1663 mpOldAnchorStck(pRdr
->pAnchorStck
),
1664 mpOldRedlines(pRdr
->mpRedlineStack
),
1665 mpOldPlcxMan(pRdr
->pPlcxMan
),
1666 mpWFlyPara(pRdr
->pWFlyPara
),
1667 mpSFlyPara(pRdr
->pSFlyPara
),
1668 mpPreviousNumPaM(pRdr
->pPreviousNumPaM
),
1669 mpPrevNumRule(pRdr
->pPrevNumRule
),
1670 mpTableDesc(pRdr
->pTableDesc
),
1671 mnInTable(pRdr
->nInTable
),
1672 mnAktColl(pRdr
->nAktColl
),
1673 mcSymbol(pRdr
->cSymbol
),
1674 mbIgnoreText(pRdr
->bIgnoreText
),
1675 mbSymbol(pRdr
->bSymbol
),
1676 mbHdFtFtnEdn(pRdr
->bHdFtFtnEdn
),
1677 mbTxbxFlySection(pRdr
->bTxbxFlySection
),
1679 mbInHyperlink(pRdr
->bInHyperlink
),
1680 mbPgSecBreak(pRdr
->bPgSecBreak
),
1681 mbWasParaEnd(pRdr
->bWasParaEnd
),
1682 mbHasBorder(pRdr
->bHasBorder
),
1683 mbFirstPara(pRdr
->bFirstPara
)
1685 pRdr
->bSymbol
= false;
1686 pRdr
->bHdFtFtnEdn
= true;
1687 pRdr
->bTxbxFlySection
= pRdr
->bAnl
= pRdr
->bPgSecBreak
= pRdr
->bWasParaEnd
1688 = pRdr
->bHasBorder
= false;
1689 pRdr
->bFirstPara
= true;
1691 pRdr
->pWFlyPara
= 0;
1692 pRdr
->pSFlyPara
= 0;
1693 pRdr
->pPreviousNumPaM
= 0;
1694 pRdr
->pPrevNumRule
= 0;
1695 pRdr
->pTableDesc
= 0;
1699 pRdr
->pCtrlStck
= new SwWW8FltControlStack(&pRdr
->rDoc
, pRdr
->nFieldFlags
,
1702 pRdr
->mpRedlineStack
= new sw::util::RedlineStack(pRdr
->rDoc
);
1704 pRdr
->pAnchorStck
= new SwWW8FltAnchorStack(&pRdr
->rDoc
, pRdr
->nFieldFlags
);
1706 // rette die Attributverwaltung: dies ist noetig, da der neu anzulegende
1707 // PLCFx Manager natuerlich auf die gleichen FKPs zugreift, wie der alte
1708 // und deren Start-End-Positionen veraendert...
1710 pRdr
->pPlcxMan
->SaveAllPLCFx(maPLCFxSave
);
1714 pRdr
->pPlcxMan
= new WW8PLCFMan(pRdr
->pSBase
,
1715 mpOldPlcxMan
->GetManType(), nStartCp
);
1718 maOldApos
.push_back(false);
1719 maOldApos
.swap(pRdr
->maApos
);
1720 maOldFieldStack
.swap(pRdr
->maFieldStack
);
1723 void WW8ReaderSave::Restore( SwWW8ImplReader
* pRdr
)
1725 pRdr
->pWFlyPara
= mpWFlyPara
;
1726 pRdr
->pSFlyPara
= mpSFlyPara
;
1727 pRdr
->pPreviousNumPaM
= mpPreviousNumPaM
;
1728 pRdr
->pPrevNumRule
= mpPrevNumRule
;
1729 pRdr
->pTableDesc
= mpTableDesc
;
1730 pRdr
->cSymbol
= mcSymbol
;
1731 pRdr
->bSymbol
= mbSymbol
;
1732 pRdr
->bIgnoreText
= mbIgnoreText
;
1733 pRdr
->bHdFtFtnEdn
= mbHdFtFtnEdn
;
1734 pRdr
->bTxbxFlySection
= mbTxbxFlySection
;
1735 pRdr
->nInTable
= mnInTable
;
1737 pRdr
->bInHyperlink
= mbInHyperlink
;
1738 pRdr
->bWasParaEnd
= mbWasParaEnd
;
1739 pRdr
->bPgSecBreak
= mbPgSecBreak
;
1740 pRdr
->nAktColl
= mnAktColl
;
1741 pRdr
->bHasBorder
= mbHasBorder
;
1742 pRdr
->bFirstPara
= mbFirstPara
;
1744 // schliesse alle Attribute, da sonst Attribute
1745 // entstehen koennen, die aus dem Fly rausragen
1746 pRdr
->DeleteCtrlStk();
1747 pRdr
->pCtrlStck
= mpOldStck
;
1749 pRdr
->mpRedlineStack
->closeall(*pRdr
->pPaM
->GetPoint());
1750 delete pRdr
->mpRedlineStack
;
1751 pRdr
->mpRedlineStack
= mpOldRedlines
;
1753 pRdr
->DeleteAnchorStk();
1754 pRdr
->pAnchorStck
= mpOldAnchorStck
;
1756 *pRdr
->pPaM
->GetPoint() = maTmpPos
;
1758 if (mpOldPlcxMan
!= pRdr
->pPlcxMan
)
1760 delete pRdr
->pPlcxMan
;
1761 pRdr
->pPlcxMan
= mpOldPlcxMan
;
1764 pRdr
->pPlcxMan
->RestoreAllPLCFx(maPLCFxSave
);
1765 pRdr
->maApos
.swap(maOldApos
);
1766 pRdr
->maFieldStack
.swap(maOldFieldStack
);
1769 void SwWW8ImplReader::Read_HdFtFtnText( const SwNodeIndex
* pSttIdx
,
1770 long nStartCp
, long nLen
, ManTypes nType
)
1772 // rettet Flags u.ae. u. setzt sie zurueck
1773 WW8ReaderSave
aSave( this );
1775 pPaM
->GetPoint()->nNode
= pSttIdx
->GetIndex() + 1; //
1776 pPaM
->GetPoint()->nContent
.Assign( pPaM
->GetCntntNode(), 0 );
1778 // dann Text fuer Header, Footer o. Footnote einlesen
1780 ReadText( nStartCp
, nLen
, nType
); // Sepx dabei ignorieren
1781 aSave
.Restore( this );
1784 //Use authornames, if not available fall back to initials.
1785 long SwWW8ImplReader::Read_And(WW8PLCFManResult
* pRes
)
1787 WW8PLCFx_SubDoc
* pSD
= pPlcxMan
->GetAtn();
1795 const WW67_ATRD
* pDescri
= (const WW67_ATRD
*)pSD
->GetData();
1796 const String
* pA
= GetAnnotationAuthor(SVBT16ToShort(pDescri
->ibst
));
1800 sAuthor
= String(pDescri
->xstUsrInitl
+ 1, pDescri
->xstUsrInitl
[0],
1801 RTL_TEXTENCODING_MS_1252
);
1805 const WW8_ATRD
* pDescri
= (const WW8_ATRD
*)pSD
->GetData();
1808 sal_uInt16 nLen
= SVBT16ToShort(pDescri
->xstUsrInitl
[0]);
1809 for(sal_uInt16 nIdx
= 1; nIdx
<= nLen
; ++nIdx
)
1810 sInitials
+= SVBT16ToShort(pDescri
->xstUsrInitl
[nIdx
]);
1813 if (const String
* pA
= GetAnnotationAuthor(SVBT16ToShort(pDescri
->ibst
)))
1816 sAuthor
= sInitials
;
1818 // If there is a bookmark tag, a text range should be commented.
1819 sal_uInt32 nTagBkmk
= SVBT32ToUInt32(pDescri
->ITagBkmk
);
1820 if (nTagBkmk
!= 0xFFFFFFFF)
1822 int nAtnIndex
= GetAnnotationIndex(nTagBkmk
);
1823 if (nAtnIndex
!= -1)
1825 WW8_CP nStart
= GetAnnotationStart(nAtnIndex
);
1826 WW8_CP nEnd
= GetAnnotationEnd(nAtnIndex
);
1827 sal_Int32 nLen
= nEnd
- nStart
;
1830 if (pPaM
->GetPoint()->nContent
.GetIndex() >= nLen
)
1833 pPaM
->GetPoint()->nContent
-= nLen
;
1835 else if (pPaM
->GetPoint()->nNode
.GetNode().IsTxtNode() )
1838 nLen
-= pPaM
->GetPoint()->nContent
.GetIndex();
1840 SwTxtNode
* pTxtNode
= 0;
1841 // Find first text node which affected by the comment
1842 while( pPaM
->GetPoint()->nNode
>= 0 )
1845 // Find previous text node
1848 pPaM
->GetPoint()->nNode
--;
1849 nLen
--; // End line character
1850 pNode
= &pPaM
->GetPoint()->nNode
.GetNode();
1852 while( !pNode
->IsTxtNode() && pPaM
->GetPoint()->nNode
>= 0 );
1854 // Subtrackt previous text node's length
1855 if( pNode
&& pNode
->IsTxtNode() )
1857 pTxtNode
= pNode
->GetTxtNode();
1858 if( nLen
< pTxtNode
->Len() )
1861 nLen
-= pTxtNode
->Len();
1865 // Set postion of the text range's first character
1868 pTxtNode
->MakeStartIndex(&pPaM
->GetPoint()->nContent
);
1869 pPaM
->GetPoint()->nContent
+= pTxtNode
->Len() - nLen
;
1877 sal_uInt32 nDateTime
= 0;
1879 if (sal_uInt8
* pExtended
= pPlcxMan
->GetExtendedAtrds()) // Word < 2002 has no date data for comments
1881 sal_uLong nIndex
= pSD
->GetIdx() & 0xFFFF; //Index is (stupidly) multiplexed for WW8PLCFx_SubDocs
1882 if (pWwFib
->lcbAtrdExtra
/18 > nIndex
)
1883 nDateTime
= SVBT32ToUInt32(*(SVBT32
*)(pExtended
+(nIndex
*18)));
1886 DateTime aDate
= msfilter::util::DTTM2DateTime(nDateTime
);
1889 OutlinerParaObject
*pOutliner
= ImportAsOutliner( sTxt
, pRes
->nCp2OrIdx
,
1890 pRes
->nCp2OrIdx
+ pRes
->nMemLen
, MAN_AND
);
1892 this->pFmtOfJustInsertedApo
= 0;
1893 SwPostItField
aPostIt(
1894 (SwPostItFieldType
*)rDoc
.GetSysFldType(RES_POSTITFLD
), sAuthor
,
1895 sTxt
, sInitials
, String(), aDate
);
1896 aPostIt
.SetTextObject(pOutliner
);
1898 // If this is a range, create the associated fieldmark.
1899 if (pPaM
->HasMark())
1901 IDocumentMarkAccess
* pMarksAccess
= rDoc
.getIDocumentMarkAccess();
1902 sw::mark::IFieldmark
* pFieldmark
= pMarksAccess
->makeFieldBookmark(*pPaM
, OUString(), ODF_COMMENTRANGE
);
1903 aPostIt
.SetName(pFieldmark
->GetName());
1908 pCtrlStck
->NewAttr(*pPaM
->GetPoint(), SvxCharHiddenItem(false, RES_CHRATR_HIDDEN
));
1909 rDoc
.InsertPoolItem(*pPaM
, SwFmtFld(aPostIt
), 0);
1910 pCtrlStck
->SetAttr(*pPaM
->GetPoint(), RES_CHRATR_HIDDEN
);
1915 void SwWW8ImplReader::Read_HdFtTextAsHackedFrame(long nStart
, long nLen
,
1916 SwFrmFmt
&rHdFtFmt
, sal_uInt16 nPageWidth
)
1918 const SwNodeIndex
* pSttIdx
= rHdFtFmt
.GetCntnt().GetCntntIdx();
1919 OSL_ENSURE(pSttIdx
, "impossible");
1923 SwPosition
aTmpPos(*pPaM
->GetPoint());
1925 pPaM
->GetPoint()->nNode
= pSttIdx
->GetIndex() + 1;
1926 pPaM
->GetPoint()->nContent
.Assign(pPaM
->GetCntntNode(), 0);
1928 SwFlyFrmFmt
*pFrame
= rDoc
.MakeFlySection(FLY_AT_PARA
, pPaM
->GetPoint());
1930 SwFmtAnchor
aAnch( pFrame
->GetAnchor() );
1931 aAnch
.SetType( FLY_AT_PARA
);
1932 pFrame
->SetFmtAttr( aAnch
);
1933 SwFmtFrmSize
aSz(ATT_MIN_SIZE
, nPageWidth
, MINLAY
);
1934 SwFrmSize eFrmSize
= ATT_MIN_SIZE
;
1935 if( eFrmSize
!= aSz
.GetWidthSizeType() )
1936 aSz
.SetWidthSizeType( eFrmSize
);
1937 pFrame
->SetFmtAttr(aSz
);
1938 pFrame
->SetFmtAttr(SwFmtSurround(SURROUND_THROUGHT
));
1939 pFrame
->SetFmtAttr(SwFmtHoriOrient(0, text::HoriOrientation::LEFT
)); //iFOO
1941 // #i43427# - send frame for header/footer into background.
1942 pFrame
->SetFmtAttr( SvxOpaqueItem( RES_OPAQUE
, false ) );
1943 SdrObject
* pFrmObj
= CreateContactObject( pFrame
);
1944 OSL_ENSURE( pFrmObj
,
1945 "<SwWW8ImplReader::Read_HdFtTextAsHackedFrame(..)> - missing SdrObject instance" );
1948 pFrmObj
->SetOrdNum( 0L );
1950 MoveInsideFly(pFrame
);
1952 const SwNodeIndex
* pHackIdx
= pFrame
->GetCntnt().GetCntntIdx();
1954 Read_HdFtFtnText(pHackIdx
, nStart
, nLen
- 1, MAN_HDFT
);
1956 MoveOutsideFly(pFrame
, aTmpPos
);
1959 void SwWW8ImplReader::Read_HdFtText(long nStart
, long nLen
, SwFrmFmt
* pHdFtFmt
)
1961 const SwNodeIndex
* pSttIdx
= pHdFtFmt
->GetCntnt().GetCntntIdx();
1965 SwPosition
aTmpPos( *pPaM
->GetPoint() ); // merke alte Cursorposition
1967 Read_HdFtFtnText(pSttIdx
, nStart
, nLen
- 1, MAN_HDFT
);
1969 *pPaM
->GetPoint() = aTmpPos
;
1973 bool SwWW8ImplReader::isValid_HdFt_CP(WW8_CP nHeaderCP
) const
1975 //each CP of Plcfhdd MUST be less than FibRgLw97.ccpHdd
1976 return (nHeaderCP
< pWwFib
->ccpHdr
) ? true : false;
1979 bool SwWW8ImplReader::HasOwnHeaderFooter(sal_uInt8 nWhichItems
, sal_uInt8 grpfIhdt
,
1986 sal_uInt8 nNumber
= 5;
1988 for( sal_uInt8 nI
= 0x20; nI
; nI
>>= 1, nNumber
-- )
1990 if (nI
& nWhichItems
)
1994 bOk
= ( pHdFt
->GetTextPos(grpfIhdt
, nI
, start
, nLen
) && nLen
>= 2 );
1997 pHdFt
->GetTextPosExact( static_cast< short >(nNumber
+ (nSect
+1)*6), start
, nLen
);
1998 bOk
= ( 2 <= nLen
) && isValid_HdFt_CP(start
);
2009 void SwWW8ImplReader::Read_HdFt(int nSect
, const SwPageDesc
*pPrev
,
2010 const wwSection
&rSection
)
2012 sal_uInt8 grpfIhdt
= rSection
.maSep
.grpfIhdt
;
2013 SwPageDesc
*pPD
= rSection
.mpPage
;
2019 sal_uInt8 nNumber
= 5;
2021 for( sal_uInt8 nI
= 0x20; nI
; nI
>>= 1, nNumber
-- )
2027 bOk
= ( pHdFt
->GetTextPos(grpfIhdt
, nI
, start
, nLen
) && nLen
>= 2 );
2030 pHdFt
->GetTextPosExact( static_cast< short >(nNumber
+ (nSect
+1)*6), start
, nLen
);
2031 bOk
= ( 2 <= nLen
) && isValid_HdFt_CP(start
);
2035 = (nI
& ( WW8_HEADER_EVEN
| WW8_FOOTER_EVEN
)) ? true: false;
2037 = (nI
& ( WW8_HEADER_FIRST
| WW8_FOOTER_FIRST
)) ? true: false;
2039 = (nI
& ( WW8_FOOTER_EVEN
| WW8_FOOTER_ODD
| WW8_FOOTER_FIRST
)) ? true: false;
2041 SwFrmFmt
& rFmt
= bUseLeft
? pPD
->GetLeft()
2042 : bUseFirst
? pPD
->GetFirstMaster()
2046 // If we have empty first page header and footer.
2047 bool bNoFirst
= !(grpfIhdt
& WW8_HEADER_FIRST
) && !(grpfIhdt
& WW8_FOOTER_FIRST
);
2051 //#i17196# Cannot have left without right
2052 if (!pPD
->GetMaster().GetFooter().GetFooterFmt())
2053 pPD
->GetMaster().SetFmtAttr(SwFmtFooter(true));
2055 pPD
->GetLeft().SetFmtAttr(SwFmtFooter(true));
2056 if (bUseFirst
|| (rSection
.maSep
.fTitlePage
&& bNoFirst
))
2057 pPD
->GetFirstMaster().SetFmtAttr(SwFmtFooter(true));
2058 pHdFtFmt
= const_cast<SwFrmFmt
*>(rFmt
.GetFooter().GetFooterFmt());
2063 //#i17196# Cannot have left without right
2064 if (!pPD
->GetMaster().GetHeader().GetHeaderFmt())
2065 pPD
->GetMaster().SetFmtAttr(SwFmtHeader(true));
2067 pPD
->GetLeft().SetFmtAttr(SwFmtHeader(true));
2068 if (bUseFirst
|| (rSection
.maSep
.fTitlePage
&& bNoFirst
))
2069 pPD
->GetFirstMaster().SetFmtAttr(SwFmtHeader(true));
2070 pHdFtFmt
= const_cast<SwFrmFmt
*>(rFmt
.GetHeader().GetHeaderFmt());
2075 bool bHackRequired
= false;
2076 if (bIsHeader
&& rSection
.IsFixedHeightHeader())
2077 bHackRequired
= true;
2078 else if (bIsFooter
&& rSection
.IsFixedHeightFooter())
2079 bHackRequired
= true;
2083 Read_HdFtTextAsHackedFrame(start
, nLen
, *pHdFtFmt
,
2084 static_cast< sal_uInt16
>(rSection
.GetTextAreaWidth()) );
2087 Read_HdFtText(start
, nLen
, pHdFtFmt
);
2089 else if (!bOk
&& pPrev
)
2090 CopyPageDescHdFt(pPrev
, pPD
, nI
);
2092 bIsHeader
= bIsFooter
= false;
2098 bool wwSectionManager::SectionIsProtected(const wwSection
&rSection
) const
2100 return (mrReader
.pWwFib
->fReadOnlyRecommended
&& !rSection
.IsNotProtected());
2103 void wwSectionManager::SetHdFt(wwSection
&rSection
, int nSect
,
2104 const wwSection
*pPrevious
)
2106 // Header / Footer nicht da
2107 if (!rSection
.maSep
.grpfIhdt
)
2110 OSL_ENSURE(rSection
.mpPage
, "makes no sense to call with a main page");
2111 if (rSection
.mpPage
)
2113 mrReader
.Read_HdFt(nSect
, pPrevious
? pPrevious
->mpPage
: 0,
2117 // Kopf / Fuss - Index Updaten
2118 // Damit der Index auch spaeter noch stimmt
2120 mrReader
.pHdFt
->UpdateIndex(rSection
.maSep
.grpfIhdt
);
2124 class AttribHere
: public std::unary_function
<const xub_StrLen
*, bool>
2127 xub_StrLen nPosition
;
2129 AttribHere(xub_StrLen nPos
) : nPosition(nPos
) {}
2130 bool operator()(const xub_StrLen
*pPosition
) const
2132 return (*pPosition
>= nPosition
);
2136 void SwWW8ImplReader::AppendTxtNode(SwPosition
& rPos
)
2138 SwTxtNode
* pTxt
= pPaM
->GetNode()->GetTxtNode();
2140 const SwNumRule
* pRule
= NULL
;
2143 pRule
= sw::util::GetNumRuleFromTxtNode(*pTxt
);
2146 pRule
&& !pWDop
->fDontUseHTMLAutoSpacing
&&
2147 (bParaAutoBefore
|| bParaAutoAfter
)
2150 // If after spacing is set to auto, set the after space to 0
2152 SetLowerSpacing(*pPaM
, 0);
2154 // If the previous textnode had numbering and
2155 // and before spacing is set to auto, set before space to 0
2156 if(pPrevNumRule
&& bParaAutoBefore
)
2157 SetUpperSpacing(*pPaM
, 0);
2159 // If the previous numbering rule was different we need
2160 // to insert a space after the previous paragraph
2161 if((pRule
!= pPrevNumRule
) && pPreviousNumPaM
)
2162 SetLowerSpacing(*pPreviousNumPaM
, GetParagraphAutoSpace(pWDop
->fDontUseHTMLAutoSpacing
));
2164 // cache current paragraph
2166 delete pPreviousNumPaM
, pPreviousNumPaM
= 0;
2168 pPreviousNumPaM
= new SwPaM(*pPaM
);
2169 pPrevNumRule
= pRule
;
2171 else if(!pRule
&& pPreviousNumPaM
)
2173 // If the previous paragraph has numbering but the current one does not
2174 // we need to add a space after the previous paragraph
2175 SetLowerSpacing(*pPreviousNumPaM
, GetParagraphAutoSpace(pWDop
->fDontUseHTMLAutoSpacing
));
2176 delete pPreviousNumPaM
, pPreviousNumPaM
= 0;
2181 // clear paragraph cache
2183 delete pPreviousNumPaM
, pPreviousNumPaM
= 0;
2184 pPrevNumRule
= pRule
;
2187 // If this is the first paragraph in the document and
2188 // Auto-spacing before paragraph is set,
2189 // set the upper spacing value to 0
2190 if(bParaAutoBefore
&& bFirstPara
&& !pWDop
->fDontUseHTMLAutoSpacing
)
2191 SetUpperSpacing(*pPaM
, 0);
2195 rDoc
.AppendTxtNode(rPos
);
2197 //We can flush all anchored graphics at the end of a paragraph.
2198 pAnchorStck
->Flush();
2201 bool SwWW8ImplReader::SetSpacing(SwPaM
&rMyPam
, int nSpace
, bool bIsUpper
)
2204 const SwPosition
* pSpacingPos
= rMyPam
.GetPoint();
2206 const SvxULSpaceItem
* pULSpaceItem
= (const SvxULSpaceItem
*)pCtrlStck
->GetFmtAttr(*pSpacingPos
, RES_UL_SPACE
);
2208 if(pULSpaceItem
!= 0)
2210 SvxULSpaceItem
aUL(*pULSpaceItem
);
2213 aUL
.SetUpper( static_cast< sal_uInt16
>(nSpace
) );
2215 aUL
.SetLower( static_cast< sal_uInt16
>(nSpace
) );
2217 xub_StrLen nEnd
= pSpacingPos
->nContent
.GetIndex();
2218 rMyPam
.GetPoint()->nContent
.Assign(rMyPam
.GetCntntNode(), 0);
2219 pCtrlStck
->NewAttr(*pSpacingPos
, aUL
);
2220 rMyPam
.GetPoint()->nContent
.Assign(rMyPam
.GetCntntNode(), nEnd
);
2221 pCtrlStck
->SetAttr(*pSpacingPos
, RES_UL_SPACE
);
2227 bool SwWW8ImplReader::SetLowerSpacing(SwPaM
&rMyPam
, int nSpace
)
2229 return SetSpacing(rMyPam
, nSpace
, false);
2232 bool SwWW8ImplReader::SetUpperSpacing(SwPaM
&rMyPam
, int nSpace
)
2234 return SetSpacing(rMyPam
, nSpace
, true);
2237 sal_uInt16
SwWW8ImplReader::TabRowSprm(int nLevel
) const
2241 return nLevel
? 0x244C : 0x2417;
2244 void SwWW8ImplReader::EndSpecial()
2246 // Frame / Table / Anl
2248 StopAllAnl(); // -> bAnl = false
2250 while(maApos
.size() > 1)
2255 if (maApos
[nInTable
] == true)
2259 if (maApos
[0] == true)
2262 OSL_ENSURE(!nInTable
, "unclosed table!");
2265 bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync
, WW8_CP nStartCp
)
2267 // Frame / Table / Anl
2273 OSL_ENSURE(nInTable
>= 0,"nInTable < 0!");
2276 bool bTableRowEnd
= (pPlcxMan
->HasParaSprm(bVer67
? 25 : 0x2417) != 0 );
2278 // es muss leider fuer jeden Absatz zuerst nachgesehen werden,
2279 // ob sich unter den sprms
2280 // das sprm 29 (bzw. 0x261B) befindet, das ein APO einleitet.
2281 // Alle weiteren sprms beziehen sich dann naemlich auf das APO und nicht
2282 // auf den normalen Text drumrum.
2283 // Dasselbe gilt fuer eine Tabelle ( sprm 24 (bzw. 0x2416) )
2284 // und Anls ( sprm 13 ).
2285 // WW: Tabelle in APO geht ( Beide Anfaende treten gleichzeitig auf )
2286 // WW: APO in Tabelle geht nicht
2287 // d.h. Wenn eine Tabelle Inhalt eines Apo ist, dann muss der
2288 // Apo-Anfang zuerst bearbeitet werden, damit die Tabelle im Apo steht
2289 // und nicht umgekehrt. Am Ende muss dagegen zuerst das Tabellenende
2290 // bearbeitet werden, da die Apo erst nach der Tabelle abgeschlossen
2291 // werden darf ( sonst wird das Apo-Ende nie gefunden ).
2292 // Dasselbe gilt fuer Fly / Anl, Tab / Anl, Fly / Tab / Anl.
2294 // Wenn die Tabelle in einem Apo steht, fehlen im TabRowEnd-Bereich
2295 // die Apo-Angaben. Damit hier die Apo nicht beendet wird, wird
2296 // ProcessApo dann nicht aufgerufen.
2298 // KHZ: When there is a table inside the Apo the Apo-flags are also
2299 // missing for the 2nd, 3rd... paragraphs of each cell.
2302 // 1st look for in-table flag, for 2000+ there is a subtable flag to
2303 // be considered, the sprm 6649 gives the level of the table
2304 sal_uInt8 nCellLevel
= 0;
2307 nCellLevel
= 0 != pPlcxMan
->HasParaSprm(24);
2310 nCellLevel
= 0 != pPlcxMan
->HasParaSprm(0x2416);
2312 nCellLevel
= 0 != pPlcxMan
->HasParaSprm(0x244B);
2316 WW8_TablePos
*pTabPos
=0;
2317 WW8_TablePos aTabPos
;
2318 if(nCellLevel
&& !bVer67
)
2320 WW8PLCFxSave1 aSave
;
2321 pPlcxMan
->GetPap()->Save( aSave
);
2323 WW8PLCFx_Cp_FKP
* pPap
= pPlcxMan
->GetPapPLCF();
2324 WW8_CP nMyStartCp
=nStartCp
;
2326 if (const sal_uInt8
*pLevel
= pPlcxMan
->HasParaSprm(0x6649))
2327 nCellLevel
= *pLevel
;
2329 bool bHasRowEnd
= SearchRowEnd(pPap
, nMyStartCp
, (nInTable
<nCellLevel
?nInTable
:nCellLevel
-1));
2331 //Bad Table, remain unchanged in level, e.g. #i19667#
2333 nCellLevel
= static_cast< sal_uInt8
>(nInTable
);
2335 if (bHasRowEnd
&& ParseTabPos(&aTabPos
,pPap
))
2338 pPlcxMan
->GetPap()->Restore( aSave
);
2341 // then look if we are in an Apo
2343 ApoTestResults aApo
= TestApo(nCellLevel
, bTableRowEnd
, pTabPos
);
2345 //look to see if we are in a Table, but Table in foot/end note not allowed
2346 bool bStartTab
= (nInTable
< nCellLevel
) && !bFtnEdn
;
2348 bool bStopTab
= bWasTabRowEnd
&& (nInTable
> nCellLevel
) && !bFtnEdn
;
2350 bWasTabRowEnd
= false; // must be deactivated right here to prevent next
2351 // WW8TabDesc::TableCellEnd() from making nonsense
2353 if (nInTable
&& !bTableRowEnd
&& !bStopTab
&& (nInTable
== nCellLevel
&& aApo
.HasStartStop()))
2354 bStopTab
= bStartTab
= true; // Required to stop and start table
2356 // Dann auf Anl (Nummerierung) testen
2357 // und dann alle Ereignisse in der richtigen Reihenfolge bearbeiten
2359 if( bAnl
&& !bTableRowEnd
)
2361 const sal_uInt8
* pSprm13
= pPlcxMan
->HasParaSprm( 13 );
2364 sal_uInt8 nT
= static_cast< sal_uInt8
>(GetNumType( *pSprm13
));
2365 if( ( nT
!= WW8_Pause
&& nT
!= nWwNumType
) // Anl-Wechsel
2366 || aApo
.HasStartStop() // erzwungenes Anl-Ende
2367 || bStopTab
|| bStartTab
)
2369 StopAnlToRestart(nT
); // Anl-Restart ( = Wechsel ) ueber sprms
2373 NextAnlLine( pSprm13
); // naechste Anl-Zeile
2377 { // Anl normal zuende
2378 StopAllAnl(); // Wirkliches Ende
2390 maApos
[nInTable
] = false;
2393 if (aApo
.mbStartApo
)
2395 maApos
[nInTable
] = StartApo(aApo
, pTabPos
);
2396 // nach StartApo ist ein ReSync noetig ( eigentlich nur, falls die Apo
2397 // ueber eine FKP-Grenze geht
2402 WW8PLCFxSave1 aSave
;
2403 pPlcxMan
->GetPap()->Save( aSave
);
2405 if (bAnl
) // Nummerierung ueber Zellengrenzen
2406 StopAllAnl(); // fuehrt zu Absturz -> keine Anls
2408 if(nInTable
< nCellLevel
)
2410 if (StartTable(nStartCp
))
2414 maApos
.push_back(false);
2416 if(nInTable
>= nCellLevel
)
2418 // nach StartTable ist ein ReSync noetig ( eigentlich nur, falls die
2419 // Tabelle ueber eine FKP-Grenze geht
2421 pPlcxMan
->GetPap()->Restore( aSave
);
2424 } while (!bFtnEdn
&& (nInTable
< nCellLevel
));
2425 return bTableRowEnd
;
2428 CharSet
SwWW8ImplReader::GetCurrentCharSet()
2432 If the hard charset is set use it, if not see if there is an open
2433 character run that has set the charset, if not then fallback to the
2434 current underlying paragraph style.
2436 CharSet eSrcCharSet
= eHardCharSet
;
2437 if (eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
)
2439 if (!maFontSrcCharSets
.empty())
2440 eSrcCharSet
= maFontSrcCharSets
.top();
2441 if ((eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
) && nCharFmt
>= 0 && (size_t)nCharFmt
< vColl
.size() )
2442 eSrcCharSet
= vColl
[nCharFmt
].GetCharSet();
2443 if ((eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
) && StyleExists(nAktColl
) && nAktColl
< vColl
.size())
2444 eSrcCharSet
= vColl
[nAktColl
].GetCharSet();
2445 if (eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
)
2449 The (default) character set used for a run of text is the default
2450 character set for the version of Word that last saved the document.
2452 This is a bit tentative, more might be required if the concept is correct.
2453 When later version of word write older 6/95 documents the charset is
2454 correctly set in the character runs involved, so its hard to reproduce
2455 documents that require this to be sure of the process involved.
2457 const SvxLanguageItem
*pLang
= (const SvxLanguageItem
*)GetFmtAttr(RES_CHRATR_LANGUAGE
);
2458 LanguageType eLang
= pLang
? pLang
->GetLanguage() : LANGUAGE_SYSTEM
;
2459 ::com::sun::star::lang::Locale
aLocale(LanguageTag(eLang
).getLocale());
2460 eSrcCharSet
= msfilter::util::getBestTextEncodingFromLocale(aLocale
);
2466 //Takashi Ono for CJK
2467 CharSet
SwWW8ImplReader::GetCurrentCJKCharSet()
2471 If the hard charset is set use it, if not see if there is an open
2472 character run that has set the charset, if not then fallback to the
2473 current underlying paragraph style.
2475 CharSet eSrcCharSet
= eHardCharSet
;
2476 if (eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
)
2478 if (!maFontSrcCJKCharSets
.empty())
2479 eSrcCharSet
= maFontSrcCJKCharSets
.top();
2482 if ((eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
) && nCharFmt
>= 0 && (size_t)nCharFmt
< vColl
.size() )
2483 eSrcCharSet
= vColl
[nCharFmt
].GetCJKCharSet();
2484 if (eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
&& nAktColl
< vColl
.size())
2485 eSrcCharSet
= vColl
[nAktColl
].GetCJKCharSet();
2487 if (eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
)
2488 { // patch from cmc for #i52786#
2491 The (default) character set used for a run of text is the default
2492 character set for the version of Word that last saved the document.
2494 This is a bit tentative, more might be required if the concept is correct.
2495 When later version of word write older 6/95 documents the charset is
2496 correctly set in the character runs involved, so its hard to reproduce
2497 documents that require this to be sure of the process involved.
2499 const SvxLanguageItem
*pLang
=
2500 (const SvxLanguageItem
*)GetFmtAttr(RES_CHRATR_LANGUAGE
);
2503 switch (pLang
->GetLanguage())
2505 case LANGUAGE_CZECH
:
2506 eSrcCharSet
= RTL_TEXTENCODING_MS_1250
;
2509 eSrcCharSet
= RTL_TEXTENCODING_MS_1252
;
2518 void SwWW8ImplReader::PostProcessAttrs()
2520 if (mpPostProcessAttrsInfo
!= NULL
)
2522 SfxItemIter
aIter(mpPostProcessAttrsInfo
->mItemSet
);
2524 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
2529 pCtrlStck
->NewAttr(*mpPostProcessAttrsInfo
->mPaM
.GetPoint(),
2531 pCtrlStck
->SetAttr(*mpPostProcessAttrsInfo
->mPaM
.GetMark(),
2532 pItem
->Which(), true);
2534 while (!aIter
.IsAtEnd() && 0 != (pItem
= aIter
.NextItem()));
2537 delete mpPostProcessAttrsInfo
;
2538 mpPostProcessAttrsInfo
= NULL
;
2544 It appears that some documents that are in a baltic 8 bit encoding which has
2545 some undefined characters can have use made of those characters, in which
2546 case they default to CP1252. If not then its perhaps that the font encoding
2547 is only in use for 6/7 and for 8+ if we are in 8bit mode then the encoding
2550 So a encoding converter that on an undefined character attempts to
2551 convert from 1252 on the undefined character
2553 sal_Size
Custom8BitToUnicode(rtl_TextToUnicodeConverter hConverter
,
2554 sal_Char
*pIn
, sal_Size nInLen
, sal_Unicode
*pOut
, sal_Size nOutLen
)
2556 const sal_uInt32 nFlags
=
2557 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
|
2558 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
|
2559 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE
|
2560 RTL_TEXTTOUNICODE_FLAGS_FLUSH
;
2562 const sal_uInt32 nFlags2
=
2563 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE
|
2564 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_IGNORE
|
2565 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE
|
2566 RTL_TEXTTOUNICODE_FLAGS_FLUSH
;
2568 sal_Size nDestChars
=0;
2569 sal_Size nConverted
=0;
2573 sal_uInt32 nInfo
= 0;
2574 sal_Size nThisConverted
=0;
2576 nDestChars
+= rtl_convertTextToUnicode(hConverter
, 0,
2577 pIn
+nConverted
, nInLen
-nConverted
,
2578 pOut
+nDestChars
, nOutLen
-nDestChars
,
2579 nFlags
, &nInfo
, &nThisConverted
);
2581 OSL_ENSURE(nInfo
== 0, "A character conversion failed!");
2583 nConverted
+= nThisConverted
;
2586 nInfo
& RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
||
2587 nInfo
& RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
2590 sal_Size nOtherConverted
;
2591 rtl_TextToUnicodeConverter hCP1252Converter
=
2592 rtl_createTextToUnicodeConverter(RTL_TEXTENCODING_MS_1252
);
2593 nDestChars
+= rtl_convertTextToUnicode(hCP1252Converter
, 0,
2595 pOut
+nDestChars
, nOutLen
-nDestChars
,
2596 nFlags2
, &nInfo
, &nOtherConverted
);
2597 rtl_destroyTextToUnicodeConverter(hCP1252Converter
);
2600 } while (nConverted
< nInLen
);
2605 bool SwWW8ImplReader::LangUsesHindiNumbers(sal_uInt16 nLang
)
2607 bool bResult
= false;
2611 case 0x1401: // Arabic(Algeria)
2612 case 0x3c01: // Arabic(Bahrain)
2613 case 0xc01: // Arabic(Egypt)
2614 case 0x801: // Arabic(Iraq)
2615 case 0x2c01: // Arabic (Jordan)
2616 case 0x3401: // Arabic(Kuwait)
2617 case 0x3001: // Arabic(Lebanon)
2618 case 0x1001: // Arabic(Libya)
2619 case 0x1801: // Arabic(Morocco)
2620 case 0x2001: // Arabic(Oman)
2621 case 0x4001: // Arabic(Qatar)
2622 case 0x401: // Arabic(Saudi Arabia)
2623 case 0x2801: // Arabic(Syria)
2624 case 0x1c01: // Arabic(Tunisia)
2625 case 0x3801: // Arabic(U.A.E)
2626 case 0x2401: // Arabic(Yemen)
2636 sal_Unicode
SwWW8ImplReader::TranslateToHindiNumbers(sal_Unicode nChar
)
2638 if (nChar
>= 0x0030 && nChar
<= 0x0039)
2639 return nChar
+ 0x0630;
2644 // Returnwert: true for no Sonderzeichen
2645 bool SwWW8ImplReader::ReadPlainChars(WW8_CP
& rPos
, long nEnd
, long nCpOfs
)
2647 sal_Size nRequestedStrLen
= nEnd
- rPos
;
2649 OSL_ENSURE(nRequestedStrLen
, "String is 0");
2650 if (!nRequestedStrLen
)
2653 sal_Size nRequestedPos
= pSBase
->WW8Cp2Fc(nCpOfs
+rPos
, &bIsUnicode
);
2654 bool bValidPos
= checkSeek(*pStrm
, nRequestedPos
);
2655 OSL_ENSURE(bValidPos
, "Document claimed to have more text than available");
2658 //Swallow missing range, e.g. #i95550#
2659 rPos
+=nRequestedStrLen
;
2663 sal_Size nAvailableStrLen
= pStrm
->remainingSize() / (bIsUnicode
? 2 : 1);
2664 OSL_ENSURE(nAvailableStrLen
, "Document claimed to have more text than available");
2665 if (!nAvailableStrLen
)
2667 //Swallow missing range, e.g. #i95550#
2668 rPos
+=nRequestedStrLen
;
2672 sal_Size nValidStrLen
= std::min(nRequestedStrLen
, nAvailableStrLen
);
2674 // Unicode-Flag neu setzen und notfalls File-Pos korrigieren
2675 // merke: Seek kostet nicht viel, da inline geprueft wird,
2676 // ob die korrekte FilePos nicht schon erreicht ist.
2678 if (nValidStrLen
<= (STRING_MAXLEN
-1))
2679 nStrLen
= writer_cast
<xub_StrLen
>(nValidStrLen
);
2681 nStrLen
= STRING_MAXLEN
-1;
2683 const CharSet eSrcCharSet
= bVer67
? GetCurrentCharSet() :
2684 RTL_TEXTENCODING_MS_1252
;
2685 const CharSet eSrcCJKCharSet
= bVer67
? GetCurrentCJKCharSet() :
2686 RTL_TEXTENCODING_MS_1252
;
2688 // allocate unicode string data
2689 rtl_uString
*pStr
= rtl_uString_alloc(nStrLen
);
2690 sal_Unicode
* pBuffer
= pStr
->buffer
;
2691 sal_Unicode
* pWork
= pBuffer
;
2693 sal_Char
* p8Bits
= NULL
;
2695 rtl_TextToUnicodeConverter hConverter
= 0;
2696 if (!bIsUnicode
|| bVer67
)
2697 hConverter
= rtl_createTextToUnicodeConverter(eSrcCharSet
);
2700 p8Bits
= new sal_Char
[nStrLen
];
2702 // read the stream data
2703 sal_uInt8 nBCode
= 0;
2707 sal_uInt16 nCTLLang
= 0;
2708 const SfxPoolItem
* pItem
= GetFmtAttr(RES_CHRATR_CTL_LANGUAGE
);
2710 nCTLLang
= dynamic_cast<const SvxLanguageItem
*>(pItem
)->GetLanguage();
2712 for( nL2
= 0; nL2
< nStrLen
; ++nL2
, ++pWork
)
2715 *pStrm
>> nUCode
; // unicode --> read 2 bytes
2718 *pStrm
>> nBCode
; // old code --> read 1 byte
2722 if (pStrm
->GetError())
2724 rPos
= WW8_CP_MAX
-10; // -> eof or other error
2725 rtl_freeMemory(pStr
);
2730 if ((32 > nUCode
) || (0xa0 == nUCode
))
2732 pStrm
->SeekRel( bIsUnicode
? -2 : -1 );
2733 break; // Sonderzeichen < 32, == 0xa0 gefunden
2742 if (nUCode
>= 0x3000) //0x8000 ?
2745 aTest
[0] = static_cast< sal_Char
>((nUCode
& 0xFF00) >> 8);
2746 aTest
[1] = static_cast< sal_Char
>(nUCode
& 0x00FF);
2747 String
aTemp(aTest
, 2, eSrcCJKCharSet
);
2748 OSL_ENSURE(aTemp
.Len() == 1, "so much for that theory");
2749 *pWork
= aTemp
.GetChar(0);
2753 sal_Char cTest
= static_cast< sal_Char
>(nUCode
& 0x00FF);
2754 Custom8BitToUnicode(hConverter
, &cTest
, 1, pWork
, 1);
2759 p8Bits
[nL2
] = nBCode
;
2764 xub_StrLen nEndUsed
= nL2
;
2767 nEndUsed
= Custom8BitToUnicode(hConverter
, p8Bits
, nL2
, pBuffer
, nStrLen
);
2769 for( xub_StrLen nI
= 0; nI
< nStrLen
; ++nI
, ++pBuffer
)
2770 if (m_bRegardHindiDigits
&& bBidi
&& LangUsesHindiNumbers(nCTLLang
))
2771 *pBuffer
= TranslateToHindiNumbers(*pBuffer
);
2773 pStr
->buffer
[nEndUsed
] = 0;
2774 pStr
->length
= nEndUsed
;
2776 emulateMSWordAddTextToParagraph(OUString(pStr
, SAL_NO_ACQUIRE
));
2779 if (!maApos
.back()) //a para end in apo doesn't count
2780 bWasParaEnd
= false; //kein CR
2784 rtl_destroyTextToUnicodeConverter(hConverter
);
2786 rtl_uString_release(pStr
);
2788 return nL2
>= nStrLen
;
2791 #define MSASCII SAL_MAX_INT16
2795 //We want to force weak chars inside 0x0020 to 0x007F to LATIN
2796 sal_Int16
lcl_getScriptType(
2797 const uno::Reference
<i18n::XBreakIterator
>& rBI
,
2798 const OUString
&rString
, sal_Int32 nPos
)
2800 sal_Int16 nScript
= rBI
->getScriptType(rString
, nPos
);
2801 if (nScript
== i18n::ScriptType::WEAK
&& rString
[nPos
] >= 0x0020 && rString
[nPos
] <= 0x007F)
2806 //We want to know about WEAK segments, so endOfScript isn't
2807 //useful, and see lcl_getScriptType anyway
2808 sal_Int32
lcl_endOfScript(
2809 const uno::Reference
<i18n::XBreakIterator
>& rBI
,
2810 const OUString
&rString
, sal_Int32 nPos
, sal_Int16 nScript
)
2812 while (nPos
< rString
.getLength())
2814 sal_Int16 nNewScript
= lcl_getScriptType(rBI
, rString
, nPos
);
2815 if (nScript
!= nNewScript
)
2822 sal_Int32
lcl_getWriterScriptType(
2823 const uno::Reference
<i18n::XBreakIterator
>& rBI
,
2824 const OUString
&rString
, sal_Int32 nPos
)
2826 sal_Int16 nScript
= i18n::ScriptType::WEAK
;
2828 if (rString
.isEmpty())
2833 nScript
= rBI
->getScriptType(rString
, nPos
);
2834 if (nScript
!= i18n::ScriptType::WEAK
)
2842 bool samePitchIgnoreUnknown(FontPitch eA
, FontPitch eB
)
2844 return (eA
== eB
|| eA
== PITCH_DONTKNOW
|| eB
== PITCH_DONTKNOW
);
2847 bool sameFontIgnoringIrrelevantFields(const SvxFontItem
&rA
, const SvxFontItem
&rB
)
2849 //Ignoring CharSet, and ignoring unknown pitch
2850 return rA
.GetFamilyName() == rB
.GetFamilyName() &&
2851 rA
.GetStyleName() == rB
.GetStyleName() &&
2852 rA
.GetFamily() == rB
.GetFamily() &&
2853 samePitchIgnoreUnknown(rA
.GetPitch(), rB
.GetPitch());
2857 //In writer we categorize text into CJK, CTL and "Western" for everything else.
2858 //Microsoft Word basically categorizes text into East Asian, Complex, ASCII,
2859 //NonEastAsian/HighAnsi, with some shared characters and some properties to to
2860 //hint as to which way to bias those shared characters.
2862 //That's four categories, we however have three categories. Given that problem
2863 //here we would ideally find out "what would word do" to see what font/language
2864 //word would assign to characters based on the unicode range they fall into and
2865 //hack the word one onto the range we use. However it's unclear what word's
2866 //categorization is. So we don't do that here yet.
2868 //Additional to the categorization, when word encounters weak text for ambigious
2869 //chars it uses idcthint to indicate which way to bias. We don't have a idcthint
2870 //feature in writer.
2872 //So what we currently do here then is to split our text into non-weak/weak
2873 //sections and uses word's idcthint to determine what font it would use and
2874 //force that on for the segment. Following what we *do* know about word's
2875 //categorization, we know that the range 0x0020 and 0x007F is sprmCRgFtc0 in
2876 //word, something we map to LATIN, so we consider all weaks chars in that range
2877 //to auto-bias to LATIN.
2879 //See https://bugs.freedesktop.org/show_bug.cgi?id=34319 for an example
2880 void SwWW8ImplReader::emulateMSWordAddTextToParagraph(const OUString
& rAddString
)
2882 if (rAddString
.isEmpty())
2885 uno::Reference
<i18n::XBreakIterator
> xBI(g_pBreakIt
->GetBreakIter());
2888 simpleAddTextToParagraph(rAddString
);
2892 sal_Int16 nScript
= lcl_getScriptType(xBI
, rAddString
, 0);
2893 sal_Int32 nLen
= rAddString
.getLength();
2895 OUString sParagraphText
;
2896 const SwCntntNode
*pCntNd
= pPaM
->GetCntntNode();
2897 const SwTxtNode
* pNd
= pCntNd
? pCntNd
->GetTxtNode() : NULL
;
2899 sParagraphText
= pNd
->GetTxt();
2900 sal_Int32 nParaOffset
= sParagraphText
.getLength();
2901 sParagraphText
= sParagraphText
+ rAddString
;
2906 sal_Int32 nEnd
= lcl_endOfScript(xBI
, rAddString
, nPos
, nScript
);
2910 OUString
sChunk(rAddString
.copy(nPos
, nEnd
-nPos
));
2911 const sal_uInt16 aIds
[] = {RES_CHRATR_FONT
, RES_CHRATR_CJK_FONT
, RES_CHRATR_CTL_FONT
};
2912 const SvxFontItem
*pOverriddenItems
[] = {NULL
, NULL
, NULL
};
2913 bool aForced
[] = {false, false, false};
2915 int nLclIdctHint
= 0xFF;
2916 if (nScript
== i18n::ScriptType::WEAK
)
2917 nLclIdctHint
= nIdctHint
;
2918 else if (nScript
== MSASCII
) //Force weak chars in ascii range to use LATIN font
2921 sal_uInt16 nForceFromFontId
= 0;
2922 if (nLclIdctHint
!= 0xFF)
2924 switch (nLclIdctHint
)
2927 nForceFromFontId
= RES_CHRATR_FONT
;
2930 nForceFromFontId
= RES_CHRATR_CJK_FONT
;
2933 nForceFromFontId
= RES_CHRATR_CTL_FONT
;
2940 if (nForceFromFontId
!= 0)
2942 //Now we know that word would use the nForceFromFontId font for this range
2943 //Try and determine what script writer would assign this range to
2945 sal_Int32 nWriterScript
= lcl_getWriterScriptType(xBI
, sParagraphText
,
2946 nPos
+ nParaOffset
);
2948 bool bWriterWillUseSameFontAsWordAutomatically
= false;
2950 if (nWriterScript
!= i18n::ScriptType::WEAK
)
2953 (nWriterScript
== i18n::ScriptType::ASIAN
&& nForceFromFontId
== RES_CHRATR_CJK_FONT
) ||
2954 (nWriterScript
== i18n::ScriptType::COMPLEX
&& nForceFromFontId
== RES_CHRATR_CTL_FONT
) ||
2955 (nWriterScript
== i18n::ScriptType::LATIN
&& nForceFromFontId
== RES_CHRATR_FONT
)
2958 bWriterWillUseSameFontAsWordAutomatically
= true;
2962 const SvxFontItem
*pSourceFont
= (const SvxFontItem
*)GetFmtAttr(nForceFromFontId
);
2963 sal_uInt16 nDestId
= aIds
[nWriterScript
-1];
2964 const SvxFontItem
*pDestFont
= (const SvxFontItem
*)GetFmtAttr(nDestId
);
2965 bWriterWillUseSameFontAsWordAutomatically
= sameFontIgnoringIrrelevantFields(*pSourceFont
, *pDestFont
);
2969 //Writer won't use the same font as word, so force the issue
2970 if (!bWriterWillUseSameFontAsWordAutomatically
)
2972 const SvxFontItem
*pSourceFont
= (const SvxFontItem
*)GetFmtAttr(nForceFromFontId
);
2974 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aIds
); ++i
)
2976 const SvxFontItem
*pDestFont
= (const SvxFontItem
*)GetFmtAttr(aIds
[i
]);
2977 aForced
[i
] = aIds
[i
] != nForceFromFontId
&& *pSourceFont
!= *pDestFont
;
2980 pOverriddenItems
[i
] =
2981 (const SvxFontItem
*)pCtrlStck
->GetStackAttr(*pPaM
->GetPoint(), aIds
[i
]);
2983 SvxFontItem
aForceFont(*pSourceFont
);
2984 aForceFont
.SetWhich(aIds
[i
]);
2985 pCtrlStck
->NewAttr(*pPaM
->GetPoint(), aForceFont
);
2991 simpleAddTextToParagraph(sChunk
);
2993 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aIds
); ++i
)
2997 pCtrlStck
->SetAttr(*pPaM
->GetPoint(), aIds
[i
]);
2998 if (pOverriddenItems
[i
])
2999 pCtrlStck
->NewAttr(*pPaM
->GetPoint(), *(pOverriddenItems
[i
]));
3005 nScript
= lcl_getScriptType(xBI
, rAddString
, nPos
);
3009 void SwWW8ImplReader::simpleAddTextToParagraph(const String
& rAddString
)
3011 if (!rAddString
.Len())
3014 #if OSL_DEBUG_LEVEL > 1
3016 OString
sText(OUStringToOString(rAddString
, RTL_TEXTENCODING_UTF8
));
3017 SAL_INFO("sw.ww8", "<addTextToParagraph>" << sText
.getStr() << "</addTextToParagraph>");
3021 const SwCntntNode
*pCntNd
= pPaM
->GetCntntNode();
3022 const SwTxtNode
* pNd
= pCntNd
? pCntNd
->GetTxtNode() : NULL
;
3024 OSL_ENSURE(pNd
, "What the hell, where's my text node");
3029 if ((pNd
->GetTxt().getLength() + rAddString
.Len()) < STRING_MAXLEN
-1)
3031 rDoc
.InsertString(*pPaM
, rAddString
);
3036 if (pNd
->GetTxt().getLength() < STRING_MAXLEN
-1)
3038 String
sTempStr (rAddString
,0,
3039 STRING_MAXLEN
- pNd
->GetTxt().getLength() -1);
3040 rDoc
.InsertString(*pPaM
, sTempStr
);
3041 sTempStr
= rAddString
.Copy(sTempStr
.Len(),
3042 rAddString
.Len() - sTempStr
.Len());
3043 AppendTxtNode(*pPaM
->GetPoint());
3044 rDoc
.InsertString(*pPaM
, sTempStr
);
3048 AppendTxtNode(*pPaM
->GetPoint());
3049 rDoc
.InsertString(*pPaM
, rAddString
);
3056 // Returnwert: true for para end
3057 bool SwWW8ImplReader::ReadChars(WW8_CP
& rPos
, WW8_CP nNextAttr
, long nTextEnd
,
3060 long nEnd
= ( nNextAttr
< nTextEnd
) ? nNextAttr
: nTextEnd
;
3062 if (bSymbol
|| bIgnoreText
)
3064 if( bSymbol
) // Spezialzeichen einfuegen
3066 for(sal_uInt16 nCh
= 0; nCh
< nEnd
- rPos
; ++nCh
)
3068 rDoc
.InsertString( *pPaM
, OUString(cSymbol
) );
3070 pCtrlStck
->SetAttr( *pPaM
->GetPoint(), RES_CHRATR_FONT
);
3072 pStrm
->SeekRel( nEnd
- rPos
);
3073 rPos
= nEnd
; // ignoriere bis Attributende
3079 if (ReadPlainChars(rPos
, nEnd
, nCpOfs
))
3080 return false; // Fertig
3082 bool bStartLine
= ReadChar(rPos
, nCpOfs
);
3084 if (bPgSecBreak
|| bStartLine
|| rPos
== nEnd
) // CR oder Fertig
3091 bool SwWW8ImplReader::HandlePageBreakChar()
3093 bool bParaEndAdded
= false;
3094 //#i1909# section/page breaks should not occur in tables, word
3095 //itself ignores them in this case.
3098 //xushanchuan add for issue106569
3100 SwTxtNode
* pTemp
= pPaM
->GetNode()->GetTxtNode();
3101 if (pTemp
&& pTemp
->GetTxt().isEmpty()
3102 && (bFirstPara
|| bFirstParaOfPage
))
3105 AppendTxtNode(*pPaM
->GetPoint());
3106 pTemp
->SetAttr(*GetDfltAttr(RES_PARATR_NUMRULE
));
3110 pCtrlStck
->KillUnlockedAttrs(*pPaM
->GetPoint());
3112 If its a 0x0c without a paragraph end before it, act like a
3113 paragraph end, but nevertheless, numbering (and perhaps other
3114 similar constructs) do not exist on the para.
3116 //xushanchuan add for issue106569
3117 if (!bWasParaEnd
&& IsTemp
)
3120 bParaEndAdded
= true;
3121 if (0 >= pPaM
->GetPoint()->nContent
.GetIndex())
3123 if (SwTxtNode
* pTxtNode
= pPaM
->GetNode()->GetTxtNode())
3126 *GetDfltAttr(RES_PARATR_NUMRULE
));
3131 return bParaEndAdded
;
3134 bool SwWW8ImplReader::ReadChar(long nPosCp
, long nCpOfs
)
3136 bool bNewParaEnd
= false;
3137 // Unicode-Flag neu setzen und notfalls File-Pos korrigieren
3138 // merke: Seek kostet nicht viel, da inline geprueft wird,
3139 // ob die korrekte FilePos nicht schon erreicht ist.
3140 sal_Size nRequestedPos
= pSBase
->WW8Cp2Fc(nCpOfs
+nPosCp
, &bIsUnicode
);
3141 if (!checkSeek(*pStrm
, nRequestedPos
))
3144 sal_uInt8
nBCode(0);
3145 sal_uInt16
nWCharVal(0);
3147 *pStrm
>> nWCharVal
; // unicode --> read 2 bytes
3150 *pStrm
>> nBCode
; // old code --> read 1 byte
3154 sal_Unicode cInsert
= '\x0';
3156 //xushanchuan add for issue106569
3157 if ( 0xc != nWCharVal
)
3158 bFirstParaOfPage
= false;
3165 SwPageNumberField
aFld(
3166 (SwPageNumberFieldType
*)rDoc
.GetSysFldType(
3167 RES_PAGENUMBERFLD
), PG_RANDOM
, SVX_NUM_ARABIC
);
3168 rDoc
.InsertPoolItem(*pPaM
, SwFmtFld(aFld
), 0);
3172 // if there is only one column word treats a column break like a pagebreak.
3173 if (maSectionManager
.CurrentSectionColCount() < 2)
3174 bRet
= HandlePageBreakChar();
3177 // Always insert a txtnode for a column break, e.g. ##
3178 SwCntntNode
*pCntNd
=pPaM
->GetCntntNode();
3179 if (pCntNd
!=NULL
&& pCntNd
->Len()>0) // if par is empty not break is needed
3180 AppendTxtNode(*pPaM
->GetPoint());
3181 rDoc
.InsertPoolItem(*pPaM
, SvxFmtBreakItem(SVX_BREAK_COLUMN_BEFORE
, RES_BREAK
), 0);
3186 TabCellEnd(); // table cell end (Flags abfragen!)
3189 if( !bSpec
) // "Satellit"
3193 if( !bSpec
) // "Para-Ende"-Zeichen
3197 if( !bSpec
) // Juristenparagraph
3201 cInsert
= '\x9'; // Tab
3204 cInsert
= '\xa'; // Hard NewLine
3207 bRet
= HandlePageBreakChar();
3209 case 0x1e: // Non-breaking hyphen
3210 rDoc
.InsertString( *pPaM
, OUString(CHAR_HARDHYPHEN
) );
3212 case 0x1f: // Non-required hyphens
3213 rDoc
.InsertString( *pPaM
, OUString(CHAR_SOFTHYPHEN
) );
3215 case 0xa0: // Non-breaking spaces
3216 rDoc
.InsertString( *pPaM
, OUString(CHAR_HARDBLANK
) );
3220 Current thinking is that if bObj is set then we have a
3221 straightforward "traditional" ole object, otherwise we have a
3222 graphic preview of an associated ole2 object (or a simple
3225 //normally in the canvas field, the code is 0x8 0x1.
3226 //in a special case, the code is 0x1 0x1, which yields a simple picture
3228 bool bReadObj
= IsInlineEscherHack();
3231 long nCurPos
= pStrm
->Tell();
3232 sal_uInt16
nWordCode(0);
3235 *pStrm
>> nWordCode
;
3238 sal_uInt8
nByteCode(0);
3239 *pStrm
>> nByteCode
;
3240 nWordCode
= nByteCode
;
3242 if( nWordCode
== 0x1 )
3244 pStrm
->Seek( nCurPos
);
3248 SwFrmFmt
*pResult
= 0;
3250 pResult
= ImportOle();
3252 pResult
= ImportGraf();
3254 //#102160# If we have a bad 0x1 insert a space instead.
3258 OSL_ENSURE(!bObj
&& !bEmbeddObj
&& !nObjLocFc
,
3259 "WW8: Please report this document, it may have a "
3265 bObj
= bEmbeddObj
= false;
3273 Read_GrafLayer( nPosCp
);
3276 bNewParaEnd
= bRet
= true;
3281 Yes complex, if there is an entry in the undocumented PLCF
3282 which I believe to be a record of cell and row boundaries
3283 see if the magic bit which I believe to mean cell end is
3284 set. I also think btw that the third byte of the 4 byte
3285 value is the level of the cell
3287 WW8PLCFspecial
* pTest
= pPlcxMan
->GetMagicTables();
3288 if (pTest
&& pTest
->SeekPosExact(nPosCp
+1+nCpOfs
) &&
3289 pTest
->Where() == nPosCp
+1+nCpOfs
)
3293 pTest
->Get(nPos
, pData
);
3294 sal_uInt32 nData
= SVBT32ToUInt32(*(SVBT32
*)pData
);
3295 if (nData
& 0x2) //Might be how it works
3301 else if (bWasTabCellEnd
)
3308 bWasTabCellEnd
= false;
3311 case 0x5: // Annotation reference
3314 case 0x2: // Auto-Footnote-Number, should be replaced by SwWW8ImplReader::End_Ftn later
3315 if (!maFtnStack
.empty())
3319 SAL_INFO( "sw.ww8.level2", "<unknownValue val=\"" << nWCharVal
<< "\">" );
3323 if( '\x0' != cInsert
)
3325 OUString
sInsert(cInsert
);
3326 emulateMSWordAddTextToParagraph(sInsert
);
3328 if (!maApos
.back()) //a para end in apo doesn't count
3329 bWasParaEnd
= bNewParaEnd
;
3333 void SwWW8ImplReader::ProcessAktCollChange(WW8PLCFManResult
& rRes
,
3334 bool* pStartAttr
, bool bCallProcessSpecial
)
3336 sal_uInt16 nOldColl
= nAktColl
;
3337 nAktColl
= pPlcxMan
->GetColl();
3340 if (nAktColl
>= vColl
.size() || !vColl
[nAktColl
].pFmt
|| !vColl
[nAktColl
].bColl
)
3343 bParaAutoBefore
= false;
3344 bParaAutoAfter
= false;
3348 bParaAutoBefore
= vColl
[nAktColl
].bParaAutoBefore
;
3349 bParaAutoAfter
= vColl
[nAktColl
].bParaAutoAfter
;
3352 if (nOldColl
>= vColl
.size())
3353 nOldColl
= 0; //guess! TODO make sure this is what we want
3355 bool bTabRowEnd
= false;
3356 if( pStartAttr
&& bCallProcessSpecial
&& !bInHyperlink
)
3359 // Frame / Table / Autonumbering List Level
3360 bTabRowEnd
= ProcessSpecial(bReSync
, rRes
.nAktCp
+pPlcxMan
->GetCpOfs());
3362 *pStartAttr
= pPlcxMan
->Get( &rRes
); // hole Attribut-Pos neu
3365 if (!bTabRowEnd
&& StyleExists(nAktColl
))
3367 SetTxtFmtCollAndListLevel( *pPaM
, vColl
[ nAktColl
]);
3368 ChkToggleAttr(vColl
[ nOldColl
].n81Flags
, vColl
[ nAktColl
].n81Flags
);
3369 ChkToggleBiDiAttr(vColl
[nOldColl
].n81BiDiFlags
,
3370 vColl
[nAktColl
].n81BiDiFlags
);
3374 long SwWW8ImplReader::ReadTextAttr(WW8_CP
& rTxtPos
, bool& rbStartLine
)
3376 long nSkipChars
= 0;
3377 WW8PLCFManResult aRes
;
3379 OSL_ENSURE(pPaM
->GetNode()->GetTxtNode(), "Missing txtnode");
3380 bool bStartAttr
= pPlcxMan
->Get(&aRes
); // hole Attribut-Pos
3381 aRes
.nAktCp
= rTxtPos
; // Akt. Cp-Pos
3383 bool bNewSection
= (aRes
.nFlags
& MAN_MASK_NEW_SEP
) && !bIgnoreText
;
3384 if ( bNewSection
) // neue Section
3386 OSL_ENSURE(pPaM
->GetNode()->GetTxtNode(), "Missing txtnode");
3387 // PageDesc erzeugen und fuellen
3388 maSectionManager
.CreateSep(rTxtPos
, bPgSecBreak
);
3389 // -> 0xc war ein Sectionbreak, aber
3391 bPgSecBreak
= false; // PageDesc erzeugen und fuellen
3392 OSL_ENSURE(pPaM
->GetNode()->GetTxtNode(), "Missing txtnode");
3395 // neuer Absatz ueber Plcx.Fkp.papx
3396 if ( (aRes
.nFlags
& MAN_MASK_NEW_PAP
)|| rbStartLine
)
3398 ProcessAktCollChange( aRes
, &bStartAttr
,
3399 MAN_MASK_NEW_PAP
== (aRes
.nFlags
& MAN_MASK_NEW_PAP
) &&
3401 rbStartLine
= false;
3404 // position of last CP that's to be ignored
3407 if( 0 < aRes
.nSprmId
) // leere Attrs ignorieren
3409 if( ( eFTN
> aRes
.nSprmId
) || ( 0x0800 <= aRes
.nSprmId
) )
3411 if( bStartAttr
) // WW-Attribute
3413 if( aRes
.nMemLen
>= 0 )
3414 ImportSprm(aRes
.pMemPos
, aRes
.nSprmId
);
3417 EndSprm( aRes
.nSprmId
); // Attr ausschalten
3419 else if( aRes
.nSprmId
< 0x800 ) // eigene Hilfs-Attribute
3423 nSkipChars
= ImportExtSprm(&aRes
);
3425 (aRes
.nSprmId
== eFTN
) || (aRes
.nSprmId
== eEDN
) ||
3426 (aRes
.nSprmId
== eFLD
) || (aRes
.nSprmId
== eAND
)
3429 // Felder/Ftn-/End-Note hier ueberlesen
3430 rTxtPos
+= nSkipChars
;
3431 nSkipPos
= rTxtPos
-1;
3435 EndExtSprm( aRes
.nSprmId
);
3439 pStrm
->Seek(pSBase
->WW8Cp2Fc( pPlcxMan
->GetCpOfs() + rTxtPos
, &bIsUnicode
));
3441 // Find next Attr position (and Skip attributes of field contents if needed)
3442 if (nSkipChars
&& !bIgnoreText
)
3443 pCtrlStck
->MarkAllAttrsOld();
3444 bool bOldIgnoreText
= bIgnoreText
;
3446 sal_uInt16 nOldColl
= nAktColl
;
3447 bool bDoPlcxManPlusPLus
= true;
3451 if( bDoPlcxManPlusPLus
)
3452 pPlcxMan
->advance();
3453 nNext
= pPlcxMan
->Where();
3455 if (mpPostProcessAttrsInfo
&&
3456 mpPostProcessAttrsInfo
->mnCpStart
== nNext
)
3458 mpPostProcessAttrsInfo
->mbCopy
= true;
3461 if( (0 <= nNext
) && (nSkipPos
>= nNext
) )
3463 nNext
= ReadTextAttr( rTxtPos
, rbStartLine
);
3464 bDoPlcxManPlusPLus
= false;
3468 if (mpPostProcessAttrsInfo
&&
3469 nNext
> mpPostProcessAttrsInfo
->mnCpEnd
)
3471 mpPostProcessAttrsInfo
->mbCopy
= false;
3474 while( nSkipPos
>= nNext
);
3475 bIgnoreText
= bOldIgnoreText
;
3478 pCtrlStck
->KillUnlockedAttrs( *pPaM
->GetPoint() );
3479 if( nOldColl
!= pPlcxMan
->GetColl() )
3480 ProcessAktCollChange(aRes
, 0, false);
3486 //Revised 2012.8.16 for the complex attribute presentation of 0x0D in MS
3487 bool SwWW8ImplReader::IsParaEndInCPs(sal_Int32 nStart
, sal_Int32 nEnd
,bool bSdOD
) const
3489 //Revised for performance consideration
3490 if (nStart
== -1 || nEnd
== -1 || nEnd
< nStart
)
3493 for (cp_vector::const_reverse_iterator aItr
= maEndParaPos
.rbegin(); aItr
!= maEndParaPos
.rend(); ++aItr
)
3495 //Revised 2012.8.16,to the 0x0D,the attribute will have two situations
3496 //*********within***********exact******//
3497 //*********but also sample with only left and the position of 0x0d is the edge of the right side***********//
3498 if ( bSdOD
&& ( (nStart
< *aItr
&& nEnd
> *aItr
) || ( nStart
== nEnd
&& *aItr
== nStart
)) )
3500 else if ( !bSdOD
&& (nStart
< *aItr
&& nEnd
>= *aItr
) )
3507 //Clear the para end position recorded in reader intermittently for the least impact on loading performance
3508 void SwWW8ImplReader::ClearParaEndPosition()
3510 if ( maEndParaPos
.size() > 0 )
3511 maEndParaPos
.clear();
3514 void SwWW8ImplReader::ReadAttrs(WW8_CP
& rNext
, WW8_CP
& rTxtPos
, bool& rbStartLine
)
3516 if( rTxtPos
>= rNext
)
3517 { // Stehen Attribute an ?
3521 maCurrAttrCP
= rTxtPos
;
3522 rNext
= ReadTextAttr( rTxtPos
, rbStartLine
);
3524 while( rTxtPos
>= rNext
);
3527 else if ( rbStartLine
)
3529 // keine Attribute, aber trotzdem neue Zeile
3530 // wenn eine Zeile mit einem Seitenumbruch aufhoert und sich keine
3531 // Absatzattribute / Absatzvorlagen aendern, ist das Zeilenende
3532 // nicht im Plcx.Fkp.papx eingetragen, d.h. ( nFlags & MAN_MASK_NEW_PAP )
3533 // ist false. Deshalb muss als Sonderbehandlung hier die Vorlage gesetzt
3535 if (!bCpxStyle
&& nAktColl
< vColl
.size())
3536 SetTxtFmtCollAndListLevel(*pPaM
, vColl
[nAktColl
]);
3537 rbStartLine
= false;
3541 // CloseAttrEnds zum Lesen nur der Attributenden am Ende eines Textes oder
3542 // Textbereiches ( Kopfzeile, Fussnote, ...). Attributanfaenge, Felder
3543 // werden ignoriert.
3544 void SwWW8ImplReader::CloseAttrEnds()
3546 //If there are any unclosed sprms then copy them to
3547 //another stack and close the ones that must be closed
3548 std::stack
<sal_uInt16
> aStack
;
3549 pPlcxMan
->TransferOpenSprms(aStack
);
3551 while (!aStack
.empty())
3553 sal_uInt16 nSprmId
= aStack
.top();
3554 if ((0 < nSprmId
) && (( eFTN
> nSprmId
) || (0x0800 <= nSprmId
)))
3562 bool SwWW8ImplReader::ReadText(long nStartCp
, long nTextLen
, ManTypes nType
)
3566 bool bStartLine
= true;
3568 short nDistance
= 0;
3570 bWasParaEnd
= false;
3575 bPgSecBreak
= false;
3577 pPlcxMan
= new WW8PLCFMan( pSBase
, nType
, nStartCp
);
3578 long nCpOfs
= pPlcxMan
->GetCpOfs(); // Offset fuer Header/Footer, Footnote
3580 WW8_CP nNext
= pPlcxMan
->Where();
3581 SwTxtNode
* pPreviousNode
= 0;
3582 sal_uInt8 nDropLines
= 0;
3583 SwCharFmt
* pNewSwCharFmt
= 0;
3584 const SwCharFmt
* pFmt
= 0;
3585 pStrm
->Seek( pSBase
->WW8Cp2Fc( nStartCp
+ nCpOfs
, &bIsUnicode
) );
3587 WW8_CP l
= nStartCp
;
3588 while ( l
<nStartCp
+nTextLen
)
3590 ReadAttrs( nNext
, l
, bStartLine
);// behandelt auch Section-Breaks
3591 OSL_ENSURE(pPaM
->GetNode()->GetTxtNode(), "Missing txtnode");
3593 if (mpPostProcessAttrsInfo
!= NULL
)
3596 if( l
>= nStartCp
+ nTextLen
)
3599 bStartLine
= ReadChars(l
, nNext
, nStartCp
+nTextLen
, nCpOfs
);
3601 // If the previous paragraph was a dropcap then do not
3602 // create a new txtnode and join the two paragraphs together
3604 if (bStartLine
&& !pPreviousNode
) // Zeilenende
3606 //We will record the CP of a paragraph end ('0x0D'), if current loading contents is from main stream;
3607 if (mbOnLoadingMain
)
3608 maEndParaPos
.push_back(l
-1);
3609 AppendTxtNode(*pPaM
->GetPoint());
3612 if (pPreviousNode
&& bStartLine
)
3614 SwTxtNode
* pEndNd
= pPaM
->GetNode()->GetTxtNode();
3615 const xub_StrLen nDropCapLen
= pPreviousNode
->GetTxt().getLength();
3617 // Need to reset the font size and text position for the dropcap
3619 SwPaM
aTmp(*pEndNd
, 0, *pEndNd
, nDropCapLen
+1);
3620 pCtrlStck
->Delete(aTmp
);
3623 // Get the default document dropcap which we can use as our template
3624 const SwFmtDrop
* defaultDrop
=
3625 (const SwFmtDrop
*) GetFmtAttr(RES_PARATR_DROP
);
3626 SwFmtDrop
aDrop(*defaultDrop
);
3628 aDrop
.GetLines() = nDropLines
;
3629 aDrop
.GetDistance() = nDistance
;
3630 aDrop
.GetChars() = writer_cast
<sal_uInt8
>(nDropCapLen
);
3631 // Word has no concept of a "whole word dropcap"
3632 aDrop
.GetWholeWord() = false;
3635 aDrop
.SetCharFmt(const_cast<SwCharFmt
*>(pFmt
));
3636 else if(pNewSwCharFmt
)
3637 aDrop
.SetCharFmt(const_cast<SwCharFmt
*>(pNewSwCharFmt
));
3639 SwPosition
aStart(*pEndNd
);
3640 pCtrlStck
->NewAttr(aStart
, aDrop
);
3641 pCtrlStck
->SetAttr(*pPaM
->GetPoint(), RES_PARATR_DROP
);
3646 // If we have found a dropcap store the textnode
3647 pPreviousNode
= pPaM
->GetNode()->GetTxtNode();
3649 const sal_uInt8
*pDCS
;
3652 pDCS
= pPlcxMan
->GetPapPLCF()->HasSprm(46);
3654 pDCS
= pPlcxMan
->GetPapPLCF()->HasSprm(0x442C);
3657 nDropLines
= (*pDCS
) >> 3;
3658 else // There is no Drop Cap Specifier hence no dropcap
3661 if (const sal_uInt8
*pDistance
= pPlcxMan
->GetPapPLCF()->HasSprm(0x842F))
3662 nDistance
= SVBT16ToShort( pDistance
);
3666 const SwFmtCharFmt
*pSwFmtCharFmt
= 0;
3669 pSwFmtCharFmt
= &(ItemGet
<SwFmtCharFmt
>(*pAktItemSet
, RES_TXTATR_CHARFMT
));
3672 pFmt
= pSwFmtCharFmt
->GetCharFmt();
3674 if(pAktItemSet
&& !pFmt
)
3676 OUString
sPrefix(OUStringBuffer("WW8Dropcap").append(nDropCap
++).makeStringAndClear());
3677 pNewSwCharFmt
= rDoc
.MakeCharFmt(sPrefix
, (SwCharFmt
*)rDoc
.GetDfltCharFmt());
3678 pAktItemSet
->ClearItem(RES_CHRATR_ESCAPEMENT
);
3679 pNewSwCharFmt
->SetFmtAttr( *pAktItemSet
);
3687 if (bStartLine
|| bWasTabRowEnd
)
3689 // alle 64 CRs aufrufen not for Header u. ae.
3690 if ((nCrCount
++ & 0x40) == 0 && nType
== MAN_MAINTEXT
)
3692 nProgress
= (sal_uInt16
)( l
* 100 / nTextLen
);
3693 ::SetProgressState(nProgress
, mpDocShell
); // Update
3697 // If we have encountered a 0x0c which indicates either section of
3698 // pagebreak then look it up to see if it is a section break, and
3699 // if it is not then insert a page break. If it is a section break
3700 // it will be handled as such in the ReadAttrs of the next loop
3703 // We need only to see if a section is ending at this cp,
3704 // the plcf will already be sitting on the correct location
3707 aTemp
.nStartPos
= aTemp
.nEndPos
= WW8_CP_MAX
;
3708 if (pPlcxMan
->GetSepPLCF())
3709 pPlcxMan
->GetSepPLCF()->GetSprms(&aTemp
);
3710 if ((aTemp
.nStartPos
!= l
) && (aTemp
.nEndPos
!= l
))
3712 // #i39251# - insert text node for page break, if no one inserted.
3713 // #i43118# - refine condition: the anchor
3714 // control stack has to have entries, otherwise it's not needed
3715 // to insert a text node.
3716 if (!bStartLine
&& !pAnchorStck
->empty())
3718 AppendTxtNode(*pPaM
->GetPoint());
3720 rDoc
.InsertPoolItem(*pPaM
,
3721 SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE
, RES_BREAK
), 0);
3722 bFirstParaOfPage
= true;//xushanchuan add for issue106569
3723 bPgSecBreak
= false;
3728 if (pPaM
->GetPoint()->nContent
.GetIndex())
3729 AppendTxtNode(*pPaM
->GetPoint());
3732 bJoined
= JoinNode(*pPaM
);
3736 delete pPlcxMan
, pPlcxMan
= 0;
3740 /***************************************************************************
3741 # class SwWW8ImplReader
3742 #**************************************************************************/
3744 SwWW8ImplReader::SwWW8ImplReader(sal_uInt8 nVersionPara
, SvStorage
* pStorage
,
3745 SvStream
* pSt
, SwDoc
& rD
, const String
& rBaseURL
, bool bNewDoc
) :
3746 mpDocShell(rD
.GetDocShell()),
3752 maSectionManager(*this),
3753 m_aExtraneousParas(rD
),
3754 maInsertedTables(rD
),
3755 maSectionNameGenerator(rD
, OUString("WW")),
3756 maGrfNameGenerator(bNewDoc
, OUString('G')),
3757 maParaStyleMapper(rD
),
3758 maCharStyleMapper(rD
),
3759 maTxtNodesHavingFirstLineOfstSet(), // #i103711#
3760 maTxtNodesHavingLeftIndentSet(), // #i105414#
3764 m_bRegardHindiDigits( false ),
3771 mbOnLoadingMain(false)
3773 pStrm
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
3774 nWantedVersion
= nVersionPara
;
3787 pDfltTxtFmtColl
= 0;
3788 pStandardFmtColl
= 0;
3792 pFlyFmtOfJustInsertedGraphic
= 0;
3793 pFmtOfJustInsertedApo
= 0;
3794 pPreviousNumPaM
= 0;
3797 nObjLocFc
= nPicLocFc
= 0;
3799 bReadNoTbl
= bPgSecBreak
= bSpec
= bObj
= bTxbxFlySection
3800 = bHasBorder
= bSymbol
= bIgnoreText
3801 = bWasTabRowEnd
= bWasTabCellEnd
= false;
3802 bShdTxtCol
= bCharShdTxtCol
= bAnl
= bHdFtFtnEdn
= bFtnEdn
3803 = bIsHeader
= bIsFooter
= bIsUnicode
= bCpxStyle
= bStyNormal
=
3804 bWWBugNormal
= false;
3806 mpPostProcessAttrsInfo
= 0;
3808 bNoAttrImport
= bEmbeddObj
= false;
3809 bAktAND_fNumberAcross
= false;
3811 bInHyperlink
= false;
3812 bWasParaEnd
= false;
3815 bFirstParaOfPage
= false;//xushanchuan add for issue106569
3816 bParaAutoBefore
= false;
3817 bParaAutoAfter
= false;
3819 nSwNumLevel
= nWwNumType
= 0xff;
3822 pNode_FLY_AT_PARA
= 0;
3825 mpDrawEditEngine
= 0;
3828 mpChosenOutlineNumRule
= 0;
3832 nLFOPosition
= USHRT_MAX
;
3833 nListLevel
= WW8ListManager::nMaxLevel
;
3834 eHardCharSet
= RTL_TEXTENCODING_DONTKNOW
;
3836 nPgChpDelim
= nPgChpLevel
= 0;
3838 maApos
.push_back(false);
3841 void SwWW8ImplReader::DeleteStk(SwFltControlStack
* pStck
)
3845 pStck
->SetAttr( *pPaM
->GetPoint(), 0, false);
3846 pStck
->SetAttr( *pPaM
->GetPoint(), 0, false);
3851 OSL_ENSURE( !this, "WW-Stack bereits geloescht" );
3855 void wwSectionManager::SetSegmentToPageDesc(const wwSection
&rSection
,
3858 SwPageDesc
&rPage
= *rSection
.mpPage
;
3860 SetNumberingType(rSection
, rPage
);
3862 SwFrmFmt
&rFmt
= rPage
.GetMaster();
3864 if(mrReader
.pWDop
->fUseBackGroundInAllmodes
) // #i56806# Make sure mrReader is initialized
3865 mrReader
.GrafikCtor();
3868 if (mrReader
.pWDop
->fUseBackGroundInAllmodes
&& mrReader
.pMSDffManager
)
3870 Rectangle
aRect(0, 0, 100, 100); //A dummy, we don't care about the size
3871 SvxMSDffImportData
aData(aRect
);
3872 SdrObject
* pObject
= 0;
3873 if (mrReader
.pMSDffManager
->GetShape(0x401, pObject
, aData
))
3875 // Only handle shape if it is a background shape
3876 if ((aData
.begin()->nFlags
& 0x400) != 0)
3878 SfxItemSet
aSet(rFmt
.GetAttrSet());
3879 mrReader
.MatchSdrItemsIntoFlySet(pObject
, aSet
, mso_lineSimple
,
3880 mso_lineSolid
, mso_sptRectangle
, aRect
);
3881 rFmt
.SetFmtAttr(aSet
.Get(RES_BACKGROUND
));
3885 wwULSpaceData aULData
;
3886 GetPageULData(rSection
, aULData
);
3887 SetPageULSpaceItems(rFmt
, aULData
, rSection
);
3889 SetPage(rPage
, rFmt
, rSection
, bIgnoreCols
);
3891 if (!(rSection
.maSep
.pgbApplyTo
& 1))
3892 mrReader
.SetPageBorder(rFmt
, rSection
);
3893 if (!(rSection
.maSep
.pgbApplyTo
& 2))
3894 mrReader
.SetPageBorder(rPage
.GetFirstMaster(), rSection
);
3896 mrReader
.SetDocumentGrid(rFmt
, rSection
);
3899 void wwSectionManager::SetUseOn(wwSection
&rSection
)
3901 bool bEven
= (rSection
.maSep
.grpfIhdt
& (WW8_HEADER_EVEN
|WW8_FOOTER_EVEN
)) ?
3904 bool bMirror
= mrReader
.pWDop
->fMirrorMargins
||
3905 mrReader
.pWDop
->doptypography
.f2on1
;
3907 UseOnPage eUseBase
= bMirror
? nsUseOnPage::PD_MIRROR
: nsUseOnPage::PD_ALL
;
3908 UseOnPage eUse
= eUseBase
;
3910 eUse
= (UseOnPage
)(eUse
| nsUseOnPage::PD_HEADERSHARE
| nsUseOnPage::PD_FOOTERSHARE
);
3911 if (!rSection
.HasTitlePage())
3912 eUse
= (UseOnPage
)(eUse
| nsUseOnPage::PD_FIRSTSHARE
);
3914 OSL_ENSURE(rSection
.mpPage
, "Makes no sense to call me with no pages to set");
3915 if (rSection
.mpPage
)
3916 rSection
.mpPage
->WriteUseOn(eUse
);
3919 //Set the page descriptor on this node, handle the different cases for a text
3921 void GiveNodePageDesc(SwNodeIndex
&rIdx
, const SwFmtPageDesc
&rPgDesc
,
3925 If its a table here, apply the pagebreak to the table
3926 properties, otherwise we add it to the para at this
3929 if (rIdx
.GetNode().IsTableNode())
3932 rIdx
.GetNode().GetTableNode()->GetTable();
3933 SwFrmFmt
* pApply
= rTable
.GetFrmFmt();
3934 OSL_ENSURE(pApply
, "impossible");
3936 pApply
->SetFmtAttr(rPgDesc
);
3940 SwPosition
aPamStart(rIdx
);
3941 aPamStart
.nContent
.Assign(
3942 rIdx
.GetNode().GetCntntNode(), 0);
3943 SwPaM
aPage(aPamStart
);
3945 rDoc
.InsertPoolItem(aPage
, rPgDesc
, 0);
3949 //Map a word section to a writer page descriptor
3950 SwFmtPageDesc
wwSectionManager::SetSwFmtPageDesc(mySegIter
&rIter
,
3951 mySegIter
&rStart
, bool bIgnoreCols
)
3953 SwFmtPageDesc aEmpty
;
3955 if (IsNewDoc() && rIter
== rStart
)
3958 mrReader
.rDoc
.GetPageDescFromPool(RES_POOLPAGE_STANDARD
);
3962 sal_uInt16 nPos
= mrReader
.rDoc
.MakePageDesc(
3963 ViewShell::GetShellRes()->GetPageDescName(mnDesc
, ShellResource::NORMAL_PAGE
),
3965 rIter
->mpPage
= &mrReader
.rDoc
.GetPageDesc(nPos
);
3967 OSL_ENSURE(rIter
->mpPage
, "no page!");
3971 //Set page before hd/ft
3972 const wwSection
*pPrevious
= 0;
3973 if (rIter
!= rStart
)
3974 pPrevious
= &(*(rIter
-1));
3975 SetHdFt(*rIter
, std::distance(rStart
, rIter
), pPrevious
);
3978 //Set hd/ft after set page
3979 SetSegmentToPageDesc(*rIter
, bIgnoreCols
);
3981 SwFmtPageDesc
aRet(rIter
->mpPage
);
3983 rIter
->mpPage
->SetFollow(rIter
->mpPage
);
3985 if (rIter
->PageRestartNo())
3986 aRet
.SetNumOffset(rIter
->PageStartAt());
3992 bool wwSectionManager::IsNewDoc() const
3994 return mrReader
.mbNewDoc
;
3997 void wwSectionManager::InsertSegments()
3999 const SvtFilterOptions
& rOpt
= SvtFilterOptions::Get();
4000 sal_Bool bUseEnhFields
= rOpt
.IsUseEnhancedFields();
4001 mySegIter aEnd
= maSegments
.end();
4002 mySegIter aStart
= maSegments
.begin();
4003 for (mySegIter aIter
= aStart
; aIter
!= aEnd
; ++aIter
)
4005 // If the section is of type "New column" (0x01), then simply insert a column break.
4006 // But only if there actually are columns on the page, otherwise a column break
4007 // seems to be handled like a page break by MSO.
4008 if ( aIter
->maSep
.bkc
== 1 && aIter
->maSep
.ccolM1
> 0 )
4010 SwPaM
start( aIter
->maStart
);
4011 mrReader
.rDoc
.InsertPoolItem( start
, SvxFmtBreakItem(SVX_BREAK_COLUMN_BEFORE
, RES_BREAK
), 0);
4015 mySegIter aNext
= aIter
+1;
4016 mySegIter aPrev
= (aIter
== aStart
) ? aIter
: aIter
-1;
4018 // If two following sections are different in following properties, Word will interprete a continuous
4019 // section break between them as if it was a section break next page.
4020 bool bThisAndPreviousAreCompatible
= ((aIter
->GetPageWidth() == aPrev
->GetPageWidth()) &&
4021 (aIter
->GetPageHeight() == aPrev
->GetPageHeight()) && (aIter
->IsLandScape() == aPrev
->IsLandScape()));
4023 bool bInsertSection
= (aIter
!= aStart
) ? (aIter
->IsContinous() && bThisAndPreviousAreCompatible
): false;
4024 bool bInsertPageDesc
= !bInsertSection
;
4025 bool bProtected
= SectionIsProtected(*aIter
); // do we really need this ?? I guess I have a different logic in editshell which disables this...
4026 if (bUseEnhFields
&& mrReader
.pWDop
->fProtEnabled
&& aIter
->IsNotProtected())
4028 // here we have the special case that the whole document is protected, with the execption of this section.
4029 // I want to address this when I do the section rework, so for the moment we disable the overall protection then...
4030 mrReader
.rDoc
.set(IDocumentSettingAccess::PROTECT_FORM
, false );
4034 if (bInsertPageDesc
)
4037 If a cont section follows this section then we won't be
4038 creating a page desc with 2+ cols as we cannot host a one
4039 col section in a 2+ col pagedesc and make it look like
4040 word. But if the current section actually has columns then
4041 we are forced to insert a section here as well as a page
4045 bool bIgnoreCols
= false;
4046 bool bThisAndNextAreCompatible
= (aNext
!= aEnd
) ? ((aIter
->GetPageWidth() == aNext
->GetPageWidth()) &&
4047 (aIter
->GetPageHeight() == aNext
->GetPageHeight()) && (aIter
->IsLandScape() == aNext
->IsLandScape())) : true;
4049 if (((aNext
!= aEnd
&& aNext
->IsContinous() && bThisAndNextAreCompatible
) || bProtected
))
4052 if ((aIter
->NoCols() > 1) || bProtected
)
4053 bInsertSection
= true;
4056 SwFmtPageDesc
aDesc(SetSwFmtPageDesc(aIter
, aStart
, bIgnoreCols
));
4057 if (!aDesc
.GetPageDesc())
4060 // special case handling for odd/even section break
4061 // a) as before create a new page style for the section break
4062 // b) set Layout of generated page style to right/left ( according
4063 // to section break odd/even )
4064 // c) create a new style to follow the break page style
4065 if ( aIter
->maSep
.bkc
== 3 || aIter
->maSep
.bkc
== 4 )
4067 // SetSwFmtPageDesc calls some methods that could
4068 // modify aIter (e.g. wwSection ).
4069 // Since we call SetSwFmtPageDesc below to generate the
4070 // 'Following' style of the Break style, it is safer
4071 // to take a copy of the contents of aIter.
4072 wwSection aTmpSection
= *aIter
;
4073 // create a new following page style
4074 SwFmtPageDesc
aFollow(SetSwFmtPageDesc(aIter
, aStart
, bIgnoreCols
));
4075 // restore any contents of aIter trashed by SetSwFmtPageDesc
4076 *aIter
= aTmpSection
;
4078 // Handle the section break
4079 UseOnPage eUseOnPage
= nsUseOnPage::PD_LEFT
;
4080 if ( aIter
->maSep
.bkc
== 4 ) // Odd ( right ) Section break
4081 eUseOnPage
= nsUseOnPage::PD_RIGHT
;
4083 aDesc
.GetPageDesc()->WriteUseOn( eUseOnPage
);
4084 aDesc
.GetPageDesc()->SetFollow( aFollow
.GetPageDesc() );
4087 GiveNodePageDesc(aIter
->maStart
, aDesc
, mrReader
.rDoc
);
4090 SwTxtNode
* pTxtNd
= 0;
4093 //Start getting the bounds of this section
4094 SwPaM
aSectPaM(*mrReader
.pPaM
);
4095 SwNodeIndex
aAnchor(aSectPaM
.GetPoint()->nNode
);
4098 aAnchor
= aNext
->maStart
;
4099 aSectPaM
.GetPoint()->nNode
= aAnchor
;
4100 aSectPaM
.GetPoint()->nContent
.Assign(
4101 aNext
->maStart
.GetNode().GetCntntNode(), 0);
4102 aSectPaM
.Move(fnMoveBackward
);
4105 const SwPosition
* pPos
= aSectPaM
.GetPoint();
4106 SwTxtNode
const*const pSttNd
= pPos
->nNode
.GetNode().GetTxtNode();
4107 const SwTableNode
* pTableNd
= pSttNd
? pSttNd
->FindTableNode() : 0;
4111 mrReader
.rDoc
.GetNodes().MakeTxtNode(aAnchor
,
4112 mrReader
.rDoc
.GetTxtCollFromPool( RES_POOLCOLL_TEXT
));
4114 aSectPaM
.GetPoint()->nNode
= SwNodeIndex(*pTxtNd
);
4115 aSectPaM
.GetPoint()->nContent
.Assign(
4116 aSectPaM
.GetCntntNode(), 0);
4121 aSectPaM
.GetPoint()->nNode
= aIter
->maStart
;
4122 aSectPaM
.GetPoint()->nContent
.Assign(
4123 aSectPaM
.GetCntntNode(), 0);
4124 //End getting the bounds of this section, quite a job eh ?
4126 SwSectionFmt
*pRet
= InsertSection(aSectPaM
, *aIter
);
4127 //The last section if continous is always unbalanced
4130 //Set the columns to be UnBalanced if that compatability option
4132 if (mrReader
.pWDop
->fNoColumnBalance
)
4133 pRet
->SetFmtAttr(SwFmtNoBalancedColumns(true));
4136 //Otherwise set to unbalanced if the following section is
4137 //not continuous, (which also means that the last section
4139 if (aNext
== aEnd
|| !aNext
->IsContinous())
4140 pRet
->SetFmtAttr(SwFmtNoBalancedColumns(true));
4144 bool bHasOwnHdFt
= false;
4146 In this nightmare scenario the continuous section has its own
4147 headers and footers so we will try and find a hard page break
4148 between here and the end of the section and put the headers and
4151 if (!bInsertPageDesc
)
4154 mrReader
.HasOwnHeaderFooter(
4155 aIter
->maSep
.grpfIhdt
& ~(WW8_HEADER_FIRST
| WW8_FOOTER_FIRST
),
4156 aIter
->maSep
.grpfIhdt
, std::distance(aStart
, aIter
)
4161 // #i40766# Need to cache the page descriptor in case there is
4162 // no page break in the section
4163 SwPageDesc
*pOrig
= aIter
->mpPage
;
4164 bool bFailed
= true;
4165 SwFmtPageDesc
aDesc(SetSwFmtPageDesc(aIter
, aStart
, true));
4166 if (aDesc
.GetPageDesc())
4168 sal_uLong nStart
= aSectPaM
.Start()->nNode
.GetIndex();
4169 sal_uLong nEnd
= aSectPaM
.End()->nNode
.GetIndex();
4170 for(; nStart
<= nEnd
; ++nStart
)
4172 SwNode
* pNode
= mrReader
.rDoc
.GetNodes()[nStart
];
4175 if (sw::util::HasPageBreak(*pNode
))
4177 SwNodeIndex
aIdx(*pNode
);
4178 GiveNodePageDesc(aIdx
, aDesc
, mrReader
.rDoc
);
4186 aIter
->mpPage
= pOrig
;
4193 SwNodeIndex
aIdx(*pTxtNd
);
4195 mrReader
.rDoc
.DelFullPara(aTest
);
4201 void wwExtraneousParas::delete_all_from_doc()
4203 typedef std::vector
<SwTxtNode
*>::iterator myParaIter
;
4204 myParaIter aEnd
= m_aTxtNodes
.end();
4205 for (myParaIter aI
= m_aTxtNodes
.begin(); aI
!= aEnd
; ++aI
)
4207 SwTxtNode
*pTxtNode
= *aI
;
4208 SwNodeIndex
aIdx(*pTxtNode
);
4210 m_rDoc
.DelFullPara(aTest
);
4212 m_aTxtNodes
.clear();
4215 void SwWW8ImplReader::StoreMacroCmds()
4217 if (pWwFib
->lcbCmds
)
4219 pTableStream
->Seek(pWwFib
->fcCmds
);
4221 uno::Reference
< embed::XStorage
> xRoot(mpDocShell
->GetStorage());
4228 uno::Reference
< io::XStream
> xStream
=
4229 xRoot
->openStreamElement( OUString(SL::aMSMacroCmds
), embed::ElementModes::READWRITE
);
4230 SvStream
* pStream
= ::utl::UcbStreamHelper::CreateStream( xStream
);
4232 sal_uInt8
*pBuffer
= new sal_uInt8
[pWwFib
->lcbCmds
];
4233 pWwFib
->lcbCmds
= pTableStream
->Read(pBuffer
, pWwFib
->lcbCmds
);
4234 pStream
->Write(pBuffer
, pWwFib
->lcbCmds
);
4238 catch ( const uno::Exception
& )
4244 void SwWW8ImplReader::ReadDocVars()
4246 std::vector
<String
> aDocVarStrings
;
4247 std::vector
<ww::bytes
> aDocVarStringIds
;
4248 std::vector
<String
> aDocValueStrings
;
4249 WW8ReadSTTBF(!bVer67
, *pTableStream
, pWwFib
->fcStwUser
,
4250 pWwFib
->lcbStwUser
, bVer67
? 2 : 0, eStructCharSet
,
4251 aDocVarStrings
, &aDocVarStringIds
, &aDocValueStrings
);
4253 using namespace ::com::sun::star
;
4255 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
4256 mpDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
4257 uno::Reference
<document::XDocumentProperties
> xDocProps(
4258 xDPS
->getDocumentProperties());
4259 OSL_ENSURE(xDocProps
.is(), "DocumentProperties is null");
4260 uno::Reference
<beans::XPropertyContainer
> xUserDefinedProps
=
4261 xDocProps
->getUserDefinedProperties();
4262 OSL_ENSURE(xUserDefinedProps
.is(), "UserDefinedProperties is null");
4264 for(size_t i
=0; i
<aDocVarStrings
.size(); i
++)
4266 uno::Any aDefaultValue
;
4267 OUString
name(aDocVarStrings
[i
]);
4269 aValue
<<= OUString(aDocValueStrings
[i
]);
4271 xUserDefinedProps
->addProperty( name
,
4272 beans::PropertyAttribute::REMOVABLE
,
4274 } catch (const uno::Exception
&) {
4281 //-----------------------------------------
4283 //-----------------------------------------
4285 void SwWW8ImplReader::ReadDocInfo()
4289 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
4290 mpDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
4291 uno::Reference
<document::XDocumentProperties
> xDocProps(
4292 xDPS
->getDocumentProperties());
4293 OSL_ENSURE(xDocProps
.is(), "DocumentProperties is null");
4295 if (xDocProps
.is()) {
4298 OUString sTemplateURL
;
4299 SfxMedium
* pMedium
= mpDocShell
->GetMedium();
4302 OUString aName
= pMedium
->GetName();
4303 INetURLObject
aURL( aName
);
4304 sTemplateURL
= aURL
.GetMainURL(INetURLObject::DECODE_TO_IURI
);
4305 if ( !sTemplateURL
.isEmpty() )
4306 xDocProps
->setTemplateURL( sTemplateURL
);
4309 else if (pWwFib
->lcbSttbfAssoc
) // not a template, and has a SttbfAssoc
4311 long nCur
= pTableStream
->Tell();
4313 pTableStream
->Seek( pWwFib
->fcSttbfAssoc
); // point at tgc record
4314 if (!aSttb
.Read( *pTableStream
) )
4315 OSL_TRACE("** Read of SttbAssoc data failed!!!! ");
4316 pTableStream
->Seek( nCur
); // return to previous position, is that necessary?
4317 #if OSL_DEBUG_LEVEL > 1
4318 aSttb
.Print( stderr
);
4320 String sPath
= aSttb
.getStringAtIndex( 0x1 );
4322 // attempt to convert to url ( won't work for obvious reasons on linux
4324 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sPath
, aURL
);
4326 xDocProps
->setTemplateURL( aURL
);
4328 xDocProps
->setTemplateURL( sPath
);
4331 sfx2::LoadOlePropertySet(xDocProps
, pStg
);
4336 static void lcl_createTemplateToProjectEntry( const uno::Reference
< container::XNameContainer
>& xPrjNameCache
, const OUString
& sTemplatePathOrURL
, const OUString
& sVBAProjName
)
4338 if ( xPrjNameCache
.is() )
4341 aObj
.SetURL( sTemplatePathOrURL
);
4342 bool bIsURL
= aObj
.GetProtocol() != INET_PROT_NOT_VALID
;
4345 aURL
= sTemplatePathOrURL
;
4348 osl::FileBase::getFileURLFromSystemPath( sTemplatePathOrURL
, aURL
);
4349 aObj
.SetURL( aURL
);
4353 OUString templateNameWithExt
= aObj
.GetLastName();
4354 OUString templateName
;
4355 sal_Int32 nIndex
= templateNameWithExt
.lastIndexOf( '.' );
4358 templateName
= templateNameWithExt
.copy( 0, nIndex
);
4359 xPrjNameCache
->insertByName( templateName
, uno::makeAny( sVBAProjName
) );
4362 catch( const uno::Exception
& )
4368 class WW8Customizations
4370 SvStream
* mpTableStream
;
4373 WW8Customizations( SvStream
*, WW8Fib
& );
4374 bool Import( SwDocShell
* pShell
);
4377 WW8Customizations::WW8Customizations( SvStream
* pTableStream
, WW8Fib
& rFib
) : mpTableStream(pTableStream
), mWw8Fib( rFib
)
4381 bool WW8Customizations::Import( SwDocShell
* pShell
)
4383 if ( mWw8Fib
.lcbCmds
== 0 || !IsEightPlus(mWw8Fib
.GetFIBVersion()) )
4388 long nCur
= mpTableStream
->Tell();
4389 mpTableStream
->Seek( mWw8Fib
.fcCmds
); // point at tgc record
4390 bool bReadResult
= aTCG
.Read( *mpTableStream
);
4391 mpTableStream
->Seek( nCur
); // return to previous position, is that necessary?
4394 SAL_WARN("sw.ww8", "** Read of Customization data failed!!!! ");
4397 #if OSL_DEBUG_LEVEL > 1
4398 aTCG
.Print( stderr
);
4400 return aTCG
.ImportCustomToolBar( *pShell
);
4404 SAL_WARN("sw.ww8", "** Read of Customization data failed!!!! epically");
4409 bool SwWW8ImplReader::ReadGlobalTemplateSettings( const OUString
& sCreatedFrom
, const uno::Reference
< container::XNameContainer
>& xPrjNameCache
)
4411 SvtPathOptions aPathOpt
;
4412 String aAddinPath
= aPathOpt
.GetAddinPath();
4413 uno::Sequence
< OUString
> sGlobalTemplates
;
4415 // first get the autoload addins in the directory STARTUP
4416 uno::Reference
<ucb::XSimpleFileAccess3
> xSFA(ucb::SimpleFileAccess::create(::comphelper::getProcessComponentContext()));
4418 if( xSFA
->isFolder( aAddinPath
) )
4419 sGlobalTemplates
= xSFA
->getFolderContents( aAddinPath
, sal_False
);
4421 sal_Int32 nEntries
= sGlobalTemplates
.getLength();
4423 for ( sal_Int32 i
=0; i
<nEntries
; ++i
)
4426 aObj
.SetURL( sGlobalTemplates
[ i
] );
4427 bool bIsURL
= aObj
.GetProtocol() != INET_PROT_NOT_VALID
;
4430 aURL
= sGlobalTemplates
[ i
];
4432 osl::FileBase::getFileURLFromSystemPath( sGlobalTemplates
[ i
], aURL
);
4433 if ( !aURL
.endsWithIgnoreAsciiCase( ".dot" ) || ( !sCreatedFrom
.isEmpty() && sCreatedFrom
.equals( aURL
) ) )
4434 continue; // don't try and read the same document as ourselves
4436 SotStorageRef rRoot
= new SotStorage( aURL
, STREAM_STD_READWRITE
, STORAGE_TRANSACTED
);
4438 BasicProjImportHelper
aBasicImporter( *mpDocShell
);
4439 // Import vba via oox filter
4440 aBasicImporter
.import( mpDocShell
->GetMedium()->GetInputStream() );
4441 lcl_createTemplateToProjectEntry( xPrjNameCache
, aURL
, aBasicImporter
.getProjectName() );
4442 // Read toolbars & menus
4443 SvStorageStreamRef refMainStream
= rRoot
->OpenSotStream( OUString( "WordDocument" ));
4444 refMainStream
->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN
);
4445 WW8Fib
aWwFib( *refMainStream
, 8 );
4446 SvStorageStreamRef xTableStream
= rRoot
->OpenSotStream(OUString::createFromAscii( aWwFib
.fWhichTblStm
? SL::a1Table
: SL::a0Table
), STREAM_STD_READ
);
4448 if (xTableStream
.Is() && SVSTREAM_OK
== xTableStream
->GetError())
4450 xTableStream
->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN
);
4451 WW8Customizations
aGblCustomisations( xTableStream
, aWwFib
);
4452 aGblCustomisations
.Import( mpDocShell
);
4458 sal_uLong
SwWW8ImplReader::CoreLoad(WW8Glossary
*pGloss
, const SwPosition
&rPos
)
4460 sal_uLong nErrRet
= 0;
4462 if (mbNewDoc
&& pStg
&& !pGloss
)
4465 ::ww8::WW8FibData
* pFibData
= new ::ww8::WW8FibData();
4467 if (pWwFib
->fReadOnlyRecommended
)
4468 pFibData
->setReadOnlyRecommended(true);
4470 pFibData
->setReadOnlyRecommended(false);
4472 if (pWwFib
->fWriteReservation
)
4473 pFibData
->setWriteReservation(true);
4475 pFibData
->setWriteReservation(false);
4477 ::sw::tExternalDataPointer
pExternalFibData(pFibData
);
4479 rDoc
.setExternalData(::sw::FIB
, pExternalFibData
);
4481 ::sw::tExternalDataPointer pSttbfAsoc
4482 (new ::ww8::WW8Sttb
<ww8::WW8Struct
>(*pTableStream
, pWwFib
->fcSttbfAssoc
, pWwFib
->lcbSttbfAssoc
));
4484 rDoc
.setExternalData(::sw::STTBF_ASSOC
, pSttbfAsoc
);
4486 if (pWwFib
->fWriteReservation
|| pWwFib
->fReadOnlyRecommended
)
4488 SwDocShell
* pDocShell
= rDoc
.GetDocShell();
4490 pDocShell
->SetReadOnlyUI(sal_True
);
4493 pPaM
= new SwPaM(rPos
);
4495 pCtrlStck
= new SwWW8FltControlStack( &rDoc
, nFieldFlags
, *this );
4497 mpRedlineStack
= new sw::util::RedlineStack(rDoc
);
4500 RefFldStck: Keeps track of bookmarks which may be inserted as
4503 pReffedStck
= new SwFltEndStack(&rDoc
, nFieldFlags
);
4504 pReffingStck
= new SwWW8FltRefStack(&rDoc
, nFieldFlags
);
4506 pAnchorStck
= new SwWW8FltAnchorStack(&rDoc
, nFieldFlags
);
4508 sal_uInt16 nPageDescOffset
= rDoc
.GetPageDescCnt();
4510 SwNodeIndex
aSttNdIdx( rDoc
.GetNodes() );
4511 SwRelNumRuleSpaces
aRelNumRule(rDoc
, mbNewDoc
);
4513 sal_uInt16 eMode
= nsRedlineMode_t::REDLINE_SHOW_INSERT
;
4515 mpSprmParser
= new wwSprmParser(pWwFib
->GetFIBVersion());
4517 // praktische Hilfsvariablen besetzen:
4518 bVer6
= (6 == pWwFib
->nVersion
);
4519 bVer7
= (7 == pWwFib
->nVersion
);
4520 bVer67
= bVer6
|| bVer7
;
4521 bVer8
= (8 == pWwFib
->nVersion
);
4523 eTextCharSet
= WW8Fib::GetFIBCharset(pWwFib
->chse
);
4524 eStructCharSet
= WW8Fib::GetFIBCharset(pWwFib
->chseTables
);
4526 bWWBugNormal
= pWwFib
->nProduct
== 0xc03d;
4529 aSttNdIdx
= pPaM
->GetPoint()->nNode
;
4531 ::StartProgress(STR_STATSTR_W4WREAD
, 0, 100, mpDocShell
);
4534 pFonts
= new WW8Fonts( *pTableStream
, *pWwFib
);
4536 // Document Properties
4537 pWDop
= new WW8Dop( *pTableStream
, pWwFib
->nFib
, pWwFib
->fcDop
,
4544 Import revisioning data: author names
4546 if( pWwFib
->lcbSttbfRMark
)
4548 ReadRevMarkAuthorStrTabl( *pTableStream
,
4549 pWwFib
->fcSttbfRMark
,
4550 pWwFib
->lcbSttbfRMark
, rDoc
);
4553 // M.M. Initialize our String/ID map for Linked Sections
4554 std::vector
<String
> aLinkStrings
;
4555 std::vector
<ww::bytes
> aStringIds
;
4557 WW8ReadSTTBF(!bVer67
, *pTableStream
, pWwFib
->fcSttbFnm
,
4558 pWwFib
->lcbSttbFnm
, bVer67
? 2 : 0, eStructCharSet
,
4559 aLinkStrings
, &aStringIds
);
4561 for (size_t i
=0; i
< aLinkStrings
.size() && i
< aStringIds
.size(); ++i
)
4563 ww::bytes stringId
= aStringIds
[i
];
4564 WW8_STRINGID
*stringIdStruct
= (WW8_STRINGID
*)(&stringId
[0]);
4565 aLinkStringMap
[SVBT16ToShort(stringIdStruct
->nStringId
)] =
4569 ReadDocVars(); // import document variables as meta information.
4571 ::SetProgressState(nProgress
, mpDocShell
); // Update
4573 pLstManager
= new WW8ListManager( *pTableStream
, *this );
4576 zuerst(!) alle Styles importieren (siehe WW8PAR2.CXX)
4577 VOR dem Import der Listen !!
4579 ::SetProgressState(nProgress
, mpDocShell
); // Update
4580 pStyles
= new WW8RStyle( *pWwFib
, this ); // Styles
4584 zu guter Letzt: (siehe ebenfalls WW8PAR3.CXX)
4586 alle Styles durchgehen und ggfs. zugehoeriges Listen-Format
4587 anhaengen NACH dem Import der Styles und NACH dem Import der
4590 ::SetProgressState(nProgress
, mpDocShell
); // Update
4591 pStyles
->PostProcessStyles();
4596 pSBase
= new WW8ScannerBase(pStrm
,pTableStream
,pDataStream
,pWwFib
);
4598 static const SvxExtNumType eNumTA
[16] =
4600 SVX_NUM_ARABIC
, SVX_NUM_ROMAN_UPPER
, SVX_NUM_ROMAN_LOWER
,
4601 SVX_NUM_CHARS_UPPER_LETTER_N
, SVX_NUM_CHARS_LOWER_LETTER_N
,
4602 SVX_NUM_ARABIC
, SVX_NUM_ARABIC
, SVX_NUM_ARABIC
,
4603 SVX_NUM_ARABIC
, SVX_NUM_ARABIC
, SVX_NUM_ARABIC
,
4604 SVX_NUM_ARABIC
, SVX_NUM_ARABIC
, SVX_NUM_ARABIC
,
4605 SVX_NUM_ARABIC
, SVX_NUM_ARABIC
4608 if (pSBase
->AreThereFootnotes())
4610 static const SwFtnNum eNumA
[4] =
4612 FTNNUM_DOC
, FTNNUM_CHAPTER
, FTNNUM_PAGE
, FTNNUM_DOC
4616 aInfo
= rDoc
.GetFtnInfo(); // Copy-Ctor privat
4618 aInfo
.ePos
= FTNPOS_PAGE
;
4619 aInfo
.eNum
= eNumA
[pWDop
->rncFtn
];
4620 aInfo
.aFmt
.SetNumberingType( static_cast< sal_uInt16
>(eNumTA
[pWDop
->nfcFtnRef
]) );
4622 aInfo
.nFtnOffset
= pWDop
->nFtn
- 1;
4623 rDoc
.SetFtnInfo( aInfo
);
4625 if( pSBase
->AreThereEndnotes() )
4627 SwEndNoteInfo aInfo
;
4628 aInfo
= rDoc
.GetEndNoteInfo(); // parallel zu Ftn
4630 aInfo
.aFmt
.SetNumberingType( static_cast< sal_uInt16
>(eNumTA
[pWDop
->nfcEdnRef
]) );
4632 aInfo
.nFtnOffset
= pWDop
->nEdn
- 1;
4633 rDoc
.SetEndNoteInfo( aInfo
);
4636 if( pWwFib
->lcbPlcfhdd
)
4637 pHdFt
= new WW8PLCF_HdFt( pTableStream
, *pWwFib
, *pWDop
);
4641 // inserting into an existing document:
4642 // As only complete paragraphs are inserted, the current one
4643 // needs to be splitted - once or even twice.
4644 const SwPosition
* pPos
= pPaM
->GetPoint();
4646 // split current paragraph to get new paragraph for the insertion
4647 rDoc
.SplitNode( *pPos
, false );
4649 // another split, if insertion position was not at the end of the current paragraph.
4650 SwTxtNode
const*const pTxtNd
= pPos
->nNode
.GetNode().GetTxtNode();
4651 if ( pTxtNd
->GetTxt().getLength() )
4653 rDoc
.SplitNode( *pPos
, false );
4654 // move PaM back to the newly empty paragraph
4655 pPaM
->Move( fnMoveBackward
);
4658 // suppress insertion of tables inside footnotes.
4659 const sal_uLong nNd
= pPos
->nNode
.GetIndex();
4660 bReadNoTbl
= ( nNd
< rDoc
.GetNodes().GetEndOfInserts().GetIndex() &&
4661 rDoc
.GetNodes().GetEndOfInserts().StartOfSectionIndex() < nNd
);
4665 ::SetProgressState(nProgress
, mpDocShell
); // Update
4667 // loop for each glossary entry and add dummy section node
4670 WW8PLCF
aPlc(*pTableStream
, pWwFib
->fcPlcfglsy
, pWwFib
->lcbPlcfglsy
, 0);
4672 WW8_CP nStart
, nEnd
;
4675 for (int i
= 0; i
< pGloss
->GetNoStrings(); ++i
, aPlc
.advance())
4677 SwNodeIndex
aIdx( rDoc
.GetNodes().GetEndOfContent());
4678 SwTxtFmtColl
* pColl
=
4679 rDoc
.GetTxtCollFromPool(RES_POOLCOLL_STANDARD
,
4681 SwStartNode
*pNode
=
4682 rDoc
.GetNodes().MakeTextSection(aIdx
,
4683 SwNormalStartNode
,pColl
);
4684 pPaM
->GetPoint()->nNode
= pNode
->GetIndex()+1;
4685 pPaM
->GetPoint()->nContent
.Assign(pPaM
->GetCntntNode(),0);
4686 aPlc
.Get( nStart
, nEnd
, pDummy
);
4687 ReadText(nStart
,nEnd
-nStart
-1,MAN_MAINTEXT
);
4690 else //ordinary case
4692 if (mbNewDoc
&& pStg
&& !pGloss
) /*meaningless for a glossary, cmc*/
4694 mpDocShell
->SetIsTemplate( pWwFib
->fDot
); // point at tgc record
4695 uno::Reference
<document::XDocumentPropertiesSupplier
> const
4696 xDocPropSupp(mpDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
4697 uno::Reference
< document::XDocumentProperties
> xDocProps( xDocPropSupp
->getDocumentProperties(), uno::UNO_QUERY_THROW
);
4699 OUString sCreatedFrom
= xDocProps
->getTemplateURL();
4700 uno::Reference
< container::XNameContainer
> xPrjNameCache
;
4701 uno::Reference
< lang::XMultiServiceFactory
> xSF(mpDocShell
->GetModel(), uno::UNO_QUERY
);
4703 xPrjNameCache
.set( xSF
->createInstance( "ooo.vba.VBAProjectNameProvider" ), uno::UNO_QUERY
);
4705 // Read Global templates
4706 ReadGlobalTemplateSettings( sCreatedFrom
, xPrjNameCache
);
4708 // Create and insert Word vba Globals
4710 uno::Sequence
< uno::Any
> aArgs(1);
4711 aArgs
[ 0 ] <<= mpDocShell
->GetModel();
4712 aGlobs
<<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( "ooo.vba.word.Globals", aArgs
);
4714 #ifndef DISABLE_SCRIPTING
4715 BasicManager
*pBasicMan
= mpDocShell
->GetBasicManager();
4717 pBasicMan
->SetGlobalUNOConstant( "VBAGlobals", aGlobs
);
4719 BasicProjImportHelper
aBasicImporter( *mpDocShell
);
4720 // Import vba via oox filter
4721 bool bRet
= aBasicImporter
.import( mpDocShell
->GetMedium()->GetInputStream() );
4723 lcl_createTemplateToProjectEntry( xPrjNameCache
, sCreatedFrom
, aBasicImporter
.getProjectName() );
4724 WW8Customizations
aCustomisations( pTableStream
, *pWwFib
);
4725 aCustomisations
.Import( mpDocShell
);
4728 rDoc
.SetContainsMSVBasic(true);
4732 mbOnLoadingMain
= true;
4733 ReadText(0, pWwFib
->ccpText
, MAN_MAINTEXT
);
4734 mbOnLoadingMain
= false;
4738 ::SetProgressState(nProgress
, mpDocShell
); // Update
4740 if (pDrawPg
&& pMSDffManager
&& pMSDffManager
->GetShapeOrders())
4742 // Hilfsarray zum Verketten der (statt SdrTxtObj) eingefuegten
4744 SvxMSDffShapeTxBxSort aTxBxSort
;
4746 // korrekte Z-Order der eingelesen Escher-Objekte sicherstellen
4747 sal_uInt16 nShapeCount
= pMSDffManager
->GetShapeOrders()->size();
4749 for (sal_uInt16 nShapeNum
=0; nShapeNum
< nShapeCount
; nShapeNum
++)
4751 SvxMSDffShapeOrder
*pOrder
=
4752 (*pMSDffManager
->GetShapeOrders())[nShapeNum
];
4753 // Pointer in neues Sort-Array einfuegen
4754 if (pOrder
->nTxBxComp
&& pOrder
->pFly
)
4755 aTxBxSort
.insert(pOrder
);
4757 // zu verkettende Rahmen jetzt verketten
4758 if( !aTxBxSort
.empty() )
4761 for( SvxMSDffShapeTxBxSort::iterator it
= aTxBxSort
.begin(); it
!= aTxBxSort
.end(); ++it
)
4763 SvxMSDffShapeOrder
*pOrder
= *it
;
4765 // Fly-Frame-Formate initialisieren
4766 SwFlyFrmFmt
* pFlyFmt
= pOrder
->pFly
;
4767 SwFlyFrmFmt
* pNextFlyFmt
= 0;
4768 SwFlyFrmFmt
* pPrevFlyFmt
= 0;
4769 // ggfs. Nachfolger ermitteln
4770 SvxMSDffShapeTxBxSort::iterator tmpIter1
= it
;
4772 if( tmpIter1
!= aTxBxSort
.end() )
4774 SvxMSDffShapeOrder
*pNextOrder
= *tmpIter1
;
4775 if ((0xFFFF0000 & pOrder
->nTxBxComp
)
4776 == (0xFFFF0000 & pNextOrder
->nTxBxComp
))
4777 pNextFlyFmt
= pNextOrder
->pFly
;
4779 // ggfs. Vorgaenger ermitteln
4780 if( it
!= aTxBxSort
.begin() )
4782 SvxMSDffShapeTxBxSort::iterator tmpIter2
= it
;
4784 SvxMSDffShapeOrder
*pPrevOrder
= *tmpIter2
;
4785 if ((0xFFFF0000 & pOrder
->nTxBxComp
)
4786 == (0xFFFF0000 & pPrevOrder
->nTxBxComp
))
4787 pPrevFlyFmt
= pPrevOrder
->pFly
;
4789 // Falls Nachfolger oder Vorgaenger vorhanden,
4790 // die Verkettung am Fly-Frame-Format eintragen
4791 if (pNextFlyFmt
|| pPrevFlyFmt
)
4793 aChain
.SetNext( pNextFlyFmt
);
4794 aChain
.SetPrev( pPrevFlyFmt
);
4795 pFlyFmt
->SetFmtAttr( aChain
);
4805 if( pWDop
->fRevMarking
)
4806 eMode
|= nsRedlineMode_t::REDLINE_ON
;
4807 if( pWDop
->fRMView
)
4808 eMode
|= nsRedlineMode_t::REDLINE_SHOW_DELETE
;
4811 maInsertedTables
.DelAndMakeTblFrms();
4812 maSectionManager
.InsertSegments();
4821 DELETEZ( pMSDffManager
);
4827 delete mpSprmParser
;
4828 ::EndProgress(mpDocShell
);
4834 mpRedlineStack
->closeall(*pPaM
->GetPoint());
4835 delete mpRedlineStack
;
4838 //For i120928,achieve the graphics from the special bookmark with is for graphic bullet
4840 std::vector
<const SwGrfNode
*> vecBulletGrf
;
4841 std::vector
<SwFrmFmt
*> vecFrmFmt
;
4843 IDocumentMarkAccess
* const pMarkAccess
=
4844 rDoc
.getIDocumentMarkAccess();
4847 IDocumentMarkAccess::const_iterator_t ppBkmk
=
4848 pMarkAccess
->findBookmark( "_PictureBullets" );
4849 if ( ppBkmk
!= pMarkAccess
->getBookmarksEnd() &&
4850 IDocumentMarkAccess::GetType( *(ppBkmk
->get()) )
4851 == IDocumentMarkAccess::BOOKMARK
)
4853 SwTxtNode
* pTxtNode
= ppBkmk
->get()->GetMarkStart().nNode
.GetNode().GetTxtNode();
4856 const SwpHints
*pHints
= pTxtNode
->GetpSwpHints();
4857 for(int nHintPos
= 0; pHints
&& nHintPos
< pHints
->Count(); ++nHintPos
)
4859 const SwTxtAttr
*pHt
= (*pHints
)[nHintPos
];
4860 xub_StrLen st
= *(pHt
->GetStart());
4861 if(pHt
&& pHt
->Which() == RES_TXTATR_FLYCNT
&& (st
>= ppBkmk
->get()->GetMarkStart().nContent
.GetIndex()))
4863 SwFrmFmt
*pFrmFmt
= pHt
->GetFlyCnt().GetFrmFmt();
4864 const SwNodeIndex
*pNdIdx
= pFrmFmt
->GetCntnt().GetCntntIdx();
4867 const SwNodes
&nos
= pNdIdx
->GetNodes();
4868 const SwGrfNode
*pGrf
= dynamic_cast<const SwGrfNode
*>(nos
[pNdIdx
->GetIndex() + 1]);
4871 vecBulletGrf
.push_back(pGrf
);
4872 vecFrmFmt
.push_back(pFrmFmt
);
4877 // update graphic bullet information
4878 size_t nCount
= pLstManager
->GetWW8LSTInfoNum();
4879 for (size_t i
= 0; i
< nCount
; ++i
)
4881 SwNumRule
* pRule
= pLstManager
->GetNumRule(i
);
4882 for (int j
= 0; j
< MAXLEVEL
; ++j
)
4884 SwNumFmt
aNumFmt(pRule
->Get(j
));
4885 sal_Int16 nType
= aNumFmt
.GetNumberingType();
4886 sal_uInt16 nGrfBulletCP
= aNumFmt
.GetGrfBulletCP();
4887 if (nType
== SVX_NUM_BITMAP
&& vecBulletGrf
.size() > nGrfBulletCP
)
4889 Graphic aGraphic
= vecBulletGrf
[nGrfBulletCP
]->GetGrf();
4890 SvxBrushItem
aBrush(aGraphic
, GPOS_AREA
, SID_ATTR_BRUSH
);
4891 Font aFont
= numfunc::GetDefBulletFont();
4892 int nHeight
= aFont
.GetHeight() * 12;//20;
4893 Size
aPrefSize( aGraphic
.GetPrefSize());
4894 if (aPrefSize
.Height() * aPrefSize
.Width() != 0 )
4896 int nWidth
= (nHeight
* aPrefSize
.Width()) / aPrefSize
.Height();
4897 Size
aSize(nWidth
, nHeight
);
4898 aNumFmt
.SetGraphicBrush(&aBrush
, &aSize
);
4902 aNumFmt
.SetNumberingType(SVX_NUM_CHAR_SPECIAL
);
4903 aNumFmt
.SetBulletChar(0x2190);
4905 pRule
->Set( j
, aNumFmt
);
4909 // Remove additional pictures
4910 for (sal_uInt16 i
= 0; i
< vecFrmFmt
.size(); ++i
)
4912 rDoc
.DelLayoutFmt(vecFrmFmt
[i
]);
4917 DELETEZ( pLstManager
);
4920 //remove extra paragraphs after attribute ctrl
4921 //stacks etc. are destroyed, and before fields
4923 m_aExtraneousParas
.delete_all_from_doc();
4927 // delete the pam before the call for hide all redlines (Bug 73683)
4929 rDoc
.SetRedlineMode((RedlineMode_t
)( eMode
));
4931 UpdatePageDescs(rDoc
, nPageDescOffset
);
4933 delete pPaM
, pPaM
= 0;
4937 sal_uLong
SwWW8ImplReader::SetSubStreams(SvStorageStreamRef
&rTableStream
,
4938 SvStorageStreamRef
&rDataStream
)
4940 sal_uLong nErrRet
= 0;
4941 // 6 stands for "6 OR 7", 7 stand for "ONLY 7"
4942 switch (pWwFib
->nVersion
)
4946 pTableStream
= pStrm
;
4947 pDataStream
= pStrm
;
4952 OSL_ENSURE( pStg
, "Version 8 muss immer einen Storage haben!" );
4953 nErrRet
= ERR_SWG_READ_ERROR
;
4957 rTableStream
= pStg
->OpenSotStream( OUString::createFromAscii(
4958 pWwFib
->fWhichTblStm
? SL::a1Table
: SL::a0Table
),
4961 pTableStream
= &rTableStream
;
4962 pTableStream
->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN
);
4964 rDataStream
= pStg
->OpenSotStream(OUString(SL::aData
),
4965 STREAM_STD_READ
| STREAM_NOCREATE
);
4967 if (rDataStream
.Is() && SVSTREAM_OK
== rDataStream
->GetError())
4969 pDataStream
= &rDataStream
;
4970 pDataStream
->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN
);
4973 pDataStream
= pStrm
;
4977 OSL_ENSURE( !this, "Es wurde vergessen, nVersion zu kodieren!" );
4978 nErrRet
= ERR_SWG_READ_ERROR
;
4986 utl::TempFile
*MakeTemp(SvFileStream
&rSt
)
4988 utl::TempFile
*pT
= new utl::TempFile
;
4989 pT
->EnableKillingFile();
4990 rSt
.Open(pT
->GetFileName(), STREAM_READWRITE
| STREAM_SHARE_DENYWRITE
);
4994 #define WW_BLOCKSIZE 0x200
4996 void DecryptRC4(msfilter::MSCodec_Std97
& rCtx
, SvStream
&rIn
, SvStream
&rOut
)
4998 rIn
.Seek(STREAM_SEEK_TO_END
);
4999 const sal_Size nLen
= rIn
.Tell();
5002 sal_uInt8 in
[WW_BLOCKSIZE
];
5003 for (sal_Size nI
= 0, nBlock
= 0; nI
< nLen
; nI
+= WW_BLOCKSIZE
, ++nBlock
)
5005 sal_Size nBS
= (nLen
- nI
> WW_BLOCKSIZE
) ? WW_BLOCKSIZE
: nLen
- nI
;
5006 nBS
= rIn
.Read(in
, nBS
);
5007 rCtx
.InitCipher(nBlock
);
5008 rCtx
.Decode(in
, nBS
, in
, nBS
);
5009 rOut
.Write(in
, nBS
);
5013 void DecryptXOR(msfilter::MSCodec_XorWord95
&rCtx
, SvStream
&rIn
, SvStream
&rOut
)
5015 sal_Size nSt
= rIn
.Tell();
5016 rIn
.Seek(STREAM_SEEK_TO_END
);
5017 sal_Size nLen
= rIn
.Tell();
5023 sal_uInt8 in
[0x4096];
5024 for (sal_Size nI
= nSt
; nI
< nLen
; nI
+= 0x4096)
5026 sal_Size nBS
= (nLen
- nI
> 0x4096 ) ? 0x4096 : nLen
- nI
;
5027 nBS
= rIn
.Read(in
, nBS
);
5028 rCtx
.Decode(in
, nBS
);
5029 rOut
.Write(in
, nBS
);
5033 //moan, copy and paste :-(
5034 String
QueryPasswordForMedium(SfxMedium
& rMedium
)
5038 using namespace com::sun::star
;
5040 const SfxItemSet
* pSet
= rMedium
.GetItemSet();
5041 const SfxPoolItem
*pPasswordItem
;
5043 if(pSet
&& SFX_ITEM_SET
== pSet
->GetItemState(SID_PASSWORD
, sal_True
, &pPasswordItem
))
5044 aPassw
= ((const SfxStringItem
*)pPasswordItem
)->GetValue();
5049 uno::Reference
< task::XInteractionHandler
> xHandler( rMedium
.GetInteractionHandler() );
5052 ::comphelper::DocPasswordRequest
* pRequest
= new ::comphelper::DocPasswordRequest(
5053 ::comphelper::DocPasswordRequestType_MS
, task::PasswordRequestMode_PASSWORD_ENTER
,
5054 INetURLObject( rMedium
.GetOrigURL() ).GetName( INetURLObject::DECODE_WITH_CHARSET
) );
5055 uno::Reference
< task::XInteractionRequest
> xRequest( pRequest
);
5057 xHandler
->handle( xRequest
);
5059 if( pRequest
->isPassword() )
5060 aPassw
= pRequest
->getPassword();
5063 catch( const uno::Exception
& )
5071 uno::Sequence
< beans::NamedValue
> InitXorWord95Codec( ::msfilter::MSCodec_XorWord95
& rCodec
, SfxMedium
& rMedium
, WW8Fib
* pWwFib
)
5073 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
5074 SFX_ITEMSET_ARG( rMedium
.GetItemSet(), pEncryptionData
, SfxUnoAnyItem
, SID_ENCRYPTIONDATA
, sal_False
);
5075 if ( pEncryptionData
&& ( pEncryptionData
->GetValue() >>= aEncryptionData
) && !rCodec
.InitCodec( aEncryptionData
) )
5076 aEncryptionData
.realloc( 0 );
5078 if ( !aEncryptionData
.getLength() )
5080 String sUniPassword
= QueryPasswordForMedium( rMedium
);
5082 OString
sPassword(OUStringToOString(sUniPassword
,
5083 WW8Fib::GetFIBCharset(pWwFib
->chseTables
)));
5085 sal_Int32 nLen
= sPassword
.getLength();
5088 sal_uInt8 pPassword
[16];
5089 memcpy(pPassword
, sPassword
.getStr(), nLen
);
5090 memset(pPassword
+nLen
, 0, sizeof(pPassword
)-nLen
);
5092 rCodec
.InitKey( pPassword
);
5093 aEncryptionData
= rCodec
.GetEncryptionData();
5095 // the export supports RC4 algorithm only, so we have to
5096 // generate the related EncryptionData as well, so that Save
5097 // can export the document without asking for a password;
5098 // as result there will be EncryptionData for both algorithms
5099 // in the MediaDescriptor
5100 ::msfilter::MSCodec_Std97 aCodec97
;
5102 // Generate random number with a seed of time as salt.
5104 osl_getSystemTime( &aTime
);
5105 rtlRandomPool aRandomPool
= rtl_random_createPool();
5106 rtl_random_addBytes ( aRandomPool
, &aTime
, 8 );
5108 sal_uInt8 pDocId
[ 16 ];
5109 rtl_random_getBytes( aRandomPool
, pDocId
, 16 );
5111 rtl_random_destroyPool( aRandomPool
);
5113 sal_uInt16 pStd97Pass
[16];
5114 memset( pStd97Pass
, 0, sizeof( pStd97Pass
) );
5115 for (xub_StrLen nChar
= 0; nChar
< nLen
; ++nChar
)
5116 pStd97Pass
[nChar
] = sUniPassword
.GetChar(nChar
);
5118 aCodec97
.InitKey( pStd97Pass
, pDocId
);
5120 // merge the EncryptionData, there should be no conflicts
5121 ::comphelper::SequenceAsHashMap
aEncryptionHash( aEncryptionData
);
5122 aEncryptionHash
.update( ::comphelper::SequenceAsHashMap( aCodec97
.GetEncryptionData() ) );
5123 aEncryptionHash
>> aEncryptionData
;
5127 return aEncryptionData
;
5130 uno::Sequence
< beans::NamedValue
> InitStd97Codec( ::msfilter::MSCodec_Std97
& rCodec
, sal_uInt8 pDocId
[16], SfxMedium
& rMedium
)
5132 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
5133 SFX_ITEMSET_ARG( rMedium
.GetItemSet(), pEncryptionData
, SfxUnoAnyItem
, SID_ENCRYPTIONDATA
, sal_False
);
5134 if ( pEncryptionData
&& ( pEncryptionData
->GetValue() >>= aEncryptionData
) && !rCodec
.InitCodec( aEncryptionData
) )
5135 aEncryptionData
.realloc( 0 );
5137 if ( !aEncryptionData
.getLength() )
5139 String sUniPassword
= QueryPasswordForMedium( rMedium
);
5141 xub_StrLen nLen
= sUniPassword
.Len();
5144 sal_Unicode pPassword
[16];
5145 memset( pPassword
, 0, sizeof( pPassword
) );
5146 for (xub_StrLen nChar
= 0; nChar
< nLen
; ++nChar
)
5147 pPassword
[nChar
] = sUniPassword
.GetChar(nChar
);
5149 rCodec
.InitKey( pPassword
, pDocId
);
5150 aEncryptionData
= rCodec
.GetEncryptionData();
5154 return aEncryptionData
;
5158 sal_uLong
SwWW8ImplReader::LoadThroughDecryption(SwPaM
& rPaM
,WW8Glossary
*pGloss
)
5160 sal_uLong nErrRet
= 0;
5162 pWwFib
= pGloss
->GetFib();
5164 pWwFib
= new WW8Fib(*pStrm
, nWantedVersion
);
5166 if (pWwFib
->nFibError
)
5167 nErrRet
= ERR_SWG_READ_ERROR
;
5169 SvStorageStreamRef xTableStream
, xDataStream
;
5172 nErrRet
= SetSubStreams(xTableStream
, xDataStream
);
5174 utl::TempFile
*pTempMain
= 0;
5175 utl::TempFile
*pTempTable
= 0;
5176 utl::TempFile
*pTempData
= 0;
5177 SvFileStream aDecryptMain
;
5178 SvFileStream aDecryptTable
;
5179 SvFileStream aDecryptData
;
5181 bool bDecrypt
= false;
5182 enum {RC4
, XOR
, Other
} eAlgo
= Other
;
5183 if (pWwFib
->fEncrypted
&& !nErrRet
)
5188 if (8 != pWwFib
->nVersion
)
5192 if (pWwFib
->nKey
!= 0)
5196 pTableStream
->Seek(0);
5197 sal_uInt32 nEncType
;
5198 *pTableStream
>> nEncType
;
5199 if (nEncType
== 0x10001)
5208 nErrRet
= ERRCODE_SVX_WRONGPASS
;
5209 SfxMedium
* pMedium
= mpDocShell
->GetMedium();
5216 nErrRet
= ERRCODE_SVX_READ_FILTER_CRYPT
;
5220 msfilter::MSCodec_XorWord95 aCtx
;
5221 uno::Sequence
< beans::NamedValue
> aEncryptionData
= InitXorWord95Codec( aCtx
, *pMedium
, pWwFib
);
5223 // if initialization has failed the EncryptionData should be empty
5224 if ( aEncryptionData
.getLength() && aCtx
.VerifyKey( pWwFib
->nKey
, pWwFib
->nHash
) )
5227 pTempMain
= MakeTemp(aDecryptMain
);
5230 size_t nUnencryptedHdr
=
5231 (8 == pWwFib
->nVersion
) ? 0x44 : 0x34;
5232 sal_uInt8
*pIn
= new sal_uInt8
[nUnencryptedHdr
];
5233 nUnencryptedHdr
= pStrm
->Read(pIn
, nUnencryptedHdr
);
5234 aDecryptMain
.Write(pIn
, nUnencryptedHdr
);
5237 DecryptXOR(aCtx
, *pStrm
, aDecryptMain
);
5239 if (!pTableStream
|| pTableStream
== pStrm
)
5240 pTableStream
= &aDecryptMain
;
5243 pTempTable
= MakeTemp(aDecryptTable
);
5244 DecryptXOR(aCtx
, *pTableStream
, aDecryptTable
);
5245 pTableStream
= &aDecryptTable
;
5248 if (!pDataStream
|| pDataStream
== pStrm
)
5249 pDataStream
= &aDecryptMain
;
5252 pTempData
= MakeTemp(aDecryptData
);
5253 DecryptXOR(aCtx
, *pDataStream
, aDecryptData
);
5254 pDataStream
= &aDecryptData
;
5257 pMedium
->GetItemSet()->ClearItem( SID_PASSWORD
);
5258 pMedium
->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) ) );
5264 sal_uInt8 aDocId
[ 16 ];
5265 sal_uInt8 aSaltData
[ 16 ];
5266 sal_uInt8 aSaltHash
[ 16 ];
5268 bool bCouldReadHeaders
=
5269 checkRead(*pTableStream
, aDocId
, 16) &&
5270 checkRead(*pTableStream
, aSaltData
, 16) &&
5271 checkRead(*pTableStream
, aSaltHash
, 16);
5273 msfilter::MSCodec_Std97 aCtx
;
5274 // if initialization has failed the EncryptionData should be empty
5275 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
5276 if (bCouldReadHeaders
)
5277 aEncryptionData
= InitStd97Codec( aCtx
, aDocId
, *pMedium
);
5278 if ( aEncryptionData
.getLength() && aCtx
.VerifyKey( aSaltData
, aSaltHash
) )
5282 pTempMain
= MakeTemp(aDecryptMain
);
5285 sal_Size nUnencryptedHdr
= 0x44;
5286 sal_uInt8
*pIn
= new sal_uInt8
[nUnencryptedHdr
];
5287 nUnencryptedHdr
= pStrm
->Read(pIn
, nUnencryptedHdr
);
5289 DecryptRC4(aCtx
, *pStrm
, aDecryptMain
);
5291 aDecryptMain
.Seek(0);
5292 aDecryptMain
.Write(pIn
, nUnencryptedHdr
);
5296 pTempTable
= MakeTemp(aDecryptTable
);
5297 DecryptRC4(aCtx
, *pTableStream
, aDecryptTable
);
5298 pTableStream
= &aDecryptTable
;
5300 if (!pDataStream
|| pDataStream
== pStrm
)
5301 pDataStream
= &aDecryptMain
;
5304 pTempData
= MakeTemp(aDecryptData
);
5305 DecryptRC4(aCtx
, *pDataStream
, aDecryptData
);
5306 pDataStream
= &aDecryptData
;
5309 pMedium
->GetItemSet()->ClearItem( SID_PASSWORD
);
5310 pMedium
->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) ) );
5319 pStrm
= &aDecryptMain
;
5322 pWwFib
= new WW8Fib(*pStrm
, nWantedVersion
);
5323 if (pWwFib
->nFibError
)
5324 nErrRet
= ERR_SWG_READ_ERROR
;
5329 nErrRet
= CoreLoad(pGloss
, *rPaM
.GetPoint());
5340 class outlineeq
: public std::unary_function
<const SwTxtFmtColl
*, bool>
5345 outlineeq(sal_uInt8 nNum
) : mnNum(nNum
) {}
5346 bool operator()(const SwTxtFmtColl
*pTest
) const
5348 return pTest
->IsAssignedToListLevelOfOutlineStyle() && pTest
->GetAssignedOutlineStyleLevel() == mnNum
; //<-end,zhaojianwei
5352 void SwWW8ImplReader::SetOutLineStyles()
5355 #i3674# & #101291# Load new document and insert document cases.
5357 SwNumRule
aOutlineRule(*rDoc
.GetOutlineNumRule());
5359 // <mpChosenOutlineNumRule> has to be set to point to local variable
5360 // <aOutlineRule>, because its used below to be compared this <&aOutlineRule>.
5361 // But at the end of the method <mpChosenOutlineNumRule> has to be set to
5362 // <rDoc.GetOutlineNumRule()>, because <aOutlineRule> will be destroyed.
5363 mpChosenOutlineNumRule
= &aOutlineRule
;
5365 sw::ParaStyles
aOutLined(sw::util::GetParaStyles(rDoc
));
5366 // #i98791# - sorting algorithm adjusted
5367 sw::util::SortByAssignedOutlineStyleListLevel(aOutLined
);
5369 typedef sw::ParaStyleIter myParaStyleIter
;
5371 If we are inserted into a document then don't clobber existing existing
5374 sal_uInt16 nFlagsStyleOutlLevel
= 0;
5377 // #i70748# - backward iteration needed due to the outline level attribute
5378 sw::ParaStyles::reverse_iterator aEnd
= aOutLined
.rend();
5379 for ( sw::ParaStyles::reverse_iterator aIter
= aOutLined
.rbegin(); aIter
< aEnd
; ++aIter
)
5381 if ((*aIter
)->IsAssignedToListLevelOfOutlineStyle())
5382 nFlagsStyleOutlLevel
|= 1 << (*aIter
)->GetAssignedOutlineStyleLevel();//<-end,zhaojianwei
5390 Only import *one* of the possible multiple outline numbering rules, so
5391 pick the one that affects most styles. If we're not importing a new
5392 document, we got to stick with what is already there.
5394 // use index in text format collection array <vColl>
5395 // as key of the outline numbering map <aRuleMap>
5396 // instead of the memory pointer of the outline numbering rule
5397 // to assure that, if two outline numbering rule affect the same
5398 // count of text formats, always the same outline numbering rule is chosen.
5399 std::map
<sal_uInt16
, int>aRuleMap
;
5400 typedef std::map
<sal_uInt16
, int>::iterator myIter
;
5401 for (sal_uInt16 nI
= 0; nI
< vColl
.size(); ++nI
)
5403 SwWW8StyInf
& rSI
= vColl
[ nI
];
5405 (MAXLEVEL
> rSI
.nOutlineLevel
) && rSI
.pOutlineNumrule
&&
5409 myIter aIter
= aRuleMap
.find(nI
);
5410 if (aIter
== aRuleMap
.end())
5420 myIter aEnd2
= aRuleMap
.end();
5421 for (myIter aIter
= aRuleMap
.begin(); aIter
!= aEnd2
; ++aIter
)
5423 if (aIter
->second
> nMax
)
5425 nMax
= aIter
->second
;
5426 if(aIter
->first
< vColl
.size())
5427 mpChosenOutlineNumRule
= vColl
[ aIter
->first
].pOutlineNumrule
;
5429 mpChosenOutlineNumRule
= 0; //TODO make sure this is what we want
5433 OSL_ENSURE(mpChosenOutlineNumRule
, "Impossible");
5434 if (mpChosenOutlineNumRule
)
5435 aOutlineRule
= *mpChosenOutlineNumRule
;
5437 if (mpChosenOutlineNumRule
!= &aOutlineRule
)
5439 // #i70748# - backward iteration needed due to the outline level attribute
5440 sw::ParaStyles::reverse_iterator aEnd
= aOutLined
.rend();
5441 for ( sw::ParaStyles::reverse_iterator aIter
= aOutLined
.rbegin(); aIter
< aEnd
; ++aIter
)
5443 if((*aIter
)->IsAssignedToListLevelOfOutlineStyle())
5444 (*aIter
)->DeleteAssignmentToListLevelOfOutlineStyle(); //<-end
5452 sal_uInt16 nOldFlags
= nFlagsStyleOutlLevel
;
5454 for (sal_uInt16 nI
= 0; nI
< vColl
.size(); ++nI
)
5456 SwWW8StyInf
& rSI
= vColl
[nI
];
5458 if (rSI
.IsOutlineNumbered())
5460 sal_uInt16 nAktFlags
= 1 << rSI
.nOutlineLevel
;
5462 (nAktFlags
& nFlagsStyleOutlLevel
) ||
5463 (rSI
.pOutlineNumrule
!= mpChosenOutlineNumRule
)
5467 If our spot is already taken by something we can't replace
5468 then don't insert and remove our outline level.
5470 rSI
.pFmt
->SetFmtAttr(
5471 SwNumRuleItem( rSI
.pOutlineNumrule
->GetName() ) );
5472 ((SwTxtFmtColl
*)rSI
.pFmt
)->DeleteAssignmentToListLevelOfOutlineStyle();//#outline level,zhaojianwei
5477 If there is a style already set for this outline
5478 numbering level and its not a style set by us already
5479 then we can remove it outline numbering.
5480 (its one of the default headings in a new document
5481 so we can clobber it)
5482 Of course if we are being inserted into a document that
5483 already has some set we can't do this, thats covered by
5484 the list of level in nFlagsStyleOutlLevel to ignore.
5486 outlineeq
aCmp(rSI
.nOutlineLevel
);
5487 myParaStyleIter aResult
= std::find_if(aOutLined
.begin(),
5488 aOutLined
.end(), aCmp
);
5490 myParaStyleIter aEnd
= aOutLined
.end();
5491 while (aResult
!= aEnd
&& aCmp(*aResult
))
5493 (*aResult
)->DeleteAssignmentToListLevelOfOutlineStyle();
5499 I believe that when a list is registered onto a winword
5500 style which is an outline numbering style (i.e.
5501 nOutlineLevel is set) that the style of numbering is for
5502 the level is indexed by the *list* level that was
5503 registered on that style, and not the outlinenumbering
5504 level, which is probably a logical sequencing, and not a
5505 physical mapping into the list style reged on that outline
5508 sal_uInt8 nFromLevel
= rSI
.nListLevel
;
5509 sal_uInt8 nToLevel
= rSI
.nOutlineLevel
;
5510 const SwNumFmt
& rRule
=rSI
.pOutlineNumrule
->Get(nFromLevel
);
5511 aOutlineRule
.Set(nToLevel
, rRule
);
5512 ((SwTxtFmtColl
*)rSI
.pFmt
)->AssignToListLevelOfOutlineStyle(nToLevel
); //<-end,zhaojianwei
5513 // If there are more styles on this level ignore them
5514 nFlagsStyleOutlLevel
|= nAktFlags
;
5518 if (nOldFlags
!= nFlagsStyleOutlLevel
)
5519 rDoc
.SetOutlineNumRule(aOutlineRule
);
5521 if ( mpChosenOutlineNumRule
== &aOutlineRule
)
5523 mpChosenOutlineNumRule
= rDoc
.GetOutlineNumRule();
5527 const String
* SwWW8ImplReader::GetAnnotationAuthor(sal_uInt16 nIdx
)
5529 if (!mpAtnNames
&& pWwFib
->lcbGrpStAtnOwners
)
5531 // Authoren bestimmen: steht im TableStream
5532 mpAtnNames
= new ::std::vector
<String
>;
5533 SvStream
& rStrm
= *pTableStream
;
5535 long nOldPos
= rStrm
.Tell();
5536 rStrm
.Seek( pWwFib
->fcGrpStAtnOwners
);
5538 long nRead
= 0, nCount
= pWwFib
->lcbGrpStAtnOwners
;
5539 while (nRead
< nCount
)
5543 mpAtnNames
->push_back(read_uInt8_PascalString(rStrm
,
5544 RTL_TEXTENCODING_MS_1252
));
5545 nRead
+= mpAtnNames
->rbegin()->Len() + 1; // Laenge + sal_uInt8 Count
5549 mpAtnNames
->push_back(read_uInt16_PascalString(rStrm
));
5550 // UNICode: doppelte Laenge + sal_uInt16 Count
5551 nRead
+= mpAtnNames
->rbegin()->Len() * 2 + 2;
5554 rStrm
.Seek( nOldPos
);
5557 const String
*pRet
= 0;
5558 if (mpAtnNames
&& nIdx
< mpAtnNames
->size())
5559 pRet
= &((*mpAtnNames
)[nIdx
]);
5563 int SwWW8ImplReader::GetAnnotationIndex(sal_uInt32 nTag
)
5565 if (!mpAtnIndexes
.get() && pWwFib
->lcbSttbfAtnbkmk
)
5567 mpAtnIndexes
.reset(new std::map
<sal_uInt32
, int>());
5568 std::vector
<String
> aStrings
;
5569 std::vector
<ww::bytes
> aEntries
;
5570 WW8ReadSTTBF(!bVer67
, *pTableStream
, pWwFib
->fcSttbfAtnbkmk
, pWwFib
->lcbSttbfAtnbkmk
, sizeof(struct WW8_ATNBE
), eStructCharSet
, aStrings
, &aEntries
);
5571 for (size_t i
= 0; i
< aStrings
.size() && i
< aEntries
.size(); ++i
)
5573 ww::bytes aEntry
= aEntries
[i
];
5574 WW8_ATNBE
* pAtnbeStruct
= (WW8_ATNBE
*)(&aEntry
[0]);
5575 mpAtnIndexes
->insert(std::pair
<sal_uInt32
, int>(SVBT32ToUInt32(pAtnbeStruct
->nTag
), i
));
5578 if (mpAtnIndexes
.get())
5580 std::map
<sal_uInt32
, int>::iterator it
= mpAtnIndexes
->find(nTag
);
5581 if (it
!= mpAtnIndexes
->end())
5587 WW8_CP
SwWW8ImplReader::GetAnnotationStart(int nIndex
)
5589 if (!mpAtnStarts
.get() && pWwFib
->lcbPlcfAtnbkf
)
5590 // A PLCFBKF is a PLC whose data elements are FBKF structures (4 bytes each).
5591 mpAtnStarts
.reset(new WW8PLCFspecial(pTableStream
, pWwFib
->fcPlcfAtnbkf
, pWwFib
->lcbPlcfAtnbkf
, 4));
5593 if (mpAtnStarts
.get())
5594 return mpAtnStarts
->GetPos(nIndex
);
5596 return SAL_MAX_INT32
;
5599 WW8_CP
SwWW8ImplReader::GetAnnotationEnd(int nIndex
)
5601 if (!mpAtnEnds
.get() && pWwFib
->lcbPlcfAtnbkl
)
5602 // The Plcfbkl structure is a PLC that contains only CPs and no additional data.
5603 mpAtnEnds
.reset(new WW8PLCFspecial(pTableStream
, pWwFib
->fcPlcfAtnbkl
, pWwFib
->lcbPlcfAtnbkl
, 0));
5605 if (mpAtnEnds
.get())
5606 return mpAtnEnds
->GetPos(nIndex
);
5608 return SAL_MAX_INT32
;
5611 sal_uLong
SwWW8ImplReader::LoadDoc( SwPaM
& rPaM
,WW8Glossary
*pGloss
)
5613 sal_uLong nErrRet
= 0;
5616 static const sal_Char
* aNames
[ 13 ] = {
5617 "WinWord/WW", "WinWord/WW8", "WinWord/WWFT",
5618 "WinWord/WWFLX", "WinWord/WWFLY",
5620 "WinWord/WWFA0", "WinWord/WWFA1", "WinWord/WWFA2",
5621 "WinWord/WWFB0", "WinWord/WWFB1", "WinWord/WWFB2",
5622 "WinWord/RegardHindiDigits"
5624 sal_uInt32 aVal
[ 13 ];
5626 SwFilterOptions
aOpt( 13, aNames
, aVal
);
5628 nIniFlags
= aVal
[ 0 ];
5629 nIniFlags1
= aVal
[ 1 ];
5630 // schiebt Flys um x twips nach rechts o. links
5631 nIniFlyDx
= aVal
[ 3 ];
5632 nIniFlyDy
= aVal
[ 4 ];
5634 nFieldFlags
= aVal
[ 5 ];
5635 nFieldTagAlways
[0] = aVal
[ 6 ];
5636 nFieldTagAlways
[1] = aVal
[ 7 ];
5637 nFieldTagAlways
[2] = aVal
[ 8 ];
5638 nFieldTagBad
[0] = aVal
[ 9 ];
5639 nFieldTagBad
[1] = aVal
[ 10 ];
5640 nFieldTagBad
[2] = aVal
[ 11 ];
5641 m_bRegardHindiDigits
= aVal
[ 12 ] > 0;
5644 sal_uInt16
nMagic(0);
5647 // beachte: 6 steht fuer "6 ODER 7", 7 steht fuer "NUR 7"
5648 switch (nWantedVersion
)
5653 (0xa5dc != nMagic
&& 0xa5db != nMagic
) &&
5654 (nMagic
< 0xa697 || nMagic
> 0xa699)
5657 // teste auf eigenen 97-Fake!
5658 if (pStg
&& 0xa5ec == nMagic
)
5660 sal_uLong nCurPos
= pStrm
->Tell();
5661 if (pStrm
->Seek(nCurPos
+ 22))
5665 if (0x300 != nfcMin
)
5666 nErrRet
= ERR_WW6_NO_WW6_FILE_ERR
;
5668 pStrm
->Seek( nCurPos
);
5671 nErrRet
= ERR_WW6_NO_WW6_FILE_ERR
;
5675 if (0xa5ec != nMagic
)
5676 nErrRet
= ERR_WW8_NO_WW8_FILE_ERR
;
5679 nErrRet
= ERR_WW8_NO_WW8_FILE_ERR
;
5680 OSL_ENSURE( !this, "Es wurde vergessen, nVersion zu kodieren!" );
5685 nErrRet
= LoadThroughDecryption(rPaM
,pGloss
);
5687 rDoc
.PropagateOutlineRule();
5692 extern "C" SAL_DLLPUBLIC_EXPORT Reader
* SAL_CALL
ImportDOC()
5694 return new WW8Reader();
5697 sal_uLong
WW8Reader::OpenMainStream( SvStorageStreamRef
& rRef
, sal_uInt16
& rBuffSize
)
5699 sal_uLong nRet
= ERR_SWG_READ_ERROR
;
5700 OSL_ENSURE( pStg
, "wo ist mein Storage?" );
5701 rRef
= pStg
->OpenSotStream( OUString("WordDocument"), STREAM_READ
| STREAM_SHARE_DENYALL
);
5705 if( SVSTREAM_OK
== rRef
->GetError() )
5707 sal_uInt16 nOld
= rRef
->GetBufferSize();
5708 rRef
->SetBufferSize( rBuffSize
);
5713 nRet
= rRef
->GetError();
5718 sal_uLong
WW8Reader::Read(SwDoc
&rDoc
, const String
& rBaseURL
, SwPaM
&rPam
, const String
& /* FileName */)
5720 sal_uInt16 nOldBuffSize
= 32768;
5721 bool bNew
= !bInsertMode
; // Neues Doc ( kein Einfuegen )
5724 SvStorageStreamRef refStrm
; // damit uns keiner den Stream klaut
5725 SvStream
* pIn
= pStrm
;
5728 sal_uInt8 nVersion
= 8;
5730 String sFltName
= GetFltName();
5731 if( sFltName
.EqualsAscii( "WW6" ) )
5737 OSL_ENSURE(!this, "WinWord 95 Reader-Read ohne Stream");
5738 nRet
= ERR_SWG_READ_ERROR
;
5743 if( sFltName
.EqualsAscii( "CWW6" ) )
5745 else if( sFltName
.EqualsAscii( "CWW7" ) )
5750 nRet
= OpenMainStream( refStrm
, nOldBuffSize
);
5755 OSL_ENSURE(!this, "WinWord 95/97 Reader-Read ohne Storage");
5756 nRet
= ERR_SWG_READ_ERROR
;
5764 // MIB 27.09.96: Umrandung uns Abstaende aus Frm-Vorlagen entf.
5765 Reader::ResetFrmFmts( rDoc
);
5767 SwWW8ImplReader
* pRdr
= new SwWW8ImplReader(nVersion
, pStg
, pIn
, rDoc
,
5771 nRet
= pRdr
->LoadDoc( rPam
);
5773 catch( const std::exception
& )
5775 nRet
= ERR_WW8_NO_WW8_FILE_ERR
;
5781 refStrm
->SetBufferSize( nOldBuffSize
);
5791 int WW8Reader::GetReaderType()
5793 return SW_STORAGE_READER
| SW_STREAM_READER
;
5796 sal_Bool
WW8Reader::HasGlossaries() const
5801 sal_Bool
WW8Reader::ReadGlossaries(SwTextBlocks
& rBlocks
, sal_Bool bSaveRelFiles
) const
5805 WW8Reader
*pThis
= const_cast<WW8Reader
*>(this);
5807 sal_uInt16 nOldBuffSize
= 32768;
5808 SvStorageStreamRef refStrm
;
5809 if (!pThis
->OpenMainStream(refStrm
, nOldBuffSize
))
5811 WW8Glossary
aGloss( refStrm
, 8, pStg
);
5812 bRet
= aGloss
.Load( rBlocks
, bSaveRelFiles
? true : false);
5814 return bRet
? true : false;
5817 sal_Bool
SwMSDffManager::GetOLEStorageName(long nOLEId
, OUString
& rStorageName
,
5818 SvStorageRef
& rSrcStorage
, uno::Reference
< embed::XStorage
>& rDestStorage
) const
5822 sal_Int32 nPictureId
= 0;
5825 // dann holen wir uns mal ueber den TextBox-PLCF die richtigen
5826 // Char Start-/End-Positionen. In dem Bereich sollte dann
5827 // das EinbettenFeld und die entsprechenden Sprms zu finden
5828 // sein. Wir brauchen hier aber nur das Sprm fuer die Picture Id
5829 long nOldPos
= rReader
.pStrm
->Tell();
5831 // #i32596# - consider return value of method
5832 // <rReader.GetTxbxTextSttEndCp(..)>. If it returns false, method
5833 // wasn't successful. Thus, continue in this case.
5834 // Note: Ask MM for initialization of <nStartCp> and <nEndCp>.
5835 // Note: Ask MM about assertions in method <rReader.GetTxbxTextSttEndCp(..)>.
5836 WW8_CP nStartCp
, nEndCp
;
5837 if ( rReader
.GetTxbxTextSttEndCp(nStartCp
, nEndCp
,
5838 static_cast<sal_uInt16
>((nOLEId
>> 16) & 0xFFFF),
5839 static_cast<sal_uInt16
>(nOLEId
& 0xFFFF)) )
5841 WW8PLCFxSaveAll aSave
;
5842 memset( &aSave
, 0, sizeof( aSave
) );
5843 rReader
.pPlcxMan
->SaveAllPLCFx( aSave
);
5845 nStartCp
+= rReader
.nDrawCpO
;
5846 nEndCp
+= rReader
.nDrawCpO
;
5847 WW8PLCFx_Cp_FKP
* pChp
= rReader
.pPlcxMan
->GetChpPLCF();
5848 wwSprmParser
aSprmParser(rReader
.pWwFib
->GetFIBVersion());
5849 while (nStartCp
<= nEndCp
&& !nPictureId
)
5852 pChp
->SeekPos( nStartCp
);
5853 pChp
->GetSprms( &aDesc
);
5855 if (aDesc
.nSprmsLen
&& aDesc
.pMemPos
) // Attribut(e) vorhanden
5857 long nLen
= aDesc
.nSprmsLen
;
5858 const sal_uInt8
* pSprm
= aDesc
.pMemPos
;
5860 while (nLen
>= 2 && !nPictureId
)
5862 sal_uInt16 nId
= aSprmParser
.GetSprmId(pSprm
);
5863 sal_uInt16 nSL
= aSprmParser
.GetSprmSize(nId
, pSprm
);
5866 break; // nicht mehr genug Bytes uebrig
5868 if( 0x6A03 == nId
&& 0 < nLen
)
5870 nPictureId
= SVBT32ToUInt32(pSprm
+
5871 aSprmParser
.DistanceToData(nId
));
5878 nStartCp
= aDesc
.nEndPos
;
5881 rReader
.pPlcxMan
->RestoreAllPLCFx( aSave
);
5884 rReader
.pStrm
->Seek( nOldPos
);
5889 rStorageName
= OUString('_');
5890 rStorageName
+= OUString::valueOf(nPictureId
);
5891 rSrcStorage
= rReader
.pStg
->OpenSotStorage(OUString(
5893 if (!rReader
.mpDocShell
)
5896 rDestStorage
= rReader
.mpDocShell
->GetStorage();
5901 sal_Bool
SwMSDffManager::ShapeHasText(sal_uLong
, sal_uLong
) const
5903 // Zur Zeit des Einlesens einer einzelnen Box, die womoeglich Teil einer
5904 // Gruppe ist, liegen noch nicht genuegend Informationen vor, um
5905 // entscheiden zu koennen, ob wir sie nicht doch als Textfeld benoetigen.
5906 // Also vorsichtshalber mal alle umwandeln:
5910 bool SwWW8ImplReader::InEqualOrHigherApo(int nLvl
) const
5915 // check size of <maApos> to assure that <maApos.begin() + nLvl> can be performed.
5916 if ( sal::static_int_cast
< sal_Int32
>(nLvl
) >= sal::static_int_cast
< sal_Int32
>(maApos
.size()) )
5920 mycApoIter aIter
= std::find(maApos
.begin() + nLvl
, maApos
.end(), true);
5921 if (aIter
!= maApos
.end())
5927 bool SwWW8ImplReader::InEqualApo(int nLvl
) const
5929 //If we are in a table, see if an apo was inserted at the level below
5933 if (nLvl
< 0 || static_cast<size_t>(nLvl
) >= maApos
.size())
5935 return maApos
[nLvl
];
5942 Position::Position(const SwPosition
&rPos
)
5943 : maPtNode(rPos
.nNode
), mnPtCntnt(rPos
.nContent
.GetIndex())
5947 Position::Position(const Position
&rPos
)
5948 : maPtNode(rPos
.maPtNode
), mnPtCntnt(rPos
.mnPtCntnt
)
5952 Position::operator SwPosition() const
5954 SwPosition
aRet(maPtNode
);
5955 aRet
.nContent
.Assign(maPtNode
.GetNode().GetCntntNode(), mnPtCntnt
);
5961 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */