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 .
20 #include <config_features.h>
22 #include <sal/config.h>
24 #include <com/sun/star/embed/ElementModes.hpp>
26 #include <i18nlangtag/languagetag.hxx>
28 #include <unotools/configmgr.hxx>
29 #include <unotools/ucbstreamhelper.hxx>
30 #include <rtl/random.h>
31 #include <rtl/ustring.hxx>
32 #include <rtl/ustrbuf.hxx>
34 #include <sfx2/docinf.hxx>
35 #include <sfx2/request.hxx>
36 #include <sfx2/frame.hxx>
37 #include <tools/urlobj.hxx>
38 #include <unotools/tempfile.hxx>
40 #include <comphelper/docpasswordrequest.hxx>
41 #include <comphelper/string.hxx>
43 #include <editeng/brushitem.hxx>
44 #include <editeng/tstpitem.hxx>
45 #include <editeng/ulspitem.hxx>
46 #include <editeng/langitem.hxx>
47 #include <editeng/opaqitem.hxx>
48 #include <editeng/charhiddenitem.hxx>
49 #include <editeng/fontitem.hxx>
50 #include <svx/unoapi.hxx>
51 #include <svx/svdoole2.hxx>
52 #include <svx/svdoashp.hxx>
53 #include <svx/svxerr.hxx>
54 #include <filter/msfilter/mscodec.hxx>
55 #include <svx/svdmodel.hxx>
56 #include <svx/xflclit.hxx>
58 #include <unotools/fltrcfg.hxx>
61 #include <fmtinfmt.hxx>
63 #include <fmthdft.hxx>
64 #include <fmtcntnt.hxx>
65 #include <fmtcnct.hxx>
66 #include <fmtanchr.hxx>
67 #include <fmtpdsc.hxx>
68 #include <ftninfo.hxx>
72 #include <pagedesc.hxx>
74 #include <fmtclbl.hxx>
75 #include <section.hxx>
77 #include <IDocumentFieldsAccess.hxx>
78 #include <IDocumentLayoutAccess.hxx>
79 #include <IDocumentStylePoolAccess.hxx>
80 #include <IDocumentExternalData.hxx>
81 #include <docufld.hxx>
82 #include <swfltopt.hxx>
84 #include <viewopt.hxx>
85 #include <shellres.hxx>
87 #include <statstr.hrc>
89 #include <swtable.hxx>
90 #include <fchrfmt.hxx>
91 #include <charfmt.hxx>
92 #include <unocrsr.hxx>
93 #include <IDocumentSettingAccess.hxx>
94 #include <sprmids.hxx>
98 #include "writerwordglue.hxx"
101 #include <editeng/editids.hrc>
102 #include <txtflcnt.hxx>
103 #include <fmtflcnt.hxx>
104 #include <txatbase.hxx>
106 #include "ww8par2.hxx"
108 #include <com/sun/star/beans/PropertyAttribute.hpp>
109 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
110 #include <com/sun/star/document/XViewDataSupplier.hpp>
111 #include <com/sun/star/document/IndexedPropertyValues.hpp>
112 #include <svl/itemiter.hxx>
114 #include <comphelper/processfactory.hxx>
115 #include <basic/basmgr.hxx>
117 #include "ww8toolbar.hxx"
118 #include <osl/file.hxx>
120 #include <breakit.hxx>
122 #if OSL_DEBUG_LEVEL > 1
124 #include <dbgoutsw.hxx>
127 #include <svx/hlnkitem.hxx>
129 #include "WW8Sttbf.hxx"
130 #include "WW8FibData.hxx"
131 #include <unordered_set>
134 using namespace ::com::sun::star
;
135 using namespace sw::util
;
136 using namespace sw::types
;
137 using namespace nsHdFtFlags
;
139 #include <com/sun/star/i18n/ScriptType.hpp>
140 #include <unotools/pathoptions.hxx>
141 #include <com/sun/star/ucb/SimpleFileAccess.hpp>
143 #include <com/sun/star/script/vba/XVBACompatibility.hpp>
144 #include <comphelper/sequenceashashmap.hxx>
145 #include <oox/ole/vbaproject.hxx>
146 #include <oox/ole/olestorage.hxx>
147 #include <comphelper/storagehelper.hxx>
148 #include <sfx2/DocumentMetadataAccess.hxx>
152 //#define VT_LPSTR 30
153 //#define VT_LPWSTR 31
155 //#define VT_TYPEMASK 0xFFF
156 /** Expands to a pointer after the last element of a STATIC data array (like STL end()). */
157 //#define STATIC_TABLE_END( array ) ((array)+STATIC_TABLE_SIZE(array))
158 /** Expands to the size of a STATIC data array. */
159 //#define STATIC_TABLE_SIZE( array ) (sizeof(array)/sizeof(*(array)))
161 SwMacroInfo
* GetMacroInfo( SdrObject
* pObj
, bool bCreate
) // static
165 sal_uInt16 nCount
= pObj
->GetUserDataCount();
166 for( sal_uInt16 i
= 0; i
< nCount
; i
++ )
168 SdrObjUserData
* pData
= pObj
->GetUserData( i
);
169 if( pData
&& pData
->GetInventor() == SdrInventor::ScOrSwDraw
170 && pData
->GetId() == SW_UD_IMAPDATA
)
172 return dynamic_cast<SwMacroInfo
*>(pData
);
177 SwMacroInfo
* pData
= new SwMacroInfo
;
178 pObj
->AppendUserData(pData
);
186 void lclGetAbsPath(OUString
& rPath
, sal_uInt16 nLevel
, SwDocShell
* pDocShell
)
194 if (!aTmpStr
.isEmpty())
199 if (!aTmpStr
.isEmpty())
201 bool bWasAbs
= false;
202 rPath
= pDocShell
->GetMedium()->GetURLObject().smartRel2Abs( aTmpStr
, bWasAbs
).GetMainURL( INetURLObject::DecodeMechanism::NONE
);
203 // full path as stored in SvxURLField must be encoded
207 void lclIgnoreString32( SvMemoryStream
& rStrm
, bool b16Bit
)
209 sal_uInt32
nChars(0);
210 rStrm
.ReadUInt32( nChars
);
213 rStrm
.SeekRel( nChars
);
216 OUString
SwWW8ImplReader::ReadRawUniString(SvMemoryStream
& rStrm
, sal_uInt16 nChars
, bool b16Bit
)
218 // Fixed-size characters
219 const sal_uInt8 WW8_NUL_C
= '\x00'; /// NUL chararcter.
220 const sal_uInt16 WW8_NUL
= WW8_NUL_C
; /// NUL chararcter (unicode).
221 sal_Unicode mcNulSubst
= '\0';
223 sal_uInt16 nCharsLeft
= nChars
;
224 sal_Unicode
* pcBuffer
= new sal_Unicode
[ nCharsLeft
+ 1 ];
226 sal_Unicode
* pcUniChar
= pcBuffer
;
227 sal_Unicode
* pcEndChar
= pcBuffer
+ nCharsLeft
;
231 sal_uInt16 nReadChar
;
232 for( ; (pcUniChar
< pcEndChar
); ++pcUniChar
)
234 rStrm
.ReadUInt16( nReadChar
);
235 (*pcUniChar
) = (nReadChar
== WW8_NUL
) ? mcNulSubst
: static_cast< sal_Unicode
>( nReadChar
);
241 for( ; (pcUniChar
< pcEndChar
); ++pcUniChar
)
243 rStrm
.ReadUChar( nReadChar
) ;
244 (*pcUniChar
) = (nReadChar
== WW8_NUL_C
) ? mcNulSubst
: static_cast< sal_Unicode
>( nReadChar
);
249 OUString
aRet(pcBuffer
);
254 void lclAppendString32(OUString
& rString
, SvMemoryStream
& rStrm
, sal_uInt32 nChars
, bool b16Bit
)
256 sal_uInt16 nReadChars
= ulimit_cast
< sal_uInt16
>( nChars
);
257 OUString urlStr
= SwWW8ImplReader::ReadRawUniString( rStrm
, nReadChars
, b16Bit
);
261 void lclAppendString32(OUString
& rString
, SvMemoryStream
& rStrm
, bool b16Bit
)
263 sal_uInt32
nValue(0);
264 rStrm
.ReadUInt32( nValue
);
265 lclAppendString32(rString
, rStrm
, nValue
, b16Bit
);
268 void SwWW8ImplReader::ReadEmbeddedData( SvMemoryStream
& rStrm
, SwDocShell
* pDocShell
, struct HyperLinksTable
& hlStr
)
271 // const sal_uInt16 WW8_ID_HLINK = 0x01B8;
272 const sal_uInt32 WW8_HLINK_BODY
= 0x00000001; /// Contains file link or URL.
273 const sal_uInt32 WW8_HLINK_ABS
= 0x00000002; /// Absolute path.
274 const sal_uInt32 WW8_HLINK_DESCR
= 0x00000014; /// Description.
275 const sal_uInt32 WW8_HLINK_MARK
= 0x00000008; /// Text mark.
276 const sal_uInt32 WW8_HLINK_FRAME
= 0x00000080; /// Target frame.
277 const sal_uInt32 WW8_HLINK_UNC
= 0x00000100; /// UNC path.
279 //sal_uInt8 maGuidStdLink[ 16 ] ={
280 // 0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
282 sal_uInt8 aGuidUrlMoniker
[ 16 ] = {
283 0xE0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
285 sal_uInt8 aGuidFileMoniker
[ 16 ] = {
286 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
289 sal_uInt32
nFlags(0);
291 rStrm
.ReadBytes(aGuid
, 16);
293 rStrm
.ReadUInt32( nFlags
);
295 sal_uInt16 nLevel
= 0; // counter for level to climb down in path
296 std::unique_ptr
< OUString
> xLongName
; // link / file name
297 std::unique_ptr
< OUString
> xShortName
; // 8.3-representation of file name
298 std::unique_ptr
< OUString
> xTextMark
; // text mark
300 // description (ignore)
301 if( ::get_flag( nFlags
, WW8_HLINK_DESCR
) )
302 lclIgnoreString32( rStrm
, true );
305 if( ::get_flag( nFlags
, WW8_HLINK_FRAME
) )
308 lclAppendString32(sFrameName
, rStrm
, true);
309 hlStr
.tarFrame
= sFrameName
;
313 if( ::get_flag( nFlags
, WW8_HLINK_UNC
) )
315 xLongName
.reset( new OUString
);
316 lclAppendString32( *xLongName
, rStrm
, true );
317 lclGetAbsPath( *xLongName
, 0 , pDocShell
);
320 else if( ::get_flag( nFlags
, WW8_HLINK_BODY
) )
322 rStrm
.ReadBytes(aGuid
, 16);
324 if( (memcmp(aGuid
, aGuidFileMoniker
, 16) == 0) )
326 rStrm
.ReadUInt16( nLevel
);
327 xShortName
.reset( new OUString
);
328 lclAppendString32( *xShortName
,rStrm
, false );
331 sal_uInt32
nStrLen(0);
332 rStrm
.ReadUInt32( nStrLen
);
336 rStrm
.ReadUInt32( nStrLen
);
339 xLongName
.reset( new OUString
);
340 lclAppendString32( *xLongName
, rStrm
,nStrLen
, true );
341 lclGetAbsPath( *xLongName
, nLevel
, pDocShell
);
344 lclGetAbsPath( *xShortName
, nLevel
, pDocShell
);
346 else if( (memcmp(aGuid
, aGuidUrlMoniker
, 16) == 0) )
348 sal_uInt32
nStrLen(0);
349 rStrm
.ReadUInt32( nStrLen
);
351 xLongName
.reset( new OUString
);
352 lclAppendString32( *xLongName
,rStrm
, nStrLen
, true );
353 if( !::get_flag( nFlags
, WW8_HLINK_ABS
) )
354 lclGetAbsPath( *xLongName
, 0 ,pDocShell
);
358 SAL_INFO("sw.ww8", "WW8Hyperlink::ReadEmbeddedData - unknown content GUID");
363 if( ::get_flag( nFlags
, WW8_HLINK_MARK
) )
365 xTextMark
.reset( new OUString
);
366 lclAppendString32( *xTextMark
, rStrm
, true );
369 if( !xLongName
.get() && xShortName
.get() )
371 xLongName
.reset( new OUString
);
372 *xLongName
= xLongName
->concat(*xShortName
);
374 else if( !xLongName
.get() && xTextMark
.get() )
375 xLongName
.reset( new OUString
);
377 if( xLongName
.get() )
379 if( xTextMark
.get() )
381 if (xLongName
->isEmpty())
382 *xTextMark
= xTextMark
->replace('!', '.');
383 *xLongName
= xLongName
->concat("#");
384 *xLongName
= xLongName
->concat(*xTextMark
);
386 hlStr
.hLinkAddr
= *xLongName
;
390 class BasicProjImportHelper
392 SwDocShell
& mrDocShell
;
393 uno::Reference
< uno::XComponentContext
> mxCtx
;
395 explicit BasicProjImportHelper( SwDocShell
& rShell
) : mrDocShell( rShell
)
397 mxCtx
= comphelper::getProcessComponentContext();
399 bool import( const uno::Reference
< io::XInputStream
>& rxIn
);
400 OUString
getProjectName();
403 bool BasicProjImportHelper::import( const uno::Reference
< io::XInputStream
>& rxIn
)
408 oox::ole::OleStorage
root( mxCtx
, rxIn
, false );
409 oox::StorageRef vbaStg
= root
.openSubStorage( "Macros" , false );
412 oox::ole::VbaProject
aVbaPrj( mxCtx
, mrDocShell
.GetModel(), OUString("Writer") );
413 bRet
= aVbaPrj
.importVbaProject( *vbaStg
);
416 catch( const uno::Exception
& )
423 OUString
BasicProjImportHelper::getProjectName()
425 OUString
sProjName( "Standard" );
426 uno::Reference
< beans::XPropertySet
> xProps( mrDocShell
.GetModel(), uno::UNO_QUERY
);
431 uno::Reference
< script::vba::XVBACompatibility
> xVBA( xProps
->getPropertyValue( "BasicLibraries" ), uno::UNO_QUERY_THROW
);
432 sProjName
= xVBA
->getProjectName();
435 catch( const uno::Exception
& )
442 class Sttb
: public TBBase
448 SBBItem() : cchData(0){}
454 std::vector
< SBBItem
> dataItems
;
456 Sttb(Sttb
const&) = delete;
457 Sttb
& operator=(Sttb
const&) = delete;
461 virtual ~Sttb() override
;
462 bool Read(SvStream
&rS
) override
;
463 #if OSL_DEBUG_LEVEL > 1
464 virtual void Print( FILE* fp
) override
;
466 OUString
getStringAtIndex( sal_uInt32
);
480 bool Sttb::Read( SvStream
& rS
)
482 SAL_INFO("sw.ww8", "stream pos " << rS
.Tell());
484 rS
.ReadUInt16( fExtend
).ReadUInt16( cData
).ReadUInt16( cbExtra
);
487 //if they are all going to be empty strings, how many could there be
488 const size_t nMaxPossibleRecords
= rS
.remainingSize() / sizeof(sal_uInt16
);
489 if (cData
> nMaxPossibleRecords
)
491 for ( sal_Int32 index
= 0; index
< cData
; ++index
)
494 rS
.ReadUInt16( aItem
.cchData
);
495 aItem
.data
= read_uInt16s_ToOUString(rS
, aItem
.cchData
);
496 dataItems
.push_back( aItem
);
502 #if OSL_DEBUG_LEVEL > 1
503 void Sttb::Print( FILE* fp
)
505 fprintf( fp
, "[ 0x%" SAL_PRIxUINT32
" ] Sttb - dump\n", nOffSet
);
506 fprintf( fp
, " fExtend 0x%x [expected 0xFFFF ]\n", fExtend
);
507 fprintf( fp
, " cData no. or string data items %d (0x%x)\n", cData
, cData
);
511 for (sal_uInt16 index
= 0; index
< cData
; ++index
)
513 if (index
>= dataItems
.size())
515 fprintf(fp
, " Sttb truncated at entry %d(0x%x)\n", static_cast< int >( index
), static_cast< unsigned int >( index
));
518 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() );
525 Sttb::getStringAtIndex( sal_uInt32 index
)
528 if ( index
< dataItems
.size() )
529 aRet
= dataItems
[ index
].data
;
534 SwMSDffManager::SwMSDffManager( SwWW8ImplReader
& rRdr
, bool bSkipImages
)
535 : SvxMSDffManager(*rRdr
.m_pTableStream
, rRdr
.GetBaseURL(), rRdr
.m_pWwFib
->m_fcDggInfo
,
536 rRdr
.m_pDataStream
, nullptr, 0, COL_WHITE
, rRdr
.m_pStrm
, bSkipImages
),
537 rReader(rRdr
), pFallbackStream(nullptr)
539 SetSvxMSDffSettings( GetSvxMSDffSettings() );
540 nSvxMSDffOLEConvFlags
= SwMSDffManager::GetFilterFlags();
543 sal_uInt32
SwMSDffManager::GetFilterFlags()
545 sal_uInt32
nFlags(0);
546 const SvtFilterOptions
& rOpt
= SvtFilterOptions::Get();
547 if (rOpt
.IsMathType2Math())
548 nFlags
|= OLE_MATHTYPE_2_STARMATH
;
549 if (rOpt
.IsExcel2Calc())
550 nFlags
|= OLE_EXCEL_2_STARCALC
;
551 if (rOpt
.IsPowerPoint2Impress())
552 nFlags
|= OLE_POWERPOINT_2_STARIMPRESS
;
553 if (rOpt
.IsWinWord2Writer())
554 nFlags
|= OLE_WINWORD_2_STARWRITER
;
559 * I would like to override the default OLE importing to add a test
560 * and conversion of OCX controls from their native OLE type into our
561 * native nonOLE Form Control Objects.
563 // #i32596# - consider new parameter <_nCalledByGroup>
564 SdrObject
* SwMSDffManager::ImportOLE( long nOLEId
,
566 const Rectangle
& rBoundRect
,
567 const Rectangle
& rVisArea
,
568 const int _nCalledByGroup
,
569 sal_Int64 nAspect
) const
571 // #i32596# - no import of OLE object, if it's inside a group.
572 // NOTE: This can be undone, if grouping of Writer fly frames is possible or
573 // if drawing OLE objects are allowed in Writer.
574 if ( _nCalledByGroup
> 0 )
579 SdrObject
* pRet
= nullptr;
580 OUString sStorageName
;
581 tools::SvRef
<SotStorage
> xSrcStg
;
582 uno::Reference
< embed::XStorage
> xDstStg
;
583 if( GetOLEStorageName( nOLEId
, sStorageName
, xSrcStg
, xDstStg
))
585 tools::SvRef
<SotStorage
> xSrc
= xSrcStg
->OpenSotStorage( sStorageName
);
586 OSL_ENSURE(rReader
.m_pFormImpl
, "No Form Implementation!");
587 css::uno::Reference
< css::drawing::XShape
> xShape
;
588 if ( (!(rReader
.m_bIsHeader
|| rReader
.m_bIsFooter
)) &&
589 rReader
.m_pFormImpl
->ReadOCXStream(xSrc
,&xShape
,true))
591 pRet
= GetSdrObjectFromXShape(xShape
);
595 ErrCode nError
= ERRCODE_NONE
;
596 pRet
= CreateSdrOLEFromStorage( sStorageName
, xSrcStg
, xDstStg
,
597 rGrf
, rBoundRect
, rVisArea
, pStData
, nError
,
598 nSvxMSDffOLEConvFlags
, nAspect
, rReader
.GetBaseURL());
604 void SwMSDffManager::DisableFallbackStream()
606 OSL_ENSURE(!pFallbackStream
,
607 "if you're recursive, you're broken");
608 pFallbackStream
= pStData2
;
609 aOldEscherBlipCache
= aEscherBlipCache
;
610 aEscherBlipCache
.clear();
614 void SwMSDffManager::EnableFallbackStream()
616 pStData2
= pFallbackStream
;
617 aEscherBlipCache
= aOldEscherBlipCache
;
618 aOldEscherBlipCache
.clear();
619 pFallbackStream
= nullptr;
622 sal_uInt16
SwWW8ImplReader::GetToggleAttrFlags() const
624 return m_pCtrlStck
? m_pCtrlStck
->GetToggleAttrFlags() : 0;
627 sal_uInt16
SwWW8ImplReader::GetToggleBiDiAttrFlags() const
629 return m_pCtrlStck
? m_pCtrlStck
->GetToggleBiDiAttrFlags() : 0;
632 void SwWW8ImplReader::SetToggleAttrFlags(sal_uInt16 nFlags
)
635 m_pCtrlStck
->SetToggleAttrFlags(nFlags
);
638 void SwWW8ImplReader::SetToggleBiDiAttrFlags(sal_uInt16 nFlags
)
641 m_pCtrlStck
->SetToggleBiDiAttrFlags(nFlags
);
644 SdrObject
* SwMSDffManager::ProcessObj(SvStream
& rSt
,
645 DffObjData
& rObjData
,
647 Rectangle
& rTextRect
,
651 if( !rTextRect
.IsEmpty() )
653 SvxMSDffImportData
& rImportData
= *static_cast<SvxMSDffImportData
*>(pData
);
654 SvxMSDffImportRec
* pImpRec
= new SvxMSDffImportRec
;
656 // fill Import Record with data
657 pImpRec
->nShapeId
= rObjData
.nShapeId
;
658 pImpRec
->eShapeType
= rObjData
.eShapeType
;
660 rObjData
.bClientAnchor
= maShapeRecords
.SeekToContent( rSt
,
661 DFF_msofbtClientAnchor
,
662 SEEK_FROM_CURRENT_AND_RESTART
);
663 if( rObjData
.bClientAnchor
)
664 ProcessClientAnchor( rSt
,
665 maShapeRecords
.Current()->nRecLen
,
666 pImpRec
->pClientAnchorBuffer
, pImpRec
->nClientAnchorLen
);
668 rObjData
.bClientData
= maShapeRecords
.SeekToContent( rSt
,
669 DFF_msofbtClientData
,
670 SEEK_FROM_CURRENT_AND_RESTART
);
671 if( rObjData
.bClientData
)
672 ProcessClientData( rSt
,
673 maShapeRecords
.Current()->nRecLen
,
674 pImpRec
->pClientDataBuffer
, pImpRec
->nClientDataLen
);
676 // process user (== Winword) defined parameters in 0xF122 record
677 // #i84783# - set special value to determine, if property is provided or not.
678 pImpRec
->nLayoutInTableCell
= 0xFFFFFFFF;
680 if( maShapeRecords
.SeekToContent( rSt
,
682 SEEK_FROM_CURRENT_AND_RESTART
)
683 && maShapeRecords
.Current()->nRecLen
)
685 sal_uInt32 nBytesLeft
= maShapeRecords
.Current()->nRecLen
;
686 auto nAvailableBytes
= rSt
.remainingSize();
687 if (nBytesLeft
> nAvailableBytes
)
689 SAL_WARN("sw.ww8", "Document claimed to have shape record of " << nBytesLeft
<< " bytes, but only " << nAvailableBytes
<< " available");
690 nBytesLeft
= nAvailableBytes
;
692 while( 5 < nBytesLeft
)
695 rSt
.ReadUInt16(nPID
);
696 sal_uInt32
nUDData(0);
697 rSt
.ReadUInt32(nUDData
);
702 case 0x038F: pImpRec
->nXAlign
= nUDData
; break;
704 delete pImpRec
->pXRelTo
;
705 pImpRec
->pXRelTo
= new sal_uInt32
;
706 *(pImpRec
->pXRelTo
) = nUDData
;
708 case 0x0391: pImpRec
->nYAlign
= nUDData
; break;
710 delete pImpRec
->pYRelTo
;
711 pImpRec
->pYRelTo
= new sal_uInt32
;
712 *(pImpRec
->pYRelTo
) = nUDData
;
714 case 0x03BF: pImpRec
->nLayoutInTableCell
= nUDData
; break;
716 // This seems to correspond to o:hrpct from .docx (even including
717 // the difference that it's in 0.1% even though the .docx spec
719 pImpRec
->relativeHorizontalWidth
= nUDData
;
722 // And this is really just a guess, but a mere presence of this
723 // flag makes a horizontal rule be as wide as the page (unless
724 // overridden by something), so it probably matches o:hr from .docx.
725 pImpRec
->isHorizontalRule
= true;
732 // Text Frame also Title or Outline
733 sal_uInt32 nTextId
= GetPropertyValue( DFF_Prop_lTxid
, 0 );
736 SfxItemSet
aSet( pSdrModel
->GetItemPool() );
738 // Originally anything that as a mso_sptTextBox was created as a
739 // textbox, this was changed to be created as a simple
740 // rect to keep impress happy. For the rest of us we'd like to turn
741 // it back into a textbox again.
742 bool bIsSimpleDrawingTextBox
= (pImpRec
->eShapeType
== mso_sptTextBox
);
743 if (!bIsSimpleDrawingTextBox
)
746 // a) it's a simple text object or
747 // b) it's a rectangle with text and square wrapping.
748 bIsSimpleDrawingTextBox
=
750 (pImpRec
->eShapeType
== mso_sptTextSimple
) ||
752 (pImpRec
->eShapeType
== mso_sptRectangle
)
753 && ShapeHasText(pImpRec
->nShapeId
, rObjData
.rSpHd
.GetRecBegFilePos() )
758 // Distance of Textbox to its surrounding Autoshape
759 sal_Int32 nTextLeft
= GetPropertyValue( DFF_Prop_dxTextLeft
, 91440L);
760 sal_Int32 nTextRight
= GetPropertyValue( DFF_Prop_dxTextRight
, 91440L );
761 sal_Int32 nTextTop
= GetPropertyValue( DFF_Prop_dyTextTop
, 45720L );
762 sal_Int32 nTextBottom
= GetPropertyValue( DFF_Prop_dyTextBottom
, 45720L );
764 ScaleEmu( nTextLeft
);
765 ScaleEmu( nTextRight
);
766 ScaleEmu( nTextTop
);
767 ScaleEmu( nTextBottom
);
769 sal_Int32 nTextRotationAngle
=0;
770 bool bVerticalText
= false;
771 if ( IsProperty( DFF_Prop_txflTextFlow
) )
773 MSO_TextFlow eTextFlow
= (MSO_TextFlow
)(GetPropertyValue(
774 DFF_Prop_txflTextFlow
, 0) & 0xFFFF);
778 nTextRotationAngle
= 9000;
782 nTextRotationAngle
= 27000;
785 bVerticalText
= true;
788 bVerticalText
= true;
789 nTextRotationAngle
= 9000;
797 if (nTextRotationAngle
)
799 if (nTextRotationAngle
== 9000)
801 long nWidth
= rTextRect
.GetWidth();
802 rTextRect
.Right() = rTextRect
.Left() + rTextRect
.GetHeight();
803 rTextRect
.Bottom() = rTextRect
.Top() + nWidth
;
805 sal_Int32 nOldTextLeft
= nTextLeft
;
806 sal_Int32 nOldTextRight
= nTextRight
;
807 sal_Int32 nOldTextTop
= nTextTop
;
808 sal_Int32 nOldTextBottom
= nTextBottom
;
810 nTextLeft
= nOldTextBottom
;
811 nTextRight
= nOldTextTop
;
812 nTextTop
= nOldTextLeft
;
813 nTextBottom
= nOldTextRight
;
815 else if (nTextRotationAngle
== 27000)
817 long nWidth
= rTextRect
.GetWidth();
818 rTextRect
.Right() = rTextRect
.Left() + rTextRect
.GetHeight();
819 rTextRect
.Bottom() = rTextRect
.Top() + nWidth
;
821 sal_Int32 nOldTextLeft
= nTextLeft
;
822 sal_Int32 nOldTextRight
= nTextRight
;
823 sal_Int32 nOldTextTop
= nTextTop
;
824 sal_Int32 nOldTextBottom
= nTextBottom
;
826 nTextLeft
= nOldTextTop
;
827 nTextRight
= nOldTextBottom
;
828 nTextTop
= nOldTextRight
;
829 nTextBottom
= nOldTextLeft
;
833 if (bIsSimpleDrawingTextBox
)
835 SdrObject::Free( pObj
);
836 pObj
= new SdrRectObj(OBJ_TEXT
, rTextRect
);
839 // The vertical paragraph justification are contained within the
840 // BoundRect so calculate it here
841 Rectangle
aNewRect(rTextRect
);
842 aNewRect
.Bottom() -= nTextTop
+ nTextBottom
;
843 aNewRect
.Right() -= nTextLeft
+ nTextRight
;
845 // Only if it's a simple Textbox, Writer can replace the Object
846 // with a Frame, else
847 if( bIsSimpleDrawingTextBox
)
849 std::shared_ptr
<SvxMSDffShapeInfo
> const xTmpRec(
850 new SvxMSDffShapeInfo(0, pImpRec
->nShapeId
));
852 SvxMSDffShapeInfos_ById::const_iterator
const it
=
853 GetShapeInfos()->find(xTmpRec
);
854 if (it
!= GetShapeInfos()->end())
856 SvxMSDffShapeInfo
& rInfo
= **it
;
857 pImpRec
->bReplaceByFly
= rInfo
.bReplaceByFly
;
861 if( bIsSimpleDrawingTextBox
)
862 ApplyAttributes( rSt
, aSet
, rObjData
);
864 if (GetPropertyValue(DFF_Prop_FitTextToShape
, 0) & 2)
866 aSet
.Put( makeSdrTextAutoGrowHeightItem( true ) );
867 aSet
.Put( makeSdrTextMinFrameHeightItem(
868 aNewRect
.Bottom() - aNewRect
.Top() ) );
869 aSet
.Put( makeSdrTextMinFrameWidthItem(
870 aNewRect
.Right() - aNewRect
.Left() ) );
874 aSet
.Put( makeSdrTextAutoGrowHeightItem( false ) );
875 aSet
.Put( makeSdrTextAutoGrowWidthItem( false ) );
878 switch ( (MSO_WrapMode
)
879 GetPropertyValue( DFF_Prop_WrapText
, mso_wrapSquare
) )
882 aSet
.Put( makeSdrTextAutoGrowWidthItem( true ) );
883 pImpRec
->bAutoWidth
= true;
885 case mso_wrapByPoints
:
886 aSet
.Put( makeSdrTextContourFrameItem( true ) );
892 // Set distances on Textbox's margins
893 aSet
.Put( makeSdrTextLeftDistItem( nTextLeft
) );
894 aSet
.Put( makeSdrTextRightDistItem( nTextRight
) );
895 aSet
.Put( makeSdrTextUpperDistItem( nTextTop
) );
896 aSet
.Put( makeSdrTextLowerDistItem( nTextBottom
) );
897 pImpRec
->nDxTextLeft
= nTextLeft
;
898 pImpRec
->nDyTextTop
= nTextTop
;
899 pImpRec
->nDxTextRight
= nTextRight
;
900 pImpRec
->nDyTextBottom
= nTextBottom
;
902 // Taking the correct default (which is mso_anchorTop)
903 sal_uInt32 eTextAnchor
=
904 GetPropertyValue( DFF_Prop_anchorText
, mso_anchorTop
);
906 SdrTextVertAdjust eTVA
= bVerticalText
907 ? SDRTEXTVERTADJUST_BLOCK
908 : SDRTEXTVERTADJUST_CENTER
;
909 SdrTextHorzAdjust eTHA
= bVerticalText
910 ? SDRTEXTHORZADJUST_CENTER
911 : SDRTEXTHORZADJUST_BLOCK
;
913 switch( eTextAnchor
)
918 eTHA
= SDRTEXTHORZADJUST_RIGHT
;
920 eTVA
= SDRTEXTVERTADJUST_TOP
;
923 case mso_anchorTopCentered
:
926 eTHA
= SDRTEXTHORZADJUST_RIGHT
;
928 eTVA
= SDRTEXTVERTADJUST_TOP
;
931 case mso_anchorMiddle
:
933 case mso_anchorMiddleCentered
:
935 case mso_anchorBottom
:
938 eTHA
= SDRTEXTHORZADJUST_LEFT
;
940 eTVA
= SDRTEXTVERTADJUST_BOTTOM
;
943 case mso_anchorBottomCentered
:
946 eTHA
= SDRTEXTHORZADJUST_LEFT
;
948 eTVA
= SDRTEXTVERTADJUST_BOTTOM
;
955 aSet
.Put( SdrTextVertAdjustItem( eTVA
) );
956 aSet
.Put( SdrTextHorzAdjustItem( eTHA
) );
960 pObj
->SetMergedItemSet(aSet
);
961 pObj
->SetModel(pSdrModel
);
965 SdrTextObj
*pTextObj
= dynamic_cast< SdrTextObj
* >(pObj
);
967 pTextObj
->SetVerticalWriting(true);
970 if ( bIsSimpleDrawingTextBox
)
972 if ( nTextRotationAngle
)
974 long nMinWH
= rTextRect
.GetWidth() < rTextRect
.GetHeight() ?
975 rTextRect
.GetWidth() : rTextRect
.GetHeight();
977 Point
aPivot(rTextRect
.TopLeft());
978 aPivot
.X() += nMinWH
;
979 aPivot
.Y() += nMinWH
;
980 double a
= nTextRotationAngle
* nPi180
;
981 pObj
->NbcRotate(aPivot
, nTextRotationAngle
, sin(a
), cos(a
));
985 if ( ( ( rObjData
.nSpFlags
& SP_FFLIPV
) || mnFix16Angle
|| nTextRotationAngle
) && dynamic_cast< SdrObjCustomShape
* >( pObj
) )
987 SdrObjCustomShape
* pCustomShape
= dynamic_cast< SdrObjCustomShape
* >( pObj
);
990 double fExtraTextRotation
= 0.0;
991 if ( mnFix16Angle
&& !( GetPropertyValue( DFF_Prop_FitTextToShape
, 0 ) & 4 ) )
992 { // text is already rotated, we have to take back the object rotation if DFF_Prop_RotateText is false
993 fExtraTextRotation
= -mnFix16Angle
;
995 if ( rObjData
.nSpFlags
& SP_FFLIPV
) // sj: in ppt the text is flipped, whereas in word the text
996 { // remains unchanged, so we have to take back the flipping here
997 fExtraTextRotation
+= 18000.0; // because our core will flip text if the shape is flipped.
999 fExtraTextRotation
+= nTextRotationAngle
;
1000 if ( !::basegfx::fTools::equalZero( fExtraTextRotation
) )
1002 fExtraTextRotation
/= 100.0;
1003 SdrCustomShapeGeometryItem
aGeometryItem( static_cast<const SdrCustomShapeGeometryItem
&>(pCustomShape
->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY
)) );
1004 const OUString
sTextRotateAngle( "TextRotateAngle" );
1005 css::beans::PropertyValue aPropVal
;
1006 aPropVal
.Name
= sTextRotateAngle
;
1007 aPropVal
.Value
<<= fExtraTextRotation
;
1008 aGeometryItem
.SetPropertyValue( aPropVal
);
1009 pCustomShape
->SetMergedItem( aGeometryItem
);
1013 else if ( mnFix16Angle
)
1015 // rotate text with shape ?
1016 double a
= mnFix16Angle
* nPi180
;
1017 pObj
->NbcRotate( rObjData
.aBoundRect
.Center(), mnFix16Angle
,
1018 sin( a
), cos( a
) );
1024 // simple rectangular objects are ignored by ImportObj() :-(
1025 // this is OK for Draw but not for Calc and Writer
1026 // cause here these objects have a default border
1027 pObj
= new SdrRectObj(rTextRect
);
1028 pObj
->SetModel( pSdrModel
);
1029 SfxItemSet
aSet( pSdrModel
->GetItemPool() );
1030 ApplyAttributes( rSt
, aSet
, rObjData
);
1032 const SfxPoolItem
* pPoolItem
=nullptr;
1033 SfxItemState eState
= aSet
.GetItemState( XATTR_FILLCOLOR
,
1034 false, &pPoolItem
);
1035 if( SfxItemState::DEFAULT
== eState
)
1036 aSet
.Put( XFillColorItem( OUString(),
1037 Color( mnDefaultColor
) ) );
1038 pObj
->SetMergedItemSet(aSet
);
1041 // Means that fBehindDocument is set
1042 if (GetPropertyValue(DFF_Prop_fPrint
, 0) & 0x20)
1043 pImpRec
->bDrawHell
= true;
1045 pImpRec
->bDrawHell
= false;
1046 if (GetPropertyValue(DFF_Prop_fPrint
, 0) & 0x02)
1047 pImpRec
->bHidden
= true;
1048 pImpRec
->nNextShapeId
= GetPropertyValue( DFF_Prop_hspNext
, 0 );
1052 pImpRec
->aTextId
.nTxBxS
= (sal_uInt16
)( nTextId
>> 16 );
1053 pImpRec
->aTextId
.nSequence
= (sal_uInt16
)nTextId
;
1056 pImpRec
->nDxWrapDistLeft
= GetPropertyValue(
1057 DFF_Prop_dxWrapDistLeft
, 114935L ) / 635L;
1058 pImpRec
->nDyWrapDistTop
= GetPropertyValue(
1059 DFF_Prop_dyWrapDistTop
, 0 ) / 635L;
1060 pImpRec
->nDxWrapDistRight
= GetPropertyValue(
1061 DFF_Prop_dxWrapDistRight
, 114935L ) / 635L;
1062 pImpRec
->nDyWrapDistBottom
= GetPropertyValue(
1063 DFF_Prop_dyWrapDistBottom
, 0 ) / 635L;
1064 // 16.16 fraction times total image width or height, as appropriate.
1066 if (SeekToContent(DFF_Prop_pWrapPolygonVertices
, rSt
))
1068 delete pImpRec
->pWrapPolygon
;
1069 pImpRec
->pWrapPolygon
= nullptr;
1071 sal_uInt16
nNumElemVert(0), nNumElemMemVert(0), nElemSizeVert(0);
1072 rSt
.ReadUInt16( nNumElemVert
).ReadUInt16( nNumElemMemVert
).ReadUInt16( nElemSizeVert
);
1074 if (nNumElemVert
&& ((nElemSizeVert
== 8) || (nElemSizeVert
== 4)))
1076 //check if there is enough data in the file to make the
1078 bOk
= rSt
.remainingSize() / nElemSizeVert
>= nNumElemVert
;
1082 pImpRec
->pWrapPolygon
= new tools::Polygon(nNumElemVert
);
1083 for (sal_uInt16 i
= 0; i
< nNumElemVert
; ++i
)
1085 sal_Int32
nX(0), nY(0);
1086 if (nElemSizeVert
== 8)
1087 rSt
.ReadInt32( nX
).ReadInt32( nY
);
1090 sal_Int16
nSmallX(0), nSmallY(0);
1091 rSt
.ReadInt16( nSmallX
).ReadInt16( nSmallY
);
1095 (*(pImpRec
->pWrapPolygon
))[i
].X() = nX
;
1096 (*(pImpRec
->pWrapPolygon
))[i
].Y() = nY
;
1101 pImpRec
->nCropFromTop
= GetPropertyValue(
1102 DFF_Prop_cropFromTop
, 0 );
1103 pImpRec
->nCropFromBottom
= GetPropertyValue(
1104 DFF_Prop_cropFromBottom
, 0 );
1105 pImpRec
->nCropFromLeft
= GetPropertyValue(
1106 DFF_Prop_cropFromLeft
, 0 );
1107 pImpRec
->nCropFromRight
= GetPropertyValue(
1108 DFF_Prop_cropFromRight
, 0 );
1110 sal_uInt32 nLineFlags
= GetPropertyValue( DFF_Prop_fNoLineDrawDash
, 0 );
1112 if ( !IsHardAttribute( DFF_Prop_fLine
) &&
1113 pImpRec
->eShapeType
== mso_sptPictureFrame
)
1115 nLineFlags
&= ~0x08;
1118 pImpRec
->eLineStyle
= (nLineFlags
& 8)
1119 ? (MSO_LineStyle
)GetPropertyValue(
1122 : (MSO_LineStyle
)USHRT_MAX
;
1123 pImpRec
->eLineDashing
= (MSO_LineDashing
)GetPropertyValue(
1124 DFF_Prop_lineDashing
, mso_lineSolid
);
1126 pImpRec
->nFlags
= rObjData
.nSpFlags
;
1128 if( pImpRec
->nShapeId
)
1130 // Complement Import Record List
1131 pImpRec
->pObj
= pObj
;
1132 rImportData
.m_Records
.insert(std::unique_ptr
<SvxMSDffImportRec
>(pImpRec
));
1134 // Complement entry in Z Order List with a pointer to this Object
1135 // Only store objects which are not deep inside the tree
1136 if( ( rObjData
.nCalledByGroup
== 0 )
1138 ( (rObjData
.nSpFlags
& SP_FGROUP
)
1139 && (rObjData
.nCalledByGroup
< 2) )
1141 StoreShapeOrder( pImpRec
->nShapeId
,
1142 ( ( (sal_uLong
)pImpRec
->aTextId
.nTxBxS
) << 16 )
1143 + pImpRec
->aTextId
.nSequence
, pObj
);
1149 sal_uInt32 nBufferSize
= GetPropertyValue( DFF_Prop_pihlShape
, 0 );
1150 if( (0 < nBufferSize
) && (nBufferSize
<= 0xFFFF) && SeekToContent( DFF_Prop_pihlShape
, rSt
) )
1152 SvMemoryStream aMemStream
;
1153 struct HyperLinksTable hlStr
;
1154 sal_uInt16 nRawRecId
,nRawRecSize
;
1155 aMemStream
.WriteUInt16( 0 ).WriteUInt16( nBufferSize
);
1157 // copy from DFF stream to memory stream
1158 std::vector
< sal_uInt8
> aBuffer( nBufferSize
);
1159 sal_uInt8
* pnData
= &aBuffer
.front();
1160 sal_uInt8 nStreamSize
;
1161 if (pnData
&& rSt
.ReadBytes(pnData
, nBufferSize
) == nBufferSize
)
1163 aMemStream
.WriteBytes(pnData
, nBufferSize
);
1164 aMemStream
.Seek( STREAM_SEEK_TO_END
);
1165 nStreamSize
= aMemStream
.Tell();
1166 aMemStream
.Seek( STREAM_SEEK_TO_BEGIN
);
1167 bool bRet
= 4 <= nStreamSize
;
1169 aMemStream
.ReadUInt16( nRawRecId
).ReadUInt16( nRawRecSize
);
1170 SwDocShell
* pDocShell
= rReader
.m_pDocShell
;
1173 SwWW8ImplReader::ReadEmbeddedData( aMemStream
, pDocShell
, hlStr
);
1177 if (pObj
&& !hlStr
.hLinkAddr
.isEmpty())
1179 SwMacroInfo
* pInfo
= GetMacroInfo( pObj
, true );
1182 pInfo
->SetShapeId( rObjData
.nShapeId
);
1183 pInfo
->SetHlink( hlStr
.hLinkAddr
);
1184 if (!hlStr
.tarFrame
.isEmpty())
1185 pInfo
->SetTarFrame( hlStr
.tarFrame
);
1186 OUString aNameStr
= GetPropertyString( DFF_Prop_wzName
, rSt
);
1187 if (!aNameStr
.isEmpty())
1188 pInfo
->SetName( aNameStr
);
1197 * Special FastSave - Attributes
1199 void SwWW8ImplReader::Read_StyleCode( sal_uInt16
, const sal_uInt8
* pData
, short nLen
)
1203 m_bCpxStyle
= false;
1206 sal_uInt16 nColl
= 0;
1207 if (m_pWwFib
->GetFIBVersion() <= ww::eWW2
)
1210 nColl
= SVBT16ToShort(pData
);
1211 if (nColl
< m_vColl
.size())
1213 SetTextFormatCollAndListLevel( *m_pPaM
, m_vColl
[nColl
] );
1219 * Read_Majority is for Majority (103) and Majority50 (108)
1221 void SwWW8ImplReader::Read_Majority( sal_uInt16
, const sal_uInt8
* , short )
1228 void SwWW8FltControlStack::NewAttr(const SwPosition
& rPos
,
1229 const SfxPoolItem
& rAttr
)
1231 OSL_ENSURE(RES_TXTATR_FIELD
!= rAttr
.Which(), "probably don't want to put"
1232 "fields into the control stack");
1233 OSL_ENSURE(RES_TXTATR_INPUTFIELD
!= rAttr
.Which(), "probably don't want to put"
1234 "input fields into the control stack");
1235 OSL_ENSURE(RES_TXTATR_ANNOTATION
!= rAttr
.Which(), "probably don't want to put"
1236 "annotations into the control stack");
1237 OSL_ENSURE(RES_FLTR_REDLINE
!= rAttr
.Which(), "probably don't want to put"
1238 "redlines into the control stack");
1239 SwFltControlStack::NewAttr(rPos
, rAttr
);
1242 SwFltStackEntry
* SwWW8FltControlStack::SetAttr(const SwPosition
& rPos
, sal_uInt16 nAttrId
,
1243 bool bTstEnde
, long nHand
, bool )
1245 SwFltStackEntry
*pRet
= nullptr;
1246 // Doing a textbox, and using the control stack only as a temporary
1247 // collection point for properties which will are not to be set into
1248 // the real document
1249 if (rReader
.m_pPlcxMan
&& rReader
.m_pPlcxMan
->GetDoingDrawTextBox())
1251 size_t nCnt
= size();
1252 for (size_t i
=0; i
< nCnt
; ++i
)
1254 SwFltStackEntry
& rEntry
= (*this)[i
];
1255 if (nAttrId
== rEntry
.pAttr
->Which())
1257 DeleteAndDestroy(i
--);
1262 else // Normal case, set the attribute into the document
1263 pRet
= SwFltControlStack::SetAttr(rPos
, nAttrId
, bTstEnde
, nHand
);
1267 long GetListFirstLineIndent(const SwNumFormat
&rFormat
)
1269 OSL_ENSURE( rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
,
1270 "<GetListFirstLineIndent> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
1272 SvxAdjust eAdj
= rFormat
.GetNumAdjust();
1273 long nReverseListIndented
;
1274 if (eAdj
== SVX_ADJUST_RIGHT
)
1275 nReverseListIndented
= -rFormat
.GetCharTextDistance();
1276 else if (eAdj
== SVX_ADJUST_CENTER
)
1277 nReverseListIndented
= rFormat
.GetFirstLineOffset()/2;
1279 nReverseListIndented
= rFormat
.GetFirstLineOffset();
1280 return nReverseListIndented
;
1283 static long lcl_GetTrueMargin(const SvxLRSpaceItem
&rLR
, const SwNumFormat
&rFormat
,
1284 long &rFirstLinePos
)
1286 OSL_ENSURE( rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
,
1287 "<lcl_GetTrueMargin> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
1289 const long nBodyIndent
= rLR
.GetTextLeft();
1290 const long nFirstLineDiff
= rLR
.GetTextFirstLineOfst();
1291 rFirstLinePos
= nBodyIndent
+ nFirstLineDiff
;
1293 const long nPseudoListBodyIndent
= rFormat
.GetAbsLSpace();
1294 const long nReverseListIndented
= GetListFirstLineIndent(rFormat
);
1295 long nExtraListIndent
= nPseudoListBodyIndent
+ nReverseListIndented
;
1297 return nExtraListIndent
> 0 ? nExtraListIndent
: 0;
1302 void SyncIndentWithList( SvxLRSpaceItem
&rLR
,
1303 const SwNumFormat
&rFormat
,
1304 const bool bFirstLineOfstSet
,
1305 const bool bLeftIndentSet
)
1307 if ( rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION
)
1309 long nWantedFirstLinePos
;
1310 long nExtraListIndent
= lcl_GetTrueMargin(rLR
, rFormat
, nWantedFirstLinePos
);
1311 rLR
.SetTextLeft(nWantedFirstLinePos
- nExtraListIndent
);
1312 rLR
.SetTextFirstLineOfst(0);
1314 else if ( rFormat
.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT
)
1316 if ( !bFirstLineOfstSet
&& bLeftIndentSet
&&
1317 rFormat
.GetFirstLineIndent() != 0 )
1319 rLR
.SetTextFirstLineOfst( rFormat
.GetFirstLineIndent() );
1321 else if ( bFirstLineOfstSet
&& !bLeftIndentSet
&&
1322 rFormat
.GetIndentAt() != 0 )
1324 rLR
.SetTextLeft( rFormat
.GetIndentAt() );
1326 else if (!bFirstLineOfstSet
&& !bLeftIndentSet
)
1328 if ( rFormat
.GetFirstLineIndent() != 0 )
1330 rLR
.SetTextFirstLineOfst( rFormat
.GetFirstLineIndent() );
1332 if ( rFormat
.GetIndentAt() != 0 )
1334 rLR
.SetTextLeft( rFormat
.GetIndentAt() );
1340 const SwNumFormat
* SwWW8FltControlStack::GetNumFormatFromStack(const SwPosition
&rPos
,
1341 const SwTextNode
&rTextNode
)
1343 const SwNumFormat
*pRet
= nullptr;
1344 const SfxPoolItem
*pItem
= GetStackAttr(rPos
, RES_FLTR_NUMRULE
);
1345 if (pItem
&& rTextNode
.GetNumRule())
1347 if (rTextNode
.IsCountedInList())
1349 OUString
sName(static_cast<const SfxStringItem
*>(pItem
)->GetValue());
1350 const SwNumRule
*pRule
= pDoc
->FindNumRulePtr(sName
);
1352 pRet
= GetNumFormatFromSwNumRuleLevel(*pRule
, rTextNode
.GetActualListLevel());
1358 sal_Int32
SwWW8FltControlStack::GetCurrAttrCP() const
1360 return rReader
.GetCurrAttrCP();
1363 bool SwWW8FltControlStack::IsParaEndInCPs(sal_Int32 nStart
,sal_Int32 nEnd
,bool bSdOD
) const
1365 return rReader
.IsParaEndInCPs(nStart
,nEnd
,bSdOD
);
1369 * Clear the para end position recorded in reader intermittently
1370 * for the least impact on loading performance.
1372 void SwWW8FltControlStack::ClearParaEndPosition()
1377 rReader
.ClearParaEndPosition();
1380 bool SwWW8FltControlStack::CheckSdOD(sal_Int32 nStart
,sal_Int32 nEnd
)
1382 return rReader
.IsParaEndInCPs(nStart
,nEnd
);
1385 void SwWW8ReferencedFltEndStack::SetAttrInDoc( const SwPosition
& rTmpPos
,
1386 SwFltStackEntry
& rEntry
)
1388 switch( rEntry
.pAttr
->Which() )
1390 case RES_FLTR_BOOKMARK
:
1392 // suppress insertion of bookmark, which is recognized as an internal bookmark used for table-of-content
1393 // and which is not referenced.
1394 bool bInsertBookmarkIntoDoc
= true;
1396 SwFltBookmark
* pFltBookmark
= dynamic_cast<SwFltBookmark
*>(rEntry
.pAttr
);
1397 if ( pFltBookmark
!= nullptr && pFltBookmark
->IsTOCBookmark() )
1399 const OUString
& rName
= pFltBookmark
->GetName();
1400 std::set
< OUString
, SwWW8::ltstr
>::const_iterator aResult
= aReferencedTOCBookmarks
.find(rName
);
1401 if ( aResult
== aReferencedTOCBookmarks
.end() )
1403 bInsertBookmarkIntoDoc
= false;
1406 if ( bInsertBookmarkIntoDoc
)
1408 SwFltEndStack::SetAttrInDoc( rTmpPos
, rEntry
);
1413 SwFltEndStack::SetAttrInDoc( rTmpPos
, rEntry
);
1419 void SwWW8FltControlStack::SetAttrInDoc(const SwPosition
& rTmpPos
,
1420 SwFltStackEntry
& rEntry
)
1422 switch (rEntry
.pAttr
->Which())
1427 Loop over the affected nodes and
1428 a) convert the word style absolute indent to indent relative
1429 to any numbering indent active on the nodes
1430 b) adjust the writer style tabstops relative to the old
1431 paragraph indent to be relative to the new paragraph indent
1433 using namespace sw::util
;
1434 SwPaM
aRegion(rTmpPos
);
1435 if (rEntry
.MakeRegion(pDoc
, aRegion
, false))
1437 SvxLRSpaceItem
aNewLR( *static_cast<SvxLRSpaceItem
*>(rEntry
.pAttr
) );
1438 sal_uLong nStart
= aRegion
.Start()->nNode
.GetIndex();
1439 sal_uLong nEnd
= aRegion
.End()->nNode
.GetIndex();
1440 for(; nStart
<= nEnd
; ++nStart
)
1442 SwNode
* pNode
= pDoc
->GetNodes()[ nStart
];
1443 if (!pNode
|| !pNode
->IsTextNode())
1446 SwContentNode
* pNd
= static_cast<SwContentNode
*>(pNode
);
1447 SvxLRSpaceItem aOldLR
= static_cast<const SvxLRSpaceItem
&>(pNd
->GetAttr(RES_LR_SPACE
));
1449 SwTextNode
*pTextNode
= static_cast<SwTextNode
*>(pNode
);
1451 const SwNumFormat
*pNum
= nullptr;
1452 pNum
= GetNumFormatFromStack( *aRegion
.GetPoint(), *pTextNode
);
1455 pNum
= GetNumFormatFromTextNode(*pTextNode
);
1461 const bool bFirstLineIndentSet
=
1462 ( rReader
.m_aTextNodesHavingFirstLineOfstSet
.end() !=
1463 rReader
.m_aTextNodesHavingFirstLineOfstSet
.find( pNode
) );
1465 const bool bLeftIndentSet
=
1466 ( rReader
.m_aTextNodesHavingLeftIndentSet
.end() !=
1467 rReader
.m_aTextNodesHavingLeftIndentSet
.find( pNode
) );
1468 SyncIndentWithList( aNewLR
, *pNum
,
1469 bFirstLineIndentSet
,
1473 if (aNewLR
== aOldLR
)
1476 pNd
->SetAttr(aNewLR
);
1483 case RES_TXTATR_FIELD
:
1484 OSL_ENSURE(false, "What is a field doing in the control stack,"
1485 "probably should have been in the endstack");
1488 case RES_TXTATR_ANNOTATION
:
1489 OSL_ENSURE(false, "What is a annotation doing in the control stack,"
1490 "probably should have been in the endstack");
1493 case RES_TXTATR_INPUTFIELD
:
1494 OSL_ENSURE(false, "What is a input field doing in the control stack,"
1495 "probably should have been in the endstack");
1498 case RES_TXTATR_INETFMT
:
1500 SwPaM
aRegion(rTmpPos
);
1501 if (rEntry
.MakeRegion(pDoc
, aRegion
, false))
1503 SwFrameFormat
*pFrame
;
1504 // If we have just one single inline graphic then
1505 // don't insert a field for the single frame, set
1506 // the frames hyperlink field attribute directly.
1507 if (nullptr != (pFrame
= SwWW8ImplReader::ContainsSingleInlineGraphic(aRegion
)))
1509 const SwFormatINetFormat
*pAttr
= static_cast<const SwFormatINetFormat
*>(
1512 aURL
.SetURL(pAttr
->GetValue(), false);
1513 aURL
.SetTargetFrameName(pAttr
->GetTargetFrame());
1514 pFrame
->SetFormatAttr(aURL
);
1518 pDoc
->getIDocumentContentOperations().InsertPoolItem(aRegion
, *rEntry
.pAttr
);
1524 SwFltControlStack::SetAttrInDoc(rTmpPos
, rEntry
);
1529 const SfxPoolItem
* SwWW8FltControlStack::GetFormatAttr(const SwPosition
& rPos
,
1532 const SfxPoolItem
*pItem
= GetStackAttr(rPos
, nWhich
);
1535 SwContentNode
const*const pNd
= rPos
.nNode
.GetNode().GetContentNode();
1537 pItem
= &pDoc
->GetAttrPool().GetDefaultItem(nWhich
);
1541 If we're hunting for the indent on a paragraph and need to use the
1542 parent style indent, then return the indent in msword format, and
1543 not writer format, because that's the style that the filter works
1546 if (nWhich
== RES_LR_SPACE
)
1548 SfxItemState eState
= SfxItemState::DEFAULT
;
1549 if (const SfxItemSet
*pSet
= pNd
->GetpSwAttrSet())
1550 eState
= pSet
->GetItemState(RES_LR_SPACE
, false);
1551 if (eState
!= SfxItemState::SET
&& rReader
.m_nAktColl
< rReader
.m_vColl
.size())
1552 pItem
= &(rReader
.m_vColl
[rReader
.m_nAktColl
].maWordLR
);
1556 If we're hunting for a character property, try and exact position
1557 within the text node for lookup
1559 if (pNd
->IsTextNode())
1561 const sal_Int32 nPos
= rPos
.nContent
.GetIndex();
1562 m_xScratchSet
.reset(new SfxItemSet(pDoc
->GetAttrPool(), nWhich
, nWhich
));
1563 if (pNd
->GetTextNode()->GetAttr(*m_xScratchSet
, nPos
, nPos
))
1564 pItem
= m_xScratchSet
->GetItem(nWhich
);
1568 pItem
= &pNd
->GetAttr(nWhich
);
1574 const SfxPoolItem
* SwWW8FltControlStack::GetStackAttr(const SwPosition
& rPos
,
1577 SwFltPosition
aFltPos(rPos
);
1579 size_t nSize
= size();
1582 const SwFltStackEntry
& rEntry
= (*this)[ --nSize
];
1583 if (rEntry
.pAttr
->Which() == nWhich
)
1585 if ( (rEntry
.bOpen
) ||
1587 (rEntry
.m_aMkPos
.m_nNode
<= aFltPos
.m_nNode
) &&
1588 (rEntry
.m_aPtPos
.m_nNode
>= aFltPos
.m_nNode
) &&
1589 (rEntry
.m_aMkPos
.m_nContent
<= aFltPos
.m_nContent
) &&
1590 (rEntry
.m_aPtPos
.m_nContent
> aFltPos
.m_nContent
)
1594 * e.g. half-open range [0-3) so asking for properties at 3
1595 * means props that end at 3 are not included
1598 return rEntry
.pAttr
;
1605 bool SwWW8FltRefStack::IsFootnoteEdnBkmField(
1606 const SwFormatField
& rFormatField
,
1609 const SwField
* pField
= rFormatField
.GetField();
1610 sal_uInt16 nSubType
;
1611 if(pField
&& (RES_GETREFFLD
== pField
->Which())
1612 && ((REF_FOOTNOTE
== (nSubType
= pField
->GetSubType())) || (REF_ENDNOTE
== nSubType
))
1613 && !static_cast<const SwGetRefField
*>(pField
)->GetSetRefName().isEmpty())
1615 const IDocumentMarkAccess
* const pMarkAccess
= pDoc
->getIDocumentMarkAccess();
1616 IDocumentMarkAccess::const_iterator_t ppBkmk
=
1617 pMarkAccess
->findMark( static_cast<const SwGetRefField
*>(pField
)->GetSetRefName() );
1618 if(ppBkmk
!= pMarkAccess
->getAllMarksEnd())
1620 // find Sequence No of corresponding Foot-/Endnote
1621 rBkmNo
= ppBkmk
- pMarkAccess
->getAllMarksBegin();
1628 void SwWW8FltRefStack::SetAttrInDoc(const SwPosition
& rTmpPos
,
1629 SwFltStackEntry
& rEntry
)
1631 switch (rEntry
.pAttr
->Which())
1634 Look up these in our lists of bookmarks that were changed to
1635 variables, and replace the ref field with a var field, otherwise
1636 do normal (?) strange stuff
1638 case RES_TXTATR_FIELD
:
1639 case RES_TXTATR_ANNOTATION
:
1640 case RES_TXTATR_INPUTFIELD
:
1642 SwNodeIndex
aIdx(rEntry
.m_aMkPos
.m_nNode
, 1);
1643 SwPaM
aPaM(aIdx
, rEntry
.m_aMkPos
.m_nContent
);
1645 SwFormatField
& rFormatField
= *static_cast<SwFormatField
*>(rEntry
.pAttr
);
1646 SwField
* pField
= rFormatField
.GetField();
1648 if (!RefToVar(pField
, rEntry
))
1651 if( IsFootnoteEdnBkmField(rFormatField
, nBkmNo
) )
1653 ::sw::mark::IMark
const * const pMark
= (pDoc
->getIDocumentMarkAccess()->getAllMarksBegin() + nBkmNo
)->get();
1655 const SwPosition
& rBkMrkPos
= pMark
->GetMarkPos();
1657 SwTextNode
* pText
= rBkMrkPos
.nNode
.GetNode().GetTextNode();
1658 if( pText
&& rBkMrkPos
.nContent
.GetIndex() )
1660 SwTextAttr
* const pFootnote
= pText
->GetTextAttrForCharAt(
1661 rBkMrkPos
.nContent
.GetIndex()-1, RES_TXTATR_FTN
);
1664 sal_uInt16 nRefNo
= static_cast<SwTextFootnote
*>(pFootnote
)->GetSeqRefNo();
1666 static_cast<SwGetRefField
*>(pField
)->SetSeqNo( nRefNo
);
1668 if( pFootnote
->GetFootnote().IsEndNote() )
1669 static_cast<SwGetRefField
*>(pField
)->SetSubType(REF_ENDNOTE
);
1675 pDoc
->getIDocumentContentOperations().InsertPoolItem(aPaM
, *rEntry
.pAttr
);
1676 MoveAttrs(*aPaM
.GetPoint());
1680 SwFltEndStack::SetAttrInDoc(rTmpPos
, rEntry
);
1683 case RES_FLTR_BOOKMARK
:
1684 OSL_ENSURE(false, "EndStck used with non field, not what we want");
1685 SwFltEndStack::SetAttrInDoc(rTmpPos
, rEntry
);
1691 For styles we will do our tabstop arithmetic in word style and adjust them to
1692 writer style after all the styles have been finished and the dust settles as
1693 to what affects what.
1695 For explicit attributes we turn the adjusted writer tabstops back into 0 based
1696 word indexes and we'll turn them back into writer indexes when setting them
1697 into the document. If explicit left indent exist which affects them, then this
1698 is handled when the explicit left indent is set into the document
1700 void SwWW8ImplReader::Read_Tab(sal_uInt16
, const sal_uInt8
* pData
, short nLen
)
1704 m_pCtrlStck
->SetAttr(*m_pPaM
->GetPoint(), RES_PARATR_TABSTOP
);
1708 sal_uInt8 nDel
= (nLen
> 0) ? pData
[0] : 0;
1709 const sal_uInt8
* pDel
= pData
+ 1; // Del - Array
1711 sal_uInt8 nIns
= (nLen
> nDel
*2+1) ? pData
[nDel
*2+1] : 0;
1712 const sal_uInt8
* pIns
= pData
+ 2*nDel
+ 2; // Ins - Array
1714 short nRequiredLength
= 2 + 2*nDel
+ 2*nIns
+ 1*nIns
;
1715 if (nRequiredLength
> nLen
)
1717 // would require more data than available to describe!
1718 // discard invalid record
1723 WW8_TBD
const * pTyp
= reinterpret_cast<WW8_TBD
const *>(pData
+ 2*nDel
+ 2*nIns
+ 2); // Type Array
1725 SvxTabStopItem
aAttr(0, 0, SvxTabAdjust::Default
, RES_PARATR_TABSTOP
);
1727 const SwTextFormatColl
* pSty
= nullptr;
1728 sal_uInt16 nTabBase
;
1729 if (m_pAktColl
&& m_nAktColl
< m_vColl
.size()) // StyleDef
1731 nTabBase
= m_vColl
[m_nAktColl
].m_nBase
;
1732 if (nTabBase
< m_vColl
.size()) // Based On
1733 pSty
= static_cast<const SwTextFormatColl
*>(m_vColl
[nTabBase
].m_pFormat
);
1737 nTabBase
= m_nAktColl
;
1738 if (m_nAktColl
< m_vColl
.size())
1739 pSty
= static_cast<const SwTextFormatColl
*>(m_vColl
[m_nAktColl
].m_pFormat
);
1740 //TODO: figure out else here
1743 bool bFound
= false;
1744 std::unordered_set
<size_t> aLoopWatch
;
1745 while (pSty
&& !bFound
)
1747 const SfxPoolItem
* pTabs
;
1748 bFound
= pSty
->GetAttrSet().GetItemState(RES_PARATR_TABSTOP
, false,
1749 &pTabs
) == SfxItemState::SET
;
1751 aAttr
= *static_cast<const SvxTabStopItem
*>(pTabs
);
1754 sal_uInt16 nOldTabBase
= nTabBase
;
1755 // If based on another
1756 if (nTabBase
< m_vColl
.size())
1757 nTabBase
= m_vColl
[nTabBase
].m_nBase
;
1760 nTabBase
< m_vColl
.size() &&
1761 nOldTabBase
!= nTabBase
&&
1762 nTabBase
!= ww::stiNil
1765 // #i61789: Stop searching when next style is the same as the
1766 // current one (prevent loop)
1767 aLoopWatch
.insert(reinterpret_cast<size_t>(pSty
));
1768 if (nTabBase
< m_vColl
.size())
1769 pSty
= static_cast<const SwTextFormatColl
*>(m_vColl
[nTabBase
].m_pFormat
);
1770 //TODO figure out the else branch
1772 if (aLoopWatch
.find(reinterpret_cast<size_t>(pSty
)) !=
1777 pSty
= nullptr; // Give up on the search
1781 SvxTabStop aTabStop
;
1782 for (short i
=0; i
< nDel
; ++i
)
1784 sal_uInt16 nPos
= aAttr
.GetPos(SVBT16ToShort(pDel
+ i
*2));
1785 if( nPos
!= SVX_TAB_NOTFOUND
)
1786 aAttr
.Remove( nPos
);
1789 for (short i
=0; i
< nIns
; ++i
)
1791 short nPos
= SVBT16ToShort(pIns
+ i
*2);
1792 aTabStop
.GetTabPos() = nPos
;
1793 switch( pTyp
[i
].aBits1
& 0x7 ) // pTyp[i].jc
1796 aTabStop
.GetAdjustment() = SvxTabAdjust::Left
;
1799 aTabStop
.GetAdjustment() = SvxTabAdjust::Center
;
1802 aTabStop
.GetAdjustment() = SvxTabAdjust::Right
;
1805 aTabStop
.GetAdjustment() = SvxTabAdjust::Decimal
;
1808 continue; // Ignore Bar
1811 switch( pTyp
[i
].aBits1
>> 3 & 0x7 )
1814 aTabStop
.GetFill() = ' ';
1817 aTabStop
.GetFill() = '.';
1820 aTabStop
.GetFill() = '-';
1824 aTabStop
.GetFill() = '_';
1828 sal_uInt16 nPos2
= aAttr
.GetPos( nPos
);
1829 if (nPos2
!= SVX_TAB_NOTFOUND
)
1830 aAttr
.Remove(nPos2
); // Or else Insert() refuses
1831 aAttr
.Insert(aTabStop
);
1838 // Here we have a tab definition which inserts no extra tabs, or deletes
1839 // no existing tabs. An older version of writer is probably the creater
1840 // of the document :-( . So if we are importing a style we can just
1841 // ignore it. But if we are importing into text we cannot as during
1842 // text SwWW8ImplReader::Read_Tab is called at the begin and end of
1843 // the range the attrib affects, and ignoring it would upset the
1845 if (!m_pAktColl
) // not importing into a style
1847 using namespace sw::util
;
1848 SvxTabStopItem aOrig
= pSty
?
1849 ItemGet
<SvxTabStopItem
>(*pSty
, RES_PARATR_TABSTOP
) :
1850 DefaultItemGet
<SvxTabStopItem
>(m_rDoc
, RES_PARATR_TABSTOP
);
1859 void SwWW8ImplReader::ImportDop()
1861 // correct the LastPrinted date in DocumentProperties
1862 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
1863 m_pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
1864 uno::Reference
<document::XDocumentProperties
> xDocuProps(
1865 xDPS
->getDocumentProperties());
1866 OSL_ENSURE(xDocuProps
.is(), "DocumentProperties is null");
1867 if (xDocuProps
.is())
1869 DateTime
aLastPrinted(
1870 msfilter::util::DTTM2DateTime(m_pWDop
->dttmLastPrint
));
1871 ::util::DateTime uDT
= aLastPrinted
.GetUNODateTime();
1872 xDocuProps
->setPrintDate(uDT
);
1875 // COMPATIBILITY FLAGS START
1877 // #i78951# - remember the unknown compatibility options
1878 // so as to export them out
1879 m_rDoc
.getIDocumentSettingAccess().Setn32DummyCompatibilityOptions1( m_pWDop
->GetCompatibilityOptions());
1880 m_rDoc
.getIDocumentSettingAccess().Setn32DummyCompatibilityOptions2( m_pWDop
->GetCompatibilityOptions2());
1882 // The distance between two paragraphs is the sum of the bottom distance of
1883 // the first paragraph and the top distance of the second one
1884 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::PARA_SPACE_MAX
, m_pWDop
->fDontUseHTMLAutoSpacing
);
1885 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::PARA_SPACE_MAX_AT_PAGES
, true );
1886 // move tabs on alignment
1887 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::TAB_COMPAT
, true);
1888 // #i24363# tab stops relative to indent
1889 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::TABS_RELATIVE_TO_INDENT
, false);
1891 // Import Default Tabs
1892 long nDefTabSiz
= m_pWDop
->dxaTab
;
1893 if( nDefTabSiz
< 56 )
1896 // We want exactly one DefaultTab
1897 SvxTabStopItem
aNewTab( 1, sal_uInt16(nDefTabSiz
), SvxTabAdjust::Default
, RES_PARATR_TABSTOP
);
1898 const_cast<SvxTabStop
&>(aNewTab
[0]).GetAdjustment() = SvxTabAdjust::Default
;
1900 m_rDoc
.GetAttrPool().SetPoolDefaultItem( aNewTab
);
1902 // Import zoom factor
1903 if (m_pWDop
->wScaleSaved
)
1905 uno::Sequence
<beans::PropertyValue
> aViewProps(3);
1906 aViewProps
[0].Name
= "ZoomFactor";
1907 aViewProps
[0].Value
<<= sal_Int16(m_pWDop
->wScaleSaved
);
1908 aViewProps
[1].Name
= "VisibleBottom";
1909 aViewProps
[1].Value
<<= sal_Int32(0);
1910 aViewProps
[2].Name
= "ZoomType";
1912 switch (m_pWDop
->zkSaved
) {
1913 case 1: aViewProps
[2].Value
<<= sal_Int16(SvxZoomType::WHOLEPAGE
); break;
1914 case 2: aViewProps
[2].Value
<<= sal_Int16(SvxZoomType::PAGEWIDTH
); break;
1915 case 3: aViewProps
[2].Value
<<= sal_Int16(SvxZoomType::OPTIMAL
); break;
1916 default: aViewProps
[2].Value
<<= sal_Int16(SvxZoomType::PERCENT
); break;
1919 uno::Reference
< uno::XComponentContext
> xComponentContext(comphelper::getProcessComponentContext());
1920 uno::Reference
<container::XIndexContainer
> xBox
= document::IndexedPropertyValues::create(xComponentContext
);
1921 xBox
->insertByIndex(sal_Int32(0), uno::makeAny(aViewProps
));
1922 uno::Reference
<container::XIndexAccess
> xIndexAccess(xBox
, uno::UNO_QUERY
);
1923 uno::Reference
<document::XViewDataSupplier
> xViewDataSupplier(m_pDocShell
->GetModel(), uno::UNO_QUERY
);
1924 xViewDataSupplier
->setViewData(xIndexAccess
);
1927 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::USE_VIRTUAL_DEVICE
, !m_pWDop
->fUsePrinterMetrics
);
1928 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::USE_HIRES_VIRTUAL_DEVICE
, true);
1929 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::ADD_FLY_OFFSETS
, true );
1930 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::ADD_EXT_LEADING
, !m_pWDop
->fNoLeading
);
1931 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::OLD_NUMBERING
, false);
1932 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING
, false); // #i47448#
1933 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK
, !m_pWDop
->fExpShRtn
); // #i49277#, #i56856#
1934 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT
, false); // #i53199#
1935 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::OLD_LINE_SPACING
, false);
1937 // #i25901# - set new compatibility option
1938 // 'Add paragraph and table spacing at bottom of table cells'
1939 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::ADD_PARA_SPACING_TO_TABLE_CELLS
, true);
1941 // #i11860# - set new compatibility option
1942 // 'Use former object positioning' to <false>
1943 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::USE_FORMER_OBJECT_POS
, false);
1945 // #i27767# - set new compatibility option
1946 // 'Consider Wrapping mode when positioning object' to <true>
1947 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::CONSIDER_WRAP_ON_OBJECT_POSITION
, true);
1949 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::USE_FORMER_TEXT_WRAPPING
, false); // #i13832#, #i24135#
1951 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::TABLE_ROW_KEEP
, true); //SetTableRowKeep( true );
1953 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION
, true); // #i3952#
1955 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::INVERT_BORDER_SPACING
, true);
1956 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::COLLAPSE_EMPTY_CELL_PARA
, true);
1957 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::TAB_OVERFLOW
, true);
1958 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::UNBREAKABLE_NUMBERINGS
, true);
1959 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::CLIPPED_PICTURES
, true);
1960 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::TAB_OVER_MARGIN
, true);
1961 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::SURROUND_TEXT_WRAP_SMALL
, true);
1962 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::PROP_LINE_SPACING_SHRINKS_FIRST_LINE
, true);
1963 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::ALLOW_PADDING_WITHOUT_BORDERS
, true);
1965 // COMPATIBILITY FLAGS END
1967 // Import magic doptypography information, if its there
1968 if (m_pWwFib
->m_nFib
> 105)
1969 ImportDopTypography(m_pWDop
->doptypography
);
1971 // disable form design mode to be able to use imported controls directly
1972 // #i31239# always disable form design mode, not only in protected docs
1974 using namespace com::sun::star
;
1976 uno::Reference
<lang::XComponent
> xModelComp(m_pDocShell
->GetModel(),
1978 uno::Reference
<beans::XPropertySet
> xDocProps(xModelComp
,
1982 uno::Reference
<beans::XPropertySetInfo
> xInfo
=
1983 xDocProps
->getPropertySetInfo();
1986 if (xInfo
->hasPropertyByName("ApplyFormDesignMode"))
1988 bool bValue
= false;
1989 xDocProps
->setPropertyValue("ApplyFormDesignMode", css::uno::makeAny(bValue
));
1995 // Still allow editing of form fields.
1996 if (!m_pWDop
->fProtEnabled
)
1997 m_pDocShell
->SetModifyPasswordHash(m_pWDop
->lKeyProtDoc
);
1999 const SvtFilterOptions
& rOpt
= SvtFilterOptions::Get();
2000 if (rOpt
.IsUseEnhancedFields())
2001 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::PROTECT_FORM
, m_pWDop
->fProtEnabled
);
2004 void SwWW8ImplReader::ImportDopTypography(const WW8DopTypography
&rTypo
)
2006 using namespace com::sun::star
;
2007 switch (rTypo
.iLevelOfKinsoku
)
2011 i18n::ForbiddenCharacters
aForbidden(rTypo
.rgxchFPunct
,
2013 m_rDoc
.getIDocumentSettingAccess().setForbiddenCharacters(rTypo
.GetConvertedLang(),
2015 // Obviously cannot set the standard level 1 for japanese, so
2016 // bail out now while we can.
2017 if (rTypo
.GetConvertedLang() == LANGUAGE_JAPANESE
)
2026 This MS hack means that level 2 of japanese is not in operation, so we put
2027 in what we know are the MS defaults, there is a complementary reverse
2028 hack in the writer. Its our default as well, but we can set it anyway
2029 as a flag for later.
2031 if (!rTypo
.reserved2
)
2033 i18n::ForbiddenCharacters
aForbidden(WW8DopTypography::GetJapanNotBeginLevel1(),
2034 WW8DopTypography::GetJapanNotEndLevel1());
2035 m_rDoc
.getIDocumentSettingAccess().setForbiddenCharacters(LANGUAGE_JAPANESE
,aForbidden
);
2038 m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::KERN_ASIAN_PUNCTUATION
, rTypo
.fKerningPunct
);
2039 m_rDoc
.getIDocumentSettingAccess().setCharacterCompressionType(static_cast<SwCharCompressType
>(rTypo
.iJustification
));
2043 * Footnotes and Endnotes
2045 WW8ReaderSave::WW8ReaderSave(SwWW8ImplReader
* pRdr
,WW8_CP nStartCp
) :
2046 maTmpPos(*pRdr
->m_pPaM
->GetPoint()),
2047 mpOldStck(pRdr
->m_pCtrlStck
),
2048 mpOldAnchorStck(pRdr
->m_pAnchorStck
),
2049 mpOldRedlines(pRdr
->m_pRedlineStack
),
2050 mpOldPlcxMan(pRdr
->m_pPlcxMan
),
2051 mpWFlyPara(pRdr
->m_pWFlyPara
),
2052 mpSFlyPara(pRdr
->m_pSFlyPara
),
2053 mpPreviousNumPaM(pRdr
->m_pPreviousNumPaM
),
2054 mpPrevNumRule(pRdr
->m_pPrevNumRule
),
2055 mpTableDesc(pRdr
->m_pTableDesc
),
2056 mnInTable(pRdr
->m_nInTable
),
2057 mnAktColl(pRdr
->m_nAktColl
),
2058 mcSymbol(pRdr
->m_cSymbol
),
2059 mbIgnoreText(pRdr
->m_bIgnoreText
),
2060 mbSymbol(pRdr
->m_bSymbol
),
2061 mbHdFtFootnoteEdn(pRdr
->m_bHdFtFootnoteEdn
),
2062 mbTxbxFlySection(pRdr
->m_bTxbxFlySection
),
2063 mbAnl(pRdr
->m_bAnl
),
2064 mbInHyperlink(pRdr
->m_bInHyperlink
),
2065 mbPgSecBreak(pRdr
->m_bPgSecBreak
),
2066 mbWasParaEnd(pRdr
->m_bWasParaEnd
),
2067 mbHasBorder(pRdr
->m_bHasBorder
),
2068 mbFirstPara(pRdr
->m_bFirstPara
)
2070 pRdr
->m_bSymbol
= false;
2071 pRdr
->m_bHdFtFootnoteEdn
= true;
2072 pRdr
->m_bTxbxFlySection
= pRdr
->m_bAnl
= pRdr
->m_bPgSecBreak
= pRdr
->m_bWasParaEnd
2073 = pRdr
->m_bHasBorder
= false;
2074 pRdr
->m_bFirstPara
= true;
2075 pRdr
->m_nInTable
= 0;
2076 pRdr
->m_pWFlyPara
= nullptr;
2077 pRdr
->m_pSFlyPara
= nullptr;
2078 pRdr
->m_pPreviousNumPaM
= nullptr;
2079 pRdr
->m_pPrevNumRule
= nullptr;
2080 pRdr
->m_pTableDesc
= nullptr;
2081 pRdr
->m_nAktColl
= 0;
2083 pRdr
->m_pCtrlStck
= new SwWW8FltControlStack(&pRdr
->m_rDoc
, pRdr
->m_nFieldFlags
,
2086 pRdr
->m_pRedlineStack
= new sw::util::RedlineStack(pRdr
->m_rDoc
);
2088 pRdr
->m_pAnchorStck
= new SwWW8FltAnchorStack(&pRdr
->m_rDoc
, pRdr
->m_nFieldFlags
);
2090 // Save the attribute manager: we need this as the newly created PLCFx Manager
2091 // access the same FKPs as the old one and their Start-End position changes.
2092 if (pRdr
->m_pPlcxMan
)
2093 pRdr
->m_pPlcxMan
->SaveAllPLCFx(maPLCFxSave
);
2097 pRdr
->m_pPlcxMan
= new WW8PLCFMan(pRdr
->m_pSBase
,
2098 mpOldPlcxMan
->GetManType(), nStartCp
);
2101 maOldApos
.push_back(false);
2102 maOldApos
.swap(pRdr
->m_aApos
);
2103 maOldFieldStack
.swap(pRdr
->m_aFieldStack
);
2106 void WW8ReaderSave::Restore( SwWW8ImplReader
* pRdr
)
2108 pRdr
->m_pWFlyPara
= mpWFlyPara
;
2109 pRdr
->m_pSFlyPara
= mpSFlyPara
;
2110 pRdr
->m_pPreviousNumPaM
= mpPreviousNumPaM
;
2111 pRdr
->m_pPrevNumRule
= mpPrevNumRule
;
2112 pRdr
->m_pTableDesc
= mpTableDesc
;
2113 pRdr
->m_cSymbol
= mcSymbol
;
2114 pRdr
->m_bSymbol
= mbSymbol
;
2115 pRdr
->m_bIgnoreText
= mbIgnoreText
;
2116 pRdr
->m_bHdFtFootnoteEdn
= mbHdFtFootnoteEdn
;
2117 pRdr
->m_bTxbxFlySection
= mbTxbxFlySection
;
2118 pRdr
->m_nInTable
= mnInTable
;
2119 pRdr
->m_bAnl
= mbAnl
;
2120 pRdr
->m_bInHyperlink
= mbInHyperlink
;
2121 pRdr
->m_bWasParaEnd
= mbWasParaEnd
;
2122 pRdr
->m_bPgSecBreak
= mbPgSecBreak
;
2123 pRdr
->m_nAktColl
= mnAktColl
;
2124 pRdr
->m_bHasBorder
= mbHasBorder
;
2125 pRdr
->m_bFirstPara
= mbFirstPara
;
2127 // Close all attributes as attributes could be created that extend the Fly
2128 pRdr
->DeleteCtrlStack();
2129 pRdr
->m_pCtrlStck
= mpOldStck
;
2131 pRdr
->m_pRedlineStack
->closeall(*pRdr
->m_pPaM
->GetPoint());
2132 delete pRdr
->m_pRedlineStack
;
2133 pRdr
->m_pRedlineStack
= mpOldRedlines
;
2135 pRdr
->DeleteAnchorStack();
2136 pRdr
->m_pAnchorStck
= mpOldAnchorStck
;
2138 *pRdr
->m_pPaM
->GetPoint() = maTmpPos
;
2140 if (mpOldPlcxMan
!= pRdr
->m_pPlcxMan
)
2142 delete pRdr
->m_pPlcxMan
;
2143 pRdr
->m_pPlcxMan
= mpOldPlcxMan
;
2145 if (pRdr
->m_pPlcxMan
)
2146 pRdr
->m_pPlcxMan
->RestoreAllPLCFx(maPLCFxSave
);
2147 pRdr
->m_aApos
.swap(maOldApos
);
2148 pRdr
->m_aFieldStack
.swap(maOldFieldStack
);
2151 void SwWW8ImplReader::Read_HdFtFootnoteText( const SwNodeIndex
* pSttIdx
,
2152 WW8_CP nStartCp
, WW8_CP nLen
, ManTypes nType
)
2154 // Saves Flags (amongst other things) and resets them
2155 WW8ReaderSave
aSave( this );
2157 m_pPaM
->GetPoint()->nNode
= pSttIdx
->GetIndex() + 1;
2158 m_pPaM
->GetPoint()->nContent
.Assign( m_pPaM
->GetContentNode(), 0 );
2160 // Read Text for Header, Footer or Footnote
2161 ReadText( nStartCp
, nLen
, nType
); // Ignore Sepx when doing so
2162 aSave
.Restore( this );
2166 * Use authornames, if not available fall back to initials.
2168 long SwWW8ImplReader::Read_And(WW8PLCFManResult
* pRes
)
2170 WW8PLCFx_SubDoc
* pSD
= m_pPlcxMan
->GetAtn();
2174 const void* pData
= pSD
->GetData();
2182 const WW67_ATRD
* pDescri
= static_cast<const WW67_ATRD
*>(pData
);
2183 const OUString
* pA
= GetAnnotationAuthor(SVBT16ToShort(pDescri
->ibst
));
2188 const sal_uInt8 nLen
= std::min
<sal_uInt8
>(pDescri
->xstUsrInitl
[0],
2189 SAL_N_ELEMENTS(pDescri
->xstUsrInitl
)-1);
2190 sAuthor
= OUString(pDescri
->xstUsrInitl
+ 1, nLen
, RTL_TEXTENCODING_MS_1252
);
2195 const WW8_ATRD
* pDescri
= static_cast<const WW8_ATRD
*>(pData
);
2197 const sal_uInt16 nLen
= std::min
<sal_uInt16
>(SVBT16ToShort(pDescri
->xstUsrInitl
[0]),
2198 SAL_N_ELEMENTS(pDescri
->xstUsrInitl
)-1);
2199 OUStringBuffer aBuf
;
2200 aBuf
.setLength(nLen
);
2201 for(sal_uInt16 nIdx
= 1; nIdx
<= nLen
; ++nIdx
)
2202 aBuf
[nIdx
-1] = SVBT16ToShort(pDescri
->xstUsrInitl
[nIdx
]);
2203 sInitials
= aBuf
.makeStringAndClear();
2206 if (const OUString
* pA
= GetAnnotationAuthor(SVBT16ToShort(pDescri
->ibst
)))
2209 sAuthor
= sInitials
;
2212 sal_uInt32 nDateTime
= 0;
2214 if (sal_uInt8
* pExtended
= m_pPlcxMan
->GetExtendedAtrds()) // Word < 2002 has no date data for comments
2216 sal_uLong nIndex
= pSD
->GetIdx() & 0xFFFF; // Index is (stupidly) multiplexed for WW8PLCFx_SubDocs
2217 if (m_pWwFib
->m_lcbAtrdExtra
/18 > nIndex
)
2218 nDateTime
= SVBT32ToUInt32(*reinterpret_cast<SVBT32
*>(pExtended
+(nIndex
*18)));
2221 DateTime aDate
= msfilter::util::DTTM2DateTime(nDateTime
);
2224 OutlinerParaObject
*pOutliner
= ImportAsOutliner( sText
, pRes
->nCp2OrIdx
,
2225 pRes
->nCp2OrIdx
+ pRes
->nMemLen
, MAN_AND
);
2227 m_pFormatOfJustInsertedApo
= nullptr;
2228 SwPostItField
aPostIt(
2229 static_cast<SwPostItFieldType
*>(m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType(RES_POSTITFLD
)), sAuthor
,
2230 sText
, sInitials
, OUString(), aDate
);
2231 aPostIt
.SetTextObject(pOutliner
);
2233 SwPaM
aEnd(*m_pPaM
->End(), *m_pPaM
->End());
2234 m_pCtrlStck
->NewAttr(*aEnd
.GetPoint(), SvxCharHiddenItem(false, RES_CHRATR_HIDDEN
));
2235 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(aEnd
, SwFormatField(aPostIt
));
2236 m_pCtrlStck
->SetAttr(*aEnd
.GetPoint(), RES_CHRATR_HIDDEN
);
2237 // If this is a range, make sure that it ends after the just inserted character, not before it.
2238 m_pReffedStck
->MoveAttrs(*aEnd
.GetPoint());
2243 void SwWW8ImplReader::Read_HdFtTextAsHackedFrame(WW8_CP nStart
, WW8_CP nLen
,
2244 SwFrameFormat
&rHdFtFormat
, sal_uInt16 nPageWidth
)
2246 const SwNodeIndex
* pSttIdx
= rHdFtFormat
.GetContent().GetContentIdx();
2247 OSL_ENSURE(pSttIdx
, "impossible");
2251 SwPosition
aTmpPos(*m_pPaM
->GetPoint());
2253 m_pPaM
->GetPoint()->nNode
= pSttIdx
->GetIndex() + 1;
2254 m_pPaM
->GetPoint()->nContent
.Assign(m_pPaM
->GetContentNode(), 0);
2256 SwFlyFrameFormat
*pFrame
= m_rDoc
.MakeFlySection(FLY_AT_PARA
, m_pPaM
->GetPoint());
2258 SwFormatAnchor
aAnch( pFrame
->GetAnchor() );
2259 aAnch
.SetType( FLY_AT_PARA
);
2260 pFrame
->SetFormatAttr( aAnch
);
2261 SwFormatFrameSize
aSz(ATT_MIN_SIZE
, nPageWidth
, MINLAY
);
2262 SwFrameSize eFrameSize
= ATT_MIN_SIZE
;
2263 if( eFrameSize
!= aSz
.GetWidthSizeType() )
2264 aSz
.SetWidthSizeType( eFrameSize
);
2265 pFrame
->SetFormatAttr(aSz
);
2266 pFrame
->SetFormatAttr(SwFormatSurround(SURROUND_THROUGHT
));
2267 pFrame
->SetFormatAttr(SwFormatHoriOrient(0, text::HoriOrientation::LEFT
)); //iFOO
2269 // #i43427# - send frame for header/footer into background.
2270 pFrame
->SetFormatAttr( SvxOpaqueItem( RES_OPAQUE
, false ) );
2271 SdrObject
* pFrameObj
= CreateContactObject( pFrame
);
2272 OSL_ENSURE( pFrameObj
,
2273 "<SwWW8ImplReader::Read_HdFtTextAsHackedFrame(..)> - missing SdrObject instance" );
2276 pFrameObj
->SetOrdNum( 0L );
2278 MoveInsideFly(pFrame
);
2280 const SwNodeIndex
* pHackIdx
= pFrame
->GetContent().GetContentIdx();
2282 Read_HdFtFootnoteText(pHackIdx
, nStart
, nLen
- 1, MAN_HDFT
);
2284 MoveOutsideFly(pFrame
, aTmpPos
);
2287 void SwWW8ImplReader::Read_HdFtText(WW8_CP nStart
, WW8_CP nLen
, SwFrameFormat
* pHdFtFormat
)
2289 const SwNodeIndex
* pSttIdx
= pHdFtFormat
->GetContent().GetContentIdx();
2293 SwPosition
aTmpPos( *m_pPaM
->GetPoint() ); // Remember old cursor position
2295 Read_HdFtFootnoteText(pSttIdx
, nStart
, nLen
- 1, MAN_HDFT
);
2297 *m_pPaM
->GetPoint() = aTmpPos
;
2300 bool SwWW8ImplReader::isValid_HdFt_CP(WW8_CP nHeaderCP
) const
2302 // Each CP of Plcfhdd MUST be less than FibRgLw97.ccpHdd
2303 return (nHeaderCP
< m_pWwFib
->m_ccpHdr
&& nHeaderCP
>= 0);
2306 bool SwWW8ImplReader::HasOwnHeaderFooter(sal_uInt8 nWhichItems
, sal_uInt8 grpfIhdt
,
2311 WW8_CP nStart
, nLen
;
2312 sal_uInt8 nNumber
= 5;
2314 for( sal_uInt8 nI
= 0x20; nI
; nI
>>= 1, nNumber
-- )
2316 if (nI
& nWhichItems
)
2320 bOk
= ( m_pHdFt
->GetTextPos(grpfIhdt
, nI
, nStart
, nLen
) && nStart
>= 0 && nLen
>= 2 );
2323 m_pHdFt
->GetTextPosExact( static_cast< short >(nNumber
+ (nSect
+1)*6), nStart
, nLen
);
2324 bOk
= ( 2 <= nLen
) && isValid_HdFt_CP(nStart
);
2335 void SwWW8ImplReader::Read_HdFt(int nSect
, const SwPageDesc
*pPrev
,
2336 const wwSection
&rSection
)
2338 sal_uInt8 grpfIhdt
= rSection
.maSep
.grpfIhdt
;
2339 SwPageDesc
*pPD
= rSection
.mpPage
;
2343 WW8_CP nStart
, nLen
;
2344 sal_uInt8 nNumber
= 5;
2346 // This loops through the 6 flags WW8_{FOOTER,HEADER}_{ODD,EVEN,FIRST}
2347 // corresponding to bit fields in grpfIhdt indicating which
2348 // header/footer(s) are present in this section
2349 for( sal_uInt8 nI
= 0x20; nI
; nI
>>= 1, nNumber
-- )
2355 bOk
= ( m_pHdFt
->GetTextPos(grpfIhdt
, nI
, nStart
, nLen
) && nLen
>= 2 );
2358 m_pHdFt
->GetTextPosExact( static_cast< short >(nNumber
+ (nSect
+1)*6), nStart
, nLen
);
2359 bOk
= ( 2 <= nLen
) && isValid_HdFt_CP(nStart
);
2363 = (nI
& ( WW8_HEADER_EVEN
| WW8_FOOTER_EVEN
)) != 0;
2365 = (nI
& ( WW8_HEADER_FIRST
| WW8_FOOTER_FIRST
)) != 0;
2367 // If we are loading a first-page header/footer which is not
2368 // actually enabled in this section (it still needs to be
2369 // loaded as it may be inherited by a later section)
2370 bool bDisabledFirst
= bUseFirst
&& !rSection
.HasTitlePage();
2373 = (nI
& ( WW8_FOOTER_EVEN
| WW8_FOOTER_ODD
| WW8_FOOTER_FIRST
)) != 0;
2375 SwFrameFormat
& rFormat
= bUseLeft
? pPD
->GetLeft()
2376 : bUseFirst
? pPD
->GetFirstMaster()
2379 SwFrameFormat
* pHdFtFormat
;
2380 // If we have empty first page header and footer.
2381 bool bNoFirst
= !(grpfIhdt
& WW8_HEADER_FIRST
) && !(grpfIhdt
& WW8_FOOTER_FIRST
);
2385 //#i17196# Cannot have left without right
2387 && !pPD
->GetMaster().GetFooter().GetFooterFormat())
2388 pPD
->GetMaster().SetFormatAttr(SwFormatFooter(true));
2390 pPD
->GetLeft().SetFormatAttr(SwFormatFooter(true));
2391 if (bUseFirst
|| (rSection
.maSep
.fTitlePage
&& bNoFirst
))
2392 pPD
->GetFirstMaster().SetFormatAttr(SwFormatFooter(true));
2393 pHdFtFormat
= const_cast<SwFrameFormat
*>(rFormat
.GetFooter().GetFooterFormat());
2398 //#i17196# Cannot have left without right
2400 && !pPD
->GetMaster().GetHeader().GetHeaderFormat())
2401 pPD
->GetMaster().SetFormatAttr(SwFormatHeader(true));
2403 pPD
->GetLeft().SetFormatAttr(SwFormatHeader(true));
2404 if (bUseFirst
|| (rSection
.maSep
.fTitlePage
&& bNoFirst
))
2405 pPD
->GetFirstMaster().SetFormatAttr(SwFormatHeader(true));
2406 pHdFtFormat
= const_cast<SwFrameFormat
*>(rFormat
.GetHeader().GetHeaderFormat());
2411 bool bHackRequired
= false;
2412 if (m_bIsHeader
&& rSection
.IsFixedHeightHeader())
2413 bHackRequired
= true;
2414 else if (m_bIsFooter
&& rSection
.IsFixedHeightFooter())
2415 bHackRequired
= true;
2419 Read_HdFtTextAsHackedFrame(nStart
, nLen
, *pHdFtFormat
,
2420 static_cast< sal_uInt16
>(rSection
.GetTextAreaWidth()) );
2423 Read_HdFtText(nStart
, nLen
, pHdFtFormat
);
2425 else if (!bOk
&& pPrev
)
2426 CopyPageDescHdFt(pPrev
, pPD
, nI
);
2428 m_bIsHeader
= m_bIsFooter
= false;
2434 bool wwSectionManager::SectionIsProtected(const wwSection
&rSection
) const
2436 return (mrReader
.m_pWwFib
->m_fReadOnlyRecommended
&& !rSection
.IsNotProtected());
2439 void wwSectionManager::SetHdFt(wwSection
&rSection
, int nSect
,
2440 const wwSection
*pPrevious
)
2442 // Header/Footer not present
2443 if (!rSection
.maSep
.grpfIhdt
)
2446 OSL_ENSURE(rSection
.mpPage
, "makes no sense to call with a main page");
2447 if (rSection
.mpPage
)
2449 mrReader
.Read_HdFt(nSect
, pPrevious
? pPrevious
->mpPage
: nullptr,
2453 // Header/Footer - Update Index
2454 // So that the index is still valid later on
2455 if (mrReader
.m_pHdFt
)
2456 mrReader
.m_pHdFt
->UpdateIndex(rSection
.maSep
.grpfIhdt
);
2460 void SwWW8ImplReader::AppendTextNode(SwPosition
& rPos
)
2462 SwTextNode
* pText
= m_pPaM
->GetNode().GetTextNode();
2464 const SwNumRule
* pRule
= nullptr;
2466 if (pText
!= nullptr)
2467 pRule
= sw::util::GetNumRuleFromTextNode(*pText
);
2470 pRule
&& !m_pWDop
->fDontUseHTMLAutoSpacing
&&
2471 (m_bParaAutoBefore
|| m_bParaAutoAfter
)
2474 // If after spacing is set to auto, set the after space to 0
2475 if (m_bParaAutoAfter
)
2476 SetLowerSpacing(*m_pPaM
, 0);
2478 // If the previous textnode had numbering and
2479 // and before spacing is set to auto, set before space to 0
2480 if(m_pPrevNumRule
&& m_bParaAutoBefore
)
2481 SetUpperSpacing(*m_pPaM
, 0);
2483 // If the previous numbering rule was different we need
2484 // to insert a space after the previous paragraph
2485 if((pRule
!= m_pPrevNumRule
) && m_pPreviousNumPaM
)
2486 SetLowerSpacing(*m_pPreviousNumPaM
, GetParagraphAutoSpace(m_pWDop
->fDontUseHTMLAutoSpacing
));
2488 // cache current paragraph
2489 if(m_pPreviousNumPaM
)
2491 delete m_pPreviousNumPaM
;
2492 m_pPreviousNumPaM
= nullptr;
2495 m_pPreviousNumPaM
= new SwPaM(*m_pPaM
, m_pPaM
);
2496 m_pPrevNumRule
= pRule
;
2498 else if(!pRule
&& m_pPreviousNumPaM
)
2500 // If the previous paragraph has numbering but the current one does not
2501 // we need to add a space after the previous paragraph
2502 SetLowerSpacing(*m_pPreviousNumPaM
, GetParagraphAutoSpace(m_pWDop
->fDontUseHTMLAutoSpacing
));
2503 delete m_pPreviousNumPaM
;
2504 m_pPreviousNumPaM
= nullptr;
2505 m_pPrevNumRule
= nullptr;
2509 // clear paragraph cache
2510 if(m_pPreviousNumPaM
)
2512 delete m_pPreviousNumPaM
;
2513 m_pPreviousNumPaM
= nullptr;
2515 m_pPrevNumRule
= pRule
;
2518 // If this is the first paragraph in the document and
2519 // Auto-spacing before paragraph is set,
2520 // set the upper spacing value to 0
2521 if(m_bParaAutoBefore
&& m_bFirstPara
&& !m_pWDop
->fDontUseHTMLAutoSpacing
)
2522 SetUpperSpacing(*m_pPaM
, 0);
2524 m_bFirstPara
= false;
2526 m_rDoc
.getIDocumentContentOperations().AppendTextNode(rPos
);
2528 // We can flush all anchored graphics at the end of a paragraph.
2529 m_pAnchorStck
->Flush();
2532 bool SwWW8ImplReader::SetSpacing(SwPaM
&rMyPam
, int nSpace
, bool bIsUpper
)
2535 const SwPosition
* pSpacingPos
= rMyPam
.GetPoint();
2537 const SvxULSpaceItem
* pULSpaceItem
= static_cast<const SvxULSpaceItem
*>(m_pCtrlStck
->GetFormatAttr(*pSpacingPos
, RES_UL_SPACE
));
2539 if(pULSpaceItem
!= nullptr)
2541 SvxULSpaceItem
aUL(*pULSpaceItem
);
2544 aUL
.SetUpper( static_cast< sal_uInt16
>(nSpace
) );
2546 aUL
.SetLower( static_cast< sal_uInt16
>(nSpace
) );
2548 const sal_Int32 nEnd
= pSpacingPos
->nContent
.GetIndex();
2549 rMyPam
.GetPoint()->nContent
.Assign(rMyPam
.GetContentNode(), 0);
2550 m_pCtrlStck
->NewAttr(*pSpacingPos
, aUL
);
2551 rMyPam
.GetPoint()->nContent
.Assign(rMyPam
.GetContentNode(), nEnd
);
2552 m_pCtrlStck
->SetAttr(*pSpacingPos
, RES_UL_SPACE
);
2558 bool SwWW8ImplReader::SetLowerSpacing(SwPaM
&rMyPam
, int nSpace
)
2560 return SetSpacing(rMyPam
, nSpace
, false);
2563 bool SwWW8ImplReader::SetUpperSpacing(SwPaM
&rMyPam
, int nSpace
)
2565 return SetSpacing(rMyPam
, nSpace
, true);
2568 sal_uInt16
SwWW8ImplReader::TabRowSprm(int nLevel
) const
2572 return nLevel
? 0x244C : 0x2417;
2575 void SwWW8ImplReader::EndSpecial()
2579 StopAllAnl(); // -> bAnl = false
2581 while(m_aApos
.size() > 1)
2586 if (m_aApos
[m_nInTable
])
2593 OSL_ENSURE(!m_nInTable
, "unclosed table!");
2596 bool SwWW8ImplReader::FloatingTableConversion(WW8PLCFx_Cp_FKP
* pPap
)
2598 // This is ww8 version of the code deciding if the table needs to be
2599 // in a floating frame.
2600 // For OOXML code, see SectionPropertyMap::FloatingTableConversion in
2601 // writerfilter/source/dmapper/PropertyMap.cxx
2602 // The two should do ~same, so if you make changes here, please check
2603 // that the other is in sync.
2605 // Note that this is just a list of heuristics till sw core can have a
2606 // table that is floating and can span over multiple pages at the same
2609 bool bResult
= true;
2611 const sal_uInt8
*pRes
= pPap
->HasSprm(NS_sprm::LN_TDefTable
);
2612 if (nullptr != pRes
)
2615 WW8TabBandDesc aDesc
;
2616 aDesc
.ReadDef(false, pRes
);
2617 int nTextAreaWidth
= m_aSectionManager
.GetTextAreaWidth();
2618 int nTableWidth
= aDesc
.nCenter
[aDesc
.nWwCols
] - aDesc
.nCenter
[0];
2620 // It seems Word has a limit here, so that in case the table width is quite
2621 // close to the text area width, then it won't perform a wrapping, even in
2622 // case the content (e.g. an empty paragraph) would fit. The magic constant
2623 // here represents this limit.
2624 const int nMagicNumber
= 469;
2626 // If the table is wider than the text area, then don't create a fly
2627 // for the table: no wrapping will be performed anyway, but multi-page
2628 // tables will be broken.
2629 if ((nTableWidth
+ nMagicNumber
) < nTextAreaWidth
)
2632 // If there are columns, do create a fly, as the flow of the columns
2633 // would otherwise restrict the table.
2634 if (!bResult
&& (m_aSectionManager
.CurrentSectionColCount() >= 2))
2640 WW8PLCFxSave1 aSave
;
2642 if (SearchTableEnd(pPap
))
2644 // Table is considered to be imported into a fly frame and we
2645 // know where the end of the table is.
2647 WW8_FC nFc
= m_pSBase
->WW8Cp2Fc(pPap
->Where(), &bIsUnicode
);
2648 sal_uInt64 nPos
= m_pStrm
->Tell();
2650 sal_uInt16 nUChar
= 0;
2652 m_pStrm
->ReadUInt16(nUChar
);
2655 sal_uInt8 nChar
= 0;
2656 m_pStrm
->ReadUChar(nChar
);
2659 m_pStrm
->Seek(nPos
);
2661 // The pap after the table starts with a page break, so
2662 // there will be no wrapping around the float-table.
2663 // Request no fly in this case, so the table can properly
2664 // be a multi-page one if necessary.
2667 pPap
->Restore(aSave
);
2673 bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync
, WW8_CP nStartCp
)
2681 OSL_ENSURE(m_nInTable
>= 0,"nInTable < 0!");
2684 bool bTableRowEnd
= (m_pPlcxMan
->HasParaSprm(m_bVer67
? 25 : 0x2417) != nullptr );
2686 // Unfortunately, for every paragraph we need to check first whether
2687 // they contain a sprm 29 (0x261B), which starts an APO.
2688 // All other sprms then refer to that APO and not to the normal text
2690 // The same holds true for a Table (sprm 24 (0x2416)) and Anls (sprm 13).
2692 // WW: Table in APO is possible (Both Start-Ends occur at the same time)
2693 // WW: APO in Table not possible
2695 // This mean that of a Table is the content of a APO, the APO start needs
2696 // to be edited first, so that the Table remains in the APO and not the
2697 // other way around.
2698 // At the End, however, we need to edit the Table End first as the APO
2699 // must end after that Table (or else we never find the APO End).
2701 // The same holds true for Fly / Anl, Tab / Anl, Fly / Tab / Anl.
2703 // If the Table is within an APO the TabRowEnd Area misses the
2705 // To not end the APO there, we do not call ProcessApo
2707 // KHZ: When there is a table inside the Apo the Apo-flags are also
2708 // missing for the 2nd, 3rd... paragraphs of each cell.
2710 // 1st look for in-table flag, for 2000+ there is a subtable flag to
2711 // be considered, the sprm 6649 gives the level of the table
2712 sal_uInt8 nCellLevel
= 0;
2715 nCellLevel
= int(nullptr != m_pPlcxMan
->HasParaSprm(24));
2718 nCellLevel
= int(nullptr != m_pPlcxMan
->HasParaSprm(0x2416));
2720 nCellLevel
= int(nullptr != m_pPlcxMan
->HasParaSprm(0x244B));
2724 WW8_TablePos
*pTabPos
=nullptr;
2725 WW8_TablePos aTabPos
;
2726 if(nCellLevel
&& !m_bVer67
)
2728 WW8PLCFxSave1 aSave
;
2729 m_pPlcxMan
->GetPap()->Save( aSave
);
2731 WW8PLCFx_Cp_FKP
* pPap
= m_pPlcxMan
->GetPapPLCF();
2732 WW8_CP nMyStartCp
=nStartCp
;
2734 if (const sal_uInt8
*pLevel
= m_pPlcxMan
->HasParaSprm(0x6649))
2735 nCellLevel
= *pLevel
;
2737 bool bHasRowEnd
= SearchRowEnd(pPap
, nMyStartCp
, (m_nInTable
<nCellLevel
?m_nInTable
:nCellLevel
-1));
2739 // Bad Table, remain unchanged in level, e.g. #i19667#
2741 nCellLevel
= static_cast< sal_uInt8
>(m_nInTable
);
2743 if (bHasRowEnd
&& ParseTabPos(&aTabPos
,pPap
))
2746 m_pPlcxMan
->GetPap()->Restore( aSave
);
2749 // Then look if we are in an Apo
2751 ApoTestResults aApo
= TestApo(nCellLevel
, bTableRowEnd
, pTabPos
);
2753 // Look to see if we are in a Table, but Table in foot/end note not allowed
2754 bool bStartTab
= (m_nInTable
< nCellLevel
) && !m_bFootnoteEdn
;
2756 bool bStopTab
= m_bWasTabRowEnd
&& (m_nInTable
> nCellLevel
) && !m_bFootnoteEdn
;
2758 m_bWasTabRowEnd
= false; // must be deactivated right here to prevent next
2759 // WW8TabDesc::TableCellEnd() from making nonsense
2761 if (m_nInTable
&& !bTableRowEnd
&& !bStopTab
&& (m_nInTable
== nCellLevel
&& aApo
.HasStartStop()))
2762 bStopTab
= bStartTab
= true; // Required to stop and start table
2764 // Test for Anl (Numbering) and process all events in the right order
2765 if( m_bAnl
&& !bTableRowEnd
)
2767 const sal_uInt8
* pSprm13
= m_pPlcxMan
->HasParaSprm( 13 );
2769 { // Still Anl left?
2770 sal_uInt8 nT
= static_cast< sal_uInt8
>(GetNumType( *pSprm13
));
2771 if( ( nT
!= WW8_Pause
&& nT
!= m_nWwNumType
) // Anl change
2772 || aApo
.HasStartStop() // Forced Anl end
2773 || bStopTab
|| bStartTab
)
2775 StopAnlToRestart(nT
); // Anl-Restart (= change) over sprms
2779 NextAnlLine( pSprm13
); // Next Anl Line
2783 { // Regular Anl end
2784 StopAllAnl(); // Actual end
2796 m_aApos
[m_nInTable
] = false;
2799 if (aApo
.mbStartApo
)
2801 m_aApos
[m_nInTable
] = StartApo(aApo
, pTabPos
);
2802 // We need an ReSync after StartApo
2803 // (actually only if the Apo extends past a FKP border)
2808 WW8PLCFxSave1 aSave
;
2809 m_pPlcxMan
->GetPap()->Save( aSave
);
2811 // Numbering for cell borders causes a crash -> no Anls in Tables
2815 if(m_nInTable
< nCellLevel
)
2817 if (StartTable(nStartCp
))
2821 m_aApos
.push_back(false);
2824 if(m_nInTable
>= nCellLevel
)
2826 // We need an ReSync after StartTable
2827 // (actually only if the Apo extends past a FKP border)
2829 m_pPlcxMan
->GetPap()->Restore( aSave
);
2832 } while (!m_bFootnoteEdn
&& (m_nInTable
< nCellLevel
));
2833 return bTableRowEnd
;
2836 rtl_TextEncoding
SwWW8ImplReader::GetCharSetFromLanguage()
2840 The (default) character set used for a run of text is the default
2841 character set for the version of Word that last saved the document.
2843 This is a bit tentative, more might be required if the concept is correct.
2844 When later version of word write older 6/95 documents the charset is
2845 correctly set in the character runs involved, so its hard to reproduce
2846 documents that require this to be sure of the process involved.
2848 const SvxLanguageItem
*pLang
= static_cast<const SvxLanguageItem
*>(GetFormatAttr(RES_CHRATR_LANGUAGE
));
2849 LanguageType eLang
= pLang
? pLang
->GetLanguage() : LANGUAGE_SYSTEM
;
2850 css::lang::Locale
aLocale(LanguageTag::convertToLocale(eLang
));
2851 return msfilter::util::getBestTextEncodingFromLocale(aLocale
);
2854 rtl_TextEncoding
SwWW8ImplReader::GetCJKCharSetFromLanguage()
2858 The (default) character set used for a run of text is the default
2859 character set for the version of Word that last saved the document.
2861 This is a bit tentative, more might be required if the concept is correct.
2862 When later version of word write older 6/95 documents the charset is
2863 correctly set in the character runs involved, so its hard to reproduce
2864 documents that require this to be sure of the process involved.
2866 const SvxLanguageItem
*pLang
= static_cast<const SvxLanguageItem
*>(GetFormatAttr(RES_CHRATR_CJK_LANGUAGE
));
2867 LanguageType eLang
= pLang
? pLang
->GetLanguage() : LANGUAGE_SYSTEM
;
2868 css::lang::Locale
aLocale(LanguageTag::convertToLocale(eLang
));
2869 return msfilter::util::getBestTextEncodingFromLocale(aLocale
);
2872 rtl_TextEncoding
SwWW8ImplReader::GetCurrentCharSet()
2876 If the hard charset is set use it, if not see if there is an open
2877 character run that has set the charset, if not then fallback to the
2878 current underlying paragraph style.
2880 rtl_TextEncoding eSrcCharSet
= m_eHardCharSet
;
2881 if (eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
)
2883 if (!m_aFontSrcCharSets
.empty())
2884 eSrcCharSet
= m_aFontSrcCharSets
.top();
2885 if ((eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
) && m_nCharFormat
>= 0 && (size_t)m_nCharFormat
< m_vColl
.size() )
2886 eSrcCharSet
= m_vColl
[m_nCharFormat
].GetCharSet();
2887 if ((eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
) && StyleExists(m_nAktColl
) && m_nAktColl
< m_vColl
.size())
2888 eSrcCharSet
= m_vColl
[m_nAktColl
].GetCharSet();
2889 if (eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
)
2890 eSrcCharSet
= GetCharSetFromLanguage();
2895 //Takashi Ono for CJK
2896 rtl_TextEncoding
SwWW8ImplReader::GetCurrentCJKCharSet()
2900 If the hard charset is set use it, if not see if there is an open
2901 character run that has set the charset, if not then fallback to the
2902 current underlying paragraph style.
2904 rtl_TextEncoding eSrcCharSet
= m_eHardCharSet
;
2905 if (eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
)
2907 if (!m_aFontSrcCJKCharSets
.empty())
2908 eSrcCharSet
= m_aFontSrcCJKCharSets
.top();
2909 if ((eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
) && m_nCharFormat
>= 0 && (size_t)m_nCharFormat
< m_vColl
.size() )
2910 eSrcCharSet
= m_vColl
[m_nCharFormat
].GetCJKCharSet();
2911 if (eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
&& StyleExists(m_nAktColl
) && m_nAktColl
< m_vColl
.size())
2912 eSrcCharSet
= m_vColl
[m_nAktColl
].GetCJKCharSet();
2913 if (eSrcCharSet
== RTL_TEXTENCODING_DONTKNOW
)
2914 eSrcCharSet
= GetCJKCharSetFromLanguage();
2919 void SwWW8ImplReader::PostProcessAttrs()
2921 if (m_pPostProcessAttrsInfo
!= nullptr)
2923 SfxItemIter
aIter(m_pPostProcessAttrsInfo
->mItemSet
);
2925 const SfxPoolItem
* pItem
= aIter
.GetCurItem();
2926 if (pItem
!= nullptr)
2930 m_pCtrlStck
->NewAttr(*m_pPostProcessAttrsInfo
->mPaM
.GetPoint(),
2932 m_pCtrlStck
->SetAttr(*m_pPostProcessAttrsInfo
->mPaM
.GetMark(),
2935 while (!aIter
.IsAtEnd() && nullptr != (pItem
= aIter
.NextItem()));
2938 delete m_pPostProcessAttrsInfo
;
2939 m_pPostProcessAttrsInfo
= nullptr;
2945 It appears that some documents that are in a baltic 8 bit encoding which has
2946 some undefined characters can have use made of those characters, in which
2947 case they default to CP1252. If not then its perhaps that the font encoding
2948 is only in use for 6/7 and for 8+ if we are in 8bit mode then the encoding
2951 So a encoding converter that on an undefined character attempts to
2952 convert from 1252 on the undefined character
2954 std::size_t Custom8BitToUnicode(rtl_TextToUnicodeConverter hConverter
,
2955 sal_Char
*pIn
, std::size_t nInLen
, sal_Unicode
*pOut
, std::size_t nOutLen
)
2957 const sal_uInt32 nFlags
=
2958 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR
|
2959 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
|
2960 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE
|
2961 RTL_TEXTTOUNICODE_FLAGS_FLUSH
;
2963 const sal_uInt32 nFlags2
=
2964 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE
|
2965 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_IGNORE
|
2966 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE
|
2967 RTL_TEXTTOUNICODE_FLAGS_FLUSH
;
2969 std::size_t nDestChars
=0;
2970 std::size_t nConverted
=0;
2974 sal_uInt32 nInfo
= 0;
2975 sal_Size nThisConverted
=0;
2977 nDestChars
+= rtl_convertTextToUnicode(hConverter
, nullptr,
2978 pIn
+nConverted
, nInLen
-nConverted
,
2979 pOut
+nDestChars
, nOutLen
-nDestChars
,
2980 nFlags
, &nInfo
, &nThisConverted
);
2982 OSL_ENSURE(nInfo
== 0, "A character conversion failed!");
2984 nConverted
+= nThisConverted
;
2987 nInfo
& RTL_TEXTTOUNICODE_INFO_UNDEFINED
||
2988 nInfo
& RTL_TEXTTOUNICODE_INFO_MBUNDEFINED
2991 sal_Size nOtherConverted
;
2992 rtl_TextToUnicodeConverter hCP1252Converter
=
2993 rtl_createTextToUnicodeConverter(RTL_TEXTENCODING_MS_1252
);
2994 nDestChars
+= rtl_convertTextToUnicode(hCP1252Converter
, nullptr,
2996 pOut
+nDestChars
, nOutLen
-nDestChars
,
2997 nFlags2
, &nInfo
, &nOtherConverted
);
2998 rtl_destroyTextToUnicodeConverter(hCP1252Converter
);
3001 } while (nConverted
< nInLen
);
3006 bool SwWW8ImplReader::LangUsesHindiNumbers(sal_uInt16 nLang
)
3008 bool bResult
= false;
3012 case 0x1401: // Arabic(Algeria)
3013 case 0x3c01: // Arabic(Bahrain)
3014 case 0xc01: // Arabic(Egypt)
3015 case 0x801: // Arabic(Iraq)
3016 case 0x2c01: // Arabic (Jordan)
3017 case 0x3401: // Arabic(Kuwait)
3018 case 0x3001: // Arabic(Lebanon)
3019 case 0x1001: // Arabic(Libya)
3020 case 0x1801: // Arabic(Morocco)
3021 case 0x2001: // Arabic(Oman)
3022 case 0x4001: // Arabic(Qatar)
3023 case 0x401: // Arabic(Saudi Arabia)
3024 case 0x2801: // Arabic(Syria)
3025 case 0x1c01: // Arabic(Tunisia)
3026 case 0x3801: // Arabic(U.A.E)
3027 case 0x2401: // Arabic(Yemen)
3037 sal_Unicode
SwWW8ImplReader::TranslateToHindiNumbers(sal_Unicode nChar
)
3039 if (nChar
>= 0x0030 && nChar
<= 0x0039)
3040 return nChar
+ 0x0630;
3046 * Return value: true for non special chars
3048 bool SwWW8ImplReader::ReadPlainChars(WW8_CP
& rPos
, sal_Int32 nEnd
, sal_Int32 nCpOfs
)
3050 sal_Int32 nRequestedStrLen
= nEnd
- rPos
;
3052 OSL_ENSURE(nRequestedStrLen
, "String is 0");
3053 if (nRequestedStrLen
<= 0)
3056 sal_Int32 nRequestedPos
= m_pSBase
->WW8Cp2Fc(nCpOfs
+rPos
, &m_bIsUnicode
);
3057 bool bValidPos
= checkSeek(*m_pStrm
, nRequestedPos
);
3058 OSL_ENSURE(bValidPos
, "Document claimed to have more text than available");
3061 // Swallow missing range, e.g. #i95550#
3062 rPos
+=nRequestedStrLen
;
3066 std::size_t nAvailableStrLen
= m_pStrm
->remainingSize() / (m_bIsUnicode
? 2 : 1);
3067 OSL_ENSURE(nAvailableStrLen
, "Document claimed to have more text than available");
3068 if (!nAvailableStrLen
)
3070 // Swallow missing range, e.g. #i95550#
3071 rPos
+=nRequestedStrLen
;
3075 sal_Int32 nValidStrLen
= std::min
<std::size_t>(nRequestedStrLen
, nAvailableStrLen
);
3077 // Reset Unicode flag and correct FilePos if needed.
3078 // Note: Seek is not expensive, as we're checking inline whether or not
3079 // the correct FilePos has already been reached.
3080 const sal_Int32 nStrLen
= std::min(nValidStrLen
, SAL_MAX_INT32
-1);
3082 rtl_TextEncoding eSrcCharSet
= m_bVer67
? GetCurrentCharSet() :
3083 RTL_TEXTENCODING_MS_1252
;
3084 if (m_bVer67
&& eSrcCharSet
== RTL_TEXTENCODING_MS_932
)
3089 Older documents exported as word 95 that use unicode aware fonts will
3090 have the charset of those fonts set to RTL_TEXTENCODING_MS_932 on
3091 export as the conversion from RTL_TEXTENCODING_UNICODE. This is a serious
3094 We will try and use a fallback encoding if the conversion from
3095 RTL_TEXTENCODING_MS_932 fails, but you can get unlucky and get a document
3096 which isn't really in RTL_TEXTENCODING_MS_932 but parts of it form
3097 valid RTL_TEXTENCODING_MS_932 by chance :-(
3099 We're not the only ones that struggle with this: Here's the help from
3100 MSOffice 2003 on the topic:
3103 Earlier versions of Microsoft Word were sometimes used in conjunction with
3104 third-party language-processing add-in programs designed to support Chinese or
3105 Korean on English versions of Microsoft Windows. Use of these add-ins sometimes
3106 results in incorrect text display in more recent versions of Word.
3108 However, you can set options to convert these documents so that text is
3109 displayed correctly. On the Tools menu, click Options, and then click the
3110 General tab. In the English Word 6.0/95 documents list, select Contain Asian
3111 text (to have Word interpret the text as Asian code page data, regardless of
3112 its font) or Automatically detect Asian text (to have Word attempt to determine
3113 which parts of the text are meant to be Asian).
3116 What we can try here is to ignore a RTL_TEXTENCODING_MS_932 codepage if
3117 the language is not Japanese
3120 const SfxPoolItem
* pItem
= GetFormatAttr(RES_CHRATR_CJK_LANGUAGE
);
3121 if (pItem
!= nullptr && LANGUAGE_JAPANESE
!= static_cast<const SvxLanguageItem
*>(pItem
)->GetLanguage())
3123 SAL_WARN("sw.ww8", "discarding word95 RTL_TEXTENCODING_MS_932 encoding");
3124 eSrcCharSet
= GetCharSetFromLanguage();
3127 const rtl_TextEncoding eSrcCJKCharSet
= m_bVer67
? GetCurrentCJKCharSet() :
3128 RTL_TEXTENCODING_MS_1252
;
3130 // allocate unicode string data
3131 rtl_uString
*pStr
= rtl_uString_alloc(nStrLen
);
3132 sal_Unicode
* pBuffer
= pStr
->buffer
;
3133 sal_Unicode
* pWork
= pBuffer
;
3135 sal_Char
* p8Bits
= nullptr;
3137 rtl_TextToUnicodeConverter hConverter
= nullptr;
3138 if (!m_bIsUnicode
|| m_bVer67
)
3139 hConverter
= rtl_createTextToUnicodeConverter(eSrcCharSet
);
3142 p8Bits
= new sal_Char
[nStrLen
];
3144 // read the stream data
3145 sal_uInt8 nBCode
= 0;
3148 sal_uInt16 nCTLLang
= 0;
3149 const SfxPoolItem
* pItem
= GetFormatAttr(RES_CHRATR_CTL_LANGUAGE
);
3150 if (pItem
!= nullptr)
3151 nCTLLang
= static_cast<const SvxLanguageItem
*>(pItem
)->GetLanguage();
3154 for( nL2
= 0; nL2
< nStrLen
; ++nL2
, ++pWork
)
3157 m_pStrm
->ReadUInt16( nUCode
); // unicode --> read 2 bytes
3160 m_pStrm
->ReadUChar( nBCode
); // old code --> read 1 byte
3164 if (m_pStrm
->GetError())
3166 rPos
= WW8_CP_MAX
-10; // -> eof or other error
3167 rtl_freeMemory(pStr
);
3172 if ((32 > nUCode
) || (0xa0 == nUCode
))
3174 m_pStrm
->SeekRel( m_bIsUnicode
? -2 : -1 );
3175 break; // Special character < 32, == 0xa0 found
3184 if (nUCode
>= 0x3000) //0x8000 ?
3187 aTest
[0] = static_cast< sal_Char
>((nUCode
& 0xFF00) >> 8);
3188 aTest
[1] = static_cast< sal_Char
>(nUCode
& 0x00FF);
3189 OUString
aTemp(aTest
, 2, eSrcCJKCharSet
);
3190 OSL_ENSURE(aTemp
.getLength() == 1, "so much for that theory");
3195 sal_Char cTest
= static_cast< sal_Char
>(nUCode
& 0x00FF);
3196 Custom8BitToUnicode(hConverter
, &cTest
, 1, pWork
, 1);
3201 p8Bits
[nL2
] = nBCode
;
3206 const sal_Int32 nEndUsed
= !m_bIsUnicode
3207 ? Custom8BitToUnicode(hConverter
, p8Bits
, nL2
, pBuffer
, nStrLen
)
3210 for( sal_Int32 nI
= 0; nI
< nStrLen
; ++nI
, ++pBuffer
)
3211 if (m_bRegardHindiDigits
&& m_bBidi
&& LangUsesHindiNumbers(nCTLLang
))
3212 *pBuffer
= TranslateToHindiNumbers(*pBuffer
);
3214 pStr
->buffer
[nEndUsed
] = 0;
3215 pStr
->length
= nEndUsed
;
3217 emulateMSWordAddTextToParagraph(OUString(pStr
, SAL_NO_ACQUIRE
));
3220 if (!m_aApos
.back()) // a para end in apo doesn't count
3221 m_bWasParaEnd
= false; // No CR
3225 rtl_destroyTextToUnicodeConverter(hConverter
);
3227 rtl_uString_release(pStr
);
3229 return nL2
>= nStrLen
;
3232 #define MSASCII SAL_MAX_INT16
3236 // We want to force weak chars inside 0x0020 to 0x007F to LATIN
3237 sal_Int16
lcl_getScriptType(
3238 const uno::Reference
<i18n::XBreakIterator
>& rBI
,
3239 const OUString
&rString
, sal_Int32 nPos
)
3241 sal_Int16 nScript
= rBI
->getScriptType(rString
, nPos
);
3242 if (nScript
== i18n::ScriptType::WEAK
&& rString
[nPos
] >= 0x0020 && rString
[nPos
] <= 0x007F)
3247 // We want to know about WEAK segments, so endOfScript isn't
3248 // useful, and see lcl_getScriptType anyway
3249 sal_Int32
lcl_endOfScript(
3250 const uno::Reference
<i18n::XBreakIterator
>& rBI
,
3251 const OUString
&rString
, sal_Int32 nPos
, sal_Int16 nScript
)
3253 while (nPos
< rString
.getLength())
3255 sal_Int16 nNewScript
= lcl_getScriptType(rBI
, rString
, nPos
);
3256 if (nScript
!= nNewScript
)
3263 sal_Int32
lcl_getWriterScriptType(
3264 const uno::Reference
<i18n::XBreakIterator
>& rBI
,
3265 const OUString
&rString
, sal_Int32 nPos
)
3267 sal_Int16 nScript
= i18n::ScriptType::WEAK
;
3269 if (rString
.isEmpty())
3274 nScript
= rBI
->getScriptType(rString
, nPos
);
3275 if (nScript
!= i18n::ScriptType::WEAK
)
3283 bool samePitchIgnoreUnknown(FontPitch eA
, FontPitch eB
)
3285 return (eA
== eB
|| eA
== PITCH_DONTKNOW
|| eB
== PITCH_DONTKNOW
);
3288 bool sameFontIgnoringIrrelevantFields(const SvxFontItem
&rA
, const SvxFontItem
&rB
)
3290 // Ignoring CharSet, and ignoring unknown pitch
3291 return rA
.GetFamilyName() == rB
.GetFamilyName() &&
3292 rA
.GetStyleName() == rB
.GetStyleName() &&
3293 rA
.GetFamily() == rB
.GetFamily() &&
3294 samePitchIgnoreUnknown(rA
.GetPitch(), rB
.GetPitch());
3298 // In writer we categorize text into CJK, CTL and "Western" for everything else.
3299 // Microsoft Word basically categorizes text into East Asian, Complex, ASCII,
3300 // NonEastAsian/HighAnsi, with some shared characters and some properties to
3301 // hint as to which way to bias those shared characters.
3303 // That's four categories, we however have three categories. Given that problem
3304 // here we would ideally find out "what would word do" to see what font/language
3305 // word would assign to characters based on the unicode range they fall into and
3306 // hack the word one onto the range we use. However it's unclear what word's
3307 // categorization is. So we don't do that here yet.
3309 // Additional to the categorization, when word encounters weak text for ambiguous
3310 // chars it uses idcthint to indicate which way to bias. We don't have a idcthint
3311 // feature in writer.
3313 // So what we currently do here then is to split our text into non-weak/weak
3314 // sections and uses word's idcthint to determine what font it would use and
3315 // force that on for the segment. Following what we *do* know about word's
3316 // categorization, we know that the range 0x0020 and 0x007F is sprmCRgFtc0 in
3317 // word, something we map to LATIN, so we consider all weaks chars in that range
3318 // to auto-bias to LATIN.
3320 // See https://bugs.libreoffice.org/show_bug.cgi?id=34319 for an example
3321 void SwWW8ImplReader::emulateMSWordAddTextToParagraph(const OUString
& rAddString
)
3323 if (rAddString
.isEmpty())
3326 uno::Reference
<i18n::XBreakIterator
> xBI(g_pBreakIt
->GetBreakIter());
3329 simpleAddTextToParagraph(rAddString
);
3333 sal_Int16 nScript
= lcl_getScriptType(xBI
, rAddString
, 0);
3334 sal_Int32 nLen
= rAddString
.getLength();
3336 OUString sParagraphText
;
3337 const SwContentNode
*pCntNd
= m_pPaM
->GetContentNode();
3338 const SwTextNode
* pNd
= pCntNd
? pCntNd
->GetTextNode() : nullptr;
3340 sParagraphText
= pNd
->GetText();
3341 sal_Int32 nParaOffset
= sParagraphText
.getLength();
3342 sParagraphText
= sParagraphText
+ rAddString
;
3347 sal_Int32 nEnd
= lcl_endOfScript(xBI
, rAddString
, nPos
, nScript
);
3351 OUString
sChunk(rAddString
.copy(nPos
, nEnd
-nPos
));
3352 const sal_uInt16 aIds
[] = {RES_CHRATR_FONT
, RES_CHRATR_CJK_FONT
, RES_CHRATR_CTL_FONT
};
3353 const SvxFontItem
*pOverriddenItems
[] = {nullptr, nullptr, nullptr};
3354 bool aForced
[] = {false, false, false};
3356 int nLclIdctHint
= 0xFF;
3357 if (nScript
== i18n::ScriptType::WEAK
)
3359 const SfxInt16Item
*pIdctHint
= static_cast<const SfxInt16Item
*>(GetFormatAttr(RES_CHRATR_IDCTHINT
));
3360 nLclIdctHint
= pIdctHint
->GetValue();
3362 else if (nScript
== MSASCII
) // Force weak chars in ascii range to use LATIN font
3365 sal_uInt16 nForceFromFontId
= 0;
3366 if (nLclIdctHint
!= 0xFF)
3368 switch (nLclIdctHint
)
3371 nForceFromFontId
= RES_CHRATR_FONT
;
3374 nForceFromFontId
= RES_CHRATR_CJK_FONT
;
3377 nForceFromFontId
= RES_CHRATR_CTL_FONT
;
3384 if (nForceFromFontId
!= 0)
3386 // Now we know that word would use the nForceFromFontId font for this range
3387 // Try and determine what script writer would assign this range to
3389 sal_Int32 nWriterScript
= lcl_getWriterScriptType(xBI
, sParagraphText
,
3390 nPos
+ nParaOffset
);
3392 bool bWriterWillUseSameFontAsWordAutomatically
= false;
3394 if (nWriterScript
!= i18n::ScriptType::WEAK
)
3397 (nWriterScript
== i18n::ScriptType::ASIAN
&& nForceFromFontId
== RES_CHRATR_CJK_FONT
) ||
3398 (nWriterScript
== i18n::ScriptType::COMPLEX
&& nForceFromFontId
== RES_CHRATR_CTL_FONT
) ||
3399 (nWriterScript
== i18n::ScriptType::LATIN
&& nForceFromFontId
== RES_CHRATR_FONT
)
3402 bWriterWillUseSameFontAsWordAutomatically
= true;
3406 const SvxFontItem
*pSourceFont
= static_cast<const SvxFontItem
*>(GetFormatAttr(nForceFromFontId
));
3407 sal_uInt16 nDestId
= aIds
[nWriterScript
-1];
3408 const SvxFontItem
*pDestFont
= static_cast<const SvxFontItem
*>(GetFormatAttr(nDestId
));
3409 bWriterWillUseSameFontAsWordAutomatically
= sameFontIgnoringIrrelevantFields(*pSourceFont
, *pDestFont
);
3413 // Writer won't use the same font as word, so force the issue
3414 if (!bWriterWillUseSameFontAsWordAutomatically
)
3416 const SvxFontItem
*pSourceFont
= static_cast<const SvxFontItem
*>(GetFormatAttr(nForceFromFontId
));
3418 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aIds
); ++i
)
3420 const SvxFontItem
*pDestFont
= static_cast<const SvxFontItem
*>(GetFormatAttr(aIds
[i
]));
3421 aForced
[i
] = aIds
[i
] != nForceFromFontId
&& *pSourceFont
!= *pDestFont
;
3424 pOverriddenItems
[i
] =
3425 static_cast<const SvxFontItem
*>(m_pCtrlStck
->GetStackAttr(*m_pPaM
->GetPoint(), aIds
[i
]));
3427 SvxFontItem
aForceFont(*pSourceFont
);
3428 aForceFont
.SetWhich(aIds
[i
]);
3429 m_pCtrlStck
->NewAttr(*m_pPaM
->GetPoint(), aForceFont
);
3435 simpleAddTextToParagraph(sChunk
);
3437 for (size_t i
= 0; i
< SAL_N_ELEMENTS(aIds
); ++i
)
3441 m_pCtrlStck
->SetAttr(*m_pPaM
->GetPoint(), aIds
[i
]);
3442 if (pOverriddenItems
[i
])
3443 m_pCtrlStck
->NewAttr(*m_pPaM
->GetPoint(), *(pOverriddenItems
[i
]));
3449 nScript
= lcl_getScriptType(xBI
, rAddString
, nPos
);
3453 void SwWW8ImplReader::simpleAddTextToParagraph(const OUString
& rAddString
)
3455 if (rAddString
.isEmpty())
3458 #if OSL_DEBUG_LEVEL > 1
3460 OString
sText(OUStringToOString(rAddString
, RTL_TEXTENCODING_UTF8
));
3461 SAL_INFO("sw.ww8", "<addTextToParagraph>" << sText
.getStr() << "</addTextToParagraph>");
3465 const SwContentNode
*pCntNd
= m_pPaM
->GetContentNode();
3466 const SwTextNode
* pNd
= pCntNd
? pCntNd
->GetTextNode() : nullptr;
3468 OSL_ENSURE(pNd
, "What the hell, where's my text node");
3473 const sal_Int32 nCharsLeft
= SAL_MAX_INT32
- pNd
->GetText().getLength();
3476 if (rAddString
.getLength() <= nCharsLeft
)
3478 m_rDoc
.getIDocumentContentOperations().InsertString(*m_pPaM
, rAddString
);
3482 m_rDoc
.getIDocumentContentOperations().InsertString(*m_pPaM
, rAddString
.copy(0, nCharsLeft
));
3483 AppendTextNode(*m_pPaM
->GetPoint());
3484 m_rDoc
.getIDocumentContentOperations().InsertString(*m_pPaM
, rAddString
.copy(nCharsLeft
));
3489 AppendTextNode(*m_pPaM
->GetPoint());
3490 m_rDoc
.getIDocumentContentOperations().InsertString(*m_pPaM
, rAddString
);
3493 m_bReadTable
= false;
3497 * Return value: true for para end
3499 bool SwWW8ImplReader::ReadChars(WW8_CP
& rPos
, WW8_CP nNextAttr
, long nTextEnd
,
3502 long nEnd
= ( nNextAttr
< nTextEnd
) ? nNextAttr
: nTextEnd
;
3504 if (m_bSymbol
|| m_bIgnoreText
)
3506 if( m_bSymbol
) // Insert special chars
3508 for(sal_uInt16 nCh
= 0; nCh
< nEnd
- rPos
; ++nCh
)
3510 m_rDoc
.getIDocumentContentOperations().InsertString( *m_pPaM
, OUString(m_cSymbol
) );
3512 m_pCtrlStck
->SetAttr( *m_pPaM
->GetPoint(), RES_CHRATR_FONT
);
3513 m_pCtrlStck
->SetAttr( *m_pPaM
->GetPoint(), RES_CHRATR_CJK_FONT
);
3514 m_pCtrlStck
->SetAttr( *m_pPaM
->GetPoint(), RES_CHRATR_CTL_FONT
);
3516 m_pStrm
->SeekRel( nEnd
- rPos
);
3517 rPos
= nEnd
; // Ignore until attribute end
3523 if (ReadPlainChars(rPos
, nEnd
, nCpOfs
))
3524 return false; // Done
3526 bool bStartLine
= ReadChar(rPos
, nCpOfs
);
3528 if (m_bPgSecBreak
|| bStartLine
|| rPos
== nEnd
) // CR or Done
3535 bool SwWW8ImplReader::HandlePageBreakChar()
3537 bool bParaEndAdded
= false;
3538 // #i1909# section/page breaks should not occur in tables, word
3539 // itself ignores them in this case.
3543 SwTextNode
* pTemp
= m_pPaM
->GetNode().GetTextNode();
3544 if (pTemp
&& pTemp
->GetText().isEmpty()
3545 && (m_bFirstPara
|| m_bFirstParaOfPage
))
3548 AppendTextNode(*m_pPaM
->GetPoint());
3549 pTemp
->SetAttr(*GetDfltAttr(RES_PARATR_NUMRULE
));
3552 m_bPgSecBreak
= true;
3553 m_pCtrlStck
->KillUnlockedAttrs(*m_pPaM
->GetPoint());
3555 If it's a 0x0c without a paragraph end before it, act like a
3556 paragraph end, but nevertheless, numbering (and perhaps other
3557 similar constructs) do not exist on the para.
3559 if (!m_bWasParaEnd
&& IsTemp
)
3561 bParaEndAdded
= true;
3562 if (0 >= m_pPaM
->GetPoint()->nContent
.GetIndex())
3564 if (SwTextNode
* pTextNode
= m_pPaM
->GetNode().GetTextNode())
3567 *GetDfltAttr(RES_PARATR_NUMRULE
));
3572 return bParaEndAdded
;
3575 bool SwWW8ImplReader::ReadChar(long nPosCp
, long nCpOfs
)
3577 bool bNewParaEnd
= false;
3578 // Reset Unicode flag and correct FilePos if needed.
3579 // Note: Seek is not expensive, as we're checking inline whether or not
3580 // the correct FilePos has already been reached.
3581 std::size_t nRequestedPos
= m_pSBase
->WW8Cp2Fc(nCpOfs
+nPosCp
, &m_bIsUnicode
);
3582 if (!checkSeek(*m_pStrm
, nRequestedPos
))
3585 sal_uInt8
nBCode(0);
3586 sal_uInt16
nWCharVal(0);
3588 m_pStrm
->ReadUInt16( nWCharVal
); // unicode --> read 2 bytes
3591 m_pStrm
-> ReadUChar( nBCode
); // old code --> read 1 byte
3595 sal_Unicode cInsert
= '\x0';
3596 bool bParaMark
= false;
3598 if ( 0xc != nWCharVal
)
3599 m_bFirstParaOfPage
= false;
3606 SwPageNumberField
aField(
3607 static_cast<SwPageNumberFieldType
*>(m_rDoc
.getIDocumentFieldsAccess().GetSysFieldType(
3608 RES_PAGENUMBERFLD
)), PG_RANDOM
, SVX_NUM_ARABIC
);
3609 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
, SwFormatField(aField
));
3613 // if there is only one column word treats a column break like a pagebreak.
3614 if (m_aSectionManager
.CurrentSectionColCount() < 2)
3615 bParaMark
= HandlePageBreakChar();
3616 else if (!m_nInTable
)
3618 // Always insert a txtnode for a column break, e.g. ##
3619 SwContentNode
*pCntNd
=m_pPaM
->GetContentNode();
3620 if (pCntNd
!=nullptr && pCntNd
->Len()>0) // if par is empty not break is needed
3621 AppendTextNode(*m_pPaM
->GetPoint());
3622 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
, SvxFormatBreakItem(SvxBreak::ColumnBefore
, RES_BREAK
));
3628 WW8PLCFxDesc
* pPap
= m_pPlcxMan
->GetPap();
3629 //The last paragraph of each cell is terminated by a special
3630 //paragraph mark called a cell mark. Following the cell mark
3631 //that ends the last cell of a table row, the table row is
3632 //terminated by a special paragraph mark called a row mark
3634 //So the 0x7 should be right at the end of the previous
3635 //range to be a real cell-end.
3636 if (pPap
->nOrigStartPos
== nPosCp
+1 ||
3637 pPap
->nOrigStartPos
== WW8_CP_MAX
)
3639 TabCellEnd(); // Table cell/row end
3646 if( !m_bSpec
) // "Satellite"
3647 cInsert
= sal_Unicode('\xa4');
3650 if( !m_bSpec
) // "Para End" char
3651 cInsert
= sal_Unicode('\xb5');
3654 if( !m_bSpec
) // Juristenparagraph
3656 cp_set::iterator aItr
= m_aTOXEndCps
.find((WW8_CP
)nPosCp
);
3657 if (aItr
== m_aTOXEndCps
.end())
3658 cInsert
= sal_Unicode('\xa7');
3660 m_aTOXEndCps
.erase(aItr
);
3664 cInsert
= '\x9'; // Tab
3667 cInsert
= '\xa'; // Hard NewLine
3670 bParaMark
= HandlePageBreakChar();
3672 case 0x1e: // Non-breaking hyphen
3673 m_rDoc
.getIDocumentContentOperations().InsertString( *m_pPaM
, OUString(CHAR_HARDHYPHEN
) );
3675 case 0x1f: // Non-required hyphens
3676 m_rDoc
.getIDocumentContentOperations().InsertString( *m_pPaM
, OUString(CHAR_SOFTHYPHEN
) );
3678 case 0xa0: // Non-breaking spaces
3679 m_rDoc
.getIDocumentContentOperations().InsertString( *m_pPaM
, OUString(CHAR_HARDBLANK
) );
3683 Current thinking is that if bObj is set then we have a
3684 straightforward "traditional" ole object, otherwise we have a
3685 graphic preview of an associated ole2 object (or a simple
3688 normally in the canvas field, the code is 0x8 0x1.
3689 in a special case, the code is 0x1 0x1, which yields a simple picture
3692 bool bReadObj
= IsInlineEscherHack();
3695 long nCurPos
= m_pStrm
->Tell();
3696 sal_uInt16
nWordCode(0);
3699 m_pStrm
->ReadUInt16( nWordCode
);
3702 sal_uInt8
nByteCode(0);
3703 m_pStrm
->ReadUChar( nByteCode
);
3704 nWordCode
= nByteCode
;
3706 if( nWordCode
== 0x1 )
3708 m_pStrm
->Seek( nCurPos
);
3712 SwFrameFormat
*pResult
= nullptr;
3714 pResult
= ImportOle();
3716 pResult
= ImportGraf();
3718 // If we have a bad 0x1 insert a space instead.
3722 OSL_ENSURE(!m_bObj
&& !m_bEmbeddObj
&& !m_nObjLocFc
,
3723 "WW8: Please report this document, it may have a "
3729 m_bObj
= m_bEmbeddObj
= false;
3737 Read_GrafLayer( nPosCp
);
3740 bNewParaEnd
= bParaMark
= true;
3745 Yes complex, if there is an entry in the undocumented PLCF
3746 which I believe to be a record of cell and row boundaries
3747 see if the magic bit which I believe to mean cell end is
3748 set. I also think btw that the third byte of the 4 byte
3749 value is the level of the cell
3751 WW8PLCFspecial
* pTest
= m_pPlcxMan
->GetMagicTables();
3752 if (pTest
&& pTest
->SeekPosExact(nPosCp
+1+nCpOfs
) &&
3753 pTest
->Where() == nPosCp
+1+nCpOfs
)
3757 pTest
->Get(nPos
, pData
);
3758 sal_uInt32 nData
= SVBT32ToUInt32(*static_cast<SVBT32
*>(pData
));
3759 if (nData
& 0x2) // Might be how it works
3765 // tdf#106799: We expect TTP marks to be also cell marks,
3766 // but sometimes sprmPFInnerTtp comes without sprmPFInnerTableCell
3767 else if (m_bWasTabCellEnd
|| m_bWasTabRowEnd
)
3774 m_bWasTabCellEnd
= false;
3777 case 0x5: // Annotation reference
3780 case 0x2: // TODO: Auto-Footnote-Number, should be replaced by SwWW8ImplReader::End_Footnote later
3781 if (!m_aFootnoteStack
.empty())
3785 SAL_INFO( "sw.ww8.level2", "<unknownValue val=\"" << nWCharVal
<< "\">" );
3789 if( '\x0' != cInsert
)
3791 OUString
sInsert(cInsert
);
3792 emulateMSWordAddTextToParagraph(sInsert
);
3794 if (!m_aApos
.back()) // a para end in apo doesn't count
3795 m_bWasParaEnd
= bNewParaEnd
;
3799 void SwWW8ImplReader::ProcessAktCollChange(WW8PLCFManResult
& rRes
,
3800 bool* pStartAttr
, bool bCallProcessSpecial
)
3802 sal_uInt16 nOldColl
= m_nAktColl
;
3803 m_nAktColl
= m_pPlcxMan
->GetColl();
3806 if (m_nAktColl
>= m_vColl
.size() || !m_vColl
[m_nAktColl
].m_pFormat
|| !m_vColl
[m_nAktColl
].m_bColl
)
3809 m_bParaAutoBefore
= false;
3810 m_bParaAutoAfter
= false;
3814 m_bParaAutoBefore
= m_vColl
[m_nAktColl
].m_bParaAutoBefore
;
3815 m_bParaAutoAfter
= m_vColl
[m_nAktColl
].m_bParaAutoAfter
;
3818 if (nOldColl
>= m_vColl
.size())
3819 nOldColl
= 0; // guess! TODO make sure this is what we want
3821 bool bTabRowEnd
= false;
3822 if( pStartAttr
&& bCallProcessSpecial
&& !m_bInHyperlink
)
3825 // Frame/Table/Autonumbering List Level
3826 bTabRowEnd
= ProcessSpecial(bReSync
, rRes
.nAktCp
+m_pPlcxMan
->GetCpOfs());
3828 *pStartAttr
= m_pPlcxMan
->Get( &rRes
); // Get Attribut-Pos again
3831 if (!bTabRowEnd
&& StyleExists(m_nAktColl
))
3833 SetTextFormatCollAndListLevel( *m_pPaM
, m_vColl
[ m_nAktColl
]);
3834 ChkToggleAttr(m_vColl
[ nOldColl
].m_n81Flags
, m_vColl
[ m_nAktColl
].m_n81Flags
);
3835 ChkToggleBiDiAttr(m_vColl
[nOldColl
].m_n81BiDiFlags
,
3836 m_vColl
[m_nAktColl
].m_n81BiDiFlags
);
3840 long SwWW8ImplReader::ReadTextAttr(WW8_CP
& rTextPos
, long nTextEnd
, bool& rbStartLine
)
3842 long nSkipChars
= 0;
3843 WW8PLCFManResult aRes
;
3845 OSL_ENSURE(m_pPaM
->GetNode().GetTextNode(), "Missing txtnode");
3846 bool bStartAttr
= m_pPlcxMan
->Get(&aRes
); // Get Attribute position again
3847 aRes
.nAktCp
= rTextPos
; // Current Cp position
3849 bool bNewSection
= (aRes
.nFlags
& MAN_MASK_NEW_SEP
) && !m_bIgnoreText
;
3850 if ( bNewSection
) // New Section
3852 OSL_ENSURE(m_pPaM
->GetNode().GetTextNode(), "Missing txtnode");
3853 // Create PageDesc and fill it
3854 m_aSectionManager
.CreateSep(rTextPos
, m_bPgSecBreak
);
3855 // -> 0xc was a Sectionbreak, but not a Pagebreak;
3856 // Create PageDesc and fill it
3857 m_bPgSecBreak
= false;
3858 OSL_ENSURE(m_pPaM
->GetNode().GetTextNode(), "Missing txtnode");
3861 // New paragraph over Plcx.Fkp.papx
3862 if ( (aRes
.nFlags
& MAN_MASK_NEW_PAP
)|| rbStartLine
)
3864 ProcessAktCollChange( aRes
, &bStartAttr
,
3865 MAN_MASK_NEW_PAP
== (aRes
.nFlags
& MAN_MASK_NEW_PAP
) &&
3867 rbStartLine
= false;
3870 // position of last CP that's to be ignored
3873 if( 0 < aRes
.nSprmId
) // Ignore empty Attrs
3875 if( ( eFTN
> aRes
.nSprmId
) || ( 0x0800 <= aRes
.nSprmId
) )
3877 if( bStartAttr
) // WW attributes
3879 if( aRes
.nMemLen
>= 0 )
3880 ImportSprm(aRes
.pMemPos
, aRes
.nMemLen
, aRes
.nSprmId
);
3883 EndSprm( aRes
.nSprmId
); // Switch off Attr
3885 else if( aRes
.nSprmId
< 0x800 ) // Own helper attributes
3889 nSkipChars
= ImportExtSprm(&aRes
);
3891 (aRes
.nSprmId
== eFTN
) || (aRes
.nSprmId
== eEDN
) ||
3892 (aRes
.nSprmId
== eFLD
) || (aRes
.nSprmId
== eAND
)
3895 WW8_CP nMaxLegalSkip
= nTextEnd
- rTextPos
;
3896 // Skip Field/Footnote-/End-Note here
3897 rTextPos
+= std::min
<WW8_CP
>(nSkipChars
, nMaxLegalSkip
);
3898 nSkipPos
= rTextPos
-1;
3902 EndExtSprm( aRes
.nSprmId
);
3906 sal_Int32 nRequestedPos
= m_pSBase
->WW8Cp2Fc(m_pPlcxMan
->GetCpOfs() + rTextPos
, &m_bIsUnicode
);
3907 bool bValidPos
= checkSeek(*m_pStrm
, nRequestedPos
);
3908 SAL_WARN_IF(!bValidPos
, "sw.ww8", "Document claimed to have text at an invalid position, skip attributes for region");
3910 // Find next Attr position (and Skip attributes of field contents if needed)
3911 if (nSkipChars
&& !m_bIgnoreText
)
3912 m_pCtrlStck
->MarkAllAttrsOld();
3913 bool bOldIgnoreText
= m_bIgnoreText
;
3914 m_bIgnoreText
= true;
3915 sal_uInt16 nOldColl
= m_nAktColl
;
3916 bool bDoPlcxManPlusPLus
= true;
3920 if( bDoPlcxManPlusPLus
)
3921 m_pPlcxMan
->advance();
3922 nNext
= bValidPos
? m_pPlcxMan
->Where() : nTextEnd
;
3924 if (m_pPostProcessAttrsInfo
&&
3925 m_pPostProcessAttrsInfo
->mnCpStart
== nNext
)
3927 m_pPostProcessAttrsInfo
->mbCopy
= true;
3930 if( (0 <= nNext
) && (nSkipPos
>= nNext
) )
3932 nNext
= ReadTextAttr(rTextPos
, nTextEnd
, rbStartLine
);
3933 bDoPlcxManPlusPLus
= false;
3934 m_bIgnoreText
= true;
3937 if (m_pPostProcessAttrsInfo
&&
3938 nNext
> m_pPostProcessAttrsInfo
->mnCpEnd
)
3940 m_pPostProcessAttrsInfo
->mbCopy
= false;
3943 while( nSkipPos
>= nNext
);
3944 m_bIgnoreText
= bOldIgnoreText
;
3947 m_pCtrlStck
->KillUnlockedAttrs( *m_pPaM
->GetPoint() );
3948 if( nOldColl
!= m_pPlcxMan
->GetColl() )
3949 ProcessAktCollChange(aRes
, nullptr, false);
3955 //Revised 2012.8.16 for the complex attribute presentation of 0x0D in MS
3956 bool SwWW8ImplReader::IsParaEndInCPs(sal_Int32 nStart
, sal_Int32 nEnd
,bool bSdOD
) const
3958 //Revised for performance consideration
3959 if (nStart
== -1 || nEnd
== -1 || nEnd
< nStart
)
3962 for (cp_vector::const_reverse_iterator aItr
= m_aEndParaPos
.rbegin(); aItr
!= m_aEndParaPos
.rend(); ++aItr
)
3964 //Revised 2012.8.16,to the 0x0D,the attribute will have two situations
3965 //*********within***********exact******
3966 //*********but also sample with only left and the position of 0x0d is the edge of the right side***********
3967 if ( bSdOD
&& ( (nStart
< *aItr
&& nEnd
> *aItr
) || ( nStart
== nEnd
&& *aItr
== nStart
)) )
3969 else if ( !bSdOD
&& (nStart
< *aItr
&& nEnd
>= *aItr
) )
3976 //Clear the para end position recorded in reader intermittently for the least impact on loading performance
3977 void SwWW8ImplReader::ClearParaEndPosition()
3979 if ( m_aEndParaPos
.size() > 0 )
3980 m_aEndParaPos
.clear();
3983 void SwWW8ImplReader::ReadAttrs(WW8_CP
& rTextPos
, WW8_CP
& rNext
, long nTextEnd
, bool& rbStartLine
)
3985 // Dow we have attributes?
3986 if( rTextPos
>= rNext
)
3990 m_aCurrAttrCP
= rTextPos
;
3991 rNext
= ReadTextAttr(rTextPos
, nTextEnd
, rbStartLine
);
3992 if (rTextPos
== rNext
&& rTextPos
>= nTextEnd
)
3995 while( rTextPos
>= rNext
);
3998 else if ( rbStartLine
)
4000 /* No attributes, but still a new line.
4001 * If a line ends with a line break and paragraph attributes or paragraph templates
4002 * do NOT change the line end was not added to the Plcx.Fkp.papx i.e. (nFlags & MAN_MASK_NEW_PAP)
4004 * Due to this we need to set the template here as a kind of special treatment.
4006 if (!m_bCpxStyle
&& m_nAktColl
< m_vColl
.size())
4007 SetTextFormatCollAndListLevel(*m_pPaM
, m_vColl
[m_nAktColl
]);
4008 rbStartLine
= false;
4013 * CloseAttrEnds to only read the attribute ends at the end of a text or a
4014 * text area (Header, Footnote, ...).
4015 * We ignore attribute starts and fields.
4017 void SwWW8ImplReader::CloseAttrEnds()
4019 // If there are any unclosed sprms then copy them to
4020 // another stack and close the ones that must be closed
4021 std::stack
<sal_uInt16
> aStack
;
4022 m_pPlcxMan
->TransferOpenSprms(aStack
);
4024 while (!aStack
.empty())
4026 sal_uInt16 nSprmId
= aStack
.top();
4027 if ((0 < nSprmId
) && (( eFTN
> nSprmId
) || (0x0800 <= nSprmId
)))
4035 bool SwWW8ImplReader::ReadText(WW8_CP nStartCp
, WW8_CP nTextLen
, ManTypes nType
)
4039 bool bStartLine
= true;
4041 short nDistance
= 0;
4043 m_bWasParaEnd
= false;
4045 m_pAktItemSet
= nullptr;
4048 m_bPgSecBreak
= false;
4050 m_pPlcxMan
= new WW8PLCFMan( m_pSBase
, nType
, nStartCp
);
4051 long nCpOfs
= m_pPlcxMan
->GetCpOfs(); // Offset for Header/Footer, Footnote
4053 WW8_CP nNext
= m_pPlcxMan
->Where();
4054 m_pPreviousNode
= nullptr;
4055 sal_uInt8 nDropLines
= 0;
4056 SwCharFormat
* pNewSwCharFormat
= nullptr;
4057 const SwCharFormat
* pFormat
= nullptr;
4058 m_pStrm
->Seek( m_pSBase
->WW8Cp2Fc( nStartCp
+ nCpOfs
, &m_bIsUnicode
) );
4060 WW8_CP l
= nStartCp
;
4061 const WW8_CP nMaxPossible
= WW8_CP_MAX
-nStartCp
;
4062 if (nTextLen
> nMaxPossible
)
4064 SAL_WARN_IF(nTextLen
> nMaxPossible
, "sw.ww8", "TextLen too long");
4065 nTextLen
= nMaxPossible
;
4067 WW8_CP nTextEnd
= nStartCp
+nTextLen
;
4068 while (l
< nTextEnd
)
4070 ReadAttrs( l
, nNext
, nTextEnd
, bStartLine
);// Takes SectionBreaks into account, too
4071 OSL_ENSURE(m_pPaM
->GetNode().GetTextNode(), "Missing txtnode");
4073 if (m_pPostProcessAttrsInfo
!= nullptr)
4079 bStartLine
= ReadChars(l
, nNext
, nTextEnd
, nCpOfs
);
4081 // If the previous paragraph was a dropcap then do not
4082 // create a new txtnode and join the two paragraphs together
4083 if (bStartLine
&& !m_pPreviousNode
) // Line end
4086 if (m_bCareFirstParaEndInToc
)
4088 m_bCareFirstParaEndInToc
= false;
4089 if (m_pPaM
->End() && m_pPaM
->End()->nNode
.GetNode().GetTextNode() && m_pPaM
->End()->nNode
.GetNode().GetTextNode()->Len() == 0)
4092 if (m_bCareLastParaEndInToc
)
4094 m_bCareLastParaEndInToc
= false;
4095 if (m_pPaM
->End() && m_pPaM
->End()->nNode
.GetNode().GetTextNode() && m_pPaM
->End()->nNode
.GetNode().GetTextNode()->Len() == 0)
4100 // We will record the CP of a paragraph end ('0x0D'), if current loading contents is from main stream;
4101 if (m_bOnLoadingMain
)
4102 m_aEndParaPos
.push_back(l
-1);
4103 AppendTextNode(*m_pPaM
->GetPoint());
4107 if (m_pPreviousNode
&& bStartLine
)
4109 SwTextNode
* pEndNd
= m_pPaM
->GetNode().GetTextNode();
4110 const sal_Int32 nDropCapLen
= m_pPreviousNode
->GetText().getLength();
4112 // Need to reset the font size and text position for the dropcap
4114 SwPaM
aTmp(*pEndNd
, 0, *pEndNd
, nDropCapLen
+1);
4115 m_pCtrlStck
->Delete(aTmp
);
4118 // Get the default document dropcap which we can use as our template
4119 const SwFormatDrop
* defaultDrop
=
4120 static_cast<const SwFormatDrop
*>( GetFormatAttr(RES_PARATR_DROP
));
4121 SwFormatDrop
aDrop(*defaultDrop
);
4123 aDrop
.GetLines() = nDropLines
;
4124 aDrop
.GetDistance() = nDistance
;
4125 aDrop
.GetChars() = writer_cast
<sal_uInt8
>(nDropCapLen
);
4126 // Word has no concept of a "whole word dropcap"
4127 aDrop
.GetWholeWord() = false;
4130 aDrop
.SetCharFormat(const_cast<SwCharFormat
*>(pFormat
));
4131 else if(pNewSwCharFormat
)
4132 aDrop
.SetCharFormat(pNewSwCharFormat
);
4134 SwPosition
aStart(*pEndNd
);
4135 m_pCtrlStck
->NewAttr(aStart
, aDrop
);
4136 m_pCtrlStck
->SetAttr(*m_pPaM
->GetPoint(), RES_PARATR_DROP
);
4137 m_pPreviousNode
= nullptr;
4139 else if (m_bDropCap
)
4141 // If we have found a dropcap store the textnode
4142 m_pPreviousNode
= m_pPaM
->GetNode().GetTextNode();
4144 const sal_uInt8
*pDCS
;
4147 pDCS
= m_pPlcxMan
->GetPapPLCF()->HasSprm(46);
4149 pDCS
= m_pPlcxMan
->GetPapPLCF()->HasSprm(0x442C);
4152 nDropLines
= (*pDCS
) >> 3;
4153 else // There is no Drop Cap Specifier hence no dropcap
4154 m_pPreviousNode
= nullptr;
4156 if (const sal_uInt8
*pDistance
= m_pPlcxMan
->GetPapPLCF()->HasSprm(0x842F))
4157 nDistance
= SVBT16ToShort( pDistance
);
4161 const SwFormatCharFormat
*pSwFormatCharFormat
= nullptr;
4164 pSwFormatCharFormat
= &(ItemGet
<SwFormatCharFormat
>(*m_pAktItemSet
, RES_TXTATR_CHARFMT
));
4166 if(pSwFormatCharFormat
)
4167 pFormat
= pSwFormatCharFormat
->GetCharFormat();
4169 if(m_pAktItemSet
&& !pFormat
)
4171 OUString
sPrefix(OUStringBuffer("WW8Dropcap").append(m_nDropCap
++).makeStringAndClear());
4172 pNewSwCharFormat
= m_rDoc
.MakeCharFormat(sPrefix
, m_rDoc
.GetDfltCharFormat());
4173 m_pAktItemSet
->ClearItem(RES_CHRATR_ESCAPEMENT
);
4174 pNewSwCharFormat
->SetFormatAttr( *m_pAktItemSet
);
4177 delete m_pAktItemSet
;
4178 m_pAktItemSet
= nullptr;
4182 if (bStartLine
|| m_bWasTabRowEnd
)
4184 // Call all 64 CRs; not for Header and the like
4185 if ((nCrCount
++ & 0x40) == 0 && nType
== MAN_MAINTEXT
)
4187 m_nProgress
= (sal_uInt16
)( l
* 100 / nTextLen
);
4188 ::SetProgressState(m_nProgress
, m_pDocShell
); // Update
4192 // If we have encountered a 0x0c which indicates either section of
4193 // pagebreak then look it up to see if it is a section break, and
4194 // if it is not then insert a page break. If it is a section break
4195 // it will be handled as such in the ReadAttrs of the next loop
4198 // We need only to see if a section is ending at this cp,
4199 // the plcf will already be sitting on the correct location
4202 aTemp
.nStartPos
= aTemp
.nEndPos
= WW8_CP_MAX
;
4203 if (m_pPlcxMan
->GetSepPLCF())
4204 m_pPlcxMan
->GetSepPLCF()->GetSprms(&aTemp
);
4205 if ((aTemp
.nStartPos
!= l
) && (aTemp
.nEndPos
!= l
))
4207 // #i39251# - insert text node for page break, if no one inserted.
4208 // #i43118# - refine condition: the anchor
4209 // control stack has to have entries, otherwise it's not needed
4210 // to insert a text node.
4211 if (!bStartLine
&& !m_pAnchorStck
->empty())
4213 AppendTextNode(*m_pPaM
->GetPoint());
4215 m_rDoc
.getIDocumentContentOperations().InsertPoolItem(*m_pPaM
,
4216 SvxFormatBreakItem(SvxBreak::PageBefore
, RES_BREAK
));
4217 m_bFirstParaOfPage
= true;
4218 m_bPgSecBreak
= false;
4223 m_pPreviousNode
= nullptr;
4225 if (m_pPaM
->GetPoint()->nContent
.GetIndex())
4226 AppendTextNode(*m_pPaM
->GetPoint());
4228 if (!m_bInHyperlink
)
4229 bJoined
= JoinNode(*m_pPaM
);
4234 m_pPlcxMan
= nullptr;
4238 SwWW8ImplReader::SwWW8ImplReader(sal_uInt8 nVersionPara
, SotStorage
* pStorage
,
4239 SvStream
* pSt
, SwDoc
& rD
, const OUString
& rBaseURL
, bool bNewDoc
, bool bSkipImages
, SwPosition
&rPos
)
4240 : m_pDocShell(rD
.GetDocShell())
4243 , m_pTableStream(nullptr)
4244 , m_pDataStream(nullptr)
4247 , m_pCtrlStck(nullptr)
4248 , m_pRedlineStack(nullptr)
4249 , m_pReffedStck(nullptr)
4250 , m_pReffingStck(nullptr)
4251 , m_pAnchorStck(nullptr)
4252 , m_aSectionManager(*this)
4253 , m_aExtraneousParas(rD
)
4254 , m_aInsertedTables(rD
)
4255 , m_aSectionNameGenerator(rD
, OUString("WW"))
4256 , m_pSprmParser(nullptr)
4257 , m_aGrfNameGenerator(bNewDoc
, OUString('G'))
4258 , m_aParaStyleMapper(rD
)
4259 , m_aCharStyleMapper(rD
)
4260 , m_pFormImpl(nullptr)
4261 , m_pFlyFormatOfJustInsertedGraphic(nullptr)
4262 , m_pFormatOfJustInsertedApo(nullptr)
4263 , m_pPreviousNumPaM(nullptr)
4264 , m_pPrevNumRule(nullptr)
4265 , m_pPostProcessAttrsInfo(nullptr)
4269 , m_pLstManager(nullptr)
4271 , m_pPlcxMan(nullptr)
4272 , m_aTextNodesHavingFirstLineOfstSet()
4273 , m_aTextNodesHavingLeftIndentSet()
4274 , m_pStyles(nullptr)
4275 , m_pAktColl(nullptr)
4276 , m_pAktItemSet(nullptr)
4277 , m_pDfltTextFormatColl(nullptr)
4278 , m_pStandardFormatColl(nullptr)
4280 , m_pWFlyPara(nullptr)
4281 , m_pSFlyPara(nullptr)
4282 , m_pTableDesc(nullptr)
4283 , m_pNumOlst(nullptr)
4284 , m_pDrawModel(nullptr)
4285 , m_pDrawPg(nullptr)
4286 , m_pDrawEditEngine(nullptr)
4287 , m_pWWZOrder(nullptr)
4288 , m_pNumFieldType(nullptr)
4289 , m_pMSDffManager(nullptr)
4290 , m_pAtnNames(nullptr)
4291 , m_sBaseURL(rBaseURL
)
4295 , m_bRegardHindiDigits( false )
4296 , m_bDrawCpOValid( false )
4302 , m_eTextCharSet(RTL_TEXTENCODING_ASCII_US
)
4303 , m_eStructCharSet(RTL_TEXTENCODING_ASCII_US
)
4304 , m_eHardCharSet(RTL_TEXTENCODING_DONTKNOW
)
4308 , m_nLFOPosition(USHRT_MAX
)
4315 , m_nWantedVersion(nVersionPara
)
4316 , m_nSwNumLevel(0xff)
4317 , m_nWwNumType(0xff)
4318 , m_nListLevel(WW8ListManager::nMaxLevel
)
4319 , m_bNewDoc(bNewDoc
)
4320 , m_bSkipImages(bSkipImages
)
4321 , m_bReadNoTable(false)
4322 , m_bPgSecBreak(false)
4325 , m_bTxbxFlySection(false)
4326 , m_bHasBorder(false)
4328 , m_bIgnoreText(false)
4330 , m_bWasTabRowEnd(false)
4331 , m_bWasTabCellEnd(false)
4333 , m_bHdFtFootnoteEdn(false)
4334 , m_bFootnoteEdn(false)
4335 , m_bIsHeader(false)
4336 , m_bIsFooter(false)
4337 , m_bIsUnicode(false)
4338 , m_bCpxStyle(false)
4339 , m_bStyNormal(false)
4340 , m_bWWBugNormal(false)
4341 , m_bNoAttrImport(false)
4342 , m_bInHyperlink(false)
4343 , m_bWasParaEnd(false)
4348 , m_bEmbeddObj(false)
4349 , m_bAktAND_fNumberAcross(false)
4350 , m_bNoLnNumYet(true)
4351 , m_bFirstPara(true)
4352 , m_bFirstParaOfPage(false)
4353 , m_bParaAutoBefore(false)
4354 , m_bParaAutoAfter(false)
4358 , m_bReadTable(false)
4359 , m_bLoadingTOXCache(false)
4360 , m_nEmbeddedTOXLevel(0)
4361 , m_bLoadingTOXHyperlink(false)
4362 , m_pPosAfterTOC(nullptr)
4363 , m_pPreviousNode(nullptr)
4364 , m_bCareFirstParaEndInToc(false)
4365 , m_bCareLastParaEndInToc(false)
4368 , m_bOnLoadingMain(false)
4370 m_pStrm
->SetEndian( SvStreamEndian::LITTLE
);
4371 m_aApos
.push_back(false);
4373 mpCursor
= m_rDoc
.CreateUnoCursor(rPos
);
4376 void SwWW8ImplReader::DeleteStack(SwFltControlStack
* pStck
)
4380 pStck
->SetAttr( *m_pPaM
->GetPoint(), 0, false);
4381 pStck
->SetAttr( *m_pPaM
->GetPoint(), 0, false);
4386 OSL_ENSURE( false, "WW-Stack bereits geloescht" );
4390 void wwSectionManager::SetSegmentToPageDesc(const wwSection
&rSection
,
4393 SwPageDesc
&rPage
= *rSection
.mpPage
;
4395 SetNumberingType(rSection
, rPage
);
4397 SwFrameFormat
&rFormat
= rPage
.GetMaster();
4399 if(mrReader
.m_pWDop
->fUseBackGroundInAllmodes
) // #i56806# Make sure mrReader is initialized
4400 mrReader
.GrafikCtor();
4402 if (mrReader
.m_pWDop
->fUseBackGroundInAllmodes
&& mrReader
.m_pMSDffManager
)
4404 Rectangle
aRect(0, 0, 100, 100); // A dummy, we don't care about the size
4405 SvxMSDffImportData
aData(aRect
);
4406 SdrObject
* pObject
= nullptr;
4407 if (mrReader
.m_pMSDffManager
->GetShape(0x401, pObject
, aData
) && !aData
.empty())
4409 // Only handle shape if it is a background shape
4410 if (((*aData
.begin())->nFlags
& 0x400) != 0)
4412 SfxItemSet
aSet(rFormat
.GetAttrSet());
4413 mrReader
.MatchSdrItemsIntoFlySet(pObject
, aSet
, mso_lineSimple
,
4414 mso_lineSolid
, mso_sptRectangle
, aRect
);
4415 rFormat
.SetFormatAttr(aSet
.Get(RES_BACKGROUND
));
4418 SdrObject::Free(pObject
);
4420 wwULSpaceData aULData
;
4421 GetPageULData(rSection
, aULData
);
4422 SetPageULSpaceItems(rFormat
, aULData
, rSection
);
4424 rPage
.SetVerticalAdjustment( rSection
.mnVerticalAdjustment
);
4426 SetPage(rPage
, rFormat
, rSection
, bIgnoreCols
);
4428 if (!(rSection
.maSep
.pgbApplyTo
& 1))
4429 SwWW8ImplReader::SetPageBorder(rFormat
, rSection
);
4430 if (!(rSection
.maSep
.pgbApplyTo
& 2))
4431 SwWW8ImplReader::SetPageBorder(rPage
.GetFirstMaster(), rSection
);
4433 mrReader
.SetDocumentGrid(rFormat
, rSection
);
4436 void wwSectionManager::SetUseOn(wwSection
&rSection
)
4438 bool bMirror
= mrReader
.m_pWDop
->fMirrorMargins
||
4439 mrReader
.m_pWDop
->doptypography
.f2on1
;
4441 UseOnPage eUseBase
= bMirror
? UseOnPage::Mirror
: UseOnPage::All
;
4442 UseOnPage eUse
= eUseBase
;
4443 if (!mrReader
.m_pWDop
->fFacingPages
)
4444 eUse
|= UseOnPage::HeaderShare
| UseOnPage::FooterShare
;
4445 if (!rSection
.HasTitlePage())
4446 eUse
|= UseOnPage::FirstShare
;
4448 OSL_ENSURE(rSection
.mpPage
, "Makes no sense to call me with no pages to set");
4449 if (rSection
.mpPage
)
4450 rSection
.mpPage
->WriteUseOn(eUse
);
4454 * Set the page descriptor on this node, handle the different cases for a text
4457 void GiveNodePageDesc(SwNodeIndex
&rIdx
, const SwFormatPageDesc
&rPgDesc
,
4461 If it's a table here, apply the pagebreak to the table
4462 properties, otherwise we add it to the para at this
4465 if (rIdx
.GetNode().IsTableNode())
4468 rIdx
.GetNode().GetTableNode()->GetTable();
4469 SwFrameFormat
* pApply
= rTable
.GetFrameFormat();
4470 OSL_ENSURE(pApply
, "impossible");
4472 pApply
->SetFormatAttr(rPgDesc
);
4476 SwPosition
aPamStart(rIdx
);
4477 aPamStart
.nContent
.Assign(
4478 rIdx
.GetNode().GetContentNode(), 0);
4479 SwPaM
aPage(aPamStart
);
4481 rDoc
.getIDocumentContentOperations().InsertPoolItem(aPage
, rPgDesc
);
4486 * Map a word section to a writer page descriptor
4488 SwFormatPageDesc
wwSectionManager::SetSwFormatPageDesc(mySegIter
&rIter
,
4489 mySegIter
&rStart
, bool bIgnoreCols
)
4491 if (mrReader
.m_bNewDoc
&& rIter
== rStart
)
4494 mrReader
.m_rDoc
.getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_STANDARD
);
4498 rIter
->mpPage
= mrReader
.m_rDoc
.MakePageDesc(
4499 SwViewShell::GetShellRes()->GetPageDescName(mnDesc
, ShellResource::NORMAL_PAGE
),
4502 OSL_ENSURE(rIter
->mpPage
, "no page!");
4504 return SwFormatPageDesc();
4506 // Set page before hd/ft
4507 const wwSection
*pPrevious
= nullptr;
4508 if (rIter
!= rStart
)
4509 pPrevious
= &(*(rIter
-1));
4510 SetHdFt(*rIter
, std::distance(rStart
, rIter
), pPrevious
);
4513 // Set hd/ft after set page
4514 SetSegmentToPageDesc(*rIter
, bIgnoreCols
);
4516 SwFormatPageDesc
aRet(rIter
->mpPage
);
4518 rIter
->mpPage
->SetFollow(rIter
->mpPage
);
4520 if (rIter
->PageRestartNo())
4521 aRet
.SetNumOffset(rIter
->PageStartAt());
4527 void wwSectionManager::InsertSegments()
4529 const SvtFilterOptions
& rOpt
= SvtFilterOptions::Get();
4530 bool bUseEnhFields
= rOpt
.IsUseEnhancedFields();
4531 mySegIter aEnd
= maSegments
.end();
4532 mySegIter aStart
= maSegments
.begin();
4533 for (mySegIter aIter
= aStart
; aIter
!= aEnd
; ++aIter
)
4535 // If the section is of type "New column" (0x01), then simply insert a column break.
4536 // But only if there actually are columns on the page, otherwise a column break
4537 // seems to be handled like a page break by MSO.
4538 if ( aIter
->maSep
.bkc
== 1 && aIter
->maSep
.ccolM1
> 0 )
4540 SwPaM
start( aIter
->maStart
);
4541 mrReader
.m_rDoc
.getIDocumentContentOperations().InsertPoolItem( start
, SvxFormatBreakItem(SvxBreak::ColumnBefore
, RES_BREAK
));
4545 mySegIter aNext
= aIter
+1;
4546 mySegIter aPrev
= (aIter
== aStart
) ? aIter
: aIter
-1;
4548 // If two following sections are different in following properties, Word will interprete a continuous
4549 // section break between them as if it was a section break next page.
4550 bool bThisAndPreviousAreCompatible
= ((aIter
->GetPageWidth() == aPrev
->GetPageWidth()) &&
4551 (aIter
->GetPageHeight() == aPrev
->GetPageHeight()) && (aIter
->IsLandScape() == aPrev
->IsLandScape()));
4553 bool bInsertSection
= (aIter
!= aStart
) && aIter
->IsContinuous() && bThisAndPreviousAreCompatible
;
4554 bool bInsertPageDesc
= !bInsertSection
;
4555 // HACK Force new pagedesc if margins change, otherwise e.g. floating tables may be anchored improperly.
4556 if( aIter
->maSep
.dyaTop
!= aPrev
->maSep
.dyaTop
|| aIter
->maSep
.dyaBottom
!= aPrev
->maSep
.dyaBottom
4557 || aIter
->maSep
.dxaLeft
!= aPrev
->maSep
.dxaLeft
|| aIter
->maSep
.dxaRight
!= aPrev
->maSep
.dxaRight
)
4558 bInsertPageDesc
= true;
4559 bool bProtected
= SectionIsProtected(*aIter
); // do we really need this ?? I guess I have a different logic in editshell which disables this...
4560 if (bUseEnhFields
&& mrReader
.m_pWDop
->fProtEnabled
&& aIter
->IsNotProtected())
4562 // here we have the special case that the whole document is protected, with the exception of this section.
4563 // I want to address this when I do the section rework, so for the moment we disable the overall protection then...
4564 mrReader
.m_rDoc
.getIDocumentSettingAccess().set(DocumentSettingId::PROTECT_FORM
, false );
4567 if (bInsertPageDesc
)
4570 If a cont section follows this section then we won't be
4571 creating a page desc with 2+ cols as we cannot host a one
4572 col section in a 2+ col pagedesc and make it look like
4573 word. But if the current section actually has columns then
4574 we are forced to insert a section here as well as a page
4578 bool bIgnoreCols
= false;
4579 bool bThisAndNextAreCompatible
= (aNext
== aEnd
) ||
4580 ((aIter
->GetPageWidth() == aNext
->GetPageWidth()) &&
4581 (aIter
->GetPageHeight() == aNext
->GetPageHeight()) &&
4582 (aIter
->IsLandScape() == aNext
->IsLandScape()));
4584 if (((aNext
!= aEnd
&& aNext
->IsContinuous() && bThisAndNextAreCompatible
) || bProtected
))
4587 if ((aIter
->NoCols() > 1) || bProtected
)
4588 bInsertSection
= true;
4591 SwFormatPageDesc
aDesc(SetSwFormatPageDesc(aIter
, aStart
, bIgnoreCols
));
4592 if (!aDesc
.GetPageDesc())
4595 // special case handling for odd/even section break
4596 // a) as before create a new page style for the section break
4597 // b) set Layout of generated page style to right/left ( according
4598 // to section break odd/even )
4599 // c) create a new style to follow the break page style
4600 if ( aIter
->maSep
.bkc
== 3 || aIter
->maSep
.bkc
== 4 )
4602 // SetSwFormatPageDesc calls some methods that could
4603 // modify aIter (e.g. wwSection ).
4604 // Since we call SetSwFormatPageDesc below to generate the
4605 // 'Following' style of the Break style, it is safer
4606 // to take a copy of the contents of aIter.
4607 wwSection aTmpSection
= *aIter
;
4608 // create a new following page style
4609 SwFormatPageDesc
aFollow(SetSwFormatPageDesc(aIter
, aStart
, bIgnoreCols
));
4610 // restore any contents of aIter trashed by SetSwFormatPageDesc
4611 *aIter
= aTmpSection
;
4613 // Handle the section break
4614 UseOnPage eUseOnPage
= UseOnPage::Left
;
4615 if ( aIter
->maSep
.bkc
== 4 ) // Odd ( right ) Section break
4616 eUseOnPage
= UseOnPage::Right
;
4618 // Keep the share flags.
4619 aDesc
.GetPageDesc()->SetUseOn( eUseOnPage
);
4620 aDesc
.GetPageDesc()->SetFollow( aFollow
.GetPageDesc() );
4623 GiveNodePageDesc(aIter
->maStart
, aDesc
, mrReader
.m_rDoc
);
4626 SwTextNode
* pTextNd
= nullptr;
4629 // Start getting the bounds of this section
4630 SwPaM
aSectPaM(*mrReader
.m_pPaM
, mrReader
.m_pPaM
);
4631 SwNodeIndex
aAnchor(aSectPaM
.GetPoint()->nNode
);
4634 aAnchor
= aNext
->maStart
;
4635 aSectPaM
.GetPoint()->nNode
= aAnchor
;
4636 aSectPaM
.GetPoint()->nContent
.Assign(
4637 aNext
->maStart
.GetNode().GetContentNode(), 0);
4638 aSectPaM
.Move(fnMoveBackward
);
4641 const SwPosition
* pPos
= aSectPaM
.GetPoint();
4642 SwTextNode
const*const pSttNd
= pPos
->nNode
.GetNode().GetTextNode();
4643 const SwTableNode
* pTableNd
= pSttNd
? pSttNd
->FindTableNode() : nullptr;
4647 mrReader
.m_rDoc
.GetNodes().MakeTextNode(aAnchor
,
4648 mrReader
.m_rDoc
.getIDocumentStylePoolAccess().GetTextCollFromPool( RES_POOLCOLL_TEXT
));
4650 aSectPaM
.GetPoint()->nNode
.Assign(*pTextNd
);
4651 aSectPaM
.GetPoint()->nContent
.Assign(
4652 aSectPaM
.GetContentNode(), 0);
4657 aSectPaM
.GetPoint()->nNode
= aIter
->maStart
;
4658 aSectPaM
.GetPoint()->nContent
.Assign(
4659 aSectPaM
.GetContentNode(), 0);
4661 bool bHasOwnHdFt
= false;
4663 In this nightmare scenario the continuous section has its own
4664 headers and footers so we will try and find a hard page break
4665 between here and the end of the section and put the headers and
4668 if (!bInsertPageDesc
)
4671 mrReader
.HasOwnHeaderFooter(
4672 aIter
->maSep
.grpfIhdt
& ~(WW8_HEADER_FIRST
| WW8_FOOTER_FIRST
),
4673 aIter
->maSep
.grpfIhdt
, std::distance(aStart
, aIter
)
4678 // #i40766# Need to cache the page descriptor in case there is
4679 // no page break in the section
4680 SwPageDesc
*pOrig
= aIter
->mpPage
;
4681 bool bFailed
= true;
4682 SwFormatPageDesc
aDesc(SetSwFormatPageDesc(aIter
, aStart
, true));
4683 if (aDesc
.GetPageDesc())
4685 sal_uLong nStart
= aSectPaM
.Start()->nNode
.GetIndex();
4686 sal_uLong nEnd
= aSectPaM
.End()->nNode
.GetIndex();
4687 for(; nStart
<= nEnd
; ++nStart
)
4689 SwNode
* pNode
= mrReader
.m_rDoc
.GetNodes()[nStart
];
4692 if (sw::util::HasPageBreak(*pNode
))
4694 SwNodeIndex
aIdx(*pNode
);
4695 GiveNodePageDesc(aIdx
, aDesc
, mrReader
.m_rDoc
);
4703 aIter
->mpPage
= pOrig
;
4707 // End getting the bounds of this section, quite a job eh?
4708 SwSectionFormat
*pRet
= InsertSection(aSectPaM
, *aIter
);
4709 // The last section if continuous is always unbalanced
4712 // Set the columns to be UnBalanced if that compatibility option is set
4713 if (mrReader
.m_pWDop
->fNoColumnBalance
)
4714 pRet
->SetFormatAttr(SwFormatNoBalancedColumns(true));
4717 // Otherwise set to unbalanced if the following section is
4718 // not continuous, (which also means that the last section
4720 if (aNext
== aEnd
|| !aNext
->IsContinuous())
4721 pRet
->SetFormatAttr(SwFormatNoBalancedColumns(true));
4728 SwNodeIndex
aIdx(*pTextNd
);
4730 mrReader
.m_rDoc
.getIDocumentContentOperations().DelFullPara(aTest
);
4736 void wwExtraneousParas::delete_all_from_doc()
4738 auto aEnd
= m_aTextNodes
.rend();
4739 for (auto aI
= m_aTextNodes
.rbegin(); aI
!= aEnd
; ++aI
)
4741 SwTextNode
*pTextNode
= *aI
;
4742 SwNodeIndex
aIdx(*pTextNode
);
4744 m_rDoc
.getIDocumentContentOperations().DelFullPara(aTest
);
4746 m_aTextNodes
.clear();
4749 void SwWW8ImplReader::StoreMacroCmds()
4751 if (m_pWwFib
->m_lcbCmds
)
4753 m_pTableStream
->Seek(m_pWwFib
->m_fcCmds
);
4755 uno::Reference
< embed::XStorage
> xRoot(m_pDocShell
->GetStorage());
4762 uno::Reference
< io::XStream
> xStream
=
4763 xRoot
->openStreamElement( SL::aMSMacroCmds
, embed::ElementModes::READWRITE
);
4764 std::unique_ptr
<SvStream
> xOutStream(::utl::UcbStreamHelper::CreateStream(xStream
));
4766 sal_uInt32 lcbCmds
= std::min
<sal_uInt32
>(m_pWwFib
->m_lcbCmds
, m_pTableStream
->remainingSize());
4767 std::unique_ptr
<sal_uInt8
[]> xBuffer(new sal_uInt8
[lcbCmds
]);
4768 m_pWwFib
->m_lcbCmds
= m_pTableStream
->ReadBytes(xBuffer
.get(), lcbCmds
);
4769 xOutStream
->WriteBytes(xBuffer
.get(), m_pWwFib
->m_lcbCmds
);
4777 void SwWW8ImplReader::ReadDocVars()
4779 std::vector
<OUString
> aDocVarStrings
;
4780 std::vector
<ww::bytes
> aDocVarStringIds
;
4781 std::vector
<OUString
> aDocValueStrings
;
4782 WW8ReadSTTBF(!m_bVer67
, *m_pTableStream
, m_pWwFib
->m_fcStwUser
,
4783 m_pWwFib
->m_lcbStwUser
, m_bVer67
? 2 : 0, m_eStructCharSet
,
4784 aDocVarStrings
, &aDocVarStringIds
, &aDocValueStrings
);
4786 using namespace ::com::sun::star
;
4788 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
4789 m_pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
4790 uno::Reference
<document::XDocumentProperties
> xDocProps(
4791 xDPS
->getDocumentProperties());
4792 OSL_ENSURE(xDocProps
.is(), "DocumentProperties is null");
4793 uno::Reference
<beans::XPropertyContainer
> xUserDefinedProps
=
4794 xDocProps
->getUserDefinedProperties();
4795 OSL_ENSURE(xUserDefinedProps
.is(), "UserDefinedProperties is null");
4797 for(size_t i
=0; i
<aDocVarStrings
.size(); i
++)
4799 const OUString
&rName
= aDocVarStrings
[i
];
4801 aValue
<<= OUString(aDocValueStrings
[i
]);
4803 xUserDefinedProps
->addProperty( rName
,
4804 beans::PropertyAttribute::REMOVABLE
,
4806 } catch (const uno::Exception
&) {
4816 void SwWW8ImplReader::ReadDocInfo()
4820 uno::Reference
<document::XDocumentPropertiesSupplier
> xDPS(
4821 m_pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
4822 uno::Reference
<document::XDocumentProperties
> xDocProps(
4823 xDPS
->getDocumentProperties());
4824 OSL_ENSURE(xDocProps
.is(), "DocumentProperties is null");
4826 if (xDocProps
.is()) {
4827 if ( m_pWwFib
->m_fDot
)
4829 OUString sTemplateURL
;
4830 SfxMedium
* pMedium
= m_pDocShell
->GetMedium();
4833 OUString aName
= pMedium
->GetName();
4834 INetURLObject
aURL( aName
);
4835 sTemplateURL
= aURL
.GetMainURL(INetURLObject::DecodeMechanism::ToIUri
);
4836 if ( !sTemplateURL
.isEmpty() )
4837 xDocProps
->setTemplateURL( sTemplateURL
);
4840 else if (m_pWwFib
->m_lcbSttbfAssoc
) // not a template, and has a SttbfAssoc
4842 long nCur
= m_pTableStream
->Tell();
4844 m_pTableStream
->Seek( m_pWwFib
->m_fcSttbfAssoc
); // point at tgc record
4845 if (!aSttb
.Read( *m_pTableStream
) )
4846 OSL_TRACE("** Read of SttbAssoc data failed!!!! ");
4847 m_pTableStream
->Seek( nCur
); // return to previous position, is that necessary?
4848 #if OSL_DEBUG_LEVEL > 1
4849 aSttb
.Print( stderr
);
4851 OUString sPath
= aSttb
.getStringAtIndex( 0x1 );
4853 // attempt to convert to url (won't work for obvious reasons on linux)
4854 if ( !sPath
.isEmpty() )
4855 osl::FileBase::getFileURLFromSystemPath( sPath
, aURL
);
4857 xDocProps
->setTemplateURL( aURL
);
4859 xDocProps
->setTemplateURL( sPath
);
4862 sfx2::LoadOlePropertySet(xDocProps
, m_pStg
);
4867 static void lcl_createTemplateToProjectEntry( const uno::Reference
< container::XNameContainer
>& xPrjNameCache
, const OUString
& sTemplatePathOrURL
, const OUString
& sVBAProjName
)
4869 if ( xPrjNameCache
.is() )
4872 aObj
.SetURL( sTemplatePathOrURL
);
4873 bool bIsURL
= aObj
.GetProtocol() != INetProtocol::NotValid
;
4876 aURL
= sTemplatePathOrURL
;
4879 osl::FileBase::getFileURLFromSystemPath( sTemplatePathOrURL
, aURL
);
4880 aObj
.SetURL( aURL
);
4884 OUString templateNameWithExt
= aObj
.GetLastName();
4885 OUString templateName
;
4886 sal_Int32 nIndex
= templateNameWithExt
.lastIndexOf( '.' );
4889 templateName
= templateNameWithExt
.copy( 0, nIndex
);
4890 xPrjNameCache
->insertByName( templateName
, uno::makeAny( sVBAProjName
) );
4893 catch( const uno::Exception
& )
4899 class WW8Customizations
4901 SvStream
* mpTableStream
;
4904 WW8Customizations( SvStream
*, WW8Fib
& );
4905 void Import( SwDocShell
* pShell
);
4908 WW8Customizations::WW8Customizations( SvStream
* pTableStream
, WW8Fib
& rFib
) : mpTableStream(pTableStream
), mWw8Fib( rFib
)
4912 void WW8Customizations::Import( SwDocShell
* pShell
)
4914 if ( mWw8Fib
.m_lcbCmds
== 0 || !IsEightPlus(mWw8Fib
.GetFIBVersion()) )
4919 long nCur
= mpTableStream
->Tell();
4920 mpTableStream
->Seek( mWw8Fib
.m_fcCmds
); // point at tgc record
4921 bool bReadResult
= aTCG
.Read( *mpTableStream
);
4922 mpTableStream
->Seek( nCur
); // return to previous position, is that necessary?
4925 SAL_WARN("sw.ww8", "** Read of Customization data failed!!!! ");
4928 #if OSL_DEBUG_LEVEL > 1
4929 aTCG
.Print( stderr
);
4931 aTCG
.ImportCustomToolBar( *pShell
);
4935 SAL_WARN("sw.ww8", "** Read of Customization data failed!!!! epically");
4939 void SwWW8ImplReader::ReadGlobalTemplateSettings( const OUString
& sCreatedFrom
, const uno::Reference
< container::XNameContainer
>& xPrjNameCache
)
4941 if (utl::ConfigManager::IsAvoidConfig())
4944 SvtPathOptions aPathOpt
;
4945 OUString aAddinPath
= aPathOpt
.GetAddinPath();
4946 uno::Sequence
< OUString
> sGlobalTemplates
;
4948 // first get the autoload addins in the directory STARTUP
4949 uno::Reference
<ucb::XSimpleFileAccess3
> xSFA(ucb::SimpleFileAccess::create(::comphelper::getProcessComponentContext()));
4951 if( xSFA
->isFolder( aAddinPath
) )
4952 sGlobalTemplates
= xSFA
->getFolderContents( aAddinPath
, false );
4954 sal_Int32 nEntries
= sGlobalTemplates
.getLength();
4955 for ( sal_Int32 i
=0; i
<nEntries
; ++i
)
4958 aObj
.SetURL( sGlobalTemplates
[ i
] );
4959 bool bIsURL
= aObj
.GetProtocol() != INetProtocol::NotValid
;
4962 aURL
= sGlobalTemplates
[ i
];
4964 osl::FileBase::getFileURLFromSystemPath( sGlobalTemplates
[ i
], aURL
);
4965 if ( !aURL
.endsWithIgnoreAsciiCase( ".dot" ) || ( !sCreatedFrom
.isEmpty() && sCreatedFrom
.equals( aURL
) ) )
4966 continue; // don't try and read the same document as ourselves
4968 tools::SvRef
<SotStorage
> rRoot
= new SotStorage( aURL
, StreamMode::STD_READWRITE
);
4970 BasicProjImportHelper
aBasicImporter( *m_pDocShell
);
4971 // Import vba via oox filter
4972 aBasicImporter
.import( m_pDocShell
->GetMedium()->GetInputStream() );
4973 lcl_createTemplateToProjectEntry( xPrjNameCache
, aURL
, aBasicImporter
.getProjectName() );
4974 // Read toolbars & menus
4975 tools::SvRef
<SotStorageStream
> refMainStream
= rRoot
->OpenSotStream( "WordDocument");
4976 refMainStream
->SetEndian(SvStreamEndian::LITTLE
);
4977 WW8Fib
aWwFib( *refMainStream
, 8 );
4978 tools::SvRef
<SotStorageStream
> xTableStream
= rRoot
->OpenSotStream(OUString::createFromAscii( aWwFib
.m_fWhichTableStm
? SL::a1Table
: SL::a0Table
), StreamMode::STD_READ
);
4980 if (xTableStream
.Is() && SVSTREAM_OK
== xTableStream
->GetError())
4982 xTableStream
->SetEndian(SvStreamEndian::LITTLE
);
4983 WW8Customizations
aGblCustomisations( xTableStream
.get(), aWwFib
);
4984 aGblCustomisations
.Import( m_pDocShell
);
4989 sal_uLong
SwWW8ImplReader::CoreLoad(WW8Glossary
*pGloss
)
4991 sal_uLong nErrRet
= 0;
4993 m_rDoc
.SetDocumentType( SwDoc::DOCTYPE_MSWORD
);
4994 if (m_bNewDoc
&& m_pStg
&& !pGloss
)
4996 // Initialize RDF metadata, to be able to add statements during the import.
4999 uno::Reference
<rdf::XDocumentMetadataAccess
> xDocumentMetadataAccess(m_rDoc
.GetDocShell()->GetBaseModel(), uno::UNO_QUERY_THROW
);
5000 uno::Reference
<uno::XComponentContext
> xComponentContext(comphelper::getProcessComponentContext());
5001 uno::Reference
<embed::XStorage
> xStorage
= comphelper::OStorageHelper::GetTemporaryStorage();
5002 const uno::Reference
<rdf::XURI
> xBaseURI(sfx2::createBaseURI(xComponentContext
, xStorage
, m_sBaseURL
));
5003 uno::Reference
<task::XInteractionHandler
> xHandler
;
5004 xDocumentMetadataAccess
->loadMetadataFromStorage(xStorage
, xBaseURI
, xHandler
);
5006 catch (const uno::Exception
& rException
)
5008 SAL_WARN("sw.ww8", "SwWW8ImplReader::CoreLoad: failed to initialize RDF metadata: " << rException
.Message
);
5013 ::ww8::WW8FibData
* pFibData
= new ::ww8::WW8FibData();
5015 if (m_pWwFib
->m_fReadOnlyRecommended
)
5016 pFibData
->setReadOnlyRecommended(true);
5018 pFibData
->setReadOnlyRecommended(false);
5020 if (m_pWwFib
->m_fWriteReservation
)
5021 pFibData
->setWriteReservation(true);
5023 pFibData
->setWriteReservation(false);
5025 ::sw::tExternalDataPointer
pExternalFibData(pFibData
);
5027 m_rDoc
.getIDocumentExternalData().setExternalData(::sw::tExternalDataType::FIB
, pExternalFibData
);
5029 ::sw::tExternalDataPointer pSttbfAsoc
5030 (new ::ww8::WW8Sttb
<ww8::WW8Struct
>(*m_pTableStream
, m_pWwFib
->m_fcSttbfAssoc
, m_pWwFib
->m_lcbSttbfAssoc
));
5032 m_rDoc
.getIDocumentExternalData().setExternalData(::sw::tExternalDataType::STTBF_ASSOC
, pSttbfAsoc
);
5034 if (m_pWwFib
->m_fWriteReservation
|| m_pWwFib
->m_fReadOnlyRecommended
)
5036 SwDocShell
* pDocShell
= m_rDoc
.GetDocShell();
5038 pDocShell
->SetReadOnlyUI();
5041 m_pPaM
= mpCursor
.get();
5043 m_pCtrlStck
= new SwWW8FltControlStack( &m_rDoc
, m_nFieldFlags
, *this );
5045 m_pRedlineStack
= new sw::util::RedlineStack(m_rDoc
);
5048 RefFieldStck: Keeps track of bookmarks which may be inserted as
5051 m_pReffedStck
= new SwWW8ReferencedFltEndStack(&m_rDoc
, m_nFieldFlags
);
5052 m_pReffingStck
= new SwWW8FltRefStack(&m_rDoc
, m_nFieldFlags
);
5054 m_pAnchorStck
= new SwWW8FltAnchorStack(&m_rDoc
, m_nFieldFlags
);
5056 size_t nPageDescOffset
= m_rDoc
.GetPageDescCnt();
5058 SwNodeIndex
aSttNdIdx( m_rDoc
.GetNodes() );
5059 SwRelNumRuleSpaces
aRelNumRule(m_rDoc
, m_bNewDoc
);
5061 RedlineFlags eMode
= RedlineFlags::ShowInsert
;
5063 m_pSprmParser
= new wwSprmParser(*m_pWwFib
);
5065 // Set handy helper variables
5066 m_bVer6
= (6 == m_pWwFib
->m_nVersion
);
5067 m_bVer7
= (7 == m_pWwFib
->m_nVersion
);
5068 m_bVer67
= m_bVer6
|| m_bVer7
;
5069 m_bVer8
= (8 == m_pWwFib
->m_nVersion
);
5071 m_eTextCharSet
= WW8Fib::GetFIBCharset(m_pWwFib
->m_chse
, m_pWwFib
->m_lid
);
5072 m_eStructCharSet
= WW8Fib::GetFIBCharset(m_pWwFib
->m_chseTables
, m_pWwFib
->m_lid
);
5074 m_bWWBugNormal
= m_pWwFib
->m_nProduct
== 0xc03d;
5077 aSttNdIdx
= m_pPaM
->GetPoint()->nNode
;
5079 ::StartProgress(STR_STATSTR_W4WREAD
, 0, 100, m_pDocShell
);
5082 m_pFonts
= new WW8Fonts( *m_pTableStream
, *m_pWwFib
);
5084 // Document Properties
5085 m_pWDop
= new WW8Dop( *m_pTableStream
, m_pWwFib
->m_nFib
, m_pWwFib
->m_fcDop
,
5086 m_pWwFib
->m_lcbDop
);
5092 Import revisioning data: author names
5094 if( m_pWwFib
->m_lcbSttbfRMark
)
5096 ReadRevMarkAuthorStrTabl( *m_pTableStream
,
5097 m_pWwFib
->m_fcSttbfRMark
,
5098 m_pWwFib
->m_lcbSttbfRMark
, m_rDoc
);
5101 // Initialize our String/ID map for Linked Sections
5102 std::vector
<OUString
> aLinkStrings
;
5103 std::vector
<ww::bytes
> aStringIds
;
5105 WW8ReadSTTBF(!m_bVer67
, *m_pTableStream
, m_pWwFib
->m_fcSttbFnm
,
5106 m_pWwFib
->m_lcbSttbFnm
, m_bVer67
? 2 : 0, m_eStructCharSet
,
5107 aLinkStrings
, &aStringIds
);
5109 for (size_t i
=0; i
< aLinkStrings
.size() && i
< aStringIds
.size(); ++i
)
5111 const ww::bytes
& stringId
= aStringIds
[i
];
5112 if (stringId
.size() < sizeof(WW8_STRINGID
))
5114 SAL_WARN("sw.ww8", "SwWW8ImplReader::CoreLoad: WW8_STRINGID is too short");
5117 const WW8_STRINGID
*stringIdStruct
= reinterpret_cast<const WW8_STRINGID
*>(stringId
.data());
5118 m_aLinkStringMap
[SVBT16ToShort(stringIdStruct
->nStringId
)] = aLinkStrings
[i
];
5121 ReadDocVars(); // import document variables as meta information.
5123 ::SetProgressState(m_nProgress
, m_pDocShell
); // Update
5125 m_pLstManager
= new WW8ListManager( *m_pTableStream
, *this );
5128 zuerst(!) alle Styles importieren (siehe WW8PAR2.CXX)
5129 VOR dem Import der Listen !!
5131 ::SetProgressState(m_nProgress
, m_pDocShell
); // Update
5132 m_pStyles
= new WW8RStyle( *m_pWwFib
, this ); // Styles
5133 m_pStyles
->Import();
5136 In the end: (also see WW8PAR3.CXX)
5138 Go through all Styles and attach respective List Format
5139 AFTER we imported the Styles and AFTER we imported the Lists!
5141 ::SetProgressState(m_nProgress
, m_pDocShell
); // Update
5142 m_pStyles
->PostProcessStyles();
5144 if (!m_vColl
.empty())
5147 m_pSBase
= new WW8ScannerBase(m_pStrm
,m_pTableStream
,m_pDataStream
,m_pWwFib
);
5149 static const SvxExtNumType eNumTA
[16] =
5151 SVX_NUM_ARABIC
, SVX_NUM_ROMAN_UPPER
, SVX_NUM_ROMAN_LOWER
,
5152 SVX_NUM_CHARS_UPPER_LETTER_N
, SVX_NUM_CHARS_LOWER_LETTER_N
,
5153 SVX_NUM_ARABIC
, SVX_NUM_ARABIC
, SVX_NUM_ARABIC
,
5154 SVX_NUM_ARABIC
, SVX_NUM_ARABIC
, SVX_NUM_ARABIC
,
5155 SVX_NUM_ARABIC
, SVX_NUM_ARABIC
, SVX_NUM_ARABIC
,
5156 SVX_NUM_ARABIC
, SVX_NUM_ARABIC
5159 if (m_pSBase
->AreThereFootnotes())
5161 static const SwFootnoteNum eNumA
[4] =
5163 FTNNUM_DOC
, FTNNUM_CHAPTER
, FTNNUM_PAGE
, FTNNUM_DOC
5166 SwFootnoteInfo aInfo
;
5167 aInfo
= m_rDoc
.GetFootnoteInfo(); // Copy-Ctor private
5169 aInfo
.ePos
= FTNPOS_PAGE
;
5170 aInfo
.eNum
= eNumA
[m_pWDop
->rncFootnote
];
5171 sal_uInt16 nfcFootnoteRef
= m_pWDop
->nfcFootnoteRef
& 0xF;
5172 aInfo
.aFormat
.SetNumberingType( static_cast< sal_uInt16
>(eNumTA
[nfcFootnoteRef
]) );
5173 if( m_pWDop
->nFootnote
)
5174 aInfo
.nFootnoteOffset
= m_pWDop
->nFootnote
- 1;
5175 m_rDoc
.SetFootnoteInfo( aInfo
);
5177 if( m_pSBase
->AreThereEndnotes() )
5179 SwEndNoteInfo aInfo
;
5180 aInfo
= m_rDoc
.GetEndNoteInfo(); // Same as for Footnote
5181 sal_uInt16 nfcEdnRef
= m_pWDop
->nfcEdnRef
& 0xF;
5182 aInfo
.aFormat
.SetNumberingType( static_cast< sal_uInt16
>(eNumTA
[nfcEdnRef
]) );
5184 aInfo
.nFootnoteOffset
= m_pWDop
->nEdn
- 1;
5185 m_rDoc
.SetEndNoteInfo( aInfo
);
5188 if( m_pWwFib
->m_lcbPlcfhdd
)
5189 m_pHdFt
= new WW8PLCF_HdFt( m_pTableStream
, *m_pWwFib
, *m_pWDop
);
5193 // inserting into an existing document:
5194 // As only complete paragraphs are inserted, the current one
5195 // needs to be splitted - once or even twice.
5196 const SwPosition
* pPos
= m_pPaM
->GetPoint();
5198 // split current paragraph to get new paragraph for the insertion
5199 m_rDoc
.getIDocumentContentOperations().SplitNode( *pPos
, false );
5201 // another split, if insertion position was not at the end of the current paragraph.
5202 SwTextNode
const*const pTextNd
= pPos
->nNode
.GetNode().GetTextNode();
5203 if ( pTextNd
->GetText().getLength() )
5205 m_rDoc
.getIDocumentContentOperations().SplitNode( *pPos
, false );
5206 // move PaM back to the newly empty paragraph
5207 m_pPaM
->Move( fnMoveBackward
);
5210 // suppress insertion of tables inside footnotes.
5211 const sal_uLong nNd
= pPos
->nNode
.GetIndex();
5212 m_bReadNoTable
= ( nNd
< m_rDoc
.GetNodes().GetEndOfInserts().GetIndex() &&
5213 m_rDoc
.GetNodes().GetEndOfInserts().StartOfSectionIndex() < nNd
);
5216 ::SetProgressState(m_nProgress
, m_pDocShell
); // Update
5218 // loop for each glossary entry and add dummy section node
5221 WW8PLCF
aPlc(*m_pTableStream
, m_pWwFib
->m_fcPlcfglsy
, m_pWwFib
->m_lcbPlcfglsy
, 0);
5223 WW8_CP nStart
, nEnd
;
5226 for (int i
= 0; i
< pGloss
->GetNoStrings(); ++i
, aPlc
.advance())
5228 SwNodeIndex
aIdx( m_rDoc
.GetNodes().GetEndOfContent());
5229 SwTextFormatColl
* pColl
=
5230 m_rDoc
.getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD
,
5232 SwStartNode
*pNode
=
5233 m_rDoc
.GetNodes().MakeTextSection(aIdx
,
5234 SwNormalStartNode
,pColl
);
5235 m_pPaM
->GetPoint()->nNode
= pNode
->GetIndex()+1;
5236 m_pPaM
->GetPoint()->nContent
.Assign(m_pPaM
->GetContentNode(),0);
5237 aPlc
.Get( nStart
, nEnd
, pDummy
);
5238 ReadText(nStart
,nEnd
-nStart
-1,MAN_MAINTEXT
);
5241 else // ordinary case
5243 if (m_bNewDoc
&& m_pStg
&& !pGloss
) /*meaningless for a glossary */
5245 m_pDocShell
->SetIsTemplate( m_pWwFib
->m_fDot
); // point at tgc record
5246 uno::Reference
<document::XDocumentPropertiesSupplier
> const
5247 xDocPropSupp(m_pDocShell
->GetModel(), uno::UNO_QUERY_THROW
);
5248 uno::Reference
< document::XDocumentProperties
> xDocProps( xDocPropSupp
->getDocumentProperties(), uno::UNO_QUERY_THROW
);
5250 OUString sCreatedFrom
= xDocProps
->getTemplateURL();
5251 uno::Reference
< container::XNameContainer
> xPrjNameCache
;
5252 uno::Reference
< lang::XMultiServiceFactory
> xSF(m_pDocShell
->GetModel(), uno::UNO_QUERY
);
5254 xPrjNameCache
.set( xSF
->createInstance( "ooo.vba.VBAProjectNameProvider" ), uno::UNO_QUERY
);
5256 // Read Global templates
5257 ReadGlobalTemplateSettings( sCreatedFrom
, xPrjNameCache
);
5259 // Create and insert Word vba Globals
5261 uno::Sequence
< uno::Any
> aArgs(1);
5262 aArgs
[ 0 ] <<= m_pDocShell
->GetModel();
5265 aGlobs
<<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( "ooo.vba.word.Globals", aArgs
);
5267 catch (const uno::Exception
&)
5269 SAL_WARN("sw.ww8", "SwWW8ImplReader::CoreLoad: ooo.vba.word.Globals is not available");
5272 #if HAVE_FEATURE_SCRIPTING
5273 if (!utl::ConfigManager::IsAvoidConfig())
5275 BasicManager
*pBasicMan
= m_pDocShell
->GetBasicManager();
5277 pBasicMan
->SetGlobalUNOConstant( "VBAGlobals", aGlobs
);
5280 BasicProjImportHelper
aBasicImporter( *m_pDocShell
);
5281 // Import vba via oox filter
5282 bool bRet
= aBasicImporter
.import( m_pDocShell
->GetMedium()->GetInputStream() );
5284 lcl_createTemplateToProjectEntry( xPrjNameCache
, sCreatedFrom
, aBasicImporter
.getProjectName() );
5285 WW8Customizations
aCustomisations( m_pTableStream
, *m_pWwFib
);
5286 aCustomisations
.Import( m_pDocShell
);
5289 m_rDoc
.SetContainsMSVBasic(true);
5293 m_bOnLoadingMain
= true;
5294 ReadText(0, m_pWwFib
->m_ccpText
, MAN_MAINTEXT
);
5295 m_bOnLoadingMain
= false;
5298 ::SetProgressState(m_nProgress
, m_pDocShell
); // Update
5300 if (m_pDrawPg
&& m_pMSDffManager
&& m_pMSDffManager
->GetShapeOrders())
5302 // Helper array to chain the inserted frames (instead of SdrTextObj)
5303 SvxMSDffShapeTxBxSort aTxBxSort
;
5305 // Ensure correct z-order of read Escher objects
5306 sal_uInt16 nShapeCount
= m_pMSDffManager
->GetShapeOrders()->size();
5308 for (sal_uInt16 nShapeNum
=0; nShapeNum
< nShapeCount
; nShapeNum
++)
5310 SvxMSDffShapeOrder
*pOrder
=
5311 (*m_pMSDffManager
->GetShapeOrders())[nShapeNum
].get();
5312 // Insert Pointer into new Sort array
5313 if (pOrder
->nTxBxComp
&& pOrder
->pFly
)
5314 aTxBxSort
.insert(pOrder
);
5317 if( !aTxBxSort
.empty() )
5319 SwFormatChain aChain
;
5320 for( SvxMSDffShapeTxBxSort::iterator it
= aTxBxSort
.begin(); it
!= aTxBxSort
.end(); ++it
)
5322 SvxMSDffShapeOrder
*pOrder
= *it
;
5324 // Initialize FlyFrame Formats
5325 SwFlyFrameFormat
* pFlyFormat
= pOrder
->pFly
;
5326 SwFlyFrameFormat
* pNextFlyFormat
= nullptr;
5327 SwFlyFrameFormat
* pPrevFlyFormat
= nullptr;
5329 // Determine successor, if we can
5330 SvxMSDffShapeTxBxSort::iterator tmpIter1
= it
;
5332 if( tmpIter1
!= aTxBxSort
.end() )
5334 SvxMSDffShapeOrder
*pNextOrder
= *tmpIter1
;
5335 if ((0xFFFF0000 & pOrder
->nTxBxComp
)
5336 == (0xFFFF0000 & pNextOrder
->nTxBxComp
))
5337 pNextFlyFormat
= pNextOrder
->pFly
;
5339 // Determine precessor, if we can
5340 if( it
!= aTxBxSort
.begin() )
5342 SvxMSDffShapeTxBxSort::iterator tmpIter2
= it
;
5344 SvxMSDffShapeOrder
*pPrevOrder
= *tmpIter2
;
5345 if ((0xFFFF0000 & pOrder
->nTxBxComp
)
5346 == (0xFFFF0000 & pPrevOrder
->nTxBxComp
))
5347 pPrevFlyFormat
= pPrevOrder
->pFly
;
5349 // If successor or predecessor present, insert the
5350 // chain at the FlyFrame Format
5351 if (pNextFlyFormat
|| pPrevFlyFormat
)
5353 aChain
.SetNext( pNextFlyFormat
);
5354 aChain
.SetPrev( pPrevFlyFormat
);
5355 pFlyFormat
->SetFormatAttr( aChain
);
5363 if( m_pWDop
->fRevMarking
)
5364 eMode
|= RedlineFlags::On
;
5365 if( m_pWDop
->fRMView
)
5366 eMode
|= RedlineFlags::ShowDelete
;
5369 m_aInsertedTables
.DelAndMakeTableFrames();
5370 m_aSectionManager
.InsertSegments();
5374 DELETEZ( m_pStyles
);
5379 DELETEZ( m_pMSDffManager
);
5381 DELETEZ( m_pSBase
);
5383 DELETEZ( m_pFonts
);
5385 delete m_pSprmParser
;
5386 ::EndProgress(m_pDocShell
);
5388 m_pDataStream
= nullptr;
5389 m_pTableStream
= nullptr;
5392 m_pRedlineStack
->closeall(*m_pPaM
->GetPoint());
5393 delete m_pRedlineStack
;
5394 DeleteAnchorStack();
5397 // For i120928,achieve the graphics from the special bookmark with is for graphic bullet
5399 std::vector
<const SwGrfNode
*> vecBulletGrf
;
5400 std::vector
<SwFrameFormat
*> vecFrameFormat
;
5402 IDocumentMarkAccess
* const pMarkAccess
= m_rDoc
.getIDocumentMarkAccess();
5405 IDocumentMarkAccess::const_iterator_t ppBkmk
= pMarkAccess
->findBookmark( "_PictureBullets" );
5406 if ( ppBkmk
!= pMarkAccess
->getBookmarksEnd() &&
5407 IDocumentMarkAccess::GetType( *(ppBkmk
->get()) ) == IDocumentMarkAccess::MarkType::BOOKMARK
)
5409 SwTextNode
* pTextNode
= ppBkmk
->get()->GetMarkStart().nNode
.GetNode().GetTextNode();
5413 const SwpHints
* pHints
= pTextNode
->GetpSwpHints();
5414 for( size_t nHintPos
= 0; pHints
&& nHintPos
< pHints
->Count(); ++nHintPos
)
5416 const SwTextAttr
*pHt
= pHints
->Get(nHintPos
);
5417 const sal_Int32 st
= pHt
->GetStart();
5419 && pHt
->Which() == RES_TXTATR_FLYCNT
5420 && (st
>= ppBkmk
->get()->GetMarkStart().nContent
.GetIndex()) )
5422 SwFrameFormat
* pFrameFormat
= pHt
->GetFlyCnt().GetFrameFormat();
5423 vecFrameFormat
.push_back(pFrameFormat
);
5424 const SwNodeIndex
* pNdIdx
= pFrameFormat
->GetContent().GetContentIdx();
5425 const SwNodes
* pNodesArray
= (pNdIdx
!= nullptr)
5426 ? &(pNdIdx
->GetNodes())
5428 const SwGrfNode
*pGrf
= (pNodesArray
!= nullptr)
5429 ? dynamic_cast<const SwGrfNode
*>((*pNodesArray
)[pNdIdx
->GetIndex() + 1])
5431 vecBulletGrf
.push_back(pGrf
);
5434 // update graphic bullet information
5435 size_t nCount
= m_pLstManager
->GetWW8LSTInfoNum();
5436 for (size_t i
= 0; i
< nCount
; ++i
)
5438 SwNumRule
* pRule
= m_pLstManager
->GetNumRule(i
);
5439 for (sal_uInt16 j
= 0; j
< MAXLEVEL
; ++j
)
5441 SwNumFormat
aNumFormat(pRule
->Get(j
));
5442 const sal_Int16 nType
= aNumFormat
.GetNumberingType();
5443 const sal_uInt16 nGrfBulletCP
= aNumFormat
.GetGrfBulletCP();
5444 if ( nType
== SVX_NUM_BITMAP
5445 && vecBulletGrf
.size() > nGrfBulletCP
5446 && vecBulletGrf
[nGrfBulletCP
] != nullptr )
5448 Graphic aGraphic
= vecBulletGrf
[nGrfBulletCP
]->GetGrf();
5449 SvxBrushItem
aBrush(aGraphic
, GPOS_AREA
, SID_ATTR_BRUSH
);
5450 const vcl::Font
& aFont
= numfunc::GetDefBulletFont();
5451 int nHeight
= aFont
.GetFontHeight() * 12;
5452 Size
aPrefSize( aGraphic
.GetPrefSize());
5453 if (aPrefSize
.Height() * aPrefSize
.Width() != 0 )
5455 int nWidth
= (nHeight
* aPrefSize
.Width()) / aPrefSize
.Height();
5456 Size
aSize(nWidth
, nHeight
);
5457 aNumFormat
.SetGraphicBrush(&aBrush
, &aSize
);
5461 aNumFormat
.SetNumberingType(SVX_NUM_CHAR_SPECIAL
);
5462 aNumFormat
.SetBulletChar(0x2190);
5464 pRule
->Set( j
, aNumFormat
);
5468 // Remove additional pictures
5469 for (SwFrameFormat
* p
: vecFrameFormat
)
5471 m_rDoc
.getIDocumentLayoutAccess().DelLayoutFormat(p
);
5476 DELETEZ( m_pLstManager
);
5479 SAL_WARN_IF(m_pTableEndPaM
, "sw.ww8", "document ended without table ending");
5480 m_pTableEndPaM
.reset(); //ensure this is deleted before pPaM
5481 m_pPosAfterTOC
.reset();
5484 m_pLastAnchorPos
.reset();//ensure this is deleted before UpdatePageDescs
5486 // remove extra paragraphs after attribute ctrl
5487 // stacks etc. are destroyed, and before fields
5489 m_aExtraneousParas
.delete_all_from_doc();
5493 DELETEZ(m_pWFlyPara
);
5494 DELETEZ(m_pSFlyPara
);
5496 // delete the pam before the call for hide all redlines (Bug 73683)
5498 m_rDoc
.getIDocumentRedlineAccess().SetRedlineFlags(eMode
);
5500 UpdatePageDescs(m_rDoc
, nPageDescOffset
);
5505 sal_uLong
SwWW8ImplReader::SetSubStreams(tools::SvRef
<SotStorageStream
> &rTableStream
,
5506 tools::SvRef
<SotStorageStream
> &rDataStream
)
5508 sal_uLong nErrRet
= 0;
5509 // 6 stands for "6 OR 7", 7 stands for "ONLY 7"
5510 switch (m_pWwFib
->m_nVersion
)
5514 m_pTableStream
= m_pStrm
;
5515 m_pDataStream
= m_pStrm
;
5520 OSL_ENSURE( m_pStg
, "Version 8 always needs to have a Storage!!" );
5521 nErrRet
= ERR_SWG_READ_ERROR
;
5525 rTableStream
= m_pStg
->OpenSotStream( OUString::createFromAscii(
5526 m_pWwFib
->m_fWhichTableStm
? SL::a1Table
: SL::a0Table
),
5527 StreamMode::STD_READ
);
5529 m_pTableStream
= rTableStream
.get();
5530 m_pTableStream
->SetEndian( SvStreamEndian::LITTLE
);
5532 rDataStream
= m_pStg
->OpenSotStream(OUString(SL::aData
),
5533 StreamMode::STD_READ
);
5535 if (rDataStream
.Is() && SVSTREAM_OK
== rDataStream
->GetError())
5537 m_pDataStream
= rDataStream
.get();
5538 m_pDataStream
->SetEndian(SvStreamEndian::LITTLE
);
5541 m_pDataStream
= m_pStrm
;
5545 OSL_ENSURE( false, "We forgot to encode nVersion!" );
5546 nErrRet
= ERR_SWG_READ_ERROR
;
5554 utl::TempFile
*MakeTemp(SvFileStream
&rSt
)
5556 utl::TempFile
*pT
= new utl::TempFile
;
5557 pT
->EnableKillingFile();
5558 rSt
.Open(pT
->GetFileName(), StreamMode::READWRITE
| StreamMode::SHARE_DENYWRITE
);
5562 #define WW_BLOCKSIZE 0x200
5564 void DecryptRC4(msfilter::MSCodec97
& rCtx
, SvStream
&rIn
, SvStream
&rOut
)
5566 rIn
.Seek(STREAM_SEEK_TO_END
);
5567 const std::size_t nLen
= rIn
.Tell();
5570 sal_uInt8 in
[WW_BLOCKSIZE
];
5571 for (std::size_t nI
= 0, nBlock
= 0; nI
< nLen
; nI
+= WW_BLOCKSIZE
, ++nBlock
)
5573 std::size_t nBS
= (nLen
- nI
> WW_BLOCKSIZE
) ? WW_BLOCKSIZE
: nLen
- nI
;
5574 nBS
= rIn
.ReadBytes(in
, nBS
);
5575 rCtx
.InitCipher(nBlock
);
5576 rCtx
.Decode(in
, nBS
, in
, nBS
);
5577 rOut
.WriteBytes(in
, nBS
);
5581 void DecryptXOR(msfilter::MSCodec_XorWord95
&rCtx
, SvStream
&rIn
, SvStream
&rOut
)
5583 std::size_t nSt
= rIn
.Tell();
5584 rIn
.Seek(STREAM_SEEK_TO_END
);
5585 std::size_t nLen
= rIn
.Tell();
5591 sal_uInt8 in
[0x4096];
5592 for (std::size_t nI
= nSt
; nI
< nLen
; nI
+= 0x4096)
5594 std::size_t nBS
= (nLen
- nI
> 0x4096 ) ? 0x4096 : nLen
- nI
;
5595 nBS
= rIn
.ReadBytes(in
, nBS
);
5596 rCtx
.Decode(in
, nBS
);
5597 rOut
.WriteBytes(in
, nBS
);
5601 // moan, copy and paste :-(
5602 OUString
QueryPasswordForMedium(SfxMedium
& rMedium
)
5606 using namespace com::sun::star
;
5608 const SfxItemSet
* pSet
= rMedium
.GetItemSet();
5609 const SfxPoolItem
*pPasswordItem
;
5611 if(pSet
&& SfxItemState::SET
== pSet
->GetItemState(SID_PASSWORD
, true, &pPasswordItem
))
5612 aPassw
= static_cast<const SfxStringItem
*>(pPasswordItem
)->GetValue();
5617 uno::Reference
< task::XInteractionHandler
> xHandler( rMedium
.GetInteractionHandler() );
5620 ::comphelper::DocPasswordRequest
* pRequest
= new ::comphelper::DocPasswordRequest(
5621 ::comphelper::DocPasswordRequestType::MS
, task::PasswordRequestMode_PASSWORD_ENTER
,
5622 INetURLObject( rMedium
.GetOrigURL() ).GetName( INetURLObject::DecodeMechanism::WithCharset
) );
5623 uno::Reference
< task::XInteractionRequest
> xRequest( pRequest
);
5625 xHandler
->handle( xRequest
);
5627 if( pRequest
->isPassword() )
5628 aPassw
= pRequest
->getPassword();
5631 catch( const uno::Exception
& )
5639 uno::Sequence
< beans::NamedValue
> InitXorWord95Codec( ::msfilter::MSCodec_XorWord95
& rCodec
, SfxMedium
& rMedium
, WW8Fib
* pWwFib
)
5641 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
5642 const SfxUnoAnyItem
* pEncryptionData
= SfxItemSet::GetItem
<SfxUnoAnyItem
>(rMedium
.GetItemSet(), SID_ENCRYPTIONDATA
, false);
5643 if ( pEncryptionData
&& ( pEncryptionData
->GetValue() >>= aEncryptionData
) && !rCodec
.InitCodec( aEncryptionData
) )
5644 aEncryptionData
.realloc( 0 );
5646 if ( !aEncryptionData
.getLength() )
5648 OUString sUniPassword
= QueryPasswordForMedium( rMedium
);
5650 OString
sPassword(OUStringToOString(sUniPassword
,
5651 WW8Fib::GetFIBCharset(pWwFib
->m_chseTables
, pWwFib
->m_lid
)));
5653 sal_Int32 nLen
= sPassword
.getLength();
5656 sal_uInt8 pPassword
[16];
5657 memcpy(pPassword
, sPassword
.getStr(), nLen
);
5658 memset(pPassword
+nLen
, 0, sizeof(pPassword
)-nLen
);
5660 rCodec
.InitKey( pPassword
);
5661 aEncryptionData
= rCodec
.GetEncryptionData();
5663 // the export supports RC4 algorithm only, so we have to
5664 // generate the related EncryptionData as well, so that Save
5665 // can export the document without asking for a password;
5666 // as result there will be EncryptionData for both algorithms
5667 // in the MediaDescriptor
5668 ::msfilter::MSCodec_Std97 aCodec97
;
5670 // Generate random number with a seed of time as salt.
5672 osl_getSystemTime( &aTime
);
5673 rtlRandomPool aRandomPool
= rtl_random_createPool();
5674 rtl_random_addBytes ( aRandomPool
, &aTime
, 8 );
5676 sal_uInt8 pDocId
[ 16 ];
5677 rtl_random_getBytes( aRandomPool
, pDocId
, 16 );
5679 rtl_random_destroyPool( aRandomPool
);
5681 sal_uInt16 pStd97Pass
[16];
5682 memset( pStd97Pass
, 0, sizeof( pStd97Pass
) );
5683 for( sal_Int32 nChar
= 0; nChar
< nLen
; ++nChar
)
5684 pStd97Pass
[nChar
] = sUniPassword
[nChar
];
5686 aCodec97
.InitKey( pStd97Pass
, pDocId
);
5688 // merge the EncryptionData, there should be no conflicts
5689 ::comphelper::SequenceAsHashMap
aEncryptionHash( aEncryptionData
);
5690 aEncryptionHash
.update( ::comphelper::SequenceAsHashMap( aCodec97
.GetEncryptionData() ) );
5691 aEncryptionHash
>> aEncryptionData
;
5695 return aEncryptionData
;
5698 uno::Sequence
< beans::NamedValue
> Init97Codec(msfilter::MSCodec97
& rCodec
, sal_uInt8 pDocId
[16], SfxMedium
& rMedium
)
5700 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
5701 const SfxUnoAnyItem
* pEncryptionData
= SfxItemSet::GetItem
<SfxUnoAnyItem
>(rMedium
.GetItemSet(), SID_ENCRYPTIONDATA
, false);
5702 if ( pEncryptionData
&& ( pEncryptionData
->GetValue() >>= aEncryptionData
) && !rCodec
.InitCodec( aEncryptionData
) )
5703 aEncryptionData
.realloc( 0 );
5705 if ( !aEncryptionData
.getLength() )
5707 OUString sUniPassword
= QueryPasswordForMedium( rMedium
);
5709 sal_Int32 nLen
= sUniPassword
.getLength();
5712 sal_uInt16 pPassword
[16];
5713 memset( pPassword
, 0, sizeof( pPassword
) );
5714 for( sal_Int32 nChar
= 0; nChar
< nLen
; ++nChar
)
5715 pPassword
[nChar
] = sUniPassword
[nChar
];
5717 rCodec
.InitKey( pPassword
, pDocId
);
5718 aEncryptionData
= rCodec
.GetEncryptionData();
5722 return aEncryptionData
;
5726 //TO-DO: merge this with lclReadFilepass8_Strong in sc which uses a different
5728 static bool lclReadCryptoAPIHeader(msfilter::RC4EncryptionInfo
&info
, SvStream
&rStream
)
5730 //Its possible there are other variants in existance but these
5731 //are the defaults I get with Word 2013
5733 rStream
.ReadUInt32(info
.header
.flags
);
5734 if (oox::getFlag( info
.header
.flags
, msfilter::ENCRYPTINFO_EXTERNAL
))
5737 sal_uInt32
nHeaderSize(0);
5738 rStream
.ReadUInt32(nHeaderSize
);
5739 sal_uInt32 actualHeaderSize
= sizeof(info
.header
);
5741 if (nHeaderSize
< actualHeaderSize
)
5744 rStream
.ReadUInt32(info
.header
.flags
);
5745 rStream
.ReadUInt32(info
.header
.sizeExtra
);
5746 rStream
.ReadUInt32(info
.header
.algId
);
5747 rStream
.ReadUInt32(info
.header
.algIdHash
);
5748 rStream
.ReadUInt32(info
.header
.keyBits
);
5749 rStream
.ReadUInt32(info
.header
.providedType
);
5750 rStream
.ReadUInt32(info
.header
.reserved1
);
5751 rStream
.ReadUInt32(info
.header
.reserved2
);
5753 rStream
.SeekRel(nHeaderSize
- actualHeaderSize
);
5755 rStream
.ReadUInt32(info
.verifier
.saltSize
);
5756 if (info
.verifier
.saltSize
!= msfilter::SALT_LENGTH
)
5758 rStream
.ReadBytes(&info
.verifier
.salt
, sizeof(info
.verifier
.salt
));
5759 rStream
.ReadBytes(&info
.verifier
.encryptedVerifier
, sizeof(info
.verifier
.encryptedVerifier
));
5761 rStream
.ReadUInt32(info
.verifier
.encryptedVerifierHashSize
);
5762 if (info
.verifier
.encryptedVerifierHashSize
!= RTL_DIGEST_LENGTH_SHA1
)
5764 rStream
.ReadBytes(&info
.verifier
.encryptedVerifierHash
, info
.verifier
.encryptedVerifierHashSize
);
5766 // check flags and algorithm IDs, required are AES128 and SHA-1
5767 if (!oox::getFlag(info
.header
.flags
, msfilter::ENCRYPTINFO_CRYPTOAPI
))
5770 if (oox::getFlag(info
.header
.flags
, msfilter::ENCRYPTINFO_AES
))
5773 if (info
.header
.algId
!= msfilter::ENCRYPT_ALGO_RC4
)
5776 // hash algorithm ID 0 defaults to SHA-1 too
5777 if (info
.header
.algIdHash
!= 0 && info
.header
.algIdHash
!= msfilter::ENCRYPT_HASH_SHA1
)
5783 sal_uLong
SwWW8ImplReader::LoadThroughDecryption(WW8Glossary
*pGloss
)
5785 sal_uLong nErrRet
= 0;
5787 m_pWwFib
= pGloss
->GetFib();
5789 m_pWwFib
= new WW8Fib(*m_pStrm
, m_nWantedVersion
);
5791 if (m_pWwFib
->m_nFibError
)
5792 nErrRet
= ERR_SWG_READ_ERROR
;
5794 tools::SvRef
<SotStorageStream
> xTableStream
, xDataStream
;
5797 nErrRet
= SetSubStreams(xTableStream
, xDataStream
);
5799 utl::TempFile
*pTempMain
= nullptr;
5800 utl::TempFile
*pTempTable
= nullptr;
5801 utl::TempFile
*pTempData
= nullptr;
5802 SvFileStream aDecryptMain
;
5803 SvFileStream aDecryptTable
;
5804 SvFileStream aDecryptData
;
5806 bool bDecrypt
= false;
5807 enum {RC4CryptoAPI
, RC4
, XOR
, Other
} eAlgo
= Other
;
5808 if (m_pWwFib
->m_fEncrypted
&& !nErrRet
)
5813 if (8 != m_pWwFib
->m_nVersion
)
5817 if (m_pWwFib
->m_nKey
!= 0)
5821 m_pTableStream
->Seek(0);
5822 sal_uInt32
nEncType(0);
5823 m_pTableStream
->ReadUInt32(nEncType
);
5824 if (nEncType
== msfilter::VERSION_INFO_1997_FORMAT
)
5826 else if (nEncType
== msfilter::VERSION_INFO_2007_FORMAT
|| nEncType
== msfilter::VERSION_INFO_2007_FORMAT_SP2
)
5827 eAlgo
= RC4CryptoAPI
;
5835 nErrRet
= ERRCODE_SVX_WRONGPASS
;
5836 SfxMedium
* pMedium
= m_pDocShell
->GetMedium();
5843 nErrRet
= ERRCODE_SVX_READ_FILTER_CRYPT
;
5847 msfilter::MSCodec_XorWord95 aCtx
;
5848 uno::Sequence
< beans::NamedValue
> aEncryptionData
= InitXorWord95Codec( aCtx
, *pMedium
, m_pWwFib
);
5850 // if initialization has failed the EncryptionData should be empty
5851 if ( aEncryptionData
.getLength() && aCtx
.VerifyKey( m_pWwFib
->m_nKey
, m_pWwFib
->m_nHash
) )
5854 pTempMain
= MakeTemp(aDecryptMain
);
5857 size_t nUnencryptedHdr
=
5858 (8 == m_pWwFib
->m_nVersion
) ? 0x44 : 0x34;
5859 sal_uInt8
*pIn
= new sal_uInt8
[nUnencryptedHdr
];
5860 nUnencryptedHdr
= m_pStrm
->ReadBytes(pIn
, nUnencryptedHdr
);
5861 aDecryptMain
.WriteBytes(pIn
, nUnencryptedHdr
);
5864 DecryptXOR(aCtx
, *m_pStrm
, aDecryptMain
);
5866 if (!m_pTableStream
|| m_pTableStream
== m_pStrm
)
5867 m_pTableStream
= &aDecryptMain
;
5870 pTempTable
= MakeTemp(aDecryptTable
);
5871 DecryptXOR(aCtx
, *m_pTableStream
, aDecryptTable
);
5872 m_pTableStream
= &aDecryptTable
;
5875 if (!m_pDataStream
|| m_pDataStream
== m_pStrm
)
5876 m_pDataStream
= &aDecryptMain
;
5879 pTempData
= MakeTemp(aDecryptData
);
5880 DecryptXOR(aCtx
, *m_pDataStream
, aDecryptData
);
5881 m_pDataStream
= &aDecryptData
;
5884 pMedium
->GetItemSet()->ClearItem( SID_PASSWORD
);
5885 pMedium
->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) ) );
5892 std::unique_ptr
<msfilter::MSCodec97
> xCtx
;
5893 msfilter::RC4EncryptionInfo info
;
5894 bool bCouldReadHeaders
;
5898 xCtx
.reset(new msfilter::MSCodec_Std97
);
5899 assert(sizeof(info
.verifier
.encryptedVerifierHash
) >= RTL_DIGEST_LENGTH_MD5
);
5901 checkRead(*m_pTableStream
, info
.verifier
.salt
, sizeof(info
.verifier
.salt
)) &&
5902 checkRead(*m_pTableStream
, info
.verifier
.encryptedVerifier
, sizeof(info
.verifier
.encryptedVerifier
)) &&
5903 checkRead(*m_pTableStream
, info
.verifier
.encryptedVerifierHash
, RTL_DIGEST_LENGTH_MD5
);
5907 xCtx
.reset(new msfilter::MSCodec_CryptoAPI
);
5908 bCouldReadHeaders
= lclReadCryptoAPIHeader(info
, *m_pTableStream
);
5911 // if initialization has failed the EncryptionData should be empty
5912 uno::Sequence
< beans::NamedValue
> aEncryptionData
;
5913 if (bCouldReadHeaders
)
5914 aEncryptionData
= Init97Codec(*xCtx
, info
.verifier
.salt
, *pMedium
);
5916 nErrRet
= ERRCODE_SVX_READ_FILTER_CRYPT
;
5917 if (aEncryptionData
.getLength() && xCtx
->VerifyKey(info
.verifier
.encryptedVerifier
,
5918 info
.verifier
.encryptedVerifierHash
))
5922 pTempMain
= MakeTemp(aDecryptMain
);
5925 std::size_t nUnencryptedHdr
= 0x44;
5926 sal_uInt8
*pIn
= new sal_uInt8
[nUnencryptedHdr
];
5927 nUnencryptedHdr
= m_pStrm
->ReadBytes(pIn
, nUnencryptedHdr
);
5929 DecryptRC4(*xCtx
, *m_pStrm
, aDecryptMain
);
5931 aDecryptMain
.Seek(0);
5932 aDecryptMain
.WriteBytes(pIn
, nUnencryptedHdr
);
5935 pTempTable
= MakeTemp(aDecryptTable
);
5936 DecryptRC4(*xCtx
, *m_pTableStream
, aDecryptTable
);
5937 m_pTableStream
= &aDecryptTable
;
5939 if (!m_pDataStream
|| m_pDataStream
== m_pStrm
)
5940 m_pDataStream
= &aDecryptMain
;
5943 pTempData
= MakeTemp(aDecryptData
);
5944 DecryptRC4(*xCtx
, *m_pDataStream
, aDecryptData
);
5945 m_pDataStream
= &aDecryptData
;
5948 pMedium
->GetItemSet()->ClearItem( SID_PASSWORD
);
5949 pMedium
->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA
, uno::makeAny( aEncryptionData
) ) );
5958 m_pStrm
= &aDecryptMain
;
5961 m_pWwFib
= new WW8Fib(*m_pStrm
, m_nWantedVersion
);
5962 if (m_pWwFib
->m_nFibError
)
5963 nErrRet
= ERR_SWG_READ_ERROR
;
5968 nErrRet
= CoreLoad(pGloss
);
5979 void SwWW8ImplReader::SetOutlineStyles()
5981 // If we are inserted into a document then don't clobber existing outline
5983 sal_uInt16 nOutlineStyleListLevelWithAssignment
= 0;
5986 ww8::ParaStyles
aOutLined(sw::util::GetParaStyles(m_rDoc
));
5987 sw::util::SortByAssignedOutlineStyleListLevel(aOutLined
);
5988 ww8::ParaStyles::reverse_iterator aEnd
= aOutLined
.rend();
5989 for ( ww8::ParaStyles::reverse_iterator aIter
= aOutLined
.rbegin(); aIter
< aEnd
; ++aIter
)
5991 if ((*aIter
)->IsAssignedToListLevelOfOutlineStyle())
5992 nOutlineStyleListLevelWithAssignment
|= 1 << (*aIter
)->GetAssignedOutlineStyleLevel();
5998 // Check applied WW8 list styles at WW8 Built-In Heading Styles
5999 // - Choose the list style which occurs most often as the one which provides
6000 // the list level properties for the Outline Style.
6001 // - Populate temporary list of WW8 Built-In Heading Styles for further
6003 std::vector
<SwWW8StyInf
*> aWW8BuiltInHeadingStyles
;
6004 const SwNumRule
* pChosenWW8ListStyle
= nullptr;
6006 std::map
<const SwNumRule
*, int> aWW8ListStyleCounts
;
6007 for (SwWW8StyInf
& rSI
: m_vColl
)
6009 if (!rSI
.IsWW8BuiltInHeadingStyle() || !rSI
.HasWW8OutlineLevel())
6014 aWW8BuiltInHeadingStyles
.push_back(&rSI
);
6016 const SwNumRule
* pWW8ListStyle
= rSI
.GetOutlineNumrule();
6017 if (pWW8ListStyle
!= nullptr)
6019 std::map
<const SwNumRule
*, int>::iterator aCountIter
6020 = aWW8ListStyleCounts
.find(pWW8ListStyle
);
6021 if (aCountIter
== aWW8ListStyleCounts
.end())
6023 aWW8ListStyleCounts
[pWW8ListStyle
] = 1;
6027 ++(aCountIter
->second
);
6032 int nCurrentMaxCount
= 0;
6033 std::map
<const SwNumRule
*, int>::iterator aCountIterEnd
6034 = aWW8ListStyleCounts
.end();
6035 for (std::map
<const SwNumRule
*, int>::iterator aIter
6036 = aWW8ListStyleCounts
.begin();
6037 aIter
!= aCountIterEnd
; ++aIter
)
6039 if (aIter
->second
> nCurrentMaxCount
)
6041 nCurrentMaxCount
= aIter
->second
;
6042 pChosenWW8ListStyle
= aIter
->first
;
6047 // - set list level properties of Outline Style - ODF's list style applied
6048 // by default to headings
6049 // - assign corresponding Heading Paragraph Styles to the Outline Style
6050 // - If a heading Paragraph Styles is not applying the WW8 list style which
6051 // had been chosen as
6052 // the one which provides the list level properties for the Outline Style,
6053 // its assignment to
6054 // the Outline Style is removed. A potential applied WW8 list style is
6055 // assigned directly and
6056 // its default outline level is applied.
6057 SwNumRule
aOutlineRule(*m_rDoc
.GetOutlineNumRule());
6058 bool bAppliedChangedOutlineStyle
= false;
6059 std::vector
<SwWW8StyInf
*>::iterator aStylesIterEnd
6060 = aWW8BuiltInHeadingStyles
.end();
6061 for (std::vector
<SwWW8StyInf
*>::iterator aStyleIter
6062 = aWW8BuiltInHeadingStyles
.begin();
6063 aStyleIter
!= aStylesIterEnd
; ++aStyleIter
)
6065 SwWW8StyInf
* pStyleInf
= (*aStyleIter
);
6067 if (!pStyleInf
->m_bColl
) //Character Style
6070 const sal_uInt16 nOutlineStyleListLevelOfWW8BuiltInHeadingStyle
6071 = 1 << pStyleInf
->mnWW8OutlineLevel
;
6072 if (nOutlineStyleListLevelOfWW8BuiltInHeadingStyle
6073 & nOutlineStyleListLevelWithAssignment
)
6078 if (pChosenWW8ListStyle
!= nullptr && pStyleInf
->mnWW8OutlineLevel
6079 == pStyleInf
->m_nListLevel
)
6081 const SwNumFormat
& rRule
6082 = pChosenWW8ListStyle
->Get(pStyleInf
->mnWW8OutlineLevel
);
6083 aOutlineRule
.Set(pStyleInf
->mnWW8OutlineLevel
, rRule
);
6084 bAppliedChangedOutlineStyle
= true;
6087 // in case that there are more styles on this level ignore them
6088 nOutlineStyleListLevelWithAssignment
6089 |= nOutlineStyleListLevelOfWW8BuiltInHeadingStyle
;
6091 SwTextFormatColl
* pTextFormatColl
= static_cast<SwTextFormatColl
*>(pStyleInf
->m_pFormat
);
6092 if (pStyleInf
->GetOutlineNumrule() != pChosenWW8ListStyle
6093 || (pStyleInf
->m_nListLevel
< WW8ListManager::nMaxLevel
6094 && pStyleInf
->mnWW8OutlineLevel
!= pStyleInf
->m_nListLevel
))
6096 // WW8 Built-In Heading Style does not apply the chosen one.
6097 // --> delete assignment to OutlineStyle, but keep its current
6099 pTextFormatColl
->DeleteAssignmentToListLevelOfOutlineStyle();
6100 // Apply existing WW8 list style a normal list style at the
6102 if (pStyleInf
->GetOutlineNumrule() != nullptr)
6104 pTextFormatColl
->SetFormatAttr(
6105 SwNumRuleItem(pStyleInf
->GetOutlineNumrule()->GetName()));
6107 // apply default outline level of WW8 Built-in Heading Style
6108 const sal_uInt8 nOutlineLevel
6109 = SwWW8StyInf::WW8OutlineLevelToOutlinelevel(
6110 pStyleInf
->mnWW8OutlineLevel
);
6111 pTextFormatColl
->SetFormatAttr(
6112 SfxUInt16Item(RES_PARATR_OUTLINELEVEL
, nOutlineLevel
));
6116 pTextFormatColl
->AssignToListLevelOfOutlineStyle(
6117 pStyleInf
->mnWW8OutlineLevel
);
6121 if (bAppliedChangedOutlineStyle
)
6123 m_rDoc
.SetOutlineNumRule(aOutlineRule
);
6127 const OUString
* SwWW8ImplReader::GetAnnotationAuthor(sal_uInt16 nIdx
)
6129 if (!m_pAtnNames
&& m_pWwFib
->m_lcbGrpStAtnOwners
)
6131 // Determine authors: can be found in the TableStream
6132 m_pAtnNames
= new std::vector
<OUString
>;
6133 SvStream
& rStrm
= *m_pTableStream
;
6135 long nOldPos
= rStrm
.Tell();
6136 rStrm
.Seek( m_pWwFib
->m_fcGrpStAtnOwners
);
6138 long nRead
= 0, nCount
= m_pWwFib
->m_lcbGrpStAtnOwners
;
6139 while (nRead
< nCount
)
6143 m_pAtnNames
->push_back(read_uInt8_PascalString(rStrm
,
6144 RTL_TEXTENCODING_MS_1252
));
6145 nRead
+= m_pAtnNames
->rbegin()->getLength() + 1; // Length + sal_uInt8 count
6149 m_pAtnNames
->push_back(read_uInt16_PascalString(rStrm
));
6150 // Unicode: double the length + sal_uInt16 count
6151 nRead
+= (m_pAtnNames
->rbegin()->getLength() + 1)*2;
6154 rStrm
.Seek( nOldPos
);
6157 const OUString
*pRet
= nullptr;
6158 if (m_pAtnNames
&& nIdx
< m_pAtnNames
->size())
6159 pRet
= &((*m_pAtnNames
)[nIdx
]);
6163 void SwWW8ImplReader::GetSmartTagInfo(SwFltRDFMark
& rMark
)
6165 if (!m_pSmartTagData
&& m_pWwFib
->m_lcbFactoidData
)
6167 m_pSmartTagData
.reset(new WW8SmartTagData());
6168 m_pSmartTagData
->Read(*m_pTableStream
, m_pWwFib
->m_fcFactoidData
, m_pWwFib
->m_lcbFactoidData
);
6171 // Check if the handle is a valid smart tag bookmark index.
6172 size_t nIndex
= rMark
.GetHandle();
6173 if (nIndex
>= m_pSmartTagData
->m_aPropBags
.size())
6176 // Check if the smart tag bookmark refers to a valid factoid type.
6177 const MSOPropertyBag
& rPropertyBag
= m_pSmartTagData
->m_aPropBags
[rMark
.GetHandle()];
6178 auto itPropertyBag
= m_pSmartTagData
->m_aPropBagStore
.m_aFactoidTypes
.begin();
6179 for (; itPropertyBag
!= m_pSmartTagData
->m_aPropBagStore
.m_aFactoidTypes
.end(); ++itPropertyBag
)
6180 if (itPropertyBag
->m_nId
== rPropertyBag
.m_nId
)
6182 if (itPropertyBag
== m_pSmartTagData
->m_aPropBagStore
.m_aFactoidTypes
.end())
6185 // Check if the factoid is an RDF one.
6186 const MSOFactoidType
& rFactoidType
= *itPropertyBag
;
6187 if (rFactoidType
.m_aUri
!= "http://www.w3.org/1999/02/22-rdf-syntax-ns#")
6190 // Finally put the relevant attributes to the mark.
6191 std::vector
< std::pair
<OUString
, OUString
> > aAttributes
;
6192 for (const MSOProperty
& rProperty
: rPropertyBag
.m_aProperties
)
6196 if (rProperty
.m_nKey
< m_pSmartTagData
->m_aPropBagStore
.m_aStringTable
.size())
6197 aKey
= m_pSmartTagData
->m_aPropBagStore
.m_aStringTable
[rProperty
.m_nKey
];
6198 if (rProperty
.m_nValue
< m_pSmartTagData
->m_aPropBagStore
.m_aStringTable
.size())
6199 aValue
= m_pSmartTagData
->m_aPropBagStore
.m_aStringTable
[rProperty
.m_nValue
];
6200 if (!aKey
.isEmpty() && !aValue
.isEmpty())
6201 aAttributes
.push_back(std::make_pair(aKey
, aValue
));
6203 rMark
.SetAttributes(aAttributes
);
6206 sal_uLong
SwWW8ImplReader::LoadDoc(WW8Glossary
*pGloss
)
6208 sal_uLong nErrRet
= 0;
6211 static const sal_Char
* aNames
[ 13 ] = {
6212 "WinWord/WW", "WinWord/WW8", "WinWord/WWFT",
6213 "WinWord/WWFLX", "WinWord/WWFLY",
6215 "WinWord/WWFA0", "WinWord/WWFA1", "WinWord/WWFA2",
6216 "WinWord/WWFB0", "WinWord/WWFB1", "WinWord/WWFB2",
6217 "WinWord/RegardHindiDigits"
6219 sal_uInt64 aVal
[ 13 ];
6221 SwFilterOptions
aOpt( 13, aNames
, aVal
);
6223 m_nIniFlags
= aVal
[ 0 ];
6224 m_nIniFlags1
= aVal
[ 1 ];
6225 // Moves Flys by x twips to the right or left
6226 m_nIniFlyDx
= aVal
[ 3 ];
6227 m_nIniFlyDy
= aVal
[ 4 ];
6229 m_nFieldFlags
= aVal
[ 5 ];
6230 m_nFieldTagAlways
[0] = aVal
[ 6 ];
6231 m_nFieldTagAlways
[1] = aVal
[ 7 ];
6232 m_nFieldTagAlways
[2] = aVal
[ 8 ];
6233 m_nFieldTagBad
[0] = aVal
[ 9 ];
6234 m_nFieldTagBad
[1] = aVal
[ 10 ];
6235 m_nFieldTagBad
[2] = aVal
[ 11 ];
6236 m_bRegardHindiDigits
= aVal
[ 12 ] > 0;
6239 sal_uInt16
nMagic(0);
6240 m_pStrm
->ReadUInt16( nMagic
);
6242 // Remember: 6 means "6 OR 7", 7 means "JUST 7"
6243 switch (m_nWantedVersion
)
6248 0xa59b != nMagic
&& 0xa59c != nMagic
&&
6249 0xa5dc != nMagic
&& 0xa5db != nMagic
&&
6250 (nMagic
< 0xa697 || nMagic
> 0xa699)
6253 // Test for own 97 fake!
6254 if (m_pStg
&& 0xa5ec == nMagic
)
6256 sal_uLong nCurPos
= m_pStrm
->Tell();
6257 if (m_pStrm
->Seek(nCurPos
+ 22))
6260 m_pStrm
->ReadUInt32( nfcMin
);
6261 if (0x300 != nfcMin
)
6262 nErrRet
= ERR_WW6_NO_WW6_FILE_ERR
;
6264 m_pStrm
->Seek( nCurPos
);
6267 nErrRet
= ERR_WW6_NO_WW6_FILE_ERR
;
6271 if (0xa5ec != nMagic
)
6272 nErrRet
= ERR_WW8_NO_WW8_FILE_ERR
;
6275 nErrRet
= ERR_WW8_NO_WW8_FILE_ERR
;
6276 OSL_ENSURE( false, "We forgot to encode nVersion!" );
6281 nErrRet
= LoadThroughDecryption(pGloss
);
6283 m_rDoc
.PropagateOutlineRule();
6288 extern "C" SAL_DLLPUBLIC_EXPORT Reader
* SAL_CALL
ImportDOC()
6290 return new WW8Reader();
6293 extern "C" SAL_DLLPUBLIC_EXPORT
bool SAL_CALL
TestImportDOC(const OUString
&rURL
, const OUString
&rFltName
)
6295 Reader
*pReader
= ImportDOC();
6297 SvFileStream
aFileStream(rURL
, StreamMode::READ
);
6298 tools::SvRef
<SotStorage
> xStorage
;
6299 pReader
->pStrm
= &aFileStream
;
6300 if (rFltName
!= "WW6")
6302 xStorage
= tools::SvRef
<SotStorage
>(new SotStorage(aFileStream
));
6303 pReader
->pStg
= xStorage
.get();
6305 pReader
->SetFltName(rFltName
);
6307 SwGlobals::ensure();
6309 SfxObjectShellLock
xDocSh(new SwDocShell(SfxObjectCreateMode::INTERNAL
));
6310 xDocSh
->DoInitNew();
6311 SwDoc
*pD
= static_cast<SwDocShell
*>((&xDocSh
))->GetDoc();
6314 *pD
->GetNodes().GetEndOfContent().StartOfSectionNode(), 1);
6315 if( !aIdx
.GetNode().IsTextNode() )
6317 pD
->GetNodes().GoNext( &aIdx
);
6320 aPaM
.GetPoint()->nContent
.Assign(aIdx
.GetNode().GetContentNode(), 0);
6321 bool bRet
= pReader
->Read(*pD
, OUString(), aPaM
, OUString()) == 0;
6326 sal_uLong
WW8Reader::OpenMainStream( tools::SvRef
<SotStorageStream
>& rRef
, sal_uInt16
& rBuffSize
)
6328 sal_uLong nRet
= ERR_SWG_READ_ERROR
;
6329 OSL_ENSURE( pStg
.get(), "Where is my Storage?" );
6330 rRef
= pStg
->OpenSotStream( "WordDocument", StreamMode::READ
| StreamMode::SHARE_DENYALL
);
6334 if( SVSTREAM_OK
== rRef
->GetError() )
6336 sal_uInt16 nOld
= rRef
->GetBufferSize();
6337 rRef
->SetBufferSize( rBuffSize
);
6342 nRet
= rRef
->GetError();
6347 sal_uLong
WW8Reader::Read(SwDoc
&rDoc
, const OUString
& rBaseURL
, SwPaM
&rPaM
, const OUString
& /* FileName */)
6349 sal_uInt16 nOldBuffSize
= 32768;
6350 bool bNew
= !bInsertMode
; // New Doc (no inserting)
6352 tools::SvRef
<SotStorageStream
> refStrm
; // So that no one else can steal the Stream
6353 SvStream
* pIn
= pStrm
;
6356 sal_uInt8 nVersion
= 8;
6358 const OUString sFltName
= GetFltName();
6359 if ( sFltName
=="WW6" )
6365 OSL_ENSURE(false, "WinWord 95 Reader-Read without Stream");
6366 nRet
= ERR_SWG_READ_ERROR
;
6371 if ( sFltName
=="CWW6" )
6373 else if ( sFltName
=="CWW7" )
6378 nRet
= OpenMainStream( refStrm
, nOldBuffSize
);
6379 pIn
= refStrm
.get();
6383 OSL_ENSURE(false, "WinWord 95/97 Reader-Read without Storage");
6384 nRet
= ERR_SWG_READ_ERROR
;
6390 std::unique_ptr
<SwWW8ImplReader
> pRdr(new SwWW8ImplReader(nVersion
, pStg
.get(), pIn
, rDoc
,
6391 rBaseURL
, bNew
, bSkipImages
, *rPaM
.GetPoint()));
6394 // Remove Frame and offsets from Frame Template
6395 Reader::ResetFrameFormats( rDoc
);
6397 rPaM
.GetBound().nContent
.Assign(nullptr, 0);
6398 rPaM
.GetBound(false).nContent
.Assign(nullptr, 0);
6403 nRet
= pRdr
->LoadDoc();
6405 catch( const std::exception
& )
6407 nRet
= ERR_WW8_NO_WW8_FILE_ERR
;
6412 refStrm
->SetBufferSize( nOldBuffSize
);
6424 int WW8Reader::GetReaderType()
6426 return SW_STORAGE_READER
| SW_STREAM_READER
;
6429 bool WW8Reader::HasGlossaries() const
6434 bool WW8Reader::ReadGlossaries(SwTextBlocks
& rBlocks
, bool bSaveRelFiles
) const
6438 WW8Reader
*pThis
= const_cast<WW8Reader
*>(this);
6440 sal_uInt16 nOldBuffSize
= 32768;
6441 tools::SvRef
<SotStorageStream
> refStrm
;
6442 if (!pThis
->OpenMainStream(refStrm
, nOldBuffSize
))
6444 WW8Glossary
aGloss( refStrm
, 8, pStg
.get() );
6445 bRet
= aGloss
.Load( rBlocks
, bSaveRelFiles
);
6450 bool SwMSDffManager::GetOLEStorageName(long nOLEId
, OUString
& rStorageName
,
6451 tools::SvRef
<SotStorage
>& rSrcStorage
, uno::Reference
< embed::XStorage
>& rDestStorage
) const
6455 sal_Int32 nPictureId
= 0;
6458 // Via the TextBox-PLCF we get the right char Start-End positions
6459 // We should then find the EmbeddedField and the corresponding Sprms
6461 // We only need the Sprm for the Picture Id.
6462 long nOldPos
= rReader
.m_pStrm
->Tell();
6464 // #i32596# - consider return value of method
6465 // <rReader.GetTxbxTextSttEndCp(..)>. If it returns false, method
6466 // wasn't successful. Thus, continue in this case.
6467 // Note: Ask MM for initialization of <nStartCp> and <nEndCp>.
6468 // Note: Ask MM about assertions in method <rReader.GetTxbxTextSttEndCp(..)>.
6469 WW8_CP nStartCp
, nEndCp
;
6470 if ( rReader
.m_bDrawCpOValid
&& rReader
.GetTxbxTextSttEndCp(nStartCp
, nEndCp
,
6471 static_cast<sal_uInt16
>((nOLEId
>> 16) & 0xFFFF),
6472 static_cast<sal_uInt16
>(nOLEId
& 0xFFFF)) )
6474 WW8PLCFxSaveAll aSave
;
6475 memset( &aSave
, 0, sizeof( aSave
) );
6476 rReader
.m_pPlcxMan
->SaveAllPLCFx( aSave
);
6478 nStartCp
+= rReader
.m_nDrawCpO
;
6479 nEndCp
+= rReader
.m_nDrawCpO
;
6480 WW8PLCFx_Cp_FKP
* pChp
= rReader
.m_pPlcxMan
->GetChpPLCF();
6481 wwSprmParser
aSprmParser(*rReader
.m_pWwFib
);
6482 while (nStartCp
<= nEndCp
&& !nPictureId
)
6484 if (!pChp
->SeekPos( nStartCp
))
6487 pChp
->GetSprms( &aDesc
);
6489 if (aDesc
.nSprmsLen
&& aDesc
.pMemPos
) // Attributes present
6491 long nLen
= aDesc
.nSprmsLen
;
6492 const sal_uInt8
* pSprm
= aDesc
.pMemPos
;
6494 while (nLen
>= 2 && !nPictureId
)
6496 sal_uInt16 nId
= aSprmParser
.GetSprmId(pSprm
);
6497 sal_uInt16 nSL
= aSprmParser
.GetSprmSize(nId
, pSprm
, nLen
);
6500 break; // Not enough Bytes left
6502 if( 0x6A03 == nId
&& 0 < nLen
)
6504 nPictureId
= SVBT32ToUInt32(pSprm
+
6505 aSprmParser
.DistanceToData(nId
));
6512 nStartCp
= aDesc
.nEndPos
;
6515 rReader
.m_pPlcxMan
->RestoreAllPLCFx( aSave
);
6518 rReader
.m_pStrm
->Seek( nOldPos
);
6524 rStorageName
+= OUString::number(nPictureId
);
6525 rSrcStorage
= rReader
.m_pStg
->OpenSotStorage(OUString(
6527 if (!rReader
.m_pDocShell
)
6530 rDestStorage
= rReader
.m_pDocShell
->GetStorage();
6536 * When reading a single Box (which possibly is part of a group), we do
6537 * not yet have enough information to decide whether we need it as a TextField
6539 * So convert all of them as a precaution.
6540 * FIXME: Actually implement this!
6542 bool SwMSDffManager::ShapeHasText(sal_uLong
, sal_uLong
) const
6547 bool SwWW8ImplReader::InEqualOrHigherApo(int nLvl
) const
6551 // #i60827# - check size of <maApos> to assure that <maApos.begin() + nLvl> can be performed.
6552 if ( sal::static_int_cast
< sal_Int32
>(nLvl
) >= sal::static_int_cast
< sal_Int32
>(m_aApos
.size()) )
6556 mycApoIter aIter
= std::find(m_aApos
.begin() + nLvl
, m_aApos
.end(), true);
6557 if (aIter
!= m_aApos
.end())
6563 bool SwWW8ImplReader::InEqualApo(int nLvl
) const
6565 // If we are in a table, see if an apo was inserted at the level below the table.
6568 if (nLvl
< 0 || static_cast<size_t>(nLvl
) >= m_aApos
.size())
6570 return m_aApos
[nLvl
];
6577 Position::Position(const SwPosition
&rPos
)
6578 : maPtNode(rPos
.nNode
), mnPtContent(rPos
.nContent
.GetIndex())
6582 Position::Position(const Position
&rPos
)
6583 : maPtNode(rPos
.maPtNode
), mnPtContent(rPos
.mnPtContent
)
6587 Position::operator SwPosition() const
6589 SwPosition
aRet(maPtNode
);
6590 aRet
.nContent
.Assign(maPtNode
.GetNode().GetContentNode(), mnPtContent
);
6596 SwMacroInfo::SwMacroInfo()
6597 : SdrObjUserData( SdrInventor::ScOrSwDraw
, SW_UD_IMAPDATA
)
6602 SwMacroInfo::~SwMacroInfo()
6606 SdrObjUserData
* SwMacroInfo::Clone( SdrObject
* /*pObj*/ ) const
6608 return new SwMacroInfo( *this );
6611 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */