xref: /trunk/main/sw/source/filter/ww8/ww8par.cxx (revision 300d4866)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
27 
28 #include <com/sun/star/embed/ElementModes.hpp>
29 #include <com/sun/star/embed/XStorage.hpp>
30 
31 #include <hash_set>
32 #include <unotools/ucbstreamhelper.hxx>
33 #include <tools/solar.h>
34 #include <rtl/tencinfo.h>
35 #include <rtl/random.h>
36 
37 #include <sot/storage.hxx>
38 #include <sfx2/docinf.hxx>
39 #include <sfx2/docfile.hxx>
40 #include <sfx2/request.hxx>
41 #include <sfx2/frame.hxx>
42 #include <tools/urlobj.hxx>
43 #include <unotools/tempfile.hxx>
44 #include <svtools/sfxecode.hxx>
45 
46 #include <comphelper/docpasswordrequest.hxx>
47 #include <hintids.hxx>
48 
49 #include <editeng/tstpitem.hxx>
50 #include <editeng/cscoitem.hxx>
51 #include <svx/svdobj.hxx>
52 #include <svx/svdpage.hxx>
53 #include <editeng/paperinf.hxx>
54 #include <editeng/lrspitem.hxx> // SvxLRSpaceItem
55 #include <editeng/ulspitem.hxx>
56 #include <editeng/langitem.hxx>
57 #include <editeng/opaqitem.hxx>
58 #include <editeng/charhiddenitem.hxx>
59 #include <filter/msfilter/svxmsbas.hxx>
60 #include <svx/unoapi.hxx>
61 #include <svx/svdoole2.hxx>
62 #include <filter/msfilter/msdffimp.hxx>
63 #include <svx/svdoashp.hxx>
64 #include <svx/svxerr.hxx>
65 #include <filter/msfilter/mscodec.hxx>
66 #include <svx/svdmodel.hxx>
67 #include <svx/svdogrp.hxx>
68 #include <svx/xflclit.hxx>
69 
70 #include <unotools/fltrcfg.hxx>
71 #include <fmtfld.hxx>
72 #include <fmturl.hxx>
73 #include <fmtinfmt.hxx>
74 #include <IMark.hxx>
75 #include <reffld.hxx>
76 #include <fmthdft.hxx>
77 #include <fmtcntnt.hxx>
78 #include <fmtcnct.hxx>
79 #include <fmtanchr.hxx>
80 #include <fmtpdsc.hxx>
81 #include <ftninfo.hxx>
82 #include <fmtftn.hxx>
83 #include <txtftn.hxx>
84 #include <pam.hxx>              // fuer SwPam
85 #include <doc.hxx>
86 #include <ndtxt.hxx>            // class SwTxtNode
87 #include <pagedesc.hxx>         // class SwPageDesc
88 #include <paratr.hxx>
89 #include <fmtclds.hxx>
90 #include <fmtclbl.hxx>
91 #include <section.hxx>
92 #include <docsh.hxx>
93 #include <docufld.hxx>
94 #include <swfltopt.hxx>
95 #include <viewsh.hxx>
96 #include <shellres.hxx>
97 #include <mdiexp.hxx>           // Progress
98 #include <statstr.hrc>          // ResId fuer Statusleiste
99 #include <swerror.h>            // ERR_WW8_...
100 #include <swunodef.hxx>
101 #include <unodraw.hxx>
102 #include <swtable.hxx>          // class SwTableLines, ...
103 // #i18732#
104 #include <fmtfollowtextflow.hxx>
105 #include <fchrfmt.hxx>
106 #include <charfmt.hxx>
107 
108 
109 #include <com/sun/star/i18n/ForbiddenCharacters.hpp>
110 #include <comphelper/extract.hxx>
111 #include <comphelper/sequenceashashmap.hxx>
112 #include <fltini.hxx>
113 
114 #include <algorithm>
115 #include <functional>
116 #include "writerhelper.hxx"
117 #include "writerwordglue.hxx"
118 
119 #include "ndgrf.hxx"
120 #include <editeng/brshitem.hxx>
121 #include <editeng/editids.hrc>
122 #include <txtflcnt.hxx>
123 #include <fmtflcnt.hxx>
124 #include <txatbase.hxx>
125 
126 #include "ww8par2.hxx"          // class WW8RStyle, class WW8AnchorPara
127 
128 #include <frmatr.hxx>
129 
130 #include <math.h>
131 #include <com/sun/star/beans/XPropertyContainer.hpp>
132 
133 #include <com/sun/star/beans/PropertyAttribute.hpp>
134 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
135 #include <com/sun/star/document/XDocumentProperties.hpp>
136 #include <svl/itemiter.hxx>  //SfxItemIter
137 
138 #include <stdio.h>
139 
140 #ifdef DEBUG
141 #include <iostream>
142 #include <dbgoutsw.hxx>
143 #endif
144 #include <svx/hlnkitem.hxx>
145 #include "WW8Sttbf.hxx"
146 #include "WW8FibData.hxx"
147 #define MM_250 1417             // WW-Default fuer Hor. Seitenraender: 2.5 cm
148 #define MM_200 1134             // WW-Default fuer u.Seitenrand: 2.0 cm
149 
150 using namespace ::com::sun::star;
151 using namespace sw::util;
152 using namespace sw::types;
153 using namespace nsHdFtFlags;
154 
155 #define VT_EMPTY			0
156 #define VT_I4				3
157 #define VT_LPSTR			30
158 #define VT_LPWSTR			31
159 #define VT_BLOB 			65
160 #define VT_TYPEMASK 		0xFFF
161 /** Expands to a pointer behind the last element of a STATIC data array (like STL end()). */
162 #define STATIC_TABLE_END( array )   ((array)+STATIC_TABLE_SIZE(array))
163 /** Expands to the size of a STATIC data array. */
164 #define STATIC_TABLE_SIZE( array )  (sizeof(array)/sizeof(*(array)))
165 
GetMacroInfo(SdrObject * pObj,sal_Bool bCreate)166 SwMacroInfo* GetMacroInfo( SdrObject* pObj, sal_Bool bCreate )             // static
167 {
168 	if ( pObj )
169 	{
170 		sal_uInt16 nCount = pObj->GetUserDataCount();
171 	    	for( sal_uInt16 i = 0; i < nCount; i++ )
172 	    	{
173 	       	SdrObjUserData* pData = pObj->GetUserData( i );
174 	        	if( pData && pData->GetInventor() == SW_DRAWLAYER
175 	              	&& pData->GetId() == SW_UD_IMAPDATA)
176 	            		return dynamic_cast<SwMacroInfo*>(pData);
177 	    	}
178 	    	if ( bCreate )
179 	    	{
180 	       	SwMacroInfo* pData = new SwMacroInfo;
181 	        	pObj->InsertUserData( pData, 0 );
182 	        	return pData;
183 	    	}
184 	}
185 
186     	return 0;
187 };
188 
lclGetAbsPath(String & rPath,sal_uInt16 nLevel,SwDocShell * pDocShell)189 void lclGetAbsPath( String& rPath, sal_uInt16 nLevel, SwDocShell* pDocShell)
190 {
191 	String aTmpStr;
192     	while( nLevel )
193     	{
194        	aTmpStr.AppendAscii( "../" );
195         	--nLevel;
196     	}
197 	if(aTmpStr.Len())
198 		aTmpStr += rPath;
199 	else
200 		aTmpStr = rPath;
201 
202 	if(aTmpStr.Len())
203 	{
204        	bool bWasAbs = false;
205         	rPath = pDocShell->GetMedium()->GetURLObject().smartRel2Abs( aTmpStr, bWasAbs ).GetMainURL( INetURLObject::NO_DECODE );
206         	// full path as stored in SvxURLField must be encoded
207 	}
208 }
209 
lclIgnoreString32(SvMemoryStream & rStrm,bool b16Bit)210 void lclIgnoreString32( SvMemoryStream& rStrm, bool b16Bit )
211 {
212  	sal_uInt32 nChars;
213     	rStrm >> nChars;
214     	if( b16Bit )
215        	nChars *= 2;
216     	rStrm.SeekRel( nChars );
217 }
218 
ReadRawUniString(SvMemoryStream & rStrm,sal_uInt16 nChars,bool b16Bit)219 String SwWW8ImplReader::ReadRawUniString( SvMemoryStream& rStrm,sal_uInt16 nChars, bool b16Bit )
220 {
221 	// Fixed-size characters
222 	const sal_uInt8 WW8_NUL_C                   = '\x00';       /// NUL character.
223 	const sal_uInt16 WW8_NUL                    = WW8_NUL_C;    /// NUL character (unicode).
224 	String aRet;
225 	sal_Unicode         mcNulSubst = '\0';
226 
227 	sal_uInt16 nCharsLeft = nChars;
228 	sal_Unicode* pcBuffer = new sal_Unicode[ nCharsLeft + 1 ];
229 
230 	sal_Unicode* pcUniChar = pcBuffer;
231        sal_Unicode* pcEndChar = pcBuffer + nCharsLeft;
232 
233        if( b16Bit )
234        {
235        	sal_uInt16 nReadChar;
236             	for( ;  (pcUniChar < pcEndChar); ++pcUniChar )
237             	{
238               	rStrm >> (nReadChar);
239                 	(*pcUniChar) = (nReadChar == WW8_NUL) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar );
240             	}
241         }
242         else
243         {
244         	sal_uInt8 nReadChar;
245             	for( ; (pcUniChar < pcEndChar); ++pcUniChar )
246             	{
247               	rStrm >> nReadChar ;
248                 	(*pcUniChar) = (nReadChar == WW8_NUL_C) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar );
249             	}
250         }
251 
252        *pcEndChar = '\0';
253        aRet.Append( pcBuffer );
254 	delete[] pcBuffer;
255 	return aRet;
256 }
257 
lclAppendString32(String & rString,SvMemoryStream & rStrm,sal_uInt32 nChars,bool b16Bit)258 void lclAppendString32( String& rString, SvMemoryStream& rStrm, sal_uInt32 nChars, bool b16Bit )
259 {
260 	sal_uInt16 nReadChars = ulimit_cast< sal_uInt16 >( nChars );
261 	String urlStr = SwWW8ImplReader::ReadRawUniString( rStrm, nReadChars, b16Bit );
262     	rString.Append( urlStr );
263 }
264 
lclAppendString32(String & rString,SvMemoryStream & rStrm,bool b16Bit)265 void lclAppendString32( String& rString, SvMemoryStream& rStrm, bool b16Bit )
266 {
267 	sal_uInt32 nValue;
268     	rStrm >>( nValue );
269     	lclAppendString32( rString, rStrm, nValue, b16Bit );
270 }
271 
ReadEmbeddedData(SvMemoryStream & rStrm,SwDocShell * pDocShell,struct HyperLinksTable & hlStr)272 void SwWW8ImplReader::ReadEmbeddedData( SvMemoryStream& rStrm, SwDocShell* pDocShell, struct HyperLinksTable& hlStr)
273 {
274 	// (0x01B8) HLINK -------------------------------------------------------------
275 	// const sal_uInt16 WW8_ID_HLINK               = 0x01B8;
276 	const sal_uInt32 WW8_HLINK_BODY             = 0x00000001;   /// Contains file link or URL.
277 	const sal_uInt32 WW8_HLINK_ABS              = 0x00000002;   /// Absolute path.
278 	const sal_uInt32 WW8_HLINK_DESCR            = 0x00000014;   /// Description.
279 	const sal_uInt32 WW8_HLINK_MARK             = 0x00000008;   /// Text mark.
280 	const sal_uInt32 WW8_HLINK_FRAME            = 0x00000080;   /// Target frame.
281 	const sal_uInt32 WW8_HLINK_UNC              = 0x00000100;   /// UNC path.
282 
283 	//	sal_uInt8 maGuidStdLink[ 16 ] ={
284 	//		0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
285 
286 	sal_uInt8 maGuidUrlMoniker[ 16 ] = {
287 	    0xE0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
288 
289 	sal_uInt8 maGuidFileMoniker[ 16 ] = {
290 		0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
291 
292 	sal_uInt8*	aGuid = new sal_uInt8[ 16 ];
293 	sal_uInt32 nFlags;
294 
295 
296     	rStrm.Read( aGuid, 16);
297     	rStrm.SeekRel( 4 );
298     	rStrm >> nFlags;
299 
300     	sal_uInt16 nLevel = 0;                  // counter for level to climb down in path
301     	::std::auto_ptr< String > xLongName;    // link / file name
302     	::std::auto_ptr< String > xShortName;   // 8.3-representation of file name
303     	::std::auto_ptr< String > xTextMark;    // text mark
304 
305    	// description (ignore)
306     	if( ::get_flag( nFlags, WW8_HLINK_DESCR ) )
307        	lclIgnoreString32( rStrm, true );
308 
309    	// target frame
310     	if( ::get_flag( nFlags, WW8_HLINK_FRAME ) )
311 	{
312 		::std::auto_ptr< String > FrmName;
313 		FrmName.reset( new String );
314 		lclAppendString32(*FrmName , rStrm , true);
315 		hlStr.tarFrm = *FrmName;
316 	}
317 
318     	// UNC path
319    	if( ::get_flag( nFlags, WW8_HLINK_UNC ) )
320     	{
321        	xLongName.reset( new String );
322         	lclAppendString32( *xLongName, rStrm, true );
323 		lclGetAbsPath( *xLongName, 0 , pDocShell);
324     	}
325     	// file link or URL
326     	else if( ::get_flag( nFlags, WW8_HLINK_BODY ) )
327     	{
328     		rStrm.Read( aGuid, 16);
329 
330         	if( (memcmp(aGuid, maGuidFileMoniker, 16) == 0) )
331         	{
332             		rStrm >> nLevel;
333             		xShortName.reset( new String );
334 			lclAppendString32( *xShortName,rStrm, false );
335 			rStrm.SeekRel( 24 );
336 
337             		sal_uInt32 nStrLen;
338             		rStrm >> nStrLen;
339             		if( nStrLen )
340             		{
341 		                rStrm >> nStrLen;
342 		                nStrLen /= 2;
343 						rStrm.SeekRel( 2 );
344 		                xLongName.reset( new String );
345 				lclAppendString32( *xLongName, rStrm,nStrLen, true );
346 				lclGetAbsPath( *xLongName, nLevel, pDocShell);
347             		}
348             		else
349 				lclGetAbsPath( *xShortName, nLevel, pDocShell);
350         	}
351       		else 	if( (memcmp(aGuid, maGuidUrlMoniker, 16) == 0) )
352         	{
353 			sal_uInt32 nStrLen;
354             		rStrm >> nStrLen;
355             		nStrLen /= 2;
356             		xLongName.reset( new String );
357 			lclAppendString32( *xLongName,rStrm, nStrLen, true );
358             		if( !::get_flag( nFlags, WW8_HLINK_ABS ) )
359 				lclGetAbsPath( *xLongName, 0 ,pDocShell);
360         	}
361         	else
362 	        {
363 	            DBG_ERRORFILE( "WW8Hyperlink::ReadEmbeddedData - unknown content GUID" );
364 	        }
365 	}
366 
367 	// text mark
368     	if( ::get_flag( nFlags, WW8_HLINK_MARK ) )
369     	{
370        	xTextMark.reset( new String );
371         	lclAppendString32( *xTextMark, rStrm, true );
372     	}
373 
374 	if( !xLongName.get() && xShortName.get() )
375 	{
376 		xLongName.reset( new String );
377        	xLongName->Append(*xShortName);
378 	}
379     	else if( !xLongName.get() && xTextMark.get() )
380        	xLongName.reset( new String );
381 
382     	if( xLongName.get() )
383     	{
384        	if( xTextMark.get() )
385         	{
386             		if( xLongName->Len() == 0 )
387                 		xTextMark->SearchAndReplaceAll( '!', '.' );
388             		xLongName->Append( '#' );
389             		xLongName->Append( *xTextMark );
390         	}
391 		hlStr.hLinkAddr = *xLongName;
392     	}
393 }
394 
SwMSDffManager(SwWW8ImplReader & rRdr)395 SwMSDffManager::SwMSDffManager( SwWW8ImplReader& rRdr )
396     : SvxMSDffManager(*rRdr.pTableStream, rRdr.GetBaseURL(), rRdr.pWwFib->fcDggInfo,
397         rRdr.pDataStream, 0, 0, COL_WHITE, 12, rRdr.pStrm,
398         rRdr.maTracer.GetTrace()),
399     rReader(rRdr), pFallbackStream(0), pOldEscherBlipCache(0)
400 {
401     SetSvxMSDffSettings( GetSvxMSDffSettings() );
402     nSvxMSDffOLEConvFlags = SwMSDffManager::GetFilterFlags();
403 }
404 
GetFilterFlags()405 sal_uInt32 SwMSDffManager::GetFilterFlags()
406 {
407     sal_uInt32 nFlags(0);
408     if (const SvtFilterOptions* pOpt = SvtFilterOptions::Get())
409     {
410         if (pOpt->IsMathType2Math())
411             nFlags |= OLE_MATHTYPE_2_STARMATH;
412         if (pOpt->IsExcel2Calc())
413             nFlags |= OLE_EXCEL_2_STARCALC;
414         if (pOpt->IsPowerPoint2Impress())
415             nFlags |= OLE_POWERPOINT_2_STARIMPRESS;
416         if (pOpt->IsWinWord2Writer())
417             nFlags |= OLE_WINWORD_2_STARWRITER;
418     }
419     return nFlags;
420 }
421 
422 /*
423  * I would like to override the default OLE importing to add a test
424  * and conversion of OCX controls from their native OLE type into our
425  * native nonOLE Form Control Objects.
426  *
427  * cmc
428  */
429 // #i32596# - consider new parameter <_nCalledByGroup>
ImportOLE(long nOLEId,const Graphic & rGrf,const Rectangle & rBoundRect,const Rectangle & rVisArea,const int _nCalledByGroup,sal_Int64 nAspect) const430 SdrObject* SwMSDffManager::ImportOLE( long nOLEId,
431                                       const Graphic& rGrf,
432                                       const Rectangle& rBoundRect,
433 									  const Rectangle& rVisArea,
434                                       const int _nCalledByGroup,
435                                       sal_Int64 nAspect ) const
436 {
437     // #i32596# - no import of OLE object, if it's inside a group.
438     // NOTE: This can be undone, if grouping of Writer fly frames is possible or
439     // if drawing OLE objects are allowed in Writer.
440     if ( _nCalledByGroup > 0 )
441     {
442         return 0L;
443     }
444 
445     SdrObject* pRet = 0;
446     String sStorageName;
447     SotStorageRef xSrcStg;
448     uno::Reference < embed::XStorage > xDstStg;
449     if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg ))
450     {
451         SvStorageRef xSrc = xSrcStg->OpenSotStorage( sStorageName,
452             STREAM_READWRITE| STREAM_SHARE_DENYALL );
453         ASSERT(rReader.pFormImpl, "No Form Implementation!");
454         STAR_REFERENCE( drawing::XShape ) xShape;
455         if ( (!(rReader.bIsHeader || rReader.bIsFooter)) &&
456             rReader.pFormImpl->ReadOCXStream(xSrc,&xShape,true))
457         {
458             pRet = GetSdrObjectFromXShape(xShape);
459         }
460         else
461         {
462             ErrCode nError = ERRCODE_NONE;
463             pRet = CreateSdrOLEFromStorage( sStorageName, xSrcStg, xDstStg,
464                 rGrf, rBoundRect, rVisArea, pStData, nError, nSvxMSDffOLEConvFlags, nAspect );
465         }
466     }
467     return pRet;
468 }
469 
DisableFallbackStream()470 void SwMSDffManager::DisableFallbackStream()
471 {
472     ASSERT(!pFallbackStream || !pOldEscherBlipCache,
473         "if you're recursive, you're broken");
474     pFallbackStream = pStData2;
475     pOldEscherBlipCache = pEscherBlipCache;
476     pEscherBlipCache = 0;
477     pStData2 = 0;
478 }
479 
EnableFallbackStream()480 void SwMSDffManager::EnableFallbackStream()
481 {
482     pStData2 = pFallbackStream;
483     pEscherBlipCache = pOldEscherBlipCache;
484     pOldEscherBlipCache = 0;
485     pFallbackStream = 0;
486 }
487 
GetToggleAttrFlags() const488 sal_uInt16 SwWW8ImplReader::GetToggleAttrFlags() const
489 {
490 	return pCtrlStck ? pCtrlStck->GetToggleAttrFlags() : 0;
491 }
492 
GetToggleBiDiAttrFlags() const493 sal_uInt16 SwWW8ImplReader::GetToggleBiDiAttrFlags() const
494 {
495 	return pCtrlStck ? pCtrlStck->GetToggleBiDiAttrFlags() : 0;
496 }
497 
SetToggleAttrFlags(sal_uInt16 nFlags)498 void SwWW8ImplReader::SetToggleAttrFlags(sal_uInt16 nFlags)
499 {
500 	if (pCtrlStck)
501 		pCtrlStck->SetToggleAttrFlags(nFlags);
502 }
503 
SetToggleBiDiAttrFlags(sal_uInt16 nFlags)504 void SwWW8ImplReader::SetToggleBiDiAttrFlags(sal_uInt16 nFlags)
505 {
506 	if (pCtrlStck)
507 		pCtrlStck->SetToggleBiDiAttrFlags(nFlags);
508 }
509 
510 
ProcessObj(SvStream & rSt,DffObjData & rObjData,void * pData,Rectangle & rTextRect,SdrObject * pObj)511 SdrObject* SwMSDffManager::ProcessObj(SvStream& rSt,
512 									   DffObjData& rObjData,
513 									   void* pData,
514 									   Rectangle& rTextRect,
515 									   SdrObject* pObj
516 									   )
517 {
518 	if( !rTextRect.IsEmpty() )
519 	{
520 		SvxMSDffImportData& rImportData = *(SvxMSDffImportData*)pData;
521 		SvxMSDffImportRec* pImpRec = new SvxMSDffImportRec;
522 
523 		// fill Import Record with data
524 		pImpRec->nShapeId   = rObjData.nShapeId;
525 		pImpRec->eShapeType = rObjData.eShapeType;
526 
527 		rObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt,
528 											DFF_msofbtClientAnchor,
529 											SEEK_FROM_CURRENT_AND_RESTART );
530 		if( rObjData.bClientAnchor )
531 			ProcessClientAnchor( rSt,
532 					maShapeRecords.Current()->nRecLen,
533 					pImpRec->pClientAnchorBuffer, pImpRec->nClientAnchorLen );
534 
535 		rObjData.bClientData = maShapeRecords.SeekToContent( rSt,
536 											DFF_msofbtClientData,
537 											SEEK_FROM_CURRENT_AND_RESTART );
538 		if( rObjData.bClientData )
539 			ProcessClientData( rSt,
540 					maShapeRecords.Current()->nRecLen,
541 					pImpRec->pClientDataBuffer, pImpRec->nClientDataLen );
542 
543 
544         // process user (== Winword) defined parameters in 0xF122 record
545         // #i84783# - set special value to determine, if property is provided or not.
546         pImpRec->nLayoutInTableCell = 0xFFFFFFFF;
547         if(    maShapeRecords.SeekToContent( rSt,
548 											 DFF_msofbtUDefProp,
549 											 SEEK_FROM_CURRENT_AND_RESTART )
550 			&& maShapeRecords.Current()->nRecLen )
551 		{
552 			sal_uInt32  nBytesLeft = maShapeRecords.Current()->nRecLen;
553 			sal_uInt32	nUDData;
554 			sal_uInt16  nPID;
555 			while( 5 < nBytesLeft )
556 			{
557 				rSt >> nPID;
558 				if ( rSt.GetError() != 0 )
559 					break;
560 				rSt >> nUDData;
561 				switch( nPID )
562 				{
563 					case 0x038F: pImpRec->nXAlign = nUDData; break;
564 					case 0x0390: pImpRec->nXRelTo = nUDData; break;
565 					case 0x0391: pImpRec->nYAlign = nUDData; break;
566 					case 0x0392: pImpRec->nYRelTo = nUDData; break;
567                     case 0x03BF: pImpRec->nLayoutInTableCell = nUDData; break;
568 				}
569 				if ( rSt.GetError() != 0 )
570 					break;
571 				pImpRec->bHasUDefProp = sal_True;
572 				nBytesLeft  -= 6;
573 			}
574 		}
575 
576 		//  Textrahmen, auch Title oder Outline
577 		sal_uInt32 nTextId = GetPropertyValue( DFF_Prop_lTxid, 0 );
578 		if( nTextId )
579 		{
580 			SfxItemSet aSet( pSdrModel->GetItemPool() );
581 
582             //Originally anything that as a mso_sptTextBox was created as a
583             //textbox, this was changed to be created as a simple
584             //rect to keep impress happy. For the rest of us we'd like to turn
585             //it back into a textbox again.
586             sal_Bool bIsSimpleDrawingTextBox = (pImpRec->eShapeType == mso_sptTextBox);
587             if (!bIsSimpleDrawingTextBox)
588             {
589                 //Either
590                 //a) its a simple text object or
591                 //b) its a rectangle with text and square wrapping.
592                 bIsSimpleDrawingTextBox =
593                 (
594                     (pImpRec->eShapeType == mso_sptTextSimple) ||
595                     (
596                         (pImpRec->eShapeType == mso_sptRectangle)
597                         // && (eWrapMode == mso_wrapSquare)
598                         && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() )
599                     )
600                 );
601             }
602 
603             // Distance of Textbox to it's surrounding Autoshape
604 			sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 91440L);
605 			sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 91440L );
606 			sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 45720L  );
607 			sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 45720L );
608 
609 			ScaleEmu( nTextLeft );
610 			ScaleEmu( nTextRight );
611 			ScaleEmu( nTextTop );
612 			ScaleEmu( nTextBottom );
613 
614             sal_Int32 nTextRotationAngle=0;
615             bool bVerticalText = false;
616             if ( IsProperty( DFF_Prop_txflTextFlow ) )
617             {
618                 MSO_TextFlow eTextFlow = (MSO_TextFlow)(GetPropertyValue(
619                     DFF_Prop_txflTextFlow) & 0xFFFF);
620                 switch( eTextFlow )
621                 {
622                     case mso_txflBtoT:
623                         nTextRotationAngle = 9000;
624                     break;
625                     case mso_txflVertN:
626                     case mso_txflTtoBN:
627                         nTextRotationAngle = 27000;
628                         break;
629                     case mso_txflTtoBA:
630                         bVerticalText = true;
631                     break;
632                     case mso_txflHorzA:
633                         bVerticalText = true;
634                         nTextRotationAngle = 9000;
635                     case mso_txflHorzN:
636                     default :
637                         break;
638                 }
639             }
640 
641             if (nTextRotationAngle)
642 			{
643                 while (nTextRotationAngle > 360000)
644                     nTextRotationAngle-=9000;
645                 switch (nTextRotationAngle)
646                 {
647                     case 9000:
648                         {
649                             long nWidth = rTextRect.GetWidth();
650                             rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight();
651                             rTextRect.Bottom() = rTextRect.Top() + nWidth;
652 
653                             sal_Int32 nOldTextLeft = nTextLeft;
654                             sal_Int32 nOldTextRight = nTextRight;
655                             sal_Int32 nOldTextTop = nTextTop;
656                             sal_Int32 nOldTextBottom = nTextBottom;
657 
658                             nTextLeft = nOldTextBottom;
659                             nTextRight = nOldTextTop;
660                             nTextTop = nOldTextLeft;
661                             nTextBottom = nOldTextRight;
662                         }
663                         break;
664                     case 27000:
665                         {
666                             long nWidth = rTextRect.GetWidth();
667                             rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight();
668                             rTextRect.Bottom() = rTextRect.Top() + nWidth;
669 
670                             sal_Int32 nOldTextLeft = nTextLeft;
671                             sal_Int32 nOldTextRight = nTextRight;
672                             sal_Int32 nOldTextTop = nTextTop;
673                             sal_Int32 nOldTextBottom = nTextBottom;
674 
675                             nTextLeft = nOldTextTop;
676                             nTextRight = nOldTextBottom;
677                             nTextTop = nOldTextRight;
678                             nTextBottom = nOldTextLeft;
679                         }
680                         break;
681                     default:
682                         break;
683                 }
684 			}
685 
686             if (bIsSimpleDrawingTextBox)
687             {
688                 SdrObject::Free( pObj );
689 				pObj = new SdrRectObj(OBJ_TEXT, rTextRect);
690             }
691 
692             // Die vertikalen Absatzeinrueckungen sind im BoundRect mit drin,
693             // hier rausrechnen
694             Rectangle aNewRect(rTextRect);
695 			aNewRect.Bottom() -= nTextTop + nTextBottom;
696             aNewRect.Right() -= nTextLeft + nTextRight;
697 
698 			// Nur falls es eine einfache Textbox ist, darf der Writer
699 			// das Objekt durch einen Rahmen ersetzen, ansonsten
700 			if( bIsSimpleDrawingTextBox )
701 			{
702 				SvxMSDffShapeInfo aTmpRec( 0, pImpRec->nShapeId );
703 				aTmpRec.bSortByShapeId = sal_True;
704 
705 				sal_uInt16 nFound;
706 				if( GetShapeInfos()->Seek_Entry( &aTmpRec, &nFound ) )
707 				{
708 					SvxMSDffShapeInfo& rInfo = *GetShapeInfos()->GetObject(nFound);
709 					pImpRec->bReplaceByFly   = rInfo.bReplaceByFly;
710 					pImpRec->bLastBoxInChain = rInfo.bLastBoxInChain;
711 				}
712 			}
713 
714 			if( bIsSimpleDrawingTextBox )
715                 ApplyAttributes( rSt, aSet, rObjData );
716 
717             bool bFitText = false;
718             if (GetPropertyValue(DFF_Prop_FitTextToShape) & 2)
719             {
720                 aSet.Put( SdrTextAutoGrowHeightItem( sal_True ) );
721                 aSet.Put( SdrTextMinFrameHeightItem(
722                     aNewRect.Bottom() - aNewRect.Top() ) );
723                 aSet.Put( SdrTextMinFrameWidthItem(
724                     aNewRect.Right() - aNewRect.Left() ) );
725                 bFitText = true;
726             }
727             else
728             {
729                 aSet.Put( SdrTextAutoGrowHeightItem( sal_False ) );
730                 aSet.Put( SdrTextAutoGrowWidthItem( sal_False ) );
731             }
732 
733 			switch ( (MSO_WrapMode)
734                 GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) )
735 			{
736 				case mso_wrapNone :
737     				aSet.Put( SdrTextAutoGrowWidthItem( sal_True ) );
738                     pImpRec->bAutoWidth = true;
739 				break;
740 				case mso_wrapByPoints :
741 					aSet.Put( SdrTextContourFrameItem( sal_True ) );
742 				break;
743 				default:
744 					;
745 			}
746 
747 			// Abstaende an den Raendern der Textbox setzen
748 			aSet.Put( SdrTextLeftDistItem( nTextLeft ) );
749 			aSet.Put( SdrTextRightDistItem( nTextRight ) );
750 			aSet.Put( SdrTextUpperDistItem( nTextTop ) );
751 			aSet.Put( SdrTextLowerDistItem( nTextBottom ) );
752 			pImpRec->nDxTextLeft	= nTextLeft;
753 			pImpRec->nDyTextTop		= nTextTop;
754 			pImpRec->nDxTextRight	= nTextRight;
755 			pImpRec->nDyTextBottom	= nTextBottom;
756 
757 			// --> SJ 2009-03-06 : taking the correct default (which is mso_anchorTop)
758 			MSO_Anchor eTextAnchor =
759                 (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop );
760 
761             SdrTextVertAdjust eTVA = bVerticalText
762                                      ? SDRTEXTVERTADJUST_BLOCK
763                                      : SDRTEXTVERTADJUST_CENTER;
764             SdrTextHorzAdjust eTHA = bVerticalText
765                                      ? SDRTEXTHORZADJUST_CENTER
766                                      : SDRTEXTHORZADJUST_BLOCK;
767 
768 			switch( eTextAnchor )
769             {
770                 case mso_anchorTop:
771                 {
772                     if ( bVerticalText )
773                         eTHA = SDRTEXTHORZADJUST_RIGHT;
774                     else
775                         eTVA = SDRTEXTVERTADJUST_TOP;
776                 }
777                 break;
778                 case mso_anchorTopCentered:
779                 {
780                     if ( bVerticalText )
781                         eTHA = SDRTEXTHORZADJUST_RIGHT;
782                     else
783                         eTVA = SDRTEXTVERTADJUST_TOP;
784                 }
785                 break;
786                 case mso_anchorMiddle:
787                 break;
788                 case mso_anchorMiddleCentered:
789                 break;
790                 case mso_anchorBottom:
791                 {
792                     if ( bVerticalText )
793                         eTHA = SDRTEXTHORZADJUST_LEFT;
794                     else
795                         eTVA = SDRTEXTVERTADJUST_BOTTOM;
796                 }
797                 break;
798                 case mso_anchorBottomCentered:
799                 {
800                     if ( bVerticalText )
801                         eTHA = SDRTEXTHORZADJUST_LEFT;
802                     else
803                         eTVA = SDRTEXTVERTADJUST_BOTTOM;
804                 }
805                 break;
806 /*
807 				case mso_anchorTopBaseline:
808 				case mso_anchorBottomBaseline:
809 				case mso_anchorTopCenteredBaseline:
810 				case mso_anchorBottomCenteredBaseline:
811 				break;
812 */
813 				default:
814 					;
815 			}
816 
817             aSet.Put( SdrTextVertAdjustItem( eTVA ) );
818             aSet.Put( SdrTextHorzAdjustItem( eTHA ) );
819 
820             if (pObj != NULL)
821             {
822                 pObj->SetMergedItemSet(aSet);
823                 pObj->SetModel(pSdrModel);
824 
825                 if (bVerticalText && dynamic_cast< SdrTextObj* >( pObj ) )
826                     dynamic_cast< SdrTextObj* >( pObj )->SetVerticalWriting(sal_True);
827 
828                 if ( bIsSimpleDrawingTextBox )
829                 {
830                     if ( nTextRotationAngle )
831                     {
832                         long nMinWH = rTextRect.GetWidth() < rTextRect.GetHeight() ?
833                             rTextRect.GetWidth() : rTextRect.GetHeight();
834                         nMinWH /= 2;
835                         Point aPivot(rTextRect.TopLeft());
836                         aPivot.X() += nMinWH;
837                         aPivot.Y() += nMinWH;
838                         double a = nTextRotationAngle * nPi180;
839                         pObj->NbcRotate(aPivot, nTextRotationAngle, sin(a), cos(a));
840                     }
841                 }
842 
843                 if ( ( ( rObjData.nSpFlags & SP_FFLIPV ) || mnFix16Angle || nTextRotationAngle ) && dynamic_cast< SdrObjCustomShape* >( pObj ) )
844                 {
845                     SdrObjCustomShape* pCustomShape = dynamic_cast< SdrObjCustomShape* >( pObj );
846 
847                     double fExtraTextRotation = 0.0;
848                     if ( mnFix16Angle && !( GetPropertyValue( DFF_Prop_FitTextToShape ) & 4 ) )
849                     {	// text is already rotated, we have to take back the object rotation if DFF_Prop_RotateText is false
850                         fExtraTextRotation = -mnFix16Angle;
851                     }
852                     if ( rObjData.nSpFlags & SP_FFLIPV )	// sj: in ppt the text is flipped, whereas in word the text
853                     {										// remains unchanged, so we have to take back the flipping here
854                         fExtraTextRotation += 18000.0;		// because our core will flip text if the shape is flipped.
855                     }
856                     fExtraTextRotation += nTextRotationAngle;
857                     if ( !::basegfx::fTools::equalZero( fExtraTextRotation ) )
858                     {
859                         fExtraTextRotation /= 100.0;
860                         SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
861                         const rtl::OUString	sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) );
862                         com::sun::star::beans::PropertyValue aPropVal;
863                         aPropVal.Name = sTextRotateAngle;
864                         aPropVal.Value <<= fExtraTextRotation;
865                         aGeometryItem.SetPropertyValue( aPropVal );
866                         pCustomShape->SetMergedItem( aGeometryItem );
867                     }
868                 }
869                 else if ( mnFix16Angle )
870                 {
871                     // rotate text with shape ?
872                     double a = mnFix16Angle * nPi180;
873                     pObj->NbcRotate( rObjData.aBoundRect.Center(), mnFix16Angle,
874                                      sin( a ), cos( a ) );
875                 }
876             }
877         }
878 		else if( !pObj )
879 		{
880 			// simple rectangular objects are ignored by ImportObj()  :-(
881 			// this is OK for Draw but not for Calc and Writer
882 			// cause here these objects have a default border
883 			pObj = new SdrRectObj(rTextRect);
884 			pObj->SetModel( pSdrModel );
885             SfxItemSet aSet( pSdrModel->GetItemPool() );
886             ApplyAttributes( rSt, aSet, rObjData );
887 
888 			const SfxPoolItem* pPoolItem=NULL;
889 			SfxItemState eState = aSet.GetItemState( XATTR_FILLCOLOR,
890 													 sal_False, &pPoolItem );
891 			if( SFX_ITEM_DEFAULT == eState )
892 				aSet.Put( XFillColorItem( String(),
893 						  Color( mnDefaultColor ) ) );
894 			pObj->SetMergedItemSet(aSet);
895 		}
896 
897         //Means that fBehindDocument is set
898         if (GetPropertyValue(DFF_Prop_fPrint) & 0x20)
899 		    pImpRec->bDrawHell = sal_True;
900         else
901 		    pImpRec->bDrawHell = sal_False;
902         if (GetPropertyValue(DFF_Prop_fPrint) & 0x02)
903             pImpRec->bHidden = sal_True;
904 		pImpRec->nNextShapeId	= GetPropertyValue( DFF_Prop_hspNext, 0 );
905 
906 		if ( nTextId )
907 		{
908 			pImpRec->aTextId.nTxBxS = (sal_uInt16)( nTextId >> 16 );
909 			pImpRec->aTextId.nSequence = (sal_uInt16)nTextId;
910 		}
911 
912 		pImpRec->nDxWrapDistLeft = GetPropertyValue(
913 									DFF_Prop_dxWrapDistLeft, 114935L ) / 635L;
914 		pImpRec->nDyWrapDistTop = GetPropertyValue(
915 									DFF_Prop_dyWrapDistTop, 0 ) / 635L;
916 		pImpRec->nDxWrapDistRight = GetPropertyValue(
917 									DFF_Prop_dxWrapDistRight, 114935L ) / 635L;
918 		pImpRec->nDyWrapDistBottom = GetPropertyValue(
919 									DFF_Prop_dyWrapDistBottom, 0 ) / 635L;
920         // 16.16 fraction times total image width or height, as appropriate.
921 
922         if (SeekToContent(DFF_Prop_pWrapPolygonVertices, rSt))
923         {
924             delete pImpRec->pWrapPolygon;
925             pImpRec->pWrapPolygon = NULL;
926 
927             sal_uInt16 nNumElemVert, nNumElemMemVert, nElemSizeVert;
928             rSt >> nNumElemVert >> nNumElemMemVert >> nElemSizeVert;
929             if (nNumElemVert && ((nElemSizeVert == 8) || (nElemSizeVert == 4)))
930             {
931                 pImpRec->pWrapPolygon = new Polygon(nNumElemVert);
932                 for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
933                 {
934                     sal_Int32 nX, nY;
935                     if (nElemSizeVert == 8)
936                         rSt >> nX >> nY;
937                     else
938                     {
939                         sal_Int16 nSmallX, nSmallY;
940                         rSt >> nSmallX >> nSmallY;
941                         nX = nSmallX;
942                         nY = nSmallY;
943                     }
944                     (*(pImpRec->pWrapPolygon))[i].X() = nX;
945                     (*(pImpRec->pWrapPolygon))[i].Y() = nY;
946                 }
947             }
948         }
949 
950 		pImpRec->nCropFromTop = GetPropertyValue(
951 									DFF_Prop_cropFromTop, 0 );
952 		pImpRec->nCropFromBottom = GetPropertyValue(
953 									DFF_Prop_cropFromBottom, 0 );
954 		pImpRec->nCropFromLeft = GetPropertyValue(
955 									DFF_Prop_cropFromLeft, 0 );
956 		pImpRec->nCropFromRight = GetPropertyValue(
957 									DFF_Prop_cropFromRight, 0 );
958 
959         sal_uInt32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash );
960         if ( !IsHardAttribute( DFF_Prop_fLine ) &&
961              pImpRec->eShapeType == mso_sptPictureFrame )
962         {
963             nLineFlags &= ~0x08;
964         }
965         pImpRec->eLineStyle = (nLineFlags & 8)
966                               ? (MSO_LineStyle)GetPropertyValue(
967                                                     DFF_Prop_lineStyle,
968                                                     mso_lineSimple )
969                               : (MSO_LineStyle)USHRT_MAX;
970 
971 		pImpRec->nFlags = rObjData.nSpFlags;
972 
973 		if( pImpRec->nShapeId )
974 		{
975 			// Import-Record-Liste ergaenzen
976 			pImpRec->pObj = pObj;
977 			rImportData.aRecords.Insert( pImpRec );
978 
979 			// Eintrag in Z-Order-Liste um Zeiger auf dieses Objekt ergaenzen
980 			/*Only store objects which are not deep inside the tree*/
981 			if( ( rObjData.nCalledByGroup == 0 )
982 				||
983 				( (rObjData.nSpFlags & SP_FGROUP)
984 				 && (rObjData.nCalledByGroup < 2) )
985 			  )
986 				StoreShapeOrder( pImpRec->nShapeId,
987 								( ( (sal_uLong)pImpRec->aTextId.nTxBxS ) << 16 )
988 									+ pImpRec->aTextId.nSequence, pObj );
989 		}
990 		else
991 			delete pImpRec;
992 	}
993 
994 	sal_uInt32 nBufferSize = GetPropertyValue( DFF_Prop_pihlShape );
995 	 if( (0 < nBufferSize) && (nBufferSize <= 0xFFFF) && SeekToContent( DFF_Prop_pihlShape, rSt ) )
996 	{
997 		SvMemoryStream aMemStream;
998 		String aStrURL;
999 		struct HyperLinksTable hlStr;
1000 		sal_uInt16 mnRawRecId,mnRawRecSize;
1001 		aMemStream << sal_uInt16( 0 ) << static_cast< sal_uInt16 >( nBufferSize );
1002 
1003 		// copy from DFF stream to memory stream
1004 		::std::vector< sal_uInt8 > aBuffer( nBufferSize );
1005 		sal_uInt8* pnData = &aBuffer.front();
1006 		sal_uInt8 mnStreamSize;
1007 		if( pnData && rSt.Read( pnData, nBufferSize ) == nBufferSize )
1008 		{
1009 			aMemStream.Write( pnData, nBufferSize );
1010 			aMemStream.Seek( STREAM_SEEK_TO_END );
1011 			mnStreamSize = aMemStream.Tell();
1012 			aMemStream.Seek( STREAM_SEEK_TO_BEGIN );
1013 			bool bRet =  4 <= mnStreamSize;
1014 			if( bRet )
1015 				aMemStream >> mnRawRecId >> mnRawRecSize;
1016 			SwDocShell* pDocShell = rReader.mpDocShell;
1017 			if(pDocShell)
1018 			{
1019 				rReader.ReadEmbeddedData( aMemStream, pDocShell, hlStr);
1020 			}
1021 		}
1022 
1023 		if(pObj && hlStr.hLinkAddr.Len() > 0)
1024 		{
1025 			SwMacroInfo* pInfo = GetMacroInfo( pObj, true );
1026 			if( pInfo )
1027 			{
1028 				pInfo->SetShapeId( rObjData.nShapeId );
1029 				pInfo->SetHlink( hlStr.hLinkAddr );
1030 				if(hlStr.tarFrm.Len() > 0)
1031 					pInfo->SetTarFrm( hlStr.tarFrm );
1032 				String aNameStr = GetPropertyString( DFF_Prop_wzName, rSt );
1033 				if(aNameStr.Len() > 0)
1034 					pInfo->SetName( aNameStr );
1035 			}
1036 		}
1037     	}
1038 
1039 	return pObj;
1040 }
1041 
1042 /***************************************************************************
1043 #  Spezial FastSave - Attribute
1044 #**************************************************************************/
1045 
Read_StyleCode(sal_uInt16,const sal_uInt8 * pData,short nLen)1046 void SwWW8ImplReader::Read_StyleCode( sal_uInt16, const sal_uInt8* pData, short nLen )
1047 {
1048     if (nLen < 0)
1049     {
1050         bCpxStyle = false;
1051         return;
1052     }
1053     sal_uInt16 nColl = 0;
1054     if (pWwFib->GetFIBVersion() <= ww::eWW2)
1055         nColl = *pData;
1056     else
1057         nColl = SVBT16ToShort(pData);
1058     if (nColl < nColls)
1059     {
1060         SetTxtFmtCollAndListLevel( *pPaM, pCollA[nColl] );
1061         bCpxStyle = true;
1062     }
1063 }
1064 
1065 // Read_Majority ist fuer Majority ( 103 ) und Majority50 ( 108 )
Read_Majority(sal_uInt16,const sal_uInt8 *,short)1066 void SwWW8ImplReader::Read_Majority( sal_uInt16, const sal_uInt8* , short )
1067 {
1068 }
1069 
1070 //-----------------------------------------
1071 //            Stack
1072 //-----------------------------------------
NewAttr(const SwPosition & rPos,const SfxPoolItem & rAttr)1073 void SwWW8FltControlStack::NewAttr(const SwPosition& rPos,
1074     const SfxPoolItem& rAttr)
1075 {
1076     ASSERT(RES_TXTATR_FIELD != rAttr.Which(), "probably don't want to put"
1077         "fields into the control stack");
1078     ASSERT(RES_TXTATR_ANNOTATION != rAttr.Which(), "probably don't want to put"
1079         "annotations into the control stack");
1080     ASSERT(RES_TXTATR_INPUTFIELD != rAttr.Which(), "probably don't want to put"
1081         "input fields into the control stack");
1082     ASSERT(RES_FLTR_REDLINE != rAttr.Which(), "probably don't want to put"
1083         "redlines into the control stack");
1084     SwFltControlStack::NewAttr(rPos, rAttr);
1085 }
1086 
SetAttr(const SwPosition & rPos,sal_uInt16 nAttrId,sal_Bool bTstEnde,long nHand,sal_Bool)1087 void SwWW8FltControlStack::SetAttr(const SwPosition& rPos, sal_uInt16 nAttrId,
1088     sal_Bool bTstEnde, long nHand, sal_Bool )
1089 {
1090     //Doing a textbox, and using the control stack only as a temporary
1091     //collection point for properties which will are not to be set into
1092     //the real document
1093     if (rReader.pPlcxMan && rReader.pPlcxMan->GetDoingDrawTextBox())
1094     {
1095         sal_uInt16 nCnt = static_cast< sal_uInt16 >(Count());
1096         for (sal_uInt16 i=0; i < nCnt; ++i)
1097         {
1098             SwFltStackEntry* pEntry = (*this)[i];
1099             if (nAttrId == pEntry->pAttr->Which())
1100             {
1101                 DeleteAndDestroy(i--);
1102                 --nCnt;
1103             }
1104         }
1105     }
1106     else //Normal case, set the attribute into the document
1107         SwFltControlStack::SetAttr(rPos, nAttrId, bTstEnde, nHand);
1108 }
1109 
GetListFirstLineIndent(const SwNumFmt & rFmt)1110 long GetListFirstLineIndent(const SwNumFmt &rFmt)
1111 {
1112     ASSERT( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
1113             "<GetListFirstLineIndent> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
1114 
1115     SvxAdjust eAdj = rFmt.GetNumAdjust();
1116     long nReverseListIndented;
1117     if (eAdj == SVX_ADJUST_RIGHT)
1118         nReverseListIndented = -rFmt.GetCharTextDistance();
1119     else if (eAdj == SVX_ADJUST_CENTER)
1120         nReverseListIndented = rFmt.GetFirstLineOffset()/2;
1121     else
1122         nReverseListIndented = rFmt.GetFirstLineOffset();
1123     return nReverseListIndented;
1124 }
1125 
lcl_GetTrueMargin(const SvxLRSpaceItem & rLR,const SwNumFmt & rFmt,long & rFirstLinePos)1126 long lcl_GetTrueMargin(const SvxLRSpaceItem &rLR, const SwNumFmt &rFmt,
1127     long &rFirstLinePos)
1128 {
1129     ASSERT( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
1130             "<lcl_GetTrueMargin> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
1131 
1132     const long nBodyIndent = rLR.GetTxtLeft();
1133     const long nFirstLineDiff = rLR.GetTxtFirstLineOfst();
1134     rFirstLinePos = nBodyIndent + nFirstLineDiff;
1135 
1136     const long nPseudoListBodyIndent = rFmt.GetAbsLSpace();
1137     const long nReverseListIndented = GetListFirstLineIndent(rFmt);
1138     long nExtraListIndent = nPseudoListBodyIndent + nReverseListIndented;
1139 
1140     return nExtraListIndent > 0 ? nExtraListIndent : 0;
1141 }
1142 
SyncIndentWithList(SvxLRSpaceItem & rLR,const SwNumFmt & rFmt,const bool bFirstLineOfstSet,const bool bLeftIndentSet)1143 void SyncIndentWithList( SvxLRSpaceItem &rLR,
1144                          const SwNumFmt &rFmt,
1145                          const bool bFirstLineOfstSet,
1146                          const bool bLeftIndentSet )
1147 {
1148     if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1149     {
1150         long nWantedFirstLinePos;
1151         long nExtraListIndent = lcl_GetTrueMargin(rLR, rFmt, nWantedFirstLinePos);
1152         rLR.SetTxtLeft(nWantedFirstLinePos - nExtraListIndent);
1153         rLR.SetTxtFirstLineOfst(0);
1154     }
1155     else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
1156     {
1157         if ( !bFirstLineOfstSet && bLeftIndentSet &&
1158              rFmt.GetFirstLineIndent() != 0 )
1159         {
1160             rLR.SetTxtFirstLineOfst( rFmt.GetFirstLineIndent() );
1161         }
1162         else if ( bFirstLineOfstSet && !bLeftIndentSet &&
1163                   rFmt.GetIndentAt() != 0 )
1164         {
1165             rLR.SetTxtLeft( rFmt.GetIndentAt() );
1166         }
1167         else if (!bFirstLineOfstSet && !bLeftIndentSet )
1168         {
1169             if ( rFmt.GetFirstLineIndent() != 0 )
1170             {
1171                 rLR.SetTxtFirstLineOfst( rFmt.GetFirstLineIndent() );
1172             }
1173             if ( rFmt.GetIndentAt() != 0 )
1174             {
1175                 rLR.SetTxtLeft( rFmt.GetIndentAt() );
1176             }
1177         }
1178     }
1179 }
1180 
GetNumFmtFromStack(const SwPosition & rPos,const SwTxtNode & rTxtNode)1181 const SwNumFmt* SwWW8FltControlStack::GetNumFmtFromStack(const SwPosition &rPos,
1182     const SwTxtNode &rTxtNode)
1183 {
1184     const SwNumFmt *pRet = 0;
1185     const SfxPoolItem *pItem = GetStackAttr(rPos, RES_FLTR_NUMRULE);
1186     if (pItem && rTxtNode.GetNumRule())
1187     {
1188         String sName(((SfxStringItem*)pItem)->GetValue());
1189         if (rTxtNode.IsCountedInList())
1190         {
1191             const SwNumRule *pRule = pDoc->FindNumRulePtr(sName);
1192             sal_uInt8 nLvl = static_cast< sal_uInt8 >(rTxtNode.GetActualListLevel());
1193             pRet = &(pRule->Get(nLvl));
1194         }
1195     }
1196     return pRet;
1197 }
1198 
1199 //Modify here for #119405, by easyfan, 2012-05-24
GetCurrAttrCP() const1200 sal_Int32 SwWW8FltControlStack::GetCurrAttrCP() const
1201 {
1202 	return rReader.GetCurrAttrCP();
1203 }
IsParaEndInCPs(sal_Int32 nStart,sal_Int32 nEnd,bool bSdOD) const1204 bool SwWW8FltControlStack::IsParaEndInCPs(sal_Int32 nStart,sal_Int32 nEnd,bool bSdOD) const
1205 {
1206 	return rReader.IsParaEndInCPs(nStart,nEnd,bSdOD);
1207 }
1208 //End of modification, by easyfan
1209 //Modify for #119405 by chengjh, 2012-08-16
1210 //Clear the para end position recorded in reader intermittently for the least impact on loading performance
ClearParaEndPosition()1211 void SwWW8FltControlStack::ClearParaEndPosition()
1212 {
1213 	if ( Count() != 0 )
1214 		return;
1215 
1216 	rReader.ClearParaEndPosition();
1217 }
CheckSdOD(sal_Int32 nStart,sal_Int32 nEnd)1218 bool SwWW8FltControlStack::CheckSdOD(sal_Int32 nStart,sal_Int32 nEnd)
1219 {
1220 	return rReader.IsParaEndInCPs(nStart,nEnd);
1221 }
1222 //End
1223 
SetAttrInDoc(const SwPosition & rTmpPos,SwFltStackEntry * pEntry)1224 void SwWW8ReferencedFltEndStack::SetAttrInDoc( const SwPosition& rTmpPos,
1225                                                SwFltStackEntry* pEntry )
1226 {
1227     switch( pEntry->pAttr->Which() )
1228     {
1229     case RES_FLTR_BOOKMARK:
1230         {
1231             // suppress insertion of bookmark, which is recognized as an internal bookmark used for table-of-content
1232             // and which is not referenced.
1233             bool bInsertBookmarkIntoDoc = true;
1234 
1235             SwFltBookmark* pFltBookmark = dynamic_cast<SwFltBookmark*>(pEntry->pAttr);
1236             if ( pFltBookmark != 0 && pFltBookmark->IsTOCBookmark() )
1237             {
1238                 const String& rName = pFltBookmark->GetName();
1239                 ::std::set< String, SwWW8::ltstr >::const_iterator aResult = aReferencedTOCBookmarks.find(rName);
1240                 if ( aResult == aReferencedTOCBookmarks.end() )
1241                 {
1242                     bInsertBookmarkIntoDoc = false;
1243                 }
1244             }
1245             if ( bInsertBookmarkIntoDoc )
1246             {
1247                 SwFltEndStack::SetAttrInDoc( rTmpPos, pEntry );
1248             }
1249             break;
1250         }
1251     default:
1252         SwFltEndStack::SetAttrInDoc( rTmpPos, pEntry );
1253         break;
1254     }
1255 
1256 }
1257 
SetAttrInDoc(const SwPosition & rTmpPos,SwFltStackEntry * pEntry)1258 void SwWW8FltControlStack::SetAttrInDoc(const SwPosition& rTmpPos,
1259     SwFltStackEntry* pEntry)
1260 {
1261     switch( pEntry->pAttr->Which() )
1262     {
1263         case RES_LR_SPACE:
1264             {
1265                 /*
1266                  Loop over the affect nodes and
1267                  a) convert the word style absolute indent to indent relative
1268                   to any numbering indent active on the nodes
1269                  b) adjust the writer style tabstops relative to the old
1270                   paragraph indent to be relative to the new paragraph indent
1271                 */
1272                 using namespace sw::util;
1273                 SwPaM aRegion(rTmpPos);
1274                 if (pEntry->MakeRegion(pDoc, aRegion, false))
1275                 {
1276                     SvxLRSpaceItem aNewLR( *(SvxLRSpaceItem*)pEntry->pAttr );
1277                     sal_uLong nStart = aRegion.Start()->nNode.GetIndex();
1278                     sal_uLong nEnd   = aRegion.End()->nNode.GetIndex();
1279                     for(; nStart <= nEnd; ++nStart)
1280                     {
1281                         SwNode* pNode = pDoc->GetNodes()[ nStart ];
1282                         if (!pNode || !pNode->IsTxtNode())
1283                             continue;
1284 
1285                         SwCntntNode* pNd = (SwCntntNode*)pNode;
1286                         SvxLRSpaceItem aOldLR = (const SvxLRSpaceItem&)pNd->GetAttr(RES_LR_SPACE);
1287 
1288                         SwTxtNode *pTxtNode = (SwTxtNode*)pNode;
1289 
1290                         const SwNumFmt *pNum = 0;
1291                         pNum = GetNumFmtFromStack( *aRegion.GetPoint(), *pTxtNode );
1292                         if (!pNum)
1293                         {
1294                             pNum = GetNumFmtFromTxtNode(*pTxtNode);
1295                         }
1296 
1297                         if ( pNum )
1298                         {
1299                             const bool bFirstLineIndentSet =
1300                                 ( rReader.maTxtNodesHavingFirstLineOfstSet.end() !=
1301                                     rReader.maTxtNodesHavingFirstLineOfstSet.find( pNode ) );
1302                             const bool bLeftIndentSet =
1303                                 (  rReader.maTxtNodesHavingLeftIndentSet.end() !=
1304                                     rReader.maTxtNodesHavingLeftIndentSet.find( pNode ) );
1305                             SyncIndentWithList( aNewLR, *pNum,
1306                                                 bFirstLineIndentSet,
1307                                                 bLeftIndentSet );
1308                         }
1309 
1310                         if (aNewLR == aOldLR)
1311                             continue;
1312 
1313                         pNd->SetAttr(aNewLR);
1314 
1315                     }
1316                 }
1317             }
1318             break;
1319 
1320         case RES_TXTATR_FIELD:
1321             ASSERT(sal_False, "What is a field doing in the control stack,"
1322                 "probably should have been in the endstack");
1323             break;
1324 
1325         case RES_TXTATR_ANNOTATION:
1326             ASSERT(sal_False, "What is a annotation doing in the control stack,"
1327                 "probably should have been in the endstack");
1328             break;
1329 
1330         case RES_TXTATR_INPUTFIELD:
1331             ASSERT(sal_False, "What is a input field doing in the control stack,"
1332                 "probably should have been in the endstack");
1333             break;
1334 
1335         case RES_TXTATR_INETFMT:
1336             {
1337                 SwPaM aRegion(rTmpPos);
1338                 if (pEntry->MakeRegion(pDoc, aRegion, false))
1339                 {
1340                     SwFrmFmt *pFrm;
1341                     //If we have just one single inline graphic then
1342                     //don't insert a field for the single frame, set
1343                     //the frames hyperlink field attribute directly.
1344                     if (0 != (pFrm = rReader.ContainsSingleInlineGraphic(aRegion)))
1345                     {
1346                         const SwFmtINetFmt *pAttr = (const SwFmtINetFmt *)
1347                             pEntry->pAttr;
1348                         SwFmtURL aURL;
1349                         aURL.SetURL(pAttr->GetValue(), false);
1350                         aURL.SetTargetFrameName(pAttr->GetTargetFrame());
1351                         pFrm->SetFmtAttr(aURL);
1352                     }
1353                     else
1354                     {
1355                         pDoc->InsertPoolItem(aRegion, *pEntry->pAttr, 0);
1356                     }
1357                 }
1358             }
1359             break;
1360         default:
1361             SwFltControlStack::SetAttrInDoc(rTmpPos, pEntry);
1362             break;
1363     }
1364 }
1365 
GetFmtAttr(const SwPosition & rPos,sal_uInt16 nWhich)1366 const SfxPoolItem* SwWW8FltControlStack::GetFmtAttr(const SwPosition& rPos,
1367     sal_uInt16 nWhich)
1368 {
1369     const SfxPoolItem *pItem = GetStackAttr(rPos, nWhich);
1370     if (!pItem)
1371     {
1372         SwCntntNode const*const pNd = rPos.nNode.GetNode().GetCntntNode();
1373         if (!pNd)
1374             pItem = &pDoc->GetAttrPool().GetDefaultItem(nWhich);
1375         else
1376         {
1377             /*
1378             If we're hunting for the indent on a paragraph and need to use the
1379             parent style indent, then return the indent in msword format, and
1380             not writer format, because that's the style that the filter works
1381             in (naturally)
1382             */
1383             if (nWhich == RES_LR_SPACE)
1384             {
1385                 SfxItemState eState = SFX_ITEM_DEFAULT;
1386                 if (const SfxItemSet *pSet = pNd->GetpSwAttrSet())
1387                     eState = pSet->GetItemState(RES_LR_SPACE, false);
1388                 if (eState != SFX_ITEM_SET && rReader.pCollA != NULL)
1389                     pItem = &(rReader.pCollA[rReader.nAktColl].maWordLR);
1390             }
1391 
1392             if (!pItem)
1393                 pItem = &pNd->GetAttr(nWhich);
1394         }
1395     }
1396     return pItem;
1397 }
1398 
GetStackAttr(const SwPosition & rPos,sal_uInt16 nWhich)1399 const SfxPoolItem* SwWW8FltControlStack::GetStackAttr(const SwPosition& rPos,
1400     sal_uInt16 nWhich)
1401 {
1402     SwNodeIndex aNode( rPos.nNode, -1 );
1403     sal_uInt16 nIdx = rPos.nContent.GetIndex();
1404 
1405     sal_uInt16 nSize = static_cast< sal_uInt16 >(Count());
1406     while (nSize)
1407     {
1408         const SwFltStackEntry* pEntry = (*this)[ --nSize ];
1409         if (pEntry->pAttr->Which() == nWhich)
1410         {
1411             if ( (pEntry->bLocked) || (
1412                 (pEntry->nMkNode <= aNode) && (pEntry->nPtNode >= aNode) &&
1413                 (pEntry->nMkCntnt <= nIdx) && (pEntry->nPtCntnt >= nIdx) ) )
1414             {
1415                 return (const SfxPoolItem*)pEntry->pAttr;
1416             }
1417         }
1418     }
1419     return 0;
1420 }
1421 
IsFtnEdnBkmField(const SwFmtFld & rFmtFld,sal_uInt16 & rBkmNo)1422 bool SwWW8FltRefStack::IsFtnEdnBkmField(
1423     const SwFmtFld& rFmtFld,
1424     sal_uInt16& rBkmNo)
1425 {
1426     const SwField* pFld = rFmtFld.GetField();
1427     sal_uInt16 nSubType;
1428     if(pFld && (RES_GETREFFLD == pFld->Which())
1429         && ((REF_FOOTNOTE == (nSubType = pFld->GetSubType())) || (REF_ENDNOTE  == nSubType))
1430         && ((SwGetRefField*)pFld)->GetSetRefName().Len())
1431     {
1432         const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1433         IDocumentMarkAccess::const_iterator_t ppBkmk =
1434             pMarkAccess->findMark( ((SwGetRefField*)pFld)->GetSetRefName() );
1435         if(ppBkmk != pMarkAccess->getAllMarksEnd())
1436         {
1437             // find Sequence No of corresponding Foot-/Endnote
1438             rBkmNo = ppBkmk - pMarkAccess->getAllMarksBegin();
1439             return true;
1440         }
1441     }
1442     return false;
1443 }
1444 
SetAttrInDoc(const SwPosition & rTmpPos,SwFltStackEntry * pEntry)1445 void SwWW8FltRefStack::SetAttrInDoc(const SwPosition& rTmpPos,
1446         SwFltStackEntry* pEntry)
1447 {
1448     switch( pEntry->pAttr->Which() )
1449     {
1450         /*
1451         Look up these in our lists of bookmarks that were changed to
1452         variables, and replace the ref field with a var field, otherwise
1453         do normal (?) strange stuff
1454         */
1455         case RES_TXTATR_FIELD:
1456         case RES_TXTATR_ANNOTATION:
1457         case RES_TXTATR_INPUTFIELD:
1458         {
1459             SwNodeIndex aIdx(pEntry->nMkNode, 1);
1460             SwPaM aPaM(aIdx, pEntry->nMkCntnt);
1461 
1462             SwFmtFld& rFmtFld   = *(SwFmtFld*)pEntry->pAttr;
1463             SwField* pFld = rFmtFld.GetField();
1464 
1465             if (!RefToVar(pFld,pEntry))
1466             {
1467                 sal_uInt16 nBkmNo;
1468                 if( IsFtnEdnBkmField(rFmtFld, nBkmNo) )
1469                 {
1470                     ::sw::mark::IMark const * const pMark = (pDoc->getIDocumentMarkAccess()->getAllMarksBegin() + nBkmNo)->get();
1471 
1472                     const SwPosition& rBkMrkPos = pMark->GetMarkPos();
1473 
1474                     SwTxtNode* pTxt = rBkMrkPos.nNode.GetNode().GetTxtNode();
1475                     if( pTxt && rBkMrkPos.nContent.GetIndex() )
1476                     {
1477                         SwTxtAttr* const pFtn = pTxt->GetTxtAttrForCharAt(
1478                             rBkMrkPos.nContent.GetIndex()-1, RES_TXTATR_FTN );
1479                         if( pFtn )
1480                         {
1481                             sal_uInt16 nRefNo = ((SwTxtFtn*)pFtn)->GetSeqRefNo();
1482 
1483                             ((SwGetRefField*)pFld)->SetSeqNo( nRefNo );
1484 
1485                             if( pFtn->GetFtn().IsEndNote() )
1486                                 ((SwGetRefField*)pFld)->SetSubType(REF_ENDNOTE);
1487                         }
1488                     }
1489                 }
1490             }
1491 
1492             pDoc->InsertPoolItem(aPaM, *pEntry->pAttr, 0);
1493             MoveAttrs(*aPaM.GetPoint());
1494         }
1495         break;
1496         case RES_FLTR_TOX:
1497             SwFltEndStack::SetAttrInDoc(rTmpPos, pEntry);
1498             break;
1499         default:
1500         case RES_FLTR_BOOKMARK:
1501             ASSERT(sal_False, "EndStck used with non field, not what we want");
1502             SwFltEndStack::SetAttrInDoc(rTmpPos, pEntry);
1503             break;
1504     }
1505 }
1506 
1507 /*
1508  For styles we will do our tabstop arithmetic in word style and adjust them to
1509  writer style after all the styles have been finished and the dust settles as
1510  to what affects what.
1511 
1512  For explicit attributes we turn the adjusted writer tabstops back into 0 based
1513  word indexes and we'll turn them back into writer indexes when setting them
1514  into the document. If explicit left indent exist which affects them, then this
1515  is handled when the explict left indent is set into the document
1516 */
Read_Tab(sal_uInt16,const sal_uInt8 * pData,short nLen)1517 void SwWW8ImplReader::Read_Tab(sal_uInt16 , const sal_uInt8* pData, short nLen)
1518 {
1519     if (nLen < 0)
1520     {
1521         pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_TABSTOP);
1522         return;
1523     }
1524 
1525     short i;
1526     const sal_uInt8* pDel = pData + 1;                       // Del - Array
1527     sal_uInt8 nDel = pData[0];
1528     const sal_uInt8* pIns = pData + 2*nDel + 2;          // Ins - Array
1529     sal_uInt8 nIns = pData[nDel*2+1];
1530     WW8_TBD* pTyp = (WW8_TBD*)(pData + 2*nDel + 2*nIns + 2);// Typ - Array
1531 
1532     SvxTabStopItem aAttr(0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP);
1533 
1534     const SwTxtFmtColl* pSty = 0;
1535     sal_uInt16 nTabBase;
1536     if (pAktColl)               // StyleDef
1537     {
1538         nTabBase = pCollA[nAktColl].nBase;
1539         if (nTabBase < nColls)              // Based On
1540             pSty = (const SwTxtFmtColl*)pCollA[nTabBase].pFmt;
1541     }
1542     else
1543     {                                       // Text
1544         nTabBase = nAktColl;
1545         pSty = (const SwTxtFmtColl*)pCollA[nAktColl].pFmt;
1546     }
1547 
1548     bool bFound = false;
1549 	::std::hash_set<size_t> aLoopWatch;
1550     while (pSty && !bFound)
1551     {
1552         const SfxPoolItem* pTabs;
1553         bFound = pSty->GetAttrSet().GetItemState(RES_PARATR_TABSTOP, false,
1554             &pTabs) == SFX_ITEM_SET;
1555         if( bFound )
1556             aAttr = *((const SvxTabStopItem*)pTabs);
1557         else
1558         {
1559 
1560             sal_uInt16 nOldTabBase = nTabBase;
1561             // If based on another
1562             if (nTabBase < nColls)
1563                 nTabBase = pCollA[nTabBase].nBase;
1564 
1565             if (
1566                     nTabBase < nColls &&
1567                     nOldTabBase != nTabBase &&
1568                     nTabBase != ww::stiNil
1569                )
1570             {
1571 				// #i61789: Stop searching when next style is the same as the
1572 				// current one (prevent loop)
1573 				aLoopWatch.insert(reinterpret_cast<size_t>(pSty));
1574                 pSty = (const SwTxtFmtColl*)pCollA[nTabBase].pFmt;
1575 
1576 				if (aLoopWatch.find(reinterpret_cast<size_t>(pSty)) !=
1577 					aLoopWatch.end())
1578 					pSty = 0;
1579             }
1580             else
1581                 pSty = 0;                           // gib die Suche auf
1582         }
1583     }
1584 
1585     SvxTabStop aTabStop;
1586     for (i=0; i < nDel; ++i)
1587     {
1588         sal_uInt16 nPos = aAttr.GetPos(SVBT16ToShort(pDel + i*2));
1589         if( nPos != SVX_TAB_NOTFOUND )
1590             aAttr.Remove( nPos, 1 );
1591     }
1592 
1593     for (i=0; i < nIns; ++i)
1594     {
1595         short nPos = SVBT16ToShort(pIns + i*2);
1596         aTabStop.GetTabPos() = nPos;
1597         switch( SVBT8ToByte( pTyp[i].aBits1 ) & 0x7 )       // pTyp[i].jc
1598         {
1599             case 0:
1600                 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_LEFT;
1601                 break;
1602             case 1:
1603                 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_CENTER;
1604                 break;
1605             case 2:
1606                 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_RIGHT;
1607                 break;
1608             case 3:
1609                 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_DECIMAL;
1610                 break;
1611             case 4:
1612                 continue;                   // ignoriere Bar
1613         }
1614 
1615         switch( SVBT8ToByte( pTyp[i].aBits1 ) >> 3 & 0x7 )
1616         {
1617             case 0:
1618                 aTabStop.GetFill() = ' ';
1619                 break;
1620             case 1:
1621                 aTabStop.GetFill() = '.';
1622                 break;
1623             case 2:
1624                 aTabStop.GetFill() = '-';
1625                 break;
1626             case 3:
1627             case 4:
1628                 aTabStop.GetFill() = '_';
1629                 break;
1630         }
1631 
1632         sal_uInt16 nPos2 = aAttr.GetPos( nPos );
1633         if (nPos2 != SVX_TAB_NOTFOUND)
1634             aAttr.Remove(nPos2, 1); // sonst weigert sich das Insert()
1635         aAttr.Insert(aTabStop);
1636     }
1637 
1638     if (nIns || nDel)
1639         NewAttr(aAttr);
1640     else
1641     {
1642         //Here we have a tab definition which inserts no extra tabs, or deletes
1643         //no existing tabs. An older version of writer is probably the creater
1644         //of the document  :-( . So if we are importing a style we can just
1645         //ignore it. But if we are importing into text we cannot as during
1646         //text SwWW8ImplReader::Read_Tab is called at the begin and end of
1647         //the range the attrib affects, and ignoring it would upset the
1648         //balance
1649         if (!pAktColl)  //not importing into a style
1650         {
1651             using namespace sw::util;
1652             SvxTabStopItem aOrig = pSty ?
1653             ItemGet<SvxTabStopItem>(*pSty, RES_PARATR_TABSTOP) :
1654             DefaultItemGet<SvxTabStopItem>(rDoc, RES_PARATR_TABSTOP);
1655             NewAttr(aOrig);
1656         }
1657     }
1658 }
1659 
1660 //-----------------------------------------
1661 //              DOP
1662 //-----------------------------------------
1663 
ImportDop()1664 void SwWW8ImplReader::ImportDop()
1665 {
1666     maTracer.EnterEnvironment(sw::log::eDocumentProperties);
1667     // correct the LastPrinted date in DocumentInfo
1668     uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1669         mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
1670     uno::Reference<document::XDocumentProperties> xDocuProps(
1671         xDPS->getDocumentProperties());
1672     DBG_ASSERT(xDocuProps.is(), "DocumentProperties is null");
1673     if (xDocuProps.is())
1674     {
1675         DateTime aLastPrinted(
1676             sw::ms::DTTM2DateTime(pWDop->dttmLastPrint));
1677        ::util::DateTime uDT(aLastPrinted.Get100Sec(),
1678             aLastPrinted.GetSec(), aLastPrinted.GetMin(),
1679             aLastPrinted.GetHour(), aLastPrinted.GetDay(),
1680             aLastPrinted.GetMonth(), aLastPrinted.GetYear());
1681         xDocuProps->setPrintDate(uDT);
1682     }
1683 
1684     //
1685     // COMPATIBILITY FLAGS START
1686     //
1687 
1688 	// #i78951# - remember the unknown compatibility options
1689 	// so as to export them out
1690 	rDoc.Setn32DummyCompatabilityOptions1( pWDop->GetCompatabilityOptions());
1691 	rDoc.Setn32DummyCompatabilityOptions2( pWDop->GetCompatabilityOptions2());
1692 
1693     // Abstand zwischen zwei Absaetzen ist die SUMME von unterem
1694     // Abst. des ersten und oberem Abst. des zweiten
1695     rDoc.set(IDocumentSettingAccess::PARA_SPACE_MAX, pWDop->fDontUseHTMLAutoSpacing);
1696     rDoc.set(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES, true );
1697     maTracer.Log(sw::log::eDontUseHTMLAutoSpacing);
1698     // move tabs on alignment
1699     rDoc.set(IDocumentSettingAccess::TAB_COMPAT, true);
1700     // #i24363# tab stops relative to indent
1701     rDoc.set(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT, false);
1702     maTracer.Log(sw::log::eTabStopDistance);
1703     // #i18732# - adjust default of option 'FollowTextFlow'
1704     rDoc.SetDefault( SwFmtFollowTextFlow( sal_False ) );
1705 
1706     // Import Default-Tabs
1707     long nDefTabSiz = pWDop->dxaTab;
1708     if( nDefTabSiz < 56 )
1709         nDefTabSiz = 709;
1710 
1711     // wir wollen genau einen DefaultTab
1712     SvxTabStopItem aNewTab( 1, sal_uInt16(nDefTabSiz), SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
1713     ((SvxTabStop&)aNewTab[0]).GetAdjustment() = SVX_TAB_ADJUST_DEFAULT;
1714 
1715     rDoc.GetAttrPool().SetPoolDefaultItem( aNewTab );
1716 
1717     if (!pWDop->fUsePrinterMetrics)
1718         maTracer.Log(sw::log::ePrinterMetrics);
1719 
1720     if (!pWDop->fNoLeading)
1721         maTracer.Log(sw::log::eExtraLeading);
1722 
1723     rDoc.set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, !pWDop->fUsePrinterMetrics);
1724     rDoc.set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, true);
1725     rDoc.set(IDocumentSettingAccess::ADD_FLY_OFFSETS, true );
1726     rDoc.set(IDocumentSettingAccess::ADD_EXT_LEADING, !pWDop->fNoLeading);
1727 
1728     rDoc.set(IDocumentSettingAccess::OLD_NUMBERING, false);
1729 
1730     // #i47448#
1731     rDoc.set(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, false);
1732 
1733     // #i49277#
1734     rDoc.set(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, !pWDop->fExpShRtn); // #i56856#
1735     // #i53199#
1736     rDoc.set(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, false);
1737 
1738     rDoc.set(IDocumentSettingAccess::OLD_LINE_SPACING, false);
1739 
1740     // #i25901#- set new compatibility option 'Add paragraph and table spacing at bottom of table cells'
1741     rDoc.set(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS, true);
1742 
1743     // #i11860# - set new compatibility option 'Use former object positioning' to <sal_False>
1744     rDoc.set(IDocumentSettingAccess::USE_FORMER_OBJECT_POS, false);
1745 
1746     // #i27767# - set new compatibility option 'Conder Wrapping mode when positioning object' to <sal_True>
1747     rDoc.set(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION, true);
1748 
1749     // #i13832#, #i24135#
1750     rDoc.set(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING, false);
1751 
1752     rDoc.set(IDocumentSettingAccess::TABLE_ROW_KEEP, true);
1753 
1754     // #i3952#
1755     rDoc.set(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, true);
1756 
1757     //
1758     // COMPATIBILITY FLAGS END
1759     //
1760 
1761     if (!pWDop->fNoLeading)
1762         maTracer.Log(sw::log::eExtraLeading);
1763 
1764     //import magic doptypography information, if its there
1765     if (pWwFib->nFib > 105)
1766         ImportDopTypography(pWDop->doptypography);
1767 
1768     // disable form design mode to be able to use imported controls directly
1769     // #i31239# always disable form design mode, not only in protected docs
1770     {
1771         using namespace com::sun::star;
1772 
1773         uno::Reference<lang::XComponent> xModelComp(mpDocShell->GetModel(),
1774            uno::UNO_QUERY);
1775         uno::Reference<beans::XPropertySet> xDocProps(xModelComp,
1776            uno::UNO_QUERY);
1777         if (xDocProps.is())
1778         {
1779             uno::Reference<beans::XPropertySetInfo> xInfo =
1780                 xDocProps->getPropertySetInfo();
1781             sal_Bool bValue = false;
1782             if (xInfo.is())
1783             {
1784                 if (xInfo->hasPropertyByName(C2U("ApplyFormDesignMode")))
1785                 {
1786                     xDocProps->setPropertyValue(C2U("ApplyFormDesignMode"),
1787                                                 cppu::bool2any(bValue));
1788                 }
1789             }
1790         }
1791     }
1792 
1793     mpDocShell->SetModifyPasswordHash(pWDop->lKeyProtDoc);
1794 
1795     {
1796         const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
1797         const sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
1798         if (bUseEnhFields)
1799         {
1800             rDoc.set(IDocumentSettingAccess::PROTECT_FORM, pWDop->fProtEnabled );
1801         }
1802     }
1803 
1804     maTracer.LeaveEnvironment(sw::log::eDocumentProperties);
1805 }
1806 
ImportDopTypography(const WW8DopTypography & rTypo)1807 void SwWW8ImplReader::ImportDopTypography(const WW8DopTypography &rTypo)
1808 {
1809     using namespace com::sun::star;
1810     switch (rTypo.iLevelOfKinsoku)
1811     {
1812         case 2: //custom
1813             {
1814                 i18n::ForbiddenCharacters aForbidden(rTypo.rgxchFPunct,
1815                     rTypo.rgxchLPunct);
1816                 rDoc.setForbiddenCharacters(rTypo.GetConvertedLang(),
1817                         aForbidden);
1818                 //Obviously cannot set the standard level 1 for japanese, so
1819                 //bail out now while we can.
1820                 if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESE)
1821                     return;
1822             }
1823             break;
1824         default:
1825             break;
1826     }
1827 
1828     /*
1829     This MS hack means that level 2 of japanese is not in operation, so we put
1830     in what we know are the MS defaults, there is a complementary reverse
1831     hack in the writer. Its our default as well, but we can set it anyway
1832     as a flag for later.
1833     */
1834     if (!rTypo.reserved2)
1835     {
1836         i18n::ForbiddenCharacters aForbidden(rTypo.GetJapanNotBeginLevel1(),
1837             rTypo.GetJapanNotEndLevel1());
1838         rDoc.setForbiddenCharacters(LANGUAGE_JAPANESE,aForbidden);
1839     }
1840 
1841     rDoc.set(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION, rTypo.fKerningPunct);
1842     rDoc.setCharacterCompressionType(static_cast<SwCharCompressType>(rTypo.iJustification));
1843 }
1844 
1845 //-----------------------------------------
1846 //      Fuss- und Endnoten
1847 
1848 //-----------------------------------------
1849 
WW8ReaderSave(SwWW8ImplReader * pRdr,WW8_CP nStartCp)1850 WW8ReaderSave::WW8ReaderSave(SwWW8ImplReader* pRdr ,WW8_CP nStartCp) :
1851     maTmpPos(*pRdr->pPaM->GetPoint()),
1852 	mpOldStck(pRdr->pCtrlStck),
1853     mpOldAnchorStck(pRdr->pAnchorStck),
1854 	mpOldRedlines(pRdr->mpRedlineStack),
1855     mpOldPlcxMan(pRdr->pPlcxMan),
1856 	mpWFlyPara(pRdr->pWFlyPara),
1857     mpSFlyPara(pRdr->pSFlyPara),
1858 	mpPreviousNumPaM(pRdr->pPreviousNumPaM),
1859     mpPrevNumRule(pRdr->pPrevNumRule),
1860 	mpTableDesc(pRdr->pTableDesc),
1861     mnInTable(pRdr->nInTable),
1862 	mnAktColl(pRdr->nAktColl),
1863     mcSymbol(pRdr->cSymbol),
1864     mbIgnoreText(pRdr->bIgnoreText),
1865 	mbSymbol(pRdr->bSymbol),
1866     mbHdFtFtnEdn(pRdr->bHdFtFtnEdn),
1867 	mbTxbxFlySection(pRdr->bTxbxFlySection),
1868     mbAnl(pRdr->bAnl),
1869 	mbInHyperlink(pRdr->bInHyperlink),
1870     mbPgSecBreak(pRdr->bPgSecBreak),
1871 	mbWasParaEnd(pRdr->bWasParaEnd),
1872     mbHasBorder(pRdr->bHasBorder),
1873     mbFirstPara(pRdr->bFirstPara)
1874 {
1875     pRdr->bSymbol = false;
1876     pRdr->bHdFtFtnEdn = true;
1877     pRdr->bTxbxFlySection = pRdr->bAnl = pRdr->bPgSecBreak = pRdr->bWasParaEnd
1878         = pRdr->bHasBorder = false;
1879     pRdr->bFirstPara = true;
1880     pRdr->nInTable = 0;
1881     pRdr->pWFlyPara = 0;
1882     pRdr->pSFlyPara = 0;
1883     pRdr->pPreviousNumPaM = 0;
1884     pRdr->pPrevNumRule = 0;
1885     pRdr->pTableDesc = 0;
1886     pRdr->nAktColl = 0;
1887 
1888 
1889     pRdr->pCtrlStck = new SwWW8FltControlStack(&pRdr->rDoc, pRdr->nFieldFlags,
1890         *pRdr);
1891 
1892     pRdr->mpRedlineStack = new sw::util::RedlineStack(pRdr->rDoc);
1893 
1894     pRdr->pAnchorStck = new SwWW8FltAnchorStack(&pRdr->rDoc, pRdr->nFieldFlags);
1895 
1896     // rette die Attributverwaltung: dies ist noetig, da der neu anzulegende
1897     // PLCFx Manager natuerlich auf die gleichen FKPs zugreift, wie der alte
1898     // und deren Start-End-Positionen veraendert...
1899     if (pRdr->pPlcxMan)
1900         pRdr->pPlcxMan->SaveAllPLCFx(maPLCFxSave);
1901 
1902     if (nStartCp != -1)
1903     {
1904         pRdr->pPlcxMan = new WW8PLCFMan(pRdr->pSBase,
1905             mpOldPlcxMan->GetManType(), nStartCp);
1906     }
1907 
1908     maOldApos.push_back(false);
1909     maOldApos.swap(pRdr->maApos);
1910     maOldFieldStack.swap(pRdr->maFieldStack);
1911 }
1912 
Restore(SwWW8ImplReader * pRdr)1913 void WW8ReaderSave::Restore( SwWW8ImplReader* pRdr )
1914 {
1915     pRdr->pWFlyPara = mpWFlyPara;
1916     pRdr->pSFlyPara = mpSFlyPara;
1917     pRdr->pPreviousNumPaM = mpPreviousNumPaM;
1918     pRdr->pPrevNumRule = mpPrevNumRule;
1919     pRdr->pTableDesc = mpTableDesc;
1920     pRdr->cSymbol = mcSymbol;
1921     pRdr->bSymbol = mbSymbol;
1922     pRdr->bIgnoreText = mbIgnoreText;
1923     pRdr->bHdFtFtnEdn = mbHdFtFtnEdn;
1924     pRdr->bTxbxFlySection = mbTxbxFlySection;
1925     pRdr->nInTable = mnInTable;
1926     pRdr->bAnl = mbAnl;
1927     pRdr->bInHyperlink = mbInHyperlink;
1928     pRdr->bWasParaEnd = mbWasParaEnd;
1929     pRdr->bPgSecBreak = mbPgSecBreak;
1930     pRdr->nAktColl = mnAktColl;
1931     pRdr->bHasBorder = mbHasBorder;
1932     pRdr->bFirstPara = mbFirstPara;
1933 
1934     // schliesse alle Attribute, da sonst Attribute
1935     // entstehen koennen, die aus dem Fly rausragen
1936     pRdr->DeleteCtrlStk();
1937     pRdr->pCtrlStck = mpOldStck;
1938 
1939     pRdr->mpRedlineStack->closeall(*pRdr->pPaM->GetPoint());
1940     delete pRdr->mpRedlineStack;
1941     pRdr->mpRedlineStack = mpOldRedlines;
1942 
1943     pRdr->DeleteAnchorStk();
1944     pRdr->pAnchorStck = mpOldAnchorStck;
1945 
1946     *pRdr->pPaM->GetPoint() = maTmpPos;
1947 
1948     if (mpOldPlcxMan != pRdr->pPlcxMan)
1949     {
1950         delete pRdr->pPlcxMan;
1951         pRdr->pPlcxMan = mpOldPlcxMan;
1952     }
1953     if (pRdr->pPlcxMan)
1954         pRdr->pPlcxMan->RestoreAllPLCFx(maPLCFxSave);
1955     pRdr->maApos.swap(maOldApos);
1956     pRdr->maFieldStack.swap(maOldFieldStack);
1957 }
1958 
Read_HdFtFtnText(const SwNodeIndex * pSttIdx,long nStartCp,long nLen,ManTypes nType)1959 void SwWW8ImplReader::Read_HdFtFtnText( const SwNodeIndex* pSttIdx,
1960     long nStartCp, long nLen, ManTypes nType )
1961 {
1962     // rettet Flags u.ae. u. setzt sie zurueck
1963     WW8ReaderSave aSave( this );
1964 
1965     pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1;      //
1966     pPaM->GetPoint()->nContent.Assign( pPaM->GetCntntNode(), 0 );
1967 
1968     // dann Text fuer Header, Footer o. Footnote einlesen
1969 
1970     ReadText( nStartCp, nLen, nType );              // Sepx dabei ignorieren
1971     aSave.Restore( this );
1972 }
1973 
1974 //Use authornames, if not available fall back to initials.
Read_And(WW8PLCFManResult * pRes)1975 long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes)
1976 {
1977     WW8PLCFx_SubDoc* pSD = pPlcxMan->GetAtn();
1978     if( !pSD )
1979         return 0;
1980 
1981     String sAuthor;
1982     if( bVer67 )
1983     {
1984         const WW67_ATRD* pDescri = (const WW67_ATRD*)pSD->GetData();
1985         const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst));
1986         if (pA)
1987             sAuthor = *pA;
1988         else
1989             sAuthor = String(pDescri->xstUsrInitl + 1, pDescri->xstUsrInitl[0],
1990                 RTL_TEXTENCODING_MS_1252);
1991     }
1992     else
1993     {
1994         const WW8_ATRD* pDescri = (const WW8_ATRD*)pSD->GetData();
1995 
1996         if (const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst)))
1997             sAuthor = *pA;
1998         else
1999         {
2000             sal_uInt16 nLen = SVBT16ToShort(pDescri->xstUsrInitl[0]);
2001             for(sal_uInt16 nIdx = 1; nIdx <= nLen; ++nIdx)
2002                 sAuthor += SVBT16ToShort(pDescri->xstUsrInitl[nIdx]);
2003         }
2004     }
2005 
2006     sal_uInt32 nDateTime = 0;
2007 
2008     if (sal_uInt8 * pExtended = pPlcxMan->GetExtendedAtrds()) // Word < 2002 has no date data for comments
2009     {
2010         sal_uLong nIndex = pSD->GetIdx() & 0xFFFF; //Index is (stupidly) multiplexed for WW8PLCFx_SubDocs
2011         if (pWwFib->lcbAtrdExtra/18 > nIndex)
2012             nDateTime = SVBT32ToUInt32(*(SVBT32*)(pExtended+(nIndex*18)));
2013     }
2014 
2015     DateTime aDate = sw::ms::DTTM2DateTime(nDateTime);
2016 
2017     String sTxt;
2018     OutlinerParaObject *pOutliner = ImportAsOutliner( sTxt, pRes->nCp2OrIdx,
2019         pRes->nCp2OrIdx + pRes->nMemLen, MAN_AND );
2020 
2021     this->pFmtOfJustInsertedApo = 0;
2022     SwPostItField aPostIt(
2023         (SwPostItFieldType*)rDoc.GetSysFldType(RES_POSTITFLD),
2024         sTxt,
2025         sAuthor,
2026         aEmptyStr,
2027         aEmptyStr,
2028         aDate );
2029     aPostIt.SetTextObject(pOutliner);
2030 
2031     pCtrlStck->NewAttr(*pPaM->GetPoint(), SvxCharHiddenItem(false, RES_CHRATR_HIDDEN));
2032     rDoc.InsertPoolItem(*pPaM, SwFmtFld(aPostIt), 0);
2033     pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_CHRATR_HIDDEN);
2034 
2035     return 0;
2036 }
2037 
Read_HdFtTextAsHackedFrame(long nStart,long nLen,SwFrmFmt & rHdFtFmt,sal_uInt16 nPageWidth)2038 void SwWW8ImplReader::Read_HdFtTextAsHackedFrame(long nStart, long nLen,
2039     SwFrmFmt &rHdFtFmt, sal_uInt16 nPageWidth)
2040 {
2041     const SwNodeIndex* pSttIdx = rHdFtFmt.GetCntnt().GetCntntIdx();
2042     ASSERT(pSttIdx, "impossible");
2043     if (!pSttIdx)
2044         return;
2045 
2046     SwPosition aTmpPos(*pPaM->GetPoint());
2047 
2048     pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1;
2049     pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(), 0);
2050 
2051     SwFlyFrmFmt *pFrame = rDoc.MakeFlySection(FLY_AT_PARA, pPaM->GetPoint());
2052 
2053     SwFmtAnchor aAnch( pFrame->GetAnchor() );
2054     aAnch.SetType( FLY_AT_PARA );
2055     pFrame->SetFmtAttr( aAnch );
2056     SwFmtFrmSize aSz(ATT_MIN_SIZE, nPageWidth, MINLAY);
2057     SwFrmSize eFrmSize = ATT_MIN_SIZE;
2058     if( eFrmSize != aSz.GetWidthSizeType() )
2059         aSz.SetWidthSizeType( eFrmSize );
2060     pFrame->SetFmtAttr(aSz);
2061     pFrame->SetFmtAttr(SwFmtSurround(SURROUND_THROUGHT));
2062     pFrame->SetFmtAttr(SwFmtHoriOrient(0, text::HoriOrientation::LEFT)); //iFOO
2063 
2064     // #i43427# - send frame for header/footer into background.
2065     pFrame->SetFmtAttr( SvxOpaqueItem( RES_OPAQUE, false ) );
2066     SdrObject* pFrmObj = CreateContactObject( pFrame );
2067     ASSERT( pFrmObj,
2068             "<SwWW8ImplReader::Read_HdFtTextAsHackedFrame(..)> - missing SdrObject instance" );
2069     if ( pFrmObj )
2070     {
2071         pFrmObj->SetOrdNum( 0L );
2072     }
2073     MoveInsideFly(pFrame);
2074 
2075     const SwNodeIndex* pHackIdx = pFrame->GetCntnt().GetCntntIdx();
2076 
2077     Read_HdFtFtnText(pHackIdx, nStart, nLen - 1, MAN_HDFT);
2078 
2079     MoveOutsideFly(pFrame, aTmpPos);
2080 }
2081 
Read_HdFtText(long nStart,long nLen,SwFrmFmt * pHdFtFmt)2082 void SwWW8ImplReader::Read_HdFtText(long nStart, long nLen, SwFrmFmt* pHdFtFmt)
2083 {
2084     const SwNodeIndex* pSttIdx = pHdFtFmt->GetCntnt().GetCntntIdx();
2085     if (!pSttIdx)
2086         return;
2087 
2088     SwPosition aTmpPos( *pPaM->GetPoint() );    // merke alte Cursorposition
2089 
2090     Read_HdFtFtnText(pSttIdx, nStart, nLen - 1, MAN_HDFT);
2091 
2092     *pPaM->GetPoint() = aTmpPos;
2093 }
2094 
2095 
isValid_HdFt_CP(WW8_CP nHeaderCP) const2096 bool SwWW8ImplReader::isValid_HdFt_CP(WW8_CP nHeaderCP) const
2097 {
2098     //each CP of Plcfhdd MUST be less than FibRgLw97.ccpHdd
2099     return (nHeaderCP < pWwFib->ccpHdr) ? true : false;
2100 }
2101 
HasOwnHeaderFooter(sal_uInt8 nWhichItems,sal_uInt8 grpfIhdt,int nSect)2102 bool SwWW8ImplReader::HasOwnHeaderFooter(sal_uInt8 nWhichItems, sal_uInt8 grpfIhdt,
2103     int nSect)
2104 {
2105     if (pHdFt)
2106     {
2107         WW8_CP start;
2108         long nLen;
2109         sal_uInt8 nNumber = 5;
2110 
2111         for( sal_uInt8 nI = 0x20; nI; nI >>= 1, nNumber-- )
2112         {
2113             if (nI & nWhichItems)
2114             {
2115                 bool bOk = true;
2116                 if( bVer67 )
2117                     bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 );
2118                 else
2119                 {
2120                     pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen);
2121                     bOk = ( 2 <= nLen ) && isValid_HdFt_CP(start);
2122                 }
2123 
2124                 if (bOk)
2125                     return true;
2126             }
2127         }
2128     }
2129     return false;
2130 }
2131 
Read_HdFt(bool bIsTitle,int nSect,const SwPageDesc * pPrev,const wwSection & rSection)2132 void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect,
2133     const SwPageDesc *pPrev, const wwSection &rSection)
2134 {
2135     sal_uInt8 nWhichItems = 0;
2136     SwPageDesc *pPD = 0;
2137     if (!bIsTitle)
2138     {
2139         nWhichItems =
2140             rSection.maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST);
2141         pPD = rSection.mpPage;
2142     }
2143     else
2144     {
2145         // Always read title page header/footer data - it could be used by following sections
2146         nWhichItems = ( WW8_HEADER_FIRST | WW8_FOOTER_FIRST );
2147         pPD = rSection.mpTitlePage;
2148     }
2149 
2150     sal_uInt8 grpfIhdt = rSection.maSep.grpfIhdt;
2151 
2152 
2153     if( pHdFt )
2154     {
2155         WW8_CP start;
2156         long nLen;
2157         sal_uInt8 nNumber = 5;
2158 
2159         for( sal_uInt8 nI = 0x20; nI; nI >>= 1, nNumber-- )
2160         {
2161             if (nI & nWhichItems)
2162             {
2163                 bool bOk = true;
2164                 if( bVer67 )
2165                     bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 );
2166                 else
2167                 {
2168                     pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen);
2169                     bOk = ( 2 <= nLen ) && isValid_HdFt_CP(start);
2170                 }
2171 
2172                 bool bUseLeft
2173                     = (nI & ( WW8_HEADER_EVEN | WW8_FOOTER_EVEN )) ? true: false;
2174                 bool bFooter
2175                     = (nI & ( WW8_FOOTER_EVEN | WW8_FOOTER_ODD | WW8_FOOTER_FIRST )) ? true: false;
2176 
2177                 SwFrmFmt* pFmt = bUseLeft ? &pPD->GetLeft() : &pPD->GetMaster();
2178 
2179                 SwFrmFmt* pHdFtFmt;
2180                 if (bFooter)
2181                 {
2182                     bIsFooter = true;
2183                     //#i17196# Cannot have left without right
2184                     if (!pPD->GetMaster().GetFooter().GetFooterFmt())
2185                         pPD->GetMaster().SetFmtAttr(SwFmtFooter(true));
2186                     if (bUseLeft)
2187                         pPD->GetLeft().SetFmtAttr(SwFmtFooter(true));
2188                     pHdFtFmt = (SwFrmFmt*)pFmt->GetFooter().GetFooterFmt();
2189                 }
2190                 else
2191                 {
2192                     bIsHeader = true;
2193                     //#i17196# Cannot have left without right
2194                     if (!pPD->GetMaster().GetHeader().GetHeaderFmt())
2195                         pPD->GetMaster().SetFmtAttr(SwFmtHeader(true));
2196                     if (bUseLeft)
2197                         pPD->GetLeft().SetFmtAttr(SwFmtHeader(true));
2198                     pHdFtFmt = (SwFrmFmt*)pFmt->GetHeader().GetHeaderFmt();
2199                 }
2200 
2201                 if (bOk)
2202                 {
2203                     bool bHackRequired = false;
2204                     if (bIsHeader && rSection.IsFixedHeightHeader())
2205                         bHackRequired = true;
2206                     else if (bIsFooter && rSection.IsFixedHeightFooter())
2207                         bHackRequired = true;
2208 
2209                     if (bHackRequired)
2210                     {
2211                         Read_HdFtTextAsHackedFrame(start, nLen, *pHdFtFmt,
2212                             static_cast< sal_uInt16 >(rSection.GetTextAreaWidth()) );
2213                     }
2214                     else
2215                         Read_HdFtText(start, nLen, pHdFtFmt);
2216                 }
2217                 else if (!bOk && pPrev)
2218                     CopyPageDescHdFt(pPrev, pPD, nI);
2219 
2220                 bIsHeader = bIsFooter = false;
2221             }
2222         }
2223     }
2224     maTracer.LeaveEnvironment(sw::log::eDocumentProperties);
2225 }
2226 
SectionIsProtected(const wwSection & rSection) const2227 bool wwSectionManager::SectionIsProtected(const wwSection &rSection) const
2228 {
2229     return (mrReader.pWwFib->fReadOnlyRecommended && !rSection.IsNotProtected());
2230 }
2231 
SetHdFt(wwSection & rSection,int nSect,const wwSection * pPrevious)2232 void wwSectionManager::SetHdFt(wwSection &rSection, int nSect,
2233     const wwSection *pPrevious)
2234 {
2235     // Header / Footer nicht da
2236     if (!rSection.maSep.grpfIhdt)
2237         return;
2238 
2239     ASSERT(rSection.mpPage, "makes no sense to call with a main page");
2240     if (rSection.mpPage)
2241     {
2242         mrReader.Read_HdFt(false, nSect, pPrevious ? pPrevious->mpPage : 0,
2243                 rSection);
2244     }
2245 
2246     if (rSection.mpTitlePage)
2247     {
2248         // 2 Pagedescs noetig: 1.Seite und folgende
2249         // 1. Seite einlesen
2250         mrReader.Read_HdFt(true, nSect, pPrevious ? pPrevious->mpTitlePage : 0,
2251             rSection);
2252     }
2253 
2254     // Kopf / Fuss - Index Updaten
2255     // Damit der Index auch spaeter noch stimmt
2256     if (mrReader.pHdFt)
2257         mrReader.pHdFt->UpdateIndex(rSection.maSep.grpfIhdt);
2258 
2259 }
2260 
2261 class AttribHere : public std::unary_function<const xub_StrLen*, bool>
2262 {
2263 private:
2264     xub_StrLen nPosition;
2265 public:
AttribHere(xub_StrLen nPos)2266     AttribHere(xub_StrLen nPos) : nPosition(nPos) {}
operator ()(const xub_StrLen * pPosition) const2267     bool operator()(const xub_StrLen *pPosition) const
2268     {
2269         return (*pPosition >= nPosition);
2270     }
2271 };
2272 
AppendTxtNode(SwPosition & rPos)2273 void SwWW8ImplReader::AppendTxtNode(SwPosition& rPos)
2274 {
2275     SwTxtNode* pTxt = pPaM->GetNode()->GetTxtNode();
2276 
2277     const SwNumRule* pRule = NULL;
2278 
2279     if (pTxt != NULL)
2280         pRule = sw::util::GetNumRuleFromTxtNode(*pTxt);
2281 
2282     if (
2283          pRule && !pWDop->fDontUseHTMLAutoSpacing &&
2284          (bParaAutoBefore || bParaAutoAfter)
2285        )
2286     {
2287         // If after spacing is set to auto, set the after space to 0
2288         if (bParaAutoAfter)
2289             SetLowerSpacing(*pPaM, 0);
2290 
2291         // If the previous textnode had numbering and
2292         // and before spacing is set to auto, set before space to 0
2293         if(pPrevNumRule && bParaAutoBefore)
2294             SetUpperSpacing(*pPaM, 0);
2295 
2296         // If the previous numbering rule was different we need
2297         // to insert a space after the previous paragraph
2298         if((pRule != pPrevNumRule) && pPreviousNumPaM)
2299             SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
2300 
2301         // cache current paragraph
2302         if(pPreviousNumPaM)
2303             delete pPreviousNumPaM, pPreviousNumPaM = 0;
2304 
2305         pPreviousNumPaM = new SwPaM(*pPaM);
2306         pPrevNumRule = pRule;
2307     }
2308     else if(!pRule && pPreviousNumPaM)
2309     {
2310         // If the previous paragraph has numbering but the current one does not
2311         // we need to add a space after the previous paragraph
2312         SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
2313         delete pPreviousNumPaM, pPreviousNumPaM = 0;
2314         pPrevNumRule = 0;
2315     }
2316     else
2317     {
2318         // clear paragraph cache
2319         if(pPreviousNumPaM)
2320             delete pPreviousNumPaM, pPreviousNumPaM = 0;
2321         pPrevNumRule = pRule;
2322     }
2323 
2324     // If this is the first paragraph in the document and
2325     // Auto-spacing before paragraph is set,
2326     // set the upper spacing value to 0
2327     if(bParaAutoBefore && bFirstPara && !pWDop->fDontUseHTMLAutoSpacing)
2328         SetUpperSpacing(*pPaM, 0);
2329 
2330     bFirstPara = false;
2331 
2332     rDoc.AppendTxtNode(rPos);
2333 
2334     //We can flush all anchored graphics at the end of a paragraph.
2335     pAnchorStck->Flush();
2336 }
2337 
SetSpacing(SwPaM & rMyPam,int nSpace,bool bIsUpper)2338 bool SwWW8ImplReader::SetSpacing(SwPaM &rMyPam, int nSpace, bool bIsUpper )
2339 {
2340         bool bRet = false;
2341         const SwPosition* pSpacingPos = rMyPam.GetPoint();
2342 
2343         const SvxULSpaceItem* pULSpaceItem = (const SvxULSpaceItem*)pCtrlStck->GetFmtAttr(*pSpacingPos, RES_UL_SPACE);
2344 
2345         if(pULSpaceItem != 0)
2346         {
2347             SvxULSpaceItem aUL(*pULSpaceItem);
2348 
2349             if(bIsUpper)
2350                 aUL.SetUpper( static_cast< sal_uInt16 >(nSpace) );
2351             else
2352                 aUL.SetLower( static_cast< sal_uInt16 >(nSpace) );
2353 
2354             xub_StrLen nEnd = pSpacingPos->nContent.GetIndex();
2355             rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), 0);
2356             pCtrlStck->NewAttr(*pSpacingPos, aUL);
2357             rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), nEnd);
2358             pCtrlStck->SetAttr(*pSpacingPos, RES_UL_SPACE);
2359             bRet = true;
2360         }
2361         return bRet;
2362 }
2363 
SetLowerSpacing(SwPaM & rMyPam,int nSpace)2364 bool SwWW8ImplReader::SetLowerSpacing(SwPaM &rMyPam, int nSpace)
2365 {
2366     return SetSpacing(rMyPam, nSpace, false);
2367 }
2368 
SetUpperSpacing(SwPaM & rMyPam,int nSpace)2369 bool SwWW8ImplReader::SetUpperSpacing(SwPaM &rMyPam, int nSpace)
2370 {
2371     return SetSpacing(rMyPam, nSpace, true);
2372 }
2373 
TabRowSprm(int nLevel) const2374 sal_uInt16 SwWW8ImplReader::TabRowSprm(int nLevel) const
2375 {
2376     if (bVer67)
2377         return 25;
2378     return nLevel ? 0x244C : 0x2417;
2379 }
2380 
EndSpecial()2381 void SwWW8ImplReader::EndSpecial()
2382 {
2383     // Frame / Table / Anl
2384     if (bAnl)
2385         StopAllAnl();                  // -> bAnl = false
2386 
2387     while(maApos.size() > 1)
2388     {
2389         StopTable();
2390         maApos.pop_back();
2391         --nInTable;
2392         if (maApos[nInTable] == true)
2393             StopApo();
2394     }
2395 
2396     if (maApos[0] == true)
2397         StopApo();
2398 
2399     ASSERT(!nInTable, "unclosed table!");
2400 }
2401 
ProcessSpecial(bool & rbReSync,WW8_CP nStartCp)2402 bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync, WW8_CP nStartCp)
2403 {
2404     // Frame / Table / Anl
2405     if (bInHyperlink)
2406         return false;
2407 
2408     rbReSync = false;
2409 
2410     ASSERT(nInTable >= 0,"nInTable < 0!");
2411 
2412     // TabRowEnd
2413     bool bTableRowEnd = (pPlcxMan->HasParaSprm(bVer67 ? 25 : 0x2417) != 0 );
2414 
2415 // es muss leider fuer jeden Absatz zuerst nachgesehen werden,
2416 // ob sich unter den sprms
2417 // das sprm 29 (bzw. 0x261B) befindet, das ein APO einleitet.
2418 // Alle weiteren sprms  beziehen sich dann naemlich auf das APO und nicht
2419 // auf den normalen Text drumrum.
2420 // Dasselbe gilt fuer eine Tabelle ( sprm 24 (bzw. 0x2416) )
2421 // und Anls ( sprm 13 ).
2422 // WW: Tabelle in APO geht ( Beide Anfaende treten gleichzeitig auf )
2423 // WW: APO in Tabelle geht nicht
2424 // d.h. Wenn eine Tabelle Inhalt eines Apo ist, dann muss der
2425 // Apo-Anfang zuerst bearbeitet werden, damit die Tabelle im Apo steht
2426 // und nicht umgekehrt. Am Ende muss dagegen zuerst das Tabellenende
2427 // bearbeitet werden, da die Apo erst nach der Tabelle abgeschlossen
2428 // werden darf ( sonst wird das Apo-Ende nie gefunden ).
2429 // Dasselbe gilt fuer Fly / Anl, Tab / Anl, Fly / Tab / Anl.
2430 //
2431 // Wenn die Tabelle in einem Apo steht, fehlen im TabRowEnd-Bereich
2432 // die Apo-Angaben. Damit hier die Apo nicht beendet wird, wird
2433 // ProcessApo dann nicht aufgerufen.
2434 
2435 // KHZ: When there is a table inside the Apo the Apo-flags are also
2436 //      missing for the 2nd, 3rd... paragraphs of each cell.
2437 
2438 
2439 //  1st look for in-table flag, for 2000+ there is a subtable flag to
2440 //  be considered, the sprm 6649 gives the level of the table
2441     sal_uInt8 nCellLevel = 0;
2442 
2443     if (bVer67)
2444         nCellLevel = 0 != pPlcxMan->HasParaSprm(24);
2445     else
2446     {
2447         nCellLevel = 0 != pPlcxMan->HasParaSprm(0x2416);
2448         if (!nCellLevel)
2449             nCellLevel = 0 != pPlcxMan->HasParaSprm(0x244B);
2450     }
2451 
2452     WW8_TablePos *pTabPos=0;
2453     WW8_TablePos aTabPos;
2454     WW8PLCFx_Cp_FKP* pPap = 0;
2455     bool bTableHasPositionInfo = false;
2456 
2457     if (nCellLevel && !bVer67)
2458     {
2459         WW8PLCFxSave1 aSave;
2460         pPlcxMan->GetPap()->Save( aSave );
2461         rbReSync = true;
2462         pPap = pPlcxMan->GetPapPLCF();
2463         WW8_CP nMyStartCp=nStartCp;
2464 
2465         if (const sal_uInt8 *pLevel = pPlcxMan->HasParaSprm(0x6649))
2466             nCellLevel = *pLevel;
2467 
2468         bool bHasRowEnd = SearchRowEnd(pPap, nMyStartCp, nCellLevel-1);
2469 
2470         //Bad Table, remain unchanged in level, e.g. #i19667#
2471         if (!bHasRowEnd)
2472             nCellLevel = static_cast< sal_uInt8 >(nInTable);
2473 
2474         sal_uLong idstart = rDoc.GetNodes().GetEndOfContent().StartOfSectionIndex(); // get the node index
2475         sal_uLong idcur = 0;
2476         if ( pPaM && pPaM->GetPoint() )
2477             idcur = pPaM->GetPoint()->nNode.GetIndex();
2478 
2479         // Memory first table position info
2480         if ( !pFirstTablePap && idstart + 1 == idcur )
2481             pFirstTablePap = pPap;
2482 
2483         if ( bHasRowEnd  && ParseTabPos(&aTabPos,pPap) )
2484         {
2485             // If table front don't have some content and it is doc first table, ignore table text wrapping property
2486             bTableHasPositionInfo = true;
2487             if ( pFirstTablePap != pPap )
2488                 pTabPos = &aTabPos;
2489         }
2490 
2491         pPlcxMan->GetPap()->Restore( aSave );
2492     }
2493 
2494 //  then look if we are in an Apo
2495 
2496     ApoTestResults aApo = TestApo(nCellLevel, bTableRowEnd, pTabPos, !(pFirstTablePap == pPap && bTableHasPositionInfo));
2497 
2498     //look to see if we are in a Table, but Table in foot/end note not allowed
2499     bool bStartTab = (nInTable < nCellLevel) && !bFtnEdn;
2500 
2501     bool bStopTab = bWasTabRowEnd && (nInTable > nCellLevel) && !bFtnEdn;
2502 
2503     bWasTabRowEnd = false;  // must be deactivated right here to prevent next
2504                             // WW8TabDesc::TableCellEnd() from making nonsense
2505 
2506     if (nInTable && !bTableRowEnd && !bStopTab && (nInTable == nCellLevel && aApo.HasStartStop()))
2507         bStopTab = bStartTab = true;    // Required to stop and start table
2508 
2509 //  Dann auf Anl (Nummerierung) testen
2510 //  und dann alle Ereignisse in der richtigen Reihenfolge bearbeiten
2511 
2512     if( bAnl && !bTableRowEnd )
2513     {
2514         const sal_uInt8* pSprm13 = pPlcxMan->HasParaSprm( 13 );
2515         if( pSprm13 )
2516         {                                   // Noch Anl ?
2517             sal_uInt8 nT = static_cast< sal_uInt8 >(GetNumType( *pSprm13 ));
2518             if( ( nT != WW8_Pause && nT != nWwNumType ) // Anl-Wechsel
2519                 || aApo.HasStartStop()                  // erzwungenes Anl-Ende
2520                 || bStopTab || bStartTab )
2521             {
2522                 StopAnlToRestart(nT);  // Anl-Restart ( = Wechsel ) ueber sprms
2523             }
2524             else
2525             {
2526                 NextAnlLine( pSprm13 );                 // naechste Anl-Zeile
2527             }
2528         }
2529         else
2530         {                                           // Anl normal zuende
2531             StopAllAnl();                                  // Wirkliches Ende
2532         }
2533     }
2534     if (bStopTab)
2535     {
2536         StopTable();
2537         maApos.pop_back();
2538         --nInTable;
2539     }
2540     if (aApo.mbStopApo)
2541     {
2542         StopApo();
2543         maApos[nInTable] = false;
2544     }
2545 
2546     if (aApo.mbStartApo)
2547     {
2548         maApos[nInTable] = StartApo(aApo, pTabPos);
2549         // nach StartApo ist ein ReSync noetig ( eigentlich nur, falls die Apo
2550         // ueber eine FKP-Grenze geht
2551         rbReSync = true;
2552     }
2553     if (bStartTab)
2554     {
2555         WW8PLCFxSave1 aSave;
2556         pPlcxMan->GetPap()->Save( aSave );
2557 
2558         if (bAnl)                           // Nummerierung ueber Zellengrenzen
2559             StopAllAnl();                   // fuehrt zu Absturz -> keine Anls
2560                                             // in Tabellen
2561         while (nInTable < nCellLevel)
2562         {
2563             if (StartTable(nStartCp))
2564                 ++nInTable;
2565             else
2566                 break;
2567 
2568             maApos.push_back(false);
2569         }
2570         // nach StartTable ist ein ReSync noetig ( eigentlich nur, falls die
2571         // Tabelle ueber eine FKP-Grenze geht
2572         rbReSync = true;
2573         pPlcxMan->GetPap()->Restore( aSave );
2574     }
2575     return bTableRowEnd;
2576 }
2577 
GetCurrentCharSet()2578 CharSet SwWW8ImplReader::GetCurrentCharSet()
2579 {
2580     /*
2581     #i2015
2582     If the hard charset is set use it, if not see if there is an open
2583     character run that has set the charset, if not then fallback to the
2584     current underlying paragraph style.
2585     */
2586     CharSet eSrcCharSet = eHardCharSet;
2587     if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2588     {
2589         if (!maFontSrcCharSets.empty())
2590             eSrcCharSet = maFontSrcCharSets.top();
2591         if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && (nCharFmt != -1))
2592             eSrcCharSet = pCollA[nCharFmt].GetCharSet();
2593         if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && StyleExists(nAktColl))
2594             eSrcCharSet = pCollA[nAktColl].GetCharSet();
2595         if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2596         { // patch from cmc for #i52786#
2597             /*
2598              #i22206#/#i52786#
2599              The (default) character set used for a run of text is the default
2600              character set for the version of Word that last saved the document.
2601 
2602              This is a bit tentative, more might be required if the concept is correct.
2603              When later version of word write older 6/95 documents the charset is
2604              correctly set in the character runs involved, so its hard to reproduce
2605              documents that require this to be sure of the process involved.
2606             */
2607             const SvxLanguageItem *pLang =
2608                 (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
2609             if (pLang)
2610             {
2611                 switch (pLang->GetLanguage())
2612                 {
2613                     case LANGUAGE_CZECH:
2614                     case LANGUAGE_HUNGARIAN:
2615                     case LANGUAGE_POLISH:
2616                         eSrcCharSet = RTL_TEXTENCODING_MS_1250;
2617                         break;
2618                     case LANGUAGE_RUSSIAN:
2619                         eSrcCharSet = RTL_TEXTENCODING_MS_1251;
2620                         break;
2621                     case LANGUAGE_GREEK:
2622                         eSrcCharSet = RTL_TEXTENCODING_MS_1253;
2623                         break;
2624                     case LANGUAGE_TURKISH:
2625                         eSrcCharSet = RTL_TEXTENCODING_MS_1254;
2626                         break;
2627                     default:
2628                         eSrcCharSet = RTL_TEXTENCODING_MS_1252;
2629                         break;
2630                 }
2631             }
2632         }
2633     }
2634     return eSrcCharSet;
2635 }
2636 
2637 //Takashi Ono for CJK
GetCurrentCJKCharSet()2638 CharSet SwWW8ImplReader::GetCurrentCJKCharSet()
2639 {
2640     /*
2641     #i2015
2642     If the hard charset is set use it, if not see if there is an open
2643     character run that has set the charset, if not then fallback to the
2644     current underlying paragraph style.
2645     */
2646     CharSet eSrcCharSet = eHardCharSet;
2647     if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2648     {
2649         if (!maFontSrcCJKCharSets.empty())
2650             eSrcCharSet = maFontSrcCJKCharSets.top();
2651         if (pCollA != NULL)
2652         {
2653             if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && (nCharFmt != -1))
2654                 eSrcCharSet = pCollA[nCharFmt].GetCJKCharSet();
2655             if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2656                 eSrcCharSet = pCollA[nAktColl].GetCJKCharSet();
2657         }
2658         if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2659         { // patch from cmc for #i52786#
2660             /*
2661              #i22206#/#i52786#
2662              The (default) character set used for a run of text is the default
2663              character set for the version of Word that last saved the document.
2664 
2665              This is a bit tentative, more might be required if the concept is correct.
2666              When later version of word write older 6/95 documents the charset is
2667              correctly set in the character runs involved, so its hard to reproduce
2668              documents that require this to be sure of the process involved.
2669             */
2670             const SvxLanguageItem *pLang =
2671                 (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
2672             if (pLang)
2673             {
2674                 switch (pLang->GetLanguage())
2675                 {
2676                     case LANGUAGE_CZECH:
2677                         eSrcCharSet = RTL_TEXTENCODING_MS_1250;
2678                         break;
2679                     default:
2680                         eSrcCharSet = RTL_TEXTENCODING_MS_1252;
2681                         break;
2682                 }
2683             }
2684         }
2685     }
2686     return eSrcCharSet;
2687 }
2688 
PostProcessAttrs()2689 void SwWW8ImplReader::PostProcessAttrs()
2690 {
2691     if (mpPostProcessAttrsInfo != NULL)
2692     {
2693         SfxItemIter aIter(mpPostProcessAttrsInfo->mItemSet);
2694 
2695         const SfxPoolItem * pItem = aIter.GetCurItem();
2696         if (pItem != NULL)
2697         {
2698             do
2699             {
2700                 pCtrlStck->NewAttr(*mpPostProcessAttrsInfo->mPaM.GetPoint(),
2701                                    *pItem);
2702                 pCtrlStck->SetAttr(*mpPostProcessAttrsInfo->mPaM.GetMark(),
2703                                    pItem->Which(), true);
2704             }
2705             while (!aIter.IsAtEnd() && 0 != (pItem = aIter.NextItem()));
2706         }
2707 
2708         delete mpPostProcessAttrsInfo;
2709         mpPostProcessAttrsInfo = NULL;
2710     }
2711 }
2712 
2713 /*
2714  #i9241#
2715  It appears that some documents that are in a baltic 8 bit encoding which has
2716  some undefined characters can have use made of those characters, in which
2717  case they default to CP1252. If not then its perhaps that the font encoding
2718  is only in use for 6/7 and for 8+ if we are in 8bit mode then the encoding
2719  is always 1252.
2720 
2721  So a encoding converter that on an undefined character attempts to
2722  convert from 1252 on the undefined character
2723 */
Custom8BitToUnicode(rtl_TextToUnicodeConverter hConverter,sal_Char * pIn,sal_Size nInLen,sal_Unicode * pOut,sal_Size nOutLen)2724 sal_Size Custom8BitToUnicode(rtl_TextToUnicodeConverter hConverter,
2725     sal_Char *pIn, sal_Size nInLen, sal_Unicode *pOut, sal_Size nOutLen)
2726 {
2727     const sal_uInt32 nFlags =
2728         RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
2729         RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
2730         RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE |
2731         RTL_TEXTTOUNICODE_FLAGS_FLUSH;
2732 
2733     const sal_uInt32 nFlags2 =
2734         RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE |
2735         RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_IGNORE |
2736         RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE |
2737         RTL_TEXTTOUNICODE_FLAGS_FLUSH;
2738 
2739     sal_Size nDestChars=0;
2740     sal_Size nConverted=0;
2741 
2742     do
2743     {
2744         sal_uInt32 nInfo = 0;
2745         sal_Size nThisConverted=0;
2746 
2747         nDestChars += rtl_convertTextToUnicode(hConverter, 0,
2748             pIn+nConverted, nInLen-nConverted,
2749             pOut+nDestChars, nOutLen-nDestChars,
2750             nFlags, &nInfo, &nThisConverted);
2751 
2752         ASSERT(nInfo == 0, "A character conversion failed!");
2753 
2754         nConverted += nThisConverted;
2755 
2756         if (
2757             nInfo & RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR ||
2758             nInfo & RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
2759            )
2760         {
2761             sal_Size nOtherConverted;
2762             rtl_TextToUnicodeConverter hCP1252Converter =
2763                 rtl_createTextToUnicodeConverter(RTL_TEXTENCODING_MS_1252);
2764             nDestChars += rtl_convertTextToUnicode(hCP1252Converter, 0,
2765                 pIn+nConverted, 1,
2766                 pOut+nDestChars, nOutLen-nDestChars,
2767                 nFlags2, &nInfo, &nOtherConverted);
2768             rtl_destroyTextToUnicodeConverter(hCP1252Converter);
2769             nConverted+=1;
2770         }
2771     } while (nConverted < nInLen);
2772 
2773     return nDestChars;
2774 }
2775 
LangUsesHindiNumbers(sal_uInt16 nLang)2776 bool SwWW8ImplReader::LangUsesHindiNumbers(sal_uInt16 nLang)
2777 {
2778 	bool bResult = false;
2779 
2780 	switch (nLang)
2781 	{
2782 		case 0x1401: // Arabic(Algeria)
2783 		case 0x3c01: // Arabic(Bahrain)
2784 		case 0xc01: // Arabic(Egypt)
2785 		case 0x801: // Arabic(Iraq)
2786 		case 0x2c01: // Arabic (Jordan)
2787 		case 0x3401: // Arabic(Kuwait)
2788 		case 0x3001: // Arabic(Lebanon)
2789 		case 0x1001: // Arabic(Libya)
2790 		case 0x1801: // Arabic(Morocco)
2791 		case 0x2001: // Arabic(Oman)
2792 		case 0x4001: // Arabic(Qatar)
2793 		case 0x401: // Arabic(Saudi Arabia)
2794 		case 0x2801: // Arabic(Syria)
2795 		case 0x1c01: // Arabic(Tunisia)
2796 		case 0x3801: // Arabic(U.A.E)
2797 		case 0x2401: // Arabic(Yemen)
2798 			bResult = true;
2799 			break;
2800 		default:
2801 			break;
2802 	}
2803 
2804 	return bResult;
2805 }
2806 
TranslateToHindiNumbers(sal_Unicode nChar)2807 sal_Unicode SwWW8ImplReader::TranslateToHindiNumbers(sal_Unicode nChar)
2808 {
2809     if (nChar >= 0x0030 && nChar <= 0x0039)
2810         return nChar + 0x0630;
2811 
2812     return nChar;
2813 }
2814 
2815 // Returnwert: true for no Sonderzeichen
ReadPlainChars(WW8_CP & rPos,long nEnd,long nCpOfs)2816 bool SwWW8ImplReader::ReadPlainChars(WW8_CP& rPos, long nEnd, long nCpOfs)
2817 {
2818     // Unicode-Flag neu setzen und notfalls File-Pos korrigieren
2819     // merke: Seek kostet nicht viel, da inline geprueft wird,
2820     //        ob die korrekte FilePos nicht schon erreicht ist.
2821     WW8_FC nStreamPos = pSBase->WW8Cp2Fc(nCpOfs+rPos, &bIsUnicode);
2822     pStrm->Seek( nStreamPos );
2823 
2824     xub_StrLen nLen;
2825     if (nEnd - rPos <= (STRING_MAXLEN-1))
2826         nLen = writer_cast<xub_StrLen>(nEnd - rPos);
2827     else
2828         nLen = STRING_MAXLEN-1;
2829     ASSERT(nLen, "String is 0");
2830     if (!nLen)
2831         return true;
2832 
2833     const CharSet eSrcCharSet = bVer67 ? GetCurrentCharSet() :
2834         RTL_TEXTENCODING_MS_1252;
2835     const CharSet eSrcCJKCharSet = bVer67 ? GetCurrentCJKCharSet() :
2836         RTL_TEXTENCODING_MS_1252;
2837 
2838     // (re)alloc UniString data
2839     String sPlainCharsBuf;
2840 
2841     sal_Unicode* pBuffer = sPlainCharsBuf.AllocBuffer( nLen );
2842     sal_Unicode* pWork = pBuffer;
2843 
2844     sal_Char* p8Bits = NULL;
2845 
2846     rtl_TextToUnicodeConverter hConverter = 0;
2847     if (!bIsUnicode || bVer67)
2848         hConverter = rtl_createTextToUnicodeConverter(eSrcCharSet);
2849 
2850     if (!bIsUnicode)
2851         p8Bits = new sal_Char[nLen];
2852 
2853     // read the stream data
2854     sal_uInt8   nBCode = 0;
2855     sal_uInt16 nUCode;
2856     xub_StrLen nL2;
2857 
2858 	sal_uInt16 nCTLLang = 0;
2859 	const SfxPoolItem * pItem = GetFmtAttr(RES_CHRATR_CTL_LANGUAGE);
2860 	if (pItem != NULL)
2861 		nCTLLang = dynamic_cast<const SvxLanguageItem *>(pItem)->GetLanguage();
2862 
2863     for( nL2 = 0; nL2 < nLen; ++nL2, ++pWork )
2864     {
2865         if (bIsUnicode)
2866             *pStrm >> nUCode;   // unicode  --> read 2 bytes
2867         else
2868         {
2869             *pStrm >> nBCode;   // old code --> read 1 byte
2870             nUCode = nBCode;
2871         }
2872 
2873         if (pStrm->GetError())
2874         {
2875             rPos = WW8_CP_MAX-10;     // -> eof or other error
2876             sPlainCharsBuf.ReleaseBufferAccess( 0 );
2877             delete [] p8Bits;
2878             return true;
2879         }
2880 
2881         if ((32 > nUCode) || (0xa0 == nUCode))
2882         {
2883             pStrm->SeekRel( bIsUnicode ? -2 : -1 );
2884             break;              // Sonderzeichen < 32, == 0xa0 gefunden
2885         }
2886 
2887         if (bIsUnicode)
2888         {
2889             if (!bVer67)
2890                 *pWork = nUCode;
2891             else
2892             {
2893                 if (nUCode >= 0x3000)       //0x8000 ?
2894                 {
2895                     sal_Char aTest[2];
2896                     aTest[0] = static_cast< sal_Char >((nUCode & 0xFF00) >> 8);
2897                     aTest[1] = static_cast< sal_Char >(nUCode & 0x00FF);
2898                     String aTemp(aTest, 2, eSrcCJKCharSet);
2899                     ASSERT(aTemp.Len() == 1, "so much for that theory");
2900                     *pWork = aTemp.GetChar(0);
2901                 }
2902                 else
2903                 {
2904                     sal_Char cTest = static_cast< sal_Char >(nUCode & 0x00FF);
2905                     Custom8BitToUnicode(hConverter, &cTest, 1, pWork, 1);
2906                 }
2907             }
2908         }
2909         else
2910             p8Bits[nL2] = nBCode;
2911     }
2912 
2913     if (nL2)
2914     {
2915         xub_StrLen nEndUsed = nL2;
2916 
2917         if (!bIsUnicode)
2918             nEndUsed = Custom8BitToUnicode(hConverter, p8Bits, nL2, pBuffer, nLen);
2919 
2920         for( xub_StrLen nI = 0; nI < nLen; ++nI, ++pBuffer )
2921             if (m_bRegardHindiDigits && bBidi && LangUsesHindiNumbers(nCTLLang))
2922                 *pBuffer = TranslateToHindiNumbers(*pBuffer);
2923 
2924         sPlainCharsBuf.ReleaseBufferAccess( nEndUsed );
2925 
2926         AddTextToParagraph(sPlainCharsBuf);
2927         rPos += nL2;
2928         if (!maApos.back()) //a para end in apo doesn't count
2929             bWasParaEnd = false;            //kein CR
2930     }
2931 
2932     if (hConverter)
2933         rtl_destroyTextToUnicodeConverter(hConverter);
2934     delete [] p8Bits;
2935     return nL2 >= nLen;
2936 }
2937 
AddTextToParagraph(const String & rAddString)2938 bool SwWW8ImplReader::AddTextToParagraph(const String& rAddString)
2939 {
2940     const SwTxtNode* pNd = pPaM->GetCntntNode()->GetTxtNode();
2941     if (rAddString.Len())
2942     {
2943 /*
2944 #ifdef DEBUG
2945 //!! does not compile with debug=t -> unresolved external (dbg_out),
2946 //!! sommeone who knows what he wants to get should fix this
2947 //        ::std::clog << "<addTextToParagraph>" << dbg_out(rAddString)
2948 //        << "</addTextToParagraph>" << ::std::endl;
2949 #endif
2950 */
2951         if ((pNd->GetTxt().Len() + rAddString.Len()) < STRING_MAXLEN -1)
2952         {
2953             rDoc.InsertString(*pPaM, rAddString);
2954         }
2955         else
2956         {
2957 
2958             if (pNd->GetTxt().Len()< STRING_MAXLEN -1)
2959             {
2960                 String sTempStr (rAddString,0,
2961                     STRING_MAXLEN - pNd->GetTxt().Len() -1);
2962                 rDoc.InsertString(*pPaM, sTempStr);
2963                 sTempStr = rAddString.Copy(sTempStr.Len(),
2964                     rAddString.Len() - sTempStr.Len());
2965                 AppendTxtNode(*pPaM->GetPoint());
2966                 rDoc.InsertString(*pPaM, sTempStr);
2967             }
2968             else
2969             {
2970                 AppendTxtNode(*pPaM->GetPoint());
2971                 rDoc.InsertString(*pPaM, rAddString);
2972             }
2973         }
2974 
2975         bReadTable = false;
2976     }
2977 
2978     return true;
2979 }
2980 
2981 // Returnwert: true for para end
ReadChars(WW8_CP & rPos,WW8_CP nNextAttr,long nTextEnd,long nCpOfs)2982 bool SwWW8ImplReader::ReadChars(WW8_CP& rPos, WW8_CP nNextAttr, long nTextEnd,
2983     long nCpOfs)
2984 {
2985     long nEnd = ( nNextAttr < nTextEnd ) ? nNextAttr : nTextEnd;
2986 
2987     if (bSymbol || bIgnoreText)
2988     {
2989         if( bSymbol )   // Spezialzeichen einfuegen
2990         {
2991             for(sal_uInt16 nCh = 0; nCh < nEnd - rPos; ++nCh)
2992             {
2993                 rDoc.InsertString( *pPaM, cSymbol );
2994             }
2995             pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_FONT );
2996         }
2997         pStrm->SeekRel( nEnd- rPos );
2998         rPos = nEnd;    // ignoriere bis Attributende
2999         return false;
3000     }
3001 
3002     while (true)
3003     {
3004         if (ReadPlainChars(rPos, nEnd, nCpOfs))
3005             return false;                   // Fertig
3006 
3007         bool bStartLine = ReadChar(rPos, nCpOfs);
3008         rPos++;
3009         if (bPgSecBreak || bStartLine || rPos == nEnd)  // CR oder Fertig
3010         {
3011             return bStartLine;
3012         }
3013     }
3014 }
3015 
HandlePageBreakChar()3016 bool SwWW8ImplReader::HandlePageBreakChar()
3017 {
3018     bool bParaEndAdded = false;
3019     //#i1909# section/page breaks should not occur in tables, word
3020     //itself ignores them in this case.
3021     if (!nInTable)
3022     {
3023         //xushanchuan add for issue106569
3024         sal_Bool IsTemp=sal_True;
3025         SwTxtNode* pTemp = pPaM->GetNode()->GetTxtNode();
3026         if ( pTemp && !( pTemp->GetTxt().Len() ) && ( bFirstPara || bFirstParaOfPage ) )
3027         {
3028             IsTemp = sal_False;
3029             AppendTxtNode(*pPaM->GetPoint());
3030             pTemp->SetAttr(*GetDfltAttr(RES_PARATR_NUMRULE));
3031         }
3032         //xushanchuan end
3033         bPgSecBreak = true;
3034         pCtrlStck->KillUnlockedAttrs(*pPaM->GetPoint());
3035         /*
3036         If its a 0x0c without a paragraph end before it, act like a
3037         paragraph end, but nevertheless, numbering (and perhaps other
3038         similar constructs) do not exist on the para.
3039         */
3040         //xushanchuan add for issue106569
3041         if (!bWasParaEnd && IsTemp)
3042             //xushanchuan end
3043         {
3044             bParaEndAdded = true;
3045             if (0 >= pPaM->GetPoint()->nContent.GetIndex())
3046             {
3047                 if (SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode())
3048                 {
3049                     pTxtNode->SetAttr(
3050                         *GetDfltAttr(RES_PARATR_NUMRULE));
3051                 }
3052             }
3053         }
3054     }
3055     return bParaEndAdded;
3056 }
3057 
ReadChar(long nPosCp,long nCpOfs)3058 bool SwWW8ImplReader::ReadChar(long nPosCp, long nCpOfs)
3059 {
3060     bool bNewParaEnd = false;
3061     // Unicode-Flag neu setzen und notfalls File-Pos korrigieren
3062     // merke: Seek kostet nicht viel, da inline geprueft wird,
3063     //        ob die korrekte FilePos nicht schon erreicht ist.
3064     pStrm->Seek( pSBase->WW8Cp2Fc(nCpOfs+nPosCp, &bIsUnicode) );
3065 
3066     sal_uInt8   nBCode;
3067     sal_uInt16 nWCharVal;
3068     if( bIsUnicode )
3069         *pStrm >> nWCharVal;    // unicode  --> read 2 bytes
3070     else
3071     {
3072         *pStrm  >>  nBCode;     // old code --> read 1 byte
3073         nWCharVal = nBCode;
3074     }
3075 
3076     sal_Char cInsert = '\x0';
3077     bool bRet = false;
3078 	//xushanchuan add for issue106569
3079 	if ( 0xc != nWCharVal )
3080 		bFirstParaOfPage = false;
3081 	//xushanchuan end
3082     switch (nWCharVal)
3083     {
3084         case 0:
3085             {
3086                 // Seitennummer
3087                 SwPageNumberField aFld(
3088                     (SwPageNumberFieldType*)rDoc.GetSysFldType(
3089                     RES_PAGENUMBERFLD ), PG_RANDOM, SVX_NUM_ARABIC);
3090                 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
3091             }
3092             break;
3093         case 0xe:
3094             // if there is only one column word treats a column break like a pagebreak.
3095             if (maSectionManager.CurrentSectionColCount() < 2)
3096                 bRet = HandlePageBreakChar();
3097             else if (!nInTable)
3098             {
3099                 // Always insert a txtnode for a column break, e.g. ##
3100                 AppendTxtNode(*pPaM->GetPoint());
3101                 rDoc.InsertPoolItem(*pPaM,
3102                     SvxFmtBreakItem(SVX_BREAK_COLUMN_BEFORE, RES_BREAK), 0);
3103             }
3104             break;
3105         case 0x7:
3106             bNewParaEnd = true;
3107             TabCellEnd();       // table cell end (Flags abfragen!)
3108             break;
3109         case 0xf:
3110             if( !bSpec )        // "Satellit"
3111                 cInsert = '\xa4';
3112             break;
3113         case 0x14:
3114             if( !bSpec )        // "Para-Ende"-Zeichen
3115                 cInsert = '\xb5';
3116             break;
3117         case 0x15:
3118             if( !bSpec )        // Juristenparagraph
3119             {
3120                 cp_set::iterator aItr = maTOXEndCps.find((WW8_CP)nPosCp);
3121 	         if (aItr == maTOXEndCps.end())
3122                     cInsert = '\xa7';
3123 	         else
3124 		      maTOXEndCps.erase(aItr);
3125             }
3126             break;
3127         case 0x9:
3128             cInsert = '\x9';    // Tab
3129             break;
3130         case 0xb:
3131             cInsert = '\xa';    // Hard NewLine
3132             break;
3133         case 0xc:
3134             bRet = HandlePageBreakChar();
3135             break;
3136         case 0x1e:   // Non-breaking hyphen
3137             rDoc.InsertString( *pPaM, CHAR_HARDHYPHEN );
3138             break;
3139         case 0x1f:   // Non-required hyphens
3140             rDoc.InsertString( *pPaM, CHAR_SOFTHYPHEN );
3141             break;
3142         case 0xa0:   // Non-breaking spaces
3143             rDoc.InsertString( *pPaM, CHAR_HARDBLANK  );
3144             break;
3145         case 0x1:
3146             /*
3147             Current thinking is that if bObj is set then we have a
3148             straightforward "traditional" ole object, otherwise we have a
3149             graphic preview of an associated ole2 object (or a simple
3150             graphic of course)
3151             */
3152 			//normally in the canvas field, the code is 0x8 0x1.
3153 			//in a special case, the code is 0x1 0x1, which yields a simple picture
3154 			{
3155 				bool bReadObj = IsInlineEscherHack();
3156 				if( bReadObj )
3157 				{
3158 					long nCurPos = pStrm->Tell();
3159 					sal_uInt8   nByteCode;
3160 					sal_uInt16 nWordCode;
3161 
3162 					if( bIsUnicode )
3163 						*pStrm >> nWordCode;
3164 					else
3165 					{
3166 						*pStrm >> nByteCode;
3167 						nWordCode = nByteCode;
3168 					}
3169 					if( nWordCode == 0x1 )
3170 						bReadObj = false;
3171 					pStrm->Seek( nCurPos );
3172 				}
3173 				if( !bReadObj )
3174 				{
3175 					SwFrmFmt *pResult = 0;
3176 					if (bObj)
3177 						pResult = ImportOle();
3178 					else if (bSpec)
3179 						pResult = ImportGraf();
3180 
3181 					// If we have a bad 0x1 insert a space instead.
3182 					if (!pResult)
3183 					{
3184 						cInsert = ' ';
3185 						ASSERT(!bObj && !bEmbeddObj && !nObjLocFc,
3186 							"WW8: Please report this document, it may have a "
3187 							"missing graphic");
3188 					}
3189 					else
3190 					{
3191 						// reset the flags.
3192 						bObj = bEmbeddObj = false;
3193 						nObjLocFc = 0;
3194 					}
3195 				}
3196 			}
3197 			break;
3198         case 0x8:
3199             if( !bObj )
3200                 Read_GrafLayer( nPosCp );
3201             break;
3202         case 0xd:
3203             bNewParaEnd = bRet = true;
3204             if (nInTable > 1)
3205             {
3206                 /*
3207                 #i9666#/#i23161#
3208                 Yes complex, if there is an entry in the undocumented PLCF
3209                 which I believe to be a record of cell and row boundaries
3210                 see if the magic bit which I believe to mean cell end is
3211                 set. I also think btw that the third byte of the 4 byte
3212                 value is the level of the cell
3213                 */
3214                 WW8PLCFspecial* pTest = pPlcxMan->GetMagicTables();
3215                 if (pTest && pTest->SeekPosExact(nPosCp+1+nCpOfs) &&
3216                     pTest->Where() == nPosCp+1+nCpOfs)
3217                 {
3218                     WW8_FC nPos;
3219                     void *pData;
3220                     pTest->Get(nPos, pData);
3221                     sal_uInt32 nData = SVBT32ToUInt32(*(SVBT32*)pData);
3222                     if (nData & 0x2)    //Might be how it works
3223                     {
3224                         TabCellEnd();
3225                         bRet = false;
3226                     }
3227                 }
3228                 else if (bWasTabCellEnd)
3229                 {
3230                     TabCellEnd();
3231                     bRet = false;
3232                 }
3233             }
3234 
3235             bWasTabCellEnd = false;
3236 
3237             break;              // line end
3238         case 0x5:               // Annotation reference
3239         case 0x13:
3240             break;
3241         case 0x2:
3242             if (!maFtnStack.empty())
3243                 cInsert = 0x2;
3244             break;                  // Auto-Fussnoten-Nummer
3245 #if OSL_DEBUG_LEVEL > 1
3246         default:
3247             ::std::clog << "<unknownValue val=\"" << nWCharVal << "\">" << ::std::endl;
3248             break;
3249 #endif
3250     }
3251 
3252     if( '\x0' != cInsert )
3253     {
3254         String sInsert = ByteString::ConvertToUnicode(cInsert,
3255             RTL_TEXTENCODING_MS_1252 );
3256         AddTextToParagraph(sInsert);
3257     }
3258     if (!maApos.back()) //a para end in apo doesn't count
3259         bWasParaEnd = bNewParaEnd;
3260     return bRet;
3261 }
3262 
ProcessAktCollChange(WW8PLCFManResult & rRes,bool * pStartAttr,bool bCallProcessSpecial)3263 void SwWW8ImplReader::ProcessAktCollChange(WW8PLCFManResult& rRes,
3264     bool* pStartAttr, bool bCallProcessSpecial)
3265 {
3266     sal_uInt16 nOldColl = nAktColl;
3267     nAktColl = pPlcxMan->GetColl();
3268 
3269     // Invalid Style-Id
3270     if (nAktColl >= nColls || !pCollA[nAktColl].pFmt || !pCollA[nAktColl].bColl)
3271     {
3272         nAktColl = 0;
3273         bParaAutoBefore = false;
3274         bParaAutoAfter = false;
3275     }
3276     else
3277     {
3278         bParaAutoBefore = pCollA[nAktColl].bParaAutoBefore;
3279         bParaAutoAfter = pCollA[nAktColl].bParaAutoAfter;
3280     }
3281 
3282     bool bTabRowEnd = false;
3283     if( pStartAttr && bCallProcessSpecial && !bInHyperlink )
3284     {
3285         bool bReSync;
3286         // Frame / Table / Autonumbering List Level
3287         bTabRowEnd = ProcessSpecial(bReSync, rRes.nAktCp+pPlcxMan->GetCpOfs());
3288         if( bReSync )
3289             *pStartAttr = pPlcxMan->Get( &rRes ); // hole Attribut-Pos neu
3290     }
3291 
3292     if (!bTabRowEnd && StyleExists(nAktColl))
3293     {
3294         SetTxtFmtCollAndListLevel( *pPaM, pCollA[ nAktColl ]);
3295         ChkToggleAttr(pCollA[ nOldColl ].n81Flags, pCollA[ nAktColl ].n81Flags);
3296         ChkToggleBiDiAttr(pCollA[nOldColl].n81BiDiFlags,
3297             pCollA[nAktColl].n81BiDiFlags);
3298     }
3299 }
3300 
ReadTextAttr(WW8_CP & rTxtPos,bool & rbStartLine)3301 long SwWW8ImplReader::ReadTextAttr(WW8_CP& rTxtPos, bool& rbStartLine)
3302 {
3303     long nSkipChars = 0;
3304     WW8PLCFManResult aRes;
3305 
3306     ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
3307     bool bStartAttr = pPlcxMan->Get(&aRes); // hole Attribut-Pos
3308     aRes.nAktCp = rTxtPos;              // Akt. Cp-Pos
3309 
3310     bool bNewSection = (aRes.nFlags & MAN_MASK_NEW_SEP) && !bIgnoreText;
3311     if ( bNewSection )	// neue Section
3312     {
3313         ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
3314         // PageDesc erzeugen und fuellen
3315         maSectionManager.CreateSep(rTxtPos, bPgSecBreak);
3316                                             // -> 0xc war ein Sectionbreak, aber
3317                                             // kein Pagebreak;
3318         bPgSecBreak = false;                // PageDesc erzeugen und fuellen
3319         ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
3320     }
3321 
3322     // neuer Absatz ueber Plcx.Fkp.papx
3323     if ( (aRes.nFlags & MAN_MASK_NEW_PAP)|| rbStartLine )
3324     {
3325         ProcessAktCollChange( aRes, &bStartAttr,
3326             MAN_MASK_NEW_PAP == (aRes.nFlags & MAN_MASK_NEW_PAP) &&
3327             !bIgnoreText );
3328         rbStartLine = false;
3329     }
3330 
3331     // position of last CP that's to be ignored
3332     long nSkipPos = -1;
3333 
3334     if( 0 < aRes.nSprmId )                      // leere Attrs ignorieren
3335     {
3336         if( ( eFTN > aRes.nSprmId ) || ( 0x0800 <= aRes.nSprmId ) )
3337         {
3338             if( bStartAttr )                            // WW-Attribute
3339             {
3340                 if( aRes.nMemLen >= 0 )
3341                     ImportSprm(aRes.pMemPos, aRes.nSprmId);
3342             }
3343             else
3344                 EndSprm( aRes.nSprmId );        // Attr ausschalten
3345         }
3346         else if( aRes.nSprmId < 0x800 ) // eigene Hilfs-Attribute
3347         {
3348             if (bStartAttr)
3349             {
3350                 nSkipChars = ImportExtSprm(&aRes);
3351                 if (
3352                     (aRes.nSprmId == eFTN) || (aRes.nSprmId == eEDN) ||
3353                     (aRes.nSprmId == eFLD) || (aRes.nSprmId == eAND)
3354                    )
3355                 {
3356                     // Felder/Ftn-/End-Note hier ueberlesen
3357                     rTxtPos += nSkipChars;
3358                     nSkipPos = rTxtPos-1;
3359                 }
3360             }
3361             else
3362                 EndExtSprm( aRes.nSprmId );
3363         }
3364     }
3365 
3366     pStrm->Seek(pSBase->WW8Cp2Fc( pPlcxMan->GetCpOfs() + rTxtPos, &bIsUnicode));
3367 
3368     // Find next Attr position (and Skip attributes of field contents if needed)
3369     if (nSkipChars && !bIgnoreText)
3370         pCtrlStck->MarkAllAttrsOld();
3371     bool bOldIgnoreText = bIgnoreText;
3372     bIgnoreText = true;
3373     sal_uInt16 nOldColl = nAktColl;
3374     bool bDoPlcxManPlusPLus = true;
3375     long nNext;
3376     do
3377     {
3378         if( bDoPlcxManPlusPLus )
3379             (*pPlcxMan)++;
3380         nNext = pPlcxMan->Where();
3381 
3382         if (mpPostProcessAttrsInfo &&
3383             mpPostProcessAttrsInfo->mnCpStart == nNext)
3384         {
3385             mpPostProcessAttrsInfo->mbCopy = true;
3386         }
3387 
3388         if( (0 <= nNext) && (nSkipPos >= nNext) )
3389         {
3390             nNext = ReadTextAttr( rTxtPos, rbStartLine );
3391             bDoPlcxManPlusPLus = false;
3392             bIgnoreText = true;
3393         }
3394 
3395         if (mpPostProcessAttrsInfo &&
3396             nNext > mpPostProcessAttrsInfo->mnCpEnd)
3397         {
3398             mpPostProcessAttrsInfo->mbCopy = false;
3399         }
3400     }
3401     while( nSkipPos >= nNext );
3402     bIgnoreText    = bOldIgnoreText;
3403     if( nSkipChars )
3404     {
3405         pCtrlStck->KillUnlockedAttrs( *pPaM->GetPoint() );
3406         if( nOldColl != pPlcxMan->GetColl() )
3407             ProcessAktCollChange(aRes, 0, false);
3408     }
3409 
3410     return nNext;
3411 }
3412 //Modify here for #119405, by easyfan, 2012-05-24
3413 //Revised 2012.8.16 for the complex attribute presentation of 0x0D in MS
IsParaEndInCPs(sal_Int32 nStart,sal_Int32 nEnd,bool bSdOD) const3414 bool SwWW8ImplReader::IsParaEndInCPs(sal_Int32 nStart, sal_Int32 nEnd,bool bSdOD) const
3415 {
3416 	//Modify for #119405 by chengjh, 2012-08-16
3417 	//Revised for performance consideration
3418 	if (nStart == -1 || nEnd == -1 || nEnd < nStart )
3419 		return false;
3420 
3421 	for (cp_vector::const_reverse_iterator aItr = maEndParaPos.rbegin(); aItr!= maEndParaPos.rend(); aItr++)
3422 	//End
3423 	{
3424 		//Revised 2012.8.16,to the 0x0D,the attribute will have two situations
3425 		//*********within***********exact******//
3426 		//*********but also sample with only left and the position of 0x0d is the edge of the right side***********//
3427 		if ( bSdOD && ( (nStart < *aItr && nEnd > *aItr) || ( nStart == nEnd && *aItr == nStart)) )
3428 			return true;
3429 		else if ( !bSdOD &&  (nStart < *aItr && nEnd >= *aItr) )
3430 			return true;
3431 	}
3432 
3433 	return false;
3434 }
3435 //End of modification, by easyfan
3436 //Modify for #119405 by chengjh, 2012-08-16
3437 //Clear the para end position recorded in reader intermittently for the least impact on loading performance
ClearParaEndPosition()3438 void SwWW8ImplReader::ClearParaEndPosition()
3439 {
3440 	if ( maEndParaPos.size() > 0 )
3441 		maEndParaPos.clear();
3442 }
3443 //End
ReadAttrs(WW8_CP & rNext,WW8_CP & rTxtPos,bool & rbStartLine)3444 void SwWW8ImplReader::ReadAttrs(WW8_CP& rNext, WW8_CP& rTxtPos, bool& rbStartLine)
3445 {
3446     if( rTxtPos >= rNext )
3447     {           // Stehen Attribute an ?
3448 
3449         do
3450         {
3451 		//Modify here for #119405, by easyfan, 2012-05-24
3452         	maCurrAttrCP = rTxtPos;
3453 		//End of modification, by easyfan
3454             rNext = ReadTextAttr( rTxtPos, rbStartLine );
3455         }
3456         while( rTxtPos >= rNext );
3457 
3458     }
3459     else if ( rbStartLine )
3460     {
3461 // keine Attribute, aber trotzdem neue Zeile
3462 // wenn eine Zeile mit einem Seitenumbruch aufhoert und sich keine
3463 // Absatzattribute / Absatzvorlagen aendern, ist das Zeilenende
3464 // nicht im Plcx.Fkp.papx eingetragen, d.h. ( nFlags & MAN_MASK_NEW_PAP )
3465 // ist false. Deshalb muss als Sonderbehandlung hier die Vorlage gesetzt
3466 // werden.
3467         if (!bCpxStyle && nAktColl < nColls)
3468             SetTxtFmtCollAndListLevel(*pPaM, pCollA[nAktColl]);
3469         rbStartLine = false;
3470     }
3471 }
3472 
3473 // CloseAttrEnds zum Lesen nur der Attributenden am Ende eines Textes oder
3474 // Textbereiches ( Kopfzeile, Fussnote, ...). Attributanfaenge, Felder
3475 // werden ignoriert.
CloseAttrEnds()3476 void SwWW8ImplReader::CloseAttrEnds()
3477 {
3478     //If there are any unclosed sprms then copy them to
3479     //another stack and close the ones that must be closed
3480     std::stack<sal_uInt16> aStack;
3481     pPlcxMan->TransferOpenSprms(aStack);
3482 
3483     while (!aStack.empty())
3484     {
3485         sal_uInt16 nSprmId = aStack.top();
3486         if ((0 < nSprmId) && (( eFTN > nSprmId) || (0x0800 <= nSprmId)))
3487             EndSprm(nSprmId);
3488         aStack.pop();
3489     }
3490 
3491     EndSpecial();
3492 }
3493 
ReadText(long nStartCp,long nTextLen,ManTypes nType)3494 bool SwWW8ImplReader::ReadText(long nStartCp, long nTextLen, ManTypes nType)
3495 {
3496     sw::log::Environment eContext = sw::log::eMainText;
3497     if (nType == MAN_MAINTEXT)
3498         eContext = sw::log::eMainText;
3499     else
3500         eContext = sw::log::eSubDoc;
3501     maTracer.EnterEnvironment(eContext);
3502 
3503     bool bJoined=false;
3504 
3505     bool bStartLine = true;
3506     short nCrCount = 0;
3507     short nDistance = 0;
3508 
3509     bWasParaEnd = false;
3510     nAktColl    =  0;
3511     pAktItemSet =  0;
3512     nCharFmt    = -1;
3513     bSpec = false;
3514     bPgSecBreak = false;
3515 
3516     pPlcxMan = new WW8PLCFMan( pSBase, nType, nStartCp );
3517     long nCpOfs = pPlcxMan->GetCpOfs(); // Offset fuer Header/Footer, Footnote
3518 
3519     WW8_CP nNext = pPlcxMan->Where();
3520     SwTxtNode* pPreviousNode = 0;
3521     sal_uInt8 nDropLines = 0;
3522     SwCharFmt* pNewSwCharFmt = 0;
3523     const SwCharFmt* pFmt = 0;
3524     pStrm->Seek( pSBase->WW8Cp2Fc( nStartCp + nCpOfs, &bIsUnicode ) );
3525 
3526     WW8_CP l = nStartCp;
3527     while ( l<nStartCp+nTextLen )
3528     {
3529         ReadAttrs( nNext, l, bStartLine );// behandelt auch Section-Breaks
3530         ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
3531 
3532         if (mpPostProcessAttrsInfo != NULL)
3533             PostProcessAttrs();
3534 
3535         if( l>= nStartCp + nTextLen )
3536             break;
3537 
3538         bStartLine = ReadChars(l, nNext, nStartCp+nTextLen, nCpOfs);
3539 
3540         // If the previous paragraph was a dropcap then do not
3541         // create a new txtnode and join the two paragraphs together
3542 
3543         if (bStartLine && !pPreviousNode) // Zeilenende
3544         {
3545             bool bSplit = true;
3546             if (mbCareFirstParaEndInToc)
3547             {
3548                 mbCareFirstParaEndInToc = false;
3549                 if (pPaM->End() && pPaM->End()->nNode.GetNode().GetTxtNode() &&  pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0)
3550                     bSplit = false;
3551             }
3552             if (mbCareLastParaEndInToc)
3553             {
3554                 mbCareLastParaEndInToc = false;
3555                 if (pPaM->End() && pPaM->End()->nNode.GetNode().GetTxtNode() &&  pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0)
3556                     bSplit = false;
3557             }
3558             if (bSplit)
3559             {
3560                 // #119405# - We will record the CP of a paragraph end ('0x0D'), if current loading contents is from main stream;
3561                 if (mbOnLoadingMain)
3562                     maEndParaPos.push_back(l-1);
3563                 AppendTxtNode(*pPaM->GetPoint());
3564             }
3565         }
3566 
3567         if (pPreviousNode && bStartLine)
3568         {
3569             SwTxtNode* pEndNd = pPaM->GetNode()->GetTxtNode();
3570             const xub_StrLen nDropCapLen = pPreviousNode->GetTxt().Len();
3571 
3572             // Need to reset the font size and text position for the dropcap
3573             {
3574                 SwPaM aTmp(*pEndNd, 0, *pEndNd, nDropCapLen+1);
3575                 pCtrlStck->Delete(aTmp);
3576             }
3577 
3578             // Get the default document dropcap which we can use as our template
3579             const SwFmtDrop* defaultDrop =
3580                 (const SwFmtDrop*) GetFmtAttr(RES_PARATR_DROP);
3581             SwFmtDrop aDrop(*defaultDrop);
3582 
3583             aDrop.GetLines() = nDropLines;
3584             aDrop.GetDistance() = nDistance;
3585             aDrop.GetChars() = writer_cast<sal_uInt8>(nDropCapLen);
3586             // Word has no concept of a "whole word dropcap"
3587             aDrop.GetWholeWord() = false;
3588 
3589             if (pFmt)
3590 			    aDrop.SetCharFmt(const_cast<SwCharFmt*>(pFmt));
3591 			else if(pNewSwCharFmt)
3592 				aDrop.SetCharFmt(const_cast<SwCharFmt*>(pNewSwCharFmt));
3593 
3594             SwPosition aStart(*pEndNd);
3595             pCtrlStck->NewAttr(aStart, aDrop);
3596             pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_DROP);
3597             pPreviousNode = 0;
3598         }
3599         else if (bDropCap)
3600         {
3601             // If we have found a dropcap store the textnode
3602             pPreviousNode = pPaM->GetNode()->GetTxtNode();
3603 
3604             const sal_uInt8 *pDCS;
3605 
3606             if (bVer67)
3607                 pDCS = pPlcxMan->GetPapPLCF()->HasSprm(46);
3608             else
3609                 pDCS = pPlcxMan->GetPapPLCF()->HasSprm(0x442C);
3610 
3611             if (pDCS)
3612                 nDropLines = (*pDCS) >> 3;
3613             else    // There is no Drop Cap Specifier hence no dropcap
3614                 pPreviousNode = 0;
3615 
3616             if (const sal_uInt8 *pDistance = pPlcxMan->GetPapPLCF()->HasSprm(0x842F))
3617                 nDistance = SVBT16ToShort( pDistance );
3618             else
3619                 nDistance = 0;
3620 
3621             const SwFmtCharFmt *pSwFmtCharFmt = 0;
3622 
3623             if(pAktItemSet)
3624                 pSwFmtCharFmt = &(ItemGet<SwFmtCharFmt>(*pAktItemSet, RES_TXTATR_CHARFMT));
3625 
3626             if(pSwFmtCharFmt)
3627                 pFmt = pSwFmtCharFmt->GetCharFmt();
3628 
3629             if(pAktItemSet && !pFmt)
3630             {
3631                 String sPrefix(CREATE_CONST_ASC( "WW8Dropcap"));
3632                 sPrefix += String::CreateFromInt32( nDropCap++ );
3633                 pNewSwCharFmt = rDoc.MakeCharFmt(sPrefix, (SwCharFmt*)rDoc.GetDfltCharFmt());
3634                  pAktItemSet->ClearItem(RES_CHRATR_ESCAPEMENT);
3635                 pNewSwCharFmt->SetFmtAttr( *pAktItemSet );
3636             }
3637 
3638             delete pAktItemSet;
3639             pAktItemSet = 0;
3640             bDropCap=false;
3641         }
3642 
3643         if (bStartLine || bWasTabRowEnd)
3644         {
3645             // alle 64 CRs aufrufen not for Header u. ae.
3646             if ((nCrCount++ & 0x40) == 0 && nType == MAN_MAINTEXT)
3647             {
3648                 nProgress = (sal_uInt16)( l * 100 / nTextLen );
3649                 ::SetProgressState(nProgress, mpDocShell); // Update
3650             }
3651         }
3652 
3653         // If we have encountered a 0x0c which indicates either section of
3654         // pagebreak then look it up to see if it is a section break, and
3655         // if it is not then insert a page break. If it is a section break
3656         // it will be handled as such in the ReadAttrs of the next loop
3657         if (bPgSecBreak)
3658         {
3659             // We need only to see if a section is ending at this cp,
3660             // the plcf will already be sitting on the correct location
3661             // if it is there.
3662             WW8PLCFxDesc aTemp;
3663             aTemp.nStartPos = aTemp.nEndPos = WW8_CP_MAX;
3664             if (pPlcxMan->GetSepPLCF())
3665                 pPlcxMan->GetSepPLCF()->GetSprms(&aTemp);
3666             if ((aTemp.nStartPos != l) && (aTemp.nEndPos != l))
3667             {
3668                 // #i39251# - insert text node for page break, if no one inserted.
3669                 // #i43118# - refine condition: the anchor control stack has to have entries,
3670                 // otherwise it's not needed to insert a text node.
3671                 if ( !bStartLine && pAnchorStck->Count() > 0 )
3672                 {
3673                     AppendTxtNode(*pPaM->GetPoint());
3674                 }
3675                 rDoc.InsertPoolItem(*pPaM,
3676                     SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK), 0);
3677                 bFirstParaOfPage = true;//xushanchuan add for issue106569
3678                 bPgSecBreak = false;
3679             }
3680         }
3681     }
3682 
3683     if (pPaM->GetPoint()->nContent.GetIndex())
3684         AppendTxtNode(*pPaM->GetPoint());
3685 
3686     if (!bInHyperlink)
3687         bJoined = JoinNode(*pPaM);
3688 
3689     CloseAttrEnds();
3690 
3691     delete pPlcxMan, pPlcxMan = 0;
3692     maTracer.LeaveEnvironment(eContext);
3693     return bJoined;
3694 }
3695 
3696 /***************************************************************************
3697 #           class SwWW8ImplReader
3698 #**************************************************************************/
3699 
SwWW8ImplReader(sal_uInt8 nVersionPara,SvStorage * pStorage,SvStream * pSt,SwDoc & rD,const String & rBaseURL,bool bNewDoc)3700 SwWW8ImplReader::SwWW8ImplReader(sal_uInt8 nVersionPara, SvStorage* pStorage,
3701     SvStream* pSt, SwDoc& rD, const String& rBaseURL, bool bNewDoc)
3702     : mpDocShell(rD.GetDocShell())
3703     , maTracer(*(mpDocShell->GetMedium()))
3704     , pStg(pStorage)
3705     , pStrm(pSt)
3706     , pTableStream(0)
3707     , pDataStream(0)
3708     , rDoc(rD)
3709     , maSectionManager(*this)
3710     , maInsertedTables(rD)
3711     , maSectionNameGenerator(rD,CREATE_CONST_ASC("WW"))
3712     , maGrfNameGenerator(bNewDoc,String('G'))
3713     , maParaStyleMapper(rD)
3714     , maCharStyleMapper(rD)
3715     , maTxtNodesHavingFirstLineOfstSet()
3716     , maTxtNodesHavingLeftIndentSet()
3717     , pMSDffManager(0)
3718     , mpAtnNames(0)
3719     , pAuthorInfos(0)
3720     , sBaseURL(rBaseURL)
3721     , m_bRegardHindiDigits( false )
3722     , mbNewDoc(bNewDoc)
3723     , nDropCap(0)
3724     , nIdctHint(0)
3725     , bBidi(false)
3726     , bReadTable(false)
3727     , mbLoadingTOXCache(false)
3728     , mnEmbeddedTOXLevel(0)
3729     , mbLoadingTOXHyperlink(false)
3730     , mpPosAfterTOC(0)
3731     , mbCareFirstParaEndInToc(false)
3732     , mbCareLastParaEndInToc(false)
3733     , maTOXEndCps()
3734 	//Modify here for #119405, by easyfan, 2012-05-24
3735 	,maCurrAttrCP(-1),
3736 	mbOnLoadingMain(false)
3737 	//End of modification, by easyfan
3738 {
3739     pStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
3740     nWantedVersion = nVersionPara;
3741     pCtrlStck   = 0;
3742     mpRedlineStack = 0;
3743     pReffedStck = 0;
3744     pReffingStck = 0;
3745     pAnchorStck = 0;
3746     pFonts = 0;
3747     pSBase = 0;
3748     pPlcxMan = 0;
3749     pStyles = 0;
3750     pAktColl = 0;
3751     pLstManager = 0;
3752     pAktItemSet = 0;
3753     pCollA = 0;
3754     pDfltTxtFmtColl = 0;
3755     pStandardFmtColl = 0;
3756     pHdFt = 0;
3757     pWFlyPara = 0;
3758     pSFlyPara = 0;
3759     pFlyFmtOfJustInsertedGraphic   = 0;
3760     pFmtOfJustInsertedApo = 0;
3761     pPreviousNumPaM = 0;
3762     pPrevNumRule = 0;
3763     nColls = nAktColl = 0;
3764     nObjLocFc = nPicLocFc = 0;
3765     nInTable=0;
3766     bReadNoTbl = bPgSecBreak = bSpec = bObj = bTxbxFlySection
3767                = bHasBorder = bSymbol = bIgnoreText
3768                = bWasTabRowEnd = bWasTabCellEnd = false;
3769     bShdTxtCol = bCharShdTxtCol = bAnl = bHdFtFtnEdn = bFtnEdn
3770                = bIsHeader = bIsFooter = bIsUnicode = bCpxStyle = bStyNormal =
3771                  bWWBugNormal  = false;
3772 
3773     mpPostProcessAttrsInfo = 0;
3774 
3775     bNoAttrImport = bPgChpLevel = bEmbeddObj = false;
3776     bAktAND_fNumberAcross = false;
3777     bNoLnNumYet = true;
3778     bInHyperlink = false;
3779     bWasParaEnd = false;
3780     bDropCap = false;
3781     bFirstPara = true;
3782 	  bFirstParaOfPage = false;//xushanchuan add for issue106569
3783     bParaAutoBefore = false;
3784     bParaAutoAfter = false;
3785     nProgress = 0;
3786     nSwNumLevel = nWwNumType = 0xff;
3787     pTableDesc = 0;
3788     pNumOlst = 0;
3789     pNode_FLY_AT_PARA = 0;
3790     pDrawModel = 0;
3791     pDrawPg = 0;
3792     mpDrawEditEngine = 0;
3793     pWWZOrder = 0;
3794     pFormImpl = 0;
3795     pNumFldType = 0;
3796     nFldNum = 0;
3797 
3798     nLFOPosition = USHRT_MAX;
3799     nListLevel = WW8ListManager::nMaxLevel;
3800     eHardCharSet = RTL_TEXTENCODING_DONTKNOW;
3801 
3802     nPgChpDelim = nPgChpLevel = 0;
3803 
3804     maApos.push_back(false);
3805 }
3806 
DeleteStk(SwFltControlStack * pStck)3807 void SwWW8ImplReader::DeleteStk(SwFltControlStack* pStck)
3808 {
3809     if( pStck )
3810     {
3811         pStck->SetAttr( *pPaM->GetPoint(), 0, false);
3812         pStck->SetAttr( *pPaM->GetPoint(), 0, false);
3813         delete pStck;
3814     }
3815     else
3816     {
3817         ASSERT( sal_False, "WW stack already deleted" );
3818     }
3819 }
3820 
SetSegmentToPageDesc(const wwSection & rSection,bool bTitlePage,bool bIgnoreCols)3821 void wwSectionManager::SetSegmentToPageDesc(const wwSection &rSection,
3822     bool bTitlePage, bool bIgnoreCols)
3823 {
3824     SwPageDesc &rPage = bTitlePage ? *rSection.mpTitlePage : *rSection.mpPage;
3825 
3826     SetNumberingType(rSection, rPage);
3827 
3828     SwFrmFmt &rFmt = rPage.GetMaster();
3829 
3830     if(mrReader.pWDop->fUseBackGroundInAllmodes)  // #i56806# Make sure mrReader is initialized
3831 		mrReader.GrafikCtor();
3832 
3833 
3834     if (mrReader.pWDop->fUseBackGroundInAllmodes && mrReader.pMSDffManager)
3835     {
3836         Rectangle aRect(0, 0, 100, 100); //A dummy, we don't care about the size
3837         SvxMSDffImportData aData(aRect);
3838         SdrObject* pObject = 0;
3839         if (mrReader.pMSDffManager->GetShape(0x401, pObject, aData))
3840         {
3841             SvxMSDffImportRec * pRec = aData.GetRecord(0);
3842 
3843             // Only handle shape if it is a background shape
3844             if ((pRec->nFlags & 0x400) != 0)
3845             {
3846                 SfxItemSet aSet(rFmt.GetAttrSet());
3847                 mrReader.MatchSdrItemsIntoFlySet(pObject, aSet, mso_lineSimple,
3848                                                  mso_sptRectangle, aRect);
3849                 rFmt.SetFmtAttr(aSet.Get(RES_BACKGROUND));
3850             }
3851         }
3852     }
3853     wwULSpaceData aULData;
3854     GetPageULData(rSection, bTitlePage, aULData);
3855     SetPageULSpaceItems(rFmt, aULData, rSection);
3856 
3857     SetPage(rPage, rFmt, rSection, bIgnoreCols);
3858 
3859     bool bSetBorder = false;
3860     switch (rSection.maSep.pgbApplyTo)
3861     {
3862         case 0:
3863         case 3:
3864             bSetBorder = true;
3865             break;
3866         case 1:
3867             bSetBorder = bTitlePage;
3868             break;
3869         case 2:
3870             bSetBorder = !bTitlePage;
3871             break;
3872     }
3873     if (bSetBorder)
3874         mrReader.SetPageBorder(rFmt, rSection);
3875 
3876     mrReader.SetDocumentGrid(rFmt, rSection);
3877 }
3878 
SetUseOn(wwSection & rSection)3879 void wwSectionManager::SetUseOn(wwSection &rSection)
3880 {
3881     bool bEven = (rSection.maSep.grpfIhdt & (WW8_HEADER_EVEN|WW8_FOOTER_EVEN)) ?
3882         true : false;
3883 
3884     bool bMirror = mrReader.pWDop->fMirrorMargins ||
3885         mrReader.pWDop->doptypography.f2on1;
3886 
3887     UseOnPage eUseBase = bMirror ? nsUseOnPage::PD_MIRROR : nsUseOnPage::PD_ALL;
3888     UseOnPage eUse = eUseBase;
3889     if (!bEven)
3890         eUse = (UseOnPage)(eUse | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE);
3891 
3892     ASSERT(rSection.mpPage, "Makes no sense to call me with no pages to set");
3893     if (rSection.mpPage)
3894         rSection.mpPage->WriteUseOn(eUse);
3895     if (rSection.mpTitlePage)
3896     {
3897         rSection.mpTitlePage->WriteUseOn(
3898             (UseOnPage) (eUseBase | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE));
3899     }
3900 }
3901 
3902 //Set the page descriptor on this node, handle the different cases for a text
3903 //node or a table
GiveNodePageDesc(SwNodeIndex & rIdx,const SwFmtPageDesc & rPgDesc,SwDoc & rDoc)3904 void GiveNodePageDesc(SwNodeIndex &rIdx, const SwFmtPageDesc &rPgDesc,
3905     SwDoc &rDoc)
3906 {
3907     /*
3908     If its a table here, apply the pagebreak to the table
3909     properties, otherwise we add it to the para at this
3910     position
3911     */
3912     if (rIdx.GetNode().IsTableNode())
3913     {
3914         SwTable& rTable =
3915             rIdx.GetNode().GetTableNode()->GetTable();
3916         SwFrmFmt* pApply = rTable.GetFrmFmt();
3917         ASSERT(pApply, "impossible");
3918         if (pApply)
3919             pApply->SetFmtAttr(rPgDesc);
3920     }
3921     else
3922     {
3923         SwPosition aPamStart(rIdx);
3924         aPamStart.nContent.Assign(
3925             rIdx.GetNode().GetCntntNode(), 0);
3926         SwPaM aPage(aPamStart);
3927 
3928         rDoc.InsertPoolItem(aPage, rPgDesc, 0);
3929     }
3930 }
3931 
3932 //Map a word section with to either one or two writer page descriptors
3933 //depending on if the word section has a title page
SetSwFmtPageDesc(mySegIter & rIter,mySegIter & rStart,bool bIgnoreCols)3934 SwFmtPageDesc wwSectionManager::SetSwFmtPageDesc(mySegIter &rIter,
3935     mySegIter &rStart, bool bIgnoreCols)
3936 {
3937     SwFmtPageDesc aEmpty;
3938     // Always read title page header/footer data - it could be used by following sections
3939     {
3940         if (IsNewDoc() && rIter == rStart)
3941         {
3942             rIter->mpTitlePage =
3943                 mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_FIRST);
3944         }
3945         else
3946         {
3947             sal_uInt16 nPos = mrReader.rDoc.MakePageDesc(
3948                 ViewShell::GetShellRes()->GetPageDescName(mnDesc)
3949                 , 0, false);
3950             rIter->mpTitlePage = &mrReader.rDoc._GetPageDesc(nPos);
3951         }
3952         ASSERT(rIter->mpTitlePage, "no page!");
3953         if (!rIter->mpTitlePage)
3954             return aEmpty;
3955 
3956         SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
3957     }
3958 
3959     if (IsNewDoc() && rIter == rStart)
3960     {
3961         rIter->mpPage =
3962             mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_STANDARD);
3963     }
3964     else
3965     {
3966         sal_uInt16 nPos = mrReader.rDoc.MakePageDesc(
3967             ViewShell::GetShellRes()->GetPageDescName(mnDesc,
3968                 false, rIter->HasTitlePage()),
3969                 rIter->mpTitlePage, false);
3970         rIter->mpPage = &mrReader.rDoc._GetPageDesc(nPos);
3971     }
3972     ASSERT(rIter->mpPage, "no page!");
3973     if (!rIter->mpPage)
3974         return aEmpty;
3975 
3976     //Set page before hd/ft
3977     const wwSection *pPrevious = 0;
3978 
3979     mySegIter aPrev = rIter;
3980     while( aPrev!= rStart )
3981     {
3982         aPrev--;
3983         pPrevious = &(*(aPrev));
3984         if( aPrev->IsContinous())
3985             continue;
3986         else{
3987             break;
3988         }
3989     }
3990 
3991     SetHdFt(*rIter, std::distance(rStart, rIter), pPrevious);
3992     SetUseOn(*rIter);
3993 
3994     //Set hd/ft after set page
3995     if (rIter->mpTitlePage)
3996         SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
3997     SetSegmentToPageDesc(*rIter, false, bIgnoreCols);
3998 
3999     SwFmtPageDesc aRet(rIter->HasTitlePage() ?
4000         rIter->mpTitlePage : rIter->mpPage);
4001 
4002     rIter->mpPage->SetFollow(rIter->mpPage);
4003 
4004     if (rIter->mpTitlePage)
4005         rIter->mpTitlePage->SetFollow(rIter->mpPage);
4006 
4007     if (rIter->PageRestartNo())
4008         aRet.SetNumOffset(rIter->PageStartAt());
4009 
4010     ++mnDesc;
4011     return aRet;
4012 }
4013 
IsNewDoc() const4014 bool wwSectionManager::IsNewDoc() const
4015 {
4016     return mrReader.mbNewDoc;
4017 }
4018 
InsertSegments()4019 void wwSectionManager::InsertSegments()
4020 {
4021     const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
4022     sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
4023     mySegIter aEnd = maSegments.end();
4024     mySegIter aStart = maSegments.begin();
4025     for (mySegIter aIter = aStart; aIter != aEnd; ++aIter)
4026     {
4027         mySegIter aNext = aIter+1;
4028         mySegIter aPrev = (aIter == aStart) ? aIter : aIter-1;
4029 
4030         // If two following sections are different in following properties, Word will interprete a continuous
4031         // section break between them as if it was a section break next page.
4032         bool bThisAndPreviousAreCompatible = ((aIter->GetPageWidth() == aPrev->GetPageWidth()) &&
4033             (aIter->GetPageHeight() == aPrev->GetPageHeight()) && (aIter->IsLandScape() == aPrev->IsLandScape()));
4034 
4035         bool bInsertSection = (aIter != aStart) ? (aIter->IsContinous() &&  bThisAndPreviousAreCompatible): false;
4036         bool bInsertPageDesc = !bInsertSection;
4037         bool bProtected = SectionIsProtected(*aIter); // do we really  need this ?? I guess I have a different logic in editshell which disales this...
4038         if (bUseEnhFields && mrReader.pWDop->fProtEnabled && aIter->IsNotProtected())
4039         {
4040             // here we have the special case that the whole document is protected, with the execption of this section.
4041             // I want to address this when I do the section rework, so for the moment we disable the overall protection then...
4042             mrReader.rDoc.set(IDocumentSettingAccess::PROTECT_FORM, false );
4043         }
4044 
4045 
4046         if (bInsertPageDesc)
4047         {
4048             /*
4049              If a cont section follows this section then we won't be
4050              creating a page desc with 2+ cols as we cannot host a one
4051              col section in a 2+ col pagedesc and make it look like
4052              word. But if the current section actually has columns then
4053              we are forced to insert a section here as well as a page
4054              descriptor.
4055             */
4056 
4057             bool bIgnoreCols = false;
4058             bool bThisAndNextAreCompatible = (aNext != aEnd) ? ((aIter->GetPageWidth() == aNext->GetPageWidth()) &&
4059                 (aIter->GetPageHeight() == aNext->GetPageHeight()) && (aIter->IsLandScape() == aNext->IsLandScape())) : true;
4060 
4061             if (((aNext != aEnd && aNext->IsContinous() && bThisAndNextAreCompatible) || bProtected))
4062             {
4063                 bIgnoreCols = true;
4064                 if ((aIter->NoCols() > 1) || bProtected)
4065                     bInsertSection = true;
4066             }
4067 
4068             SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, bIgnoreCols));
4069             if (!aDesc.GetPageDesc())
4070                 continue;
4071             GiveNodePageDesc(aIter->maStart, aDesc, mrReader.rDoc);
4072         }
4073 
4074         SwTxtNode* pTxtNd = 0;
4075         if (bInsertSection)
4076         {
4077             //Start getting the bounds of this section
4078             SwPaM aSectPaM(*mrReader.pPaM);
4079             SwNodeIndex aAnchor(aSectPaM.GetPoint()->nNode);
4080             if (aNext != aEnd)
4081             {
4082                 aAnchor = aNext->maStart;
4083                 aSectPaM.GetPoint()->nNode = aAnchor;
4084                 aSectPaM.GetPoint()->nContent.Assign(
4085                     aNext->maStart.GetNode().GetCntntNode(), 0);
4086                 aSectPaM.Move(fnMoveBackward);
4087             }
4088 
4089             const SwPosition* pPos  = aSectPaM.GetPoint();
4090             SwTxtNode const*const pSttNd = pPos->nNode.GetNode().GetTxtNode();
4091             const SwTableNode* pTableNd = pSttNd ? pSttNd->FindTableNode() : 0;
4092             if (pTableNd)
4093             {
4094                 pTxtNd =
4095                     mrReader.rDoc.GetNodes().MakeTxtNode(aAnchor,
4096                     mrReader.rDoc.GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
4097 
4098                 aSectPaM.GetPoint()->nNode = SwNodeIndex(*pTxtNd);
4099                 aSectPaM.GetPoint()->nContent.Assign(
4100                     aSectPaM.GetCntntNode(), 0);
4101             }
4102 
4103             aSectPaM.SetMark();
4104 
4105             aSectPaM.GetPoint()->nNode = aIter->maStart;
4106             aSectPaM.GetPoint()->nContent.Assign(
4107                 aSectPaM.GetCntntNode(), 0);
4108             //End getting the bounds of this section, quite a job eh ?
4109 
4110             SwSectionFmt *pRet = InsertSection(aSectPaM, *aIter);
4111             //The last section if continuous is always unbalanced
4112             if (pRet)
4113             {
4114                 //Set the columns to be UnBalanced if that compatibility option
4115                 //is set
4116                 if (mrReader.pWDop->fNoColumnBalance)
4117                     pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
4118                 else
4119                 {
4120                     //Otherwise set to unbalanced if the following section is
4121                     //not continuous, (which also means that the last section
4122                     //is unbalanced)
4123                     if (aNext == aEnd || !aNext->IsContinous())
4124                         pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
4125                 }
4126             }
4127 
4128             bool bHasOwnHdFt = false;
4129             /*
4130              In this nightmare scenario the continuous section has its own
4131              headers and footers so we will try and find a hard page break
4132              between here and the end of the section and put the headers and
4133              footers there.
4134             */
4135             if (!bInsertPageDesc)
4136             {
4137                bHasOwnHdFt =
4138                 mrReader.HasOwnHeaderFooter(
4139                  aIter->maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST),
4140                  aIter->maSep.grpfIhdt, std::distance(aStart, aIter)
4141                 );
4142             }
4143             if (bHasOwnHdFt)
4144             {
4145 				// #i40766# Need to cache the page descriptor in case there is
4146 				// no page break in the section
4147 				SwPageDesc *pOrig = aIter->mpPage;
4148 				SwPageDesc *pOrigTitle = aIter->mpTitlePage;
4149 				bool bFailed = true;
4150                 SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, true));
4151                 if (aDesc.GetPageDesc())
4152                 {
4153                     sal_uLong nStart = aSectPaM.Start()->nNode.GetIndex();
4154                     sal_uLong nEnd   = aSectPaM.End()->nNode.GetIndex();
4155                     for(; nStart <= nEnd; ++nStart)
4156                     {
4157                         SwNode* pNode = mrReader.rDoc.GetNodes()[nStart];
4158                         if (!pNode)
4159                             continue;
4160                         if (sw::util::HasPageBreak(*pNode))
4161                         {
4162                             SwNodeIndex aIdx(*pNode);
4163                             GiveNodePageDesc(aIdx, aDesc, mrReader.rDoc);
4164 							bFailed = false;
4165                             break;
4166                         }
4167                     }
4168                 }
4169 				if(bFailed)
4170 				{
4171 					aIter->mpPage = pOrig;
4172 					aIter->mpTitlePage = pOrigTitle;
4173 				}
4174             }
4175         }
4176 
4177         if (pTxtNd)
4178         {
4179             SwNodeIndex aIdx(*pTxtNd);
4180             SwPosition aPos(aIdx);
4181             SwPaM aTest(aPos);
4182             mrReader.rDoc.DelFullPara(aTest);
4183             pTxtNd = 0;
4184         }
4185     }
4186 }
4187 
StoreMacroCmds()4188 void SwWW8ImplReader::StoreMacroCmds()
4189 {
4190     if (pWwFib->lcbCmds)
4191     {
4192         maTracer.Log(sw::log::eContainsWordBasic);
4193 
4194         pTableStream->Seek(pWwFib->fcCmds);
4195 
4196         uno::Reference < embed::XStorage > xRoot(mpDocShell->GetStorage());
4197         try
4198         {
4199             uno::Reference < io::XStream > xStream =
4200                     xRoot->openStreamElement( CREATE_CONST_ASC(SL::aMSMacroCmds), embed::ElementModes::READWRITE );
4201             SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xStream );
4202 
4203             sal_uInt8 *pBuffer = new sal_uInt8[pWwFib->lcbCmds];
4204             pTableStream->Read(pBuffer, pWwFib->lcbCmds);
4205             pStream->Write(pBuffer, pWwFib->lcbCmds);
4206             delete[] pBuffer;
4207             delete pStream;
4208         }
4209         catch ( uno::Exception& )
4210         {
4211         }
4212     }
4213 }
4214 
ReadDocVars()4215 void SwWW8ImplReader::ReadDocVars()
4216 {
4217     std::vector<String> aDocVarStrings;
4218     std::vector<ww::bytes> aDocVarStringIds;
4219     std::vector<String> aDocValueStrings;
4220     WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcStwUser,
4221         pWwFib->lcbStwUser, bVer67 ? 2 : 0, eStructCharSet,
4222         aDocVarStrings, &aDocVarStringIds, &aDocValueStrings);
4223     if (!bVer67) {
4224         using namespace ::com::sun::star;
4225 
4226         uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
4227             mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
4228         uno::Reference<document::XDocumentProperties> xDocProps(
4229             xDPS->getDocumentProperties());
4230         DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
4231         uno::Reference<beans::XPropertyContainer> xUserDefinedProps =
4232             xDocProps->getUserDefinedProperties();
4233         DBG_ASSERT(xUserDefinedProps.is(), "UserDefinedProperties is null");
4234 
4235         for(size_t i=0; i<aDocVarStrings.size(); i++)
4236         {
4237             uno::Any aDefaultValue;
4238             ::rtl::OUString name(aDocVarStrings[i]);
4239             uno::Any aValue;
4240             aValue <<= ::rtl::OUString(aDocValueStrings[i]);
4241             try {
4242                 xUserDefinedProps->addProperty( name,
4243                     beans::PropertyAttribute::REMOVEABLE,
4244                     aValue );
4245             } catch (uno::Exception &) {
4246                 // ignore
4247             }
4248         }
4249 	}
4250 }
4251 
4252 //-----------------------------------------
4253 //      Document Info
4254 //-----------------------------------------
4255 
ReadDocInfo()4256 void SwWW8ImplReader::ReadDocInfo()
4257 {
4258     if( pStg )
4259     {
4260         uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
4261             mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
4262         uno::Reference<document::XDocumentProperties> xDocProps(
4263             xDPS->getDocumentProperties());
4264         DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
4265 
4266         if (xDocProps.is()) {
4267             sfx2::LoadOlePropertySet(xDocProps, pStg);
4268         }
4269     }
4270 }
4271 
CoreLoad(WW8Glossary * pGloss,const SwPosition & rPos)4272 sal_uLong SwWW8ImplReader::CoreLoad(WW8Glossary *pGloss, const SwPosition &rPos)
4273 {
4274     sal_uLong nErrRet = 0;
4275 
4276 	rDoc.SetDocumentType( SwDoc::DOCTYPE_MSWORD );
4277     if (mbNewDoc && pStg && !pGloss)
4278         ReadDocInfo();
4279 
4280     ::ww8::WW8FibData * pFibData = new ::ww8::WW8FibData();
4281 
4282     if (pWwFib->fReadOnlyRecommended)
4283         pFibData->setReadOnlyRecommended(true);
4284     else
4285         pFibData->setReadOnlyRecommended(false);
4286 
4287     if (pWwFib->fWriteReservation)
4288         pFibData->setWriteReservation(true);
4289     else
4290         pFibData->setWriteReservation(false);
4291 
4292     ::sw::tExternalDataPointer pExternalFibData(pFibData);
4293 
4294     rDoc.setExternalData(::sw::FIB, pExternalFibData);
4295 
4296     ::sw::tExternalDataPointer pSttbfAsoc
4297           (new ::ww8::WW8Sttb<ww8::WW8Struct>(*pTableStream, pWwFib->fcSttbfAssoc, pWwFib->lcbSttbfAssoc));
4298 
4299     rDoc.setExternalData(::sw::STTBF_ASSOC, pSttbfAsoc);
4300 
4301     if (pWwFib->fWriteReservation || pWwFib->fReadOnlyRecommended)
4302     {
4303         SwDocShell * pDocShell = rDoc.GetDocShell();
4304         if (pDocShell)
4305             pDocShell->SetReadOnlyUI(sal_True);
4306     }
4307 
4308     pPaM = new SwPaM(rPos);
4309 
4310     pCtrlStck = new SwWW8FltControlStack( &rDoc, nFieldFlags, *this );
4311 
4312     mpRedlineStack = new sw::util::RedlineStack(rDoc);
4313 
4314     /*
4315         RefFldStck: Keeps track of bookmarks which may be inserted as
4316         variables intstead.
4317     */
4318     pReffedStck = new SwWW8ReferencedFltEndStack(&rDoc, nFieldFlags);
4319     pReffingStck = new SwWW8FltRefStack(&rDoc, nFieldFlags);
4320 
4321     pAnchorStck = new SwWW8FltAnchorStack(&rDoc, nFieldFlags);
4322 
4323     sal_uInt16 nPageDescOffset = rDoc.GetPageDescCnt();
4324 
4325     SwNodeIndex aSttNdIdx( rDoc.GetNodes() );
4326     SwRelNumRuleSpaces aRelNumRule(rDoc, mbNewDoc);
4327 
4328     sal_uInt16 eMode = nsRedlineMode_t::REDLINE_SHOW_INSERT;
4329 
4330     mpSprmParser = new wwSprmParser(pWwFib->GetFIBVersion());
4331 
4332     // praktische Hilfsvariablen besetzen:
4333     bVer6  = (6 == pWwFib->nVersion);
4334     bVer7  = (7 == pWwFib->nVersion);
4335     bVer67 = bVer6 || bVer7;
4336     bVer8  = (8 == pWwFib->nVersion);
4337 
4338     eTextCharSet = WW8Fib::GetFIBCharset(pWwFib->chse);
4339     eStructCharSet = WW8Fib::GetFIBCharset(pWwFib->chseTables);
4340 
4341     bWWBugNormal = pWwFib->nProduct == 0xc03d;
4342 
4343     if (!mbNewDoc)
4344         aSttNdIdx = pPaM->GetPoint()->nNode;
4345 
4346     ::StartProgress(STR_STATSTR_W4WREAD, 0, 100, mpDocShell);
4347 
4348 #ifdef DEBUGDUMP
4349     //experimental embedded ttf dumper
4350     if (pWwFib->lcbSttbttmbd && (7 < pWwFib->nVersion))
4351     {
4352         pTableStream->Seek(pWwFib->fcSttbttmbd);
4353         sal_uInt16 nZeros;
4354         *pTableStream >> nZeros;
4355         sal_uInt16 nNoEntries;
4356         *pTableStream >> nNoEntries;
4357         sal_uInt32 nUnknown1;
4358         *pTableStream >> nUnknown1;
4359         sal_uInt16 nUnknown2;
4360         *pTableStream >> nUnknown2;
4361         std::vector<sal_uInt32> aOffsets;
4362         for (sal_uInt16 nI = 0; nI < nNoEntries; ++nI)
4363         {
4364             sal_uInt32 nOffset;
4365             *pTableStream >> nOffset;
4366             aOffsets.push_back(nOffset);
4367             sal_uInt32 nUnknown3;
4368             *pTableStream >> nUnknown3;
4369             sal_uInt32 nUnknown4;
4370             *pTableStream >> nUnknown4;
4371         }
4372         typedef std::vector<sal_uInt32>::iterator myIter;
4373         myIter aEnd = aOffsets.end();
4374         myIter aIter = aOffsets.begin();
4375         while (aIter != aEnd)
4376         {
4377             sal_uInt32 nOffset = *aIter;
4378             sal_uInt32 nLen = STREAM_SEEK_TO_END;
4379             ++aIter;
4380             pStrm->Seek(nOffset);
4381             if (aIter != aEnd)
4382                 nLen = *aIter - nOffset;
4383             SvStream *pDbg = sw::hack::CreateDebuggingStream(CREATE_CONST_ASC(".ttf.dump"));
4384             sw::hack::DumpStream(*pStrm, *pDbg, nLen);
4385             delete pDbg;
4386         }
4387     }
4388 #endif
4389 
4390     // read Font Table
4391     pFonts = new WW8Fonts( *pTableStream, *pWwFib );
4392 
4393     // Document Properties
4394     pWDop = new WW8Dop( *pTableStream, pWwFib->nFib, pWwFib->fcDop,
4395         pWwFib->lcbDop );
4396 
4397     if (mbNewDoc)
4398         ImportDop();
4399 
4400     /*
4401         Import revisioning data: author names
4402     */
4403     if( pWwFib->lcbSttbfRMark )
4404     {
4405         ReadRevMarkAuthorStrTabl( *pTableStream,
4406                                     pWwFib->fcSttbfRMark,
4407                                     pWwFib->lcbSttbfRMark, rDoc );
4408     }
4409 
4410     // M.M. Initialize our String/ID map for Linked Sections
4411     std::vector<String> aLinkStrings;
4412     std::vector<ww::bytes> aStringIds;
4413 
4414     WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcSttbFnm,
4415         pWwFib->lcbSttbFnm, bVer67 ? 2 : 0, eStructCharSet,
4416         aLinkStrings, &aStringIds);
4417 
4418     for (size_t i=0; i < aLinkStrings.size(); ++i)
4419     {
4420         ww::bytes stringId = aStringIds[i];
4421         WW8_STRINGID *stringIdStruct = (WW8_STRINGID*)(&stringId[0]);
4422         aLinkStringMap[SVBT16ToShort(stringIdStruct->nStringId)] =
4423             aLinkStrings[i];
4424     }
4425 
4426 	ReadDocVars(); // import document variables as meta information.
4427 
4428     ::SetProgressState(nProgress, mpDocShell);    // Update
4429 
4430     pLstManager = new WW8ListManager( *pTableStream, *this );
4431 
4432     /*
4433         zuerst(!) alle Styles importieren   (siehe WW8PAR2.CXX)
4434             VOR dem Import der Listen !!
4435     */
4436     ::SetProgressState(nProgress, mpDocShell);    // Update
4437     pStyles = new WW8RStyle( *pWwFib, this );   // Styles
4438     pStyles->Import();
4439 
4440     /*
4441         zu guter Letzt: (siehe ebenfalls WW8PAR3.CXX)
4442         ===============
4443         alle Styles durchgehen und ggfs. zugehoeriges Listen-Format
4444         anhaengen NACH dem Import der Styles und NACH dem Import der
4445         Listen !!
4446     */
4447     ::SetProgressState(nProgress, mpDocShell);    // Update
4448     pStyles->PostProcessStyles();
4449 
4450     if (pCollA)
4451         SetOutlineStyles();
4452 
4453     pSBase = new WW8ScannerBase(pStrm,pTableStream,pDataStream,pWwFib);
4454 
4455     if ( !pSBase->IsValid() )
4456     {
4457         return ERR_SWG_READ_ERROR;
4458     }
4459 
4460     static const SvxExtNumType eNumTA[16] =
4461     {
4462         SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,
4463         SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N,
4464         SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
4465         SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
4466         SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
4467         SVX_NUM_ARABIC, SVX_NUM_ARABIC
4468     };
4469 
4470     if (pSBase->AreThereFootnotes())
4471     {
4472         static const SwFtnNum eNumA[4] =
4473         {
4474             FTNNUM_DOC, FTNNUM_CHAPTER, FTNNUM_PAGE, FTNNUM_DOC
4475         };
4476 
4477         SwFtnInfo aInfo;
4478         aInfo = rDoc.GetFtnInfo();      // Copy-Ctor privat
4479 
4480         aInfo.ePos = FTNPOS_PAGE;
4481         aInfo.eNum = eNumA[pWDop->rncFtn];
4482         aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcFtnRef]) );
4483         if( pWDop->nFtn )
4484             aInfo.nFtnOffset = pWDop->nFtn - 1;
4485         rDoc.SetFtnInfo( aInfo );
4486     }
4487     if( pSBase->AreThereEndnotes() )
4488     {
4489         SwEndNoteInfo aInfo;
4490         aInfo = rDoc.GetEndNoteInfo();  // parallel zu Ftn
4491 
4492         // Ich kann nicht setzen, wann neu nummerieren...
4493         //  aInfo.eNum = eNumA[pWDop->pDop->rncEdn];
4494         aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcEdnRef]) );
4495         if( pWDop->nEdn )
4496             aInfo.nFtnOffset = pWDop->nEdn - 1;
4497         rDoc.SetEndNoteInfo( aInfo );
4498     }
4499 
4500     if( pWwFib->lcbPlcfhdd )
4501         pHdFt = new WW8PLCF_HdFt( pTableStream, *pWwFib, *pWDop );
4502 
4503     if (!mbNewDoc)
4504     {
4505         // inserting into an existing document:
4506         // As only complete paragraphs are inserted, the current one
4507         // needs to be splitted - once or even twice.
4508         const SwPosition* pPos = pPaM->GetPoint();
4509 
4510         // split current paragraph to get new paragraph for the insertion
4511         rDoc.SplitNode( *pPos, false );
4512 
4513         // another split, if insertion position was not at the end of the current paragraph.
4514         SwTxtNode const*const pTxtNd = pPos->nNode.GetNode().GetTxtNode();
4515         if ( pTxtNd->GetTxt().Len() )
4516         {
4517             rDoc.SplitNode( *pPos, false );
4518             // move PaM back to the newly empty paragraph
4519             pPaM->Move( fnMoveBackward );
4520         }
4521 
4522         // suppress insertion of tables inside footnotes.
4523         const sal_uLong nNd = pPos->nNode.GetIndex();
4524         bReadNoTbl = ( nNd < rDoc.GetNodes().GetEndOfInserts().GetIndex() &&
4525                        rDoc.GetNodes().GetEndOfInserts().StartOfSectionIndex() < nNd );
4526 
4527     }
4528 
4529     ::SetProgressState(nProgress, mpDocShell);    // Update
4530 
4531     // loop for each glossary entry and add dummy section node
4532     if (pGloss)
4533     {
4534         WW8PLCF aPlc(pTableStream, pWwFib->fcPlcfglsy, pWwFib->lcbPlcfglsy, 0);
4535         if ( aPlc.IsValid() )
4536         {
4537             WW8_CP nStart, nEnd;
4538             void* pDummy;
4539 
4540             for (int i=0; i<pGloss->GetNoStrings(); i++,aPlc++)
4541             {
4542                 SwNodeIndex aIdx( rDoc.GetNodes().GetEndOfContent());
4543                 SwTxtFmtColl* pColl =
4544                     rDoc.GetTxtCollFromPool(RES_POOLCOLL_STANDARD,
4545                     false);
4546                 SwStartNode *pNode =
4547                     rDoc.GetNodes().MakeTextSection(aIdx,
4548                     SwNormalStartNode,pColl);
4549                 pPaM->GetPoint()->nNode = pNode->GetIndex()+1;
4550                 pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(),0);
4551                 aPlc.Get( nStart, nEnd, pDummy );
4552                 ReadText(nStart,nEnd-nStart-1,MAN_MAINTEXT);
4553             }
4554         }
4555     }
4556     else //ordinary case
4557     {
4558         //Modify here for #119405, by easyfan, 2012-05-24
4559         mbOnLoadingMain = true;
4560         //End of modification, by easyfan
4561         ReadText( 0, pWwFib->ccpText, MAN_MAINTEXT );
4562         //Modify here for #119405, by easyfan, 2012-05-24
4563         mbOnLoadingMain = false;
4564         //End of modification, by easyfan
4565     }
4566 
4567     ::SetProgressState(nProgress, mpDocShell);    // Update
4568 
4569     if (pDrawPg && pMSDffManager && pMSDffManager->GetShapeOrders())
4570     {
4571         // Hilfsarray zum Verketten der (statt SdrTxtObj) eingefuegten
4572         // Rahmen
4573         SvxMSDffShapeTxBxSort aTxBxSort;
4574 
4575         // korrekte Z-Order der eingelesen Escher-Objekte sicherstellen
4576         sal_uInt16 nShapeCount = pMSDffManager->GetShapeOrders()->Count();
4577 
4578         for (sal_uInt16 nShapeNum=0; nShapeNum < nShapeCount; nShapeNum++)
4579         {
4580             SvxMSDffShapeOrder *pOrder =
4581                 pMSDffManager->GetShapeOrders()->GetObject(nShapeNum);
4582             // Pointer in neues Sort-Array einfuegen
4583             if (pOrder->nTxBxComp && pOrder->pFly)
4584                 aTxBxSort.Insert(pOrder);
4585         }
4586         // zu verkettende Rahmen jetzt verketten
4587         sal_uInt16 nTxBxCount = aTxBxSort.Count();
4588         if( nTxBxCount )
4589         {
4590             SwFmtChain aChain;
4591             for (sal_uInt16 nTxBxNum=0; nTxBxNum < nTxBxCount; nTxBxNum++)
4592             {
4593                 SvxMSDffShapeOrder *pOrder =
4594                     aTxBxSort.GetObject(nTxBxNum);
4595 
4596                 // Fly-Frame-Formate initialisieren
4597                 SwFlyFrmFmt* pFlyFmt     = pOrder->pFly;
4598                 SwFlyFrmFmt* pNextFlyFmt = 0;
4599                 SwFlyFrmFmt* pPrevFlyFmt = 0;
4600                 // ggfs. Nachfolger ermitteln
4601                 if( 1+nTxBxNum < nTxBxCount )
4602                 {
4603                     SvxMSDffShapeOrder *pNextOrder =
4604                         aTxBxSort.GetObject(nTxBxNum+1);
4605                     if ((0xFFFF0000 & pOrder->nTxBxComp)
4606                            == (0xFFFF0000 & pNextOrder->nTxBxComp))
4607                         pNextFlyFmt = pNextOrder->pFly;
4608                 }
4609                 // ggfs. Vorgaenger ermitteln
4610                 if( nTxBxNum )
4611                 {
4612                     SvxMSDffShapeOrder *pPrevOrder =
4613                         aTxBxSort.GetObject(nTxBxNum-1);
4614                     if ((0xFFFF0000 & pOrder->nTxBxComp)
4615                            == (0xFFFF0000 & pPrevOrder->nTxBxComp))
4616                         pPrevFlyFmt = pPrevOrder->pFly;
4617                 }
4618                 // Falls Nachfolger oder Vorgaenger vorhanden,
4619                 // die Verkettung am Fly-Frame-Format eintragen
4620                 if (pNextFlyFmt || pPrevFlyFmt)
4621                 {
4622                     aChain.SetNext( pNextFlyFmt );
4623                     aChain.SetPrev( pPrevFlyFmt );
4624                     pFlyFmt->SetFmtAttr( aChain );
4625                 }
4626             }
4627 
4628         }
4629 
4630     }
4631 
4632     if (mbNewDoc)
4633     {
4634         if( pWDop->fRevMarking )
4635             eMode |= nsRedlineMode_t::REDLINE_ON;
4636         if( pWDop->fRMView )
4637             eMode |= nsRedlineMode_t::REDLINE_SHOW_DELETE;
4638         if (pStg && !pGloss) /*meaningless for a glossary, cmc*/
4639         {
4640             const SvtFilterOptions* pVBAFlags = SvtFilterOptions::Get();
4641             maTracer.EnterEnvironment(sw::log::eMacros);
4642             SvxImportMSVBasic aVBasic(*mpDocShell, *pStg,
4643                             pVBAFlags->IsLoadWordBasicCode(),
4644                             pVBAFlags->IsLoadWordBasicStorage() );
4645             String s1(CREATE_CONST_ASC("Macros"));
4646             String s2(CREATE_CONST_ASC("VBA"));
4647             int nRet = aVBasic.Import( s1, s2 );
4648             if( 2 & nRet )
4649             {
4650                 maTracer.Log(sw::log::eContainsVisualBasic);
4651                 rDoc.SetContainsMSVBasic(true);
4652             }
4653 
4654             StoreMacroCmds();
4655 
4656             maTracer.LeaveEnvironment(sw::log::eMacros);
4657         }
4658     }
4659 
4660     maInsertedTables.DelAndMakeTblFrms();
4661     maSectionManager.InsertSegments();
4662 
4663     if (pCollA)
4664         delete[] pCollA;
4665 
4666     DELETEZ( pStyles );
4667 
4668     if( pFormImpl )
4669         DeleteFormImpl();
4670     GrafikDtor();
4671     DELETEZ( pMSDffManager );
4672     DELETEZ( pHdFt );
4673     //For i120928,delay the destruct action
4674     //DELETEZ( pLstManager );
4675     DELETEZ( pSBase );
4676     delete pWDop;
4677     DELETEZ( pFonts );
4678     delete mpAtnNames;
4679     DELETEZ( pAuthorInfos );
4680     delete mpSprmParser;
4681     ::EndProgress(mpDocShell);
4682 
4683     pDataStream = 0;
4684     pTableStream = 0;
4685 
4686     DeleteCtrlStk();
4687     mpRedlineStack->closeall(*pPaM->GetPoint());
4688     delete mpRedlineStack;
4689     DeleteAnchorStk();
4690     DeleteRefStks();
4691 
4692     //For i120928,achieve the graphics from the special bookmark with is for graphic bullet
4693     {
4694         std::vector<const SwGrfNode*> vecBulletGrf;
4695         std::vector<SwFrmFmt*> vecFrmFmt;
4696 
4697         IDocumentMarkAccess* const pMarkAccess =
4698             rDoc.getIDocumentMarkAccess();
4699         if ( pMarkAccess )
4700         {
4701             IDocumentMarkAccess::const_iterator_t ppBkmk =
4702                 pMarkAccess->findBookmark( C2U("_PictureBullets") );
4703             if ( ppBkmk != pMarkAccess->getBookmarksEnd()
4704                  && IDocumentMarkAccess::GetType( *(ppBkmk->get()) ) == IDocumentMarkAccess::BOOKMARK )
4705             {
4706                 SwTxtNode* pTxtNode = ppBkmk->get()->GetMarkStart().nNode.GetNode().GetTxtNode();
4707                 if ( pTxtNode )
4708                 {
4709                     const SwpHints* pHints = pTxtNode->GetpSwpHints();
4710                     for( sal_uInt16 nHintPos = 0; pHints && nHintPos < pHints->Count(); ++nHintPos)
4711                     {
4712                         const SwTxtAttr *pHt = (*pHints)[nHintPos];
4713                         const xub_StrLen st = *(pHt->GetStart());
4714                         if( pHt
4715                             && pHt->Which() == RES_TXTATR_FLYCNT
4716                             && (st >= ppBkmk->get()->GetMarkStart().nContent.GetIndex()) )
4717                         {
4718                             SwFrmFmt* pFrmFmt = pHt->GetFlyCnt().GetFrmFmt();
4719                             vecFrmFmt.push_back(pFrmFmt);
4720                             const SwNodeIndex* pNdIdx = pFrmFmt->GetCntnt().GetCntntIdx();
4721                             const SwNodes* pNodesArray = (pNdIdx != NULL)
4722                                                          ? &(pNdIdx->GetNodes())
4723                                                          : NULL;
4724                             const SwGrfNode *pGrf = (pNodesArray != NULL)
4725                                                     ? dynamic_cast<const SwGrfNode*>((*pNodesArray)[pNdIdx->GetIndex() + 1])
4726                                                     : NULL;
4727                             vecBulletGrf.push_back(pGrf);
4728                         }
4729                     }
4730                     // update graphic bullet information
4731                     sal_uInt16 nCount = pLstManager->GetWW8LSTInfoNum();
4732                     for (sal_uInt16 i = 0; i < nCount; ++i)
4733                     {
4734                         SwNumRule* pRule = pLstManager->GetNumRule(i);
4735                         for (sal_uInt16 j = 0; j < MAXLEVEL; ++j)
4736                         {
4737                             SwNumFmt aNumFmt(pRule->Get(j));
4738                             const sal_Int16 nType = aNumFmt.GetNumberingType();
4739                             const sal_uInt16 nGrfBulletCP = aNumFmt.GetGrfBulletCP();
4740                             if ( nType == SVX_NUM_BITMAP
4741                                  && vecBulletGrf.size() > nGrfBulletCP
4742                                  && vecBulletGrf[nGrfBulletCP] != NULL )
4743                             {
4744                                 Graphic aGraphic = vecBulletGrf[nGrfBulletCP]->GetGrf();
4745                                 SvxBrushItem aBrush(aGraphic, GPOS_AREA, SID_ATTR_BRUSH);
4746                                 Font aFont = numfunc::GetDefBulletFont();
4747                                 int nHeight = aFont.GetHeight() * 12;
4748                                 Size aPrefSize( aGraphic.GetPrefSize());
4749                                 if (aPrefSize.Height() * aPrefSize.Width() != 0 )
4750                                 {
4751                                     int nWidth = (nHeight * aPrefSize.Width()) / aPrefSize.Height();
4752                                     Size aSize(nWidth, nHeight);
4753                                     aNumFmt.SetGraphicBrush(&aBrush, &aSize);
4754                                 }
4755                                 else
4756                                 {
4757                                     aNumFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
4758                                     aNumFmt.SetBulletChar(0x2190);
4759                                 }
4760                                 pRule->Set( j, aNumFmt );
4761                             }
4762                         }
4763                     }
4764                     // Remove additional pictures
4765                     for (sal_uInt16 i = 0; i < vecFrmFmt.size(); ++i)
4766                     {
4767                         rDoc.DelLayoutFmt(vecFrmFmt[i]);
4768                     }
4769                 }
4770             }
4771             DELETEZ( pLstManager );
4772         }
4773     }
4774 
4775     UpdateFields();
4776 
4777     // delete the pam before the call for hide all redlines (Bug 73683)
4778     if (mbNewDoc)
4779       rDoc.SetRedlineMode((RedlineMode_t)( eMode ));
4780 
4781     UpdatePageDescs(rDoc, nPageDescOffset);
4782 
4783     delete pPaM, pPaM = 0;
4784     return nErrRet;
4785 }
4786 
SetSubStreams(SvStorageStreamRef & rTableStream,SvStorageStreamRef & rDataStream)4787 sal_uLong SwWW8ImplReader::SetSubStreams(SvStorageStreamRef &rTableStream,
4788     SvStorageStreamRef &rDataStream)
4789 {
4790     sal_uLong nErrRet = 0;
4791     // 6 stands for "6 OR 7",  7 stand for "ONLY 7"
4792     switch (pWwFib->nVersion)
4793     {
4794         case 6:
4795         case 7:
4796             pTableStream = pStrm;
4797             pDataStream = pStrm;
4798             break;
4799         case 8:
4800             if(!pStg)
4801             {
4802                 ASSERT( pStg, "Version 8 muss immer einen Storage haben!" );
4803                 nErrRet = ERR_SWG_READ_ERROR;
4804                 break;
4805             }
4806 
4807             rTableStream = pStg->OpenSotStream( String::CreateFromAscii(
4808                 pWwFib->fWhichTblStm ? SL::a1Table : SL::a0Table),
4809                 STREAM_STD_READ);
4810 
4811             pTableStream = &rTableStream;
4812             pTableStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
4813 
4814             rDataStream = pStg->OpenSotStream(CREATE_CONST_ASC(SL::aData),
4815                 STREAM_STD_READ | STREAM_NOCREATE );
4816 
4817             if (rDataStream.Is() && SVSTREAM_OK == rDataStream->GetError())
4818             {
4819                 pDataStream = &rDataStream;
4820                 pDataStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
4821             }
4822             else
4823                 pDataStream = pStrm;
4824             break;
4825         default:
4826             // Programm-Fehler!
4827             ASSERT( sal_False, "It was forgotten to encode nVersion!" );
4828             nErrRet = ERR_SWG_READ_ERROR;
4829             break;
4830     }
4831     return nErrRet;
4832 }
4833 
4834 namespace
4835 {
MakeTemp(SvFileStream & rSt)4836     utl::TempFile *MakeTemp(SvFileStream &rSt)
4837     {
4838         utl::TempFile *pT = new utl::TempFile;
4839         pT->EnableKillingFile();
4840         rSt.Open(pT->GetFileName(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE);
4841         return pT;
4842     }
4843 
4844 #define WW_BLOCKSIZE 0x200
4845 
DecryptRC4(msfilter::MSCodec_Std97 & rCtx,SvStream & rIn,SvStream & rOut)4846     void DecryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
4847     {
4848         rIn.Seek(STREAM_SEEK_TO_END);
4849         sal_uLong nLen = rIn.Tell();
4850         rIn.Seek(0);
4851 
4852         sal_uInt8 in[WW_BLOCKSIZE];
4853         for (sal_uLong nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
4854         {
4855             sal_uLong nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI;
4856             rIn.Read(in, nBS);
4857             rCtx.InitCipher(nBlock);
4858             rCtx.Decode(in, nBS, in, nBS);
4859             rOut.Write(in, nBS);
4860         }
4861     }
4862 
DecryptXOR(msfilter::MSCodec_XorWord95 & rCtx,SvStream & rIn,SvStream & rOut)4863     void DecryptXOR(msfilter::MSCodec_XorWord95 &rCtx, SvStream &rIn, SvStream &rOut)
4864     {
4865         sal_uLong nSt = rIn.Tell();
4866         rIn.Seek(STREAM_SEEK_TO_END);
4867         sal_uLong nLen = rIn.Tell();
4868         rIn.Seek(nSt);
4869 
4870         rCtx.InitCipher();
4871         rCtx.Skip(nSt);
4872 
4873         sal_uInt8 in[0x4096];
4874         for (sal_uLong nI = nSt; nI < nLen; nI += 0x4096)
4875         {
4876             sal_uLong nBS = (nLen - nI > 0x4096 ) ? 0x4096 : nLen - nI;
4877             rIn.Read(in, nBS);
4878             rCtx.Decode(in, nBS);
4879             rOut.Write(in, nBS);
4880         }
4881     }
4882 
4883     //moan, copy and paste :-(
QueryPasswordForMedium(SfxMedium & rMedium)4884     String QueryPasswordForMedium(SfxMedium& rMedium)
4885     {
4886         String aPassw;
4887 
4888         using namespace com::sun::star;
4889 
4890         const SfxItemSet* pSet = rMedium.GetItemSet();
4891         const SfxPoolItem *pPasswordItem;
4892 
4893         if(pSet && SFX_ITEM_SET == pSet->GetItemState(SID_PASSWORD, sal_True, &pPasswordItem))
4894             aPassw = ((const SfxStringItem *)pPasswordItem)->GetValue();
4895         else
4896         {
4897             try
4898             {
4899                 uno::Reference< task::XInteractionHandler > xHandler( rMedium.GetInteractionHandler() );
4900                 if( xHandler.is() )
4901                 {
4902                     ::comphelper::DocPasswordRequest* pRequest = new ::comphelper::DocPasswordRequest(
4903                         ::comphelper::DocPasswordRequestType_MS, task::PasswordRequestMode_PASSWORD_ENTER,
4904                         INetURLObject( rMedium.GetOrigURL() ).GetName( INetURLObject::DECODE_WITH_CHARSET ) );
4905                     uno::Reference< task::XInteractionRequest > xRequest( pRequest );
4906 
4907                     xHandler->handle( xRequest );
4908 
4909                     if( pRequest->isPassword() )
4910                         aPassw = pRequest->getPassword();
4911                 }
4912             }
4913             catch( uno::Exception& )
4914             {
4915             }
4916         }
4917 
4918         return aPassw;
4919     }
4920 
InitXorWord95Codec(::msfilter::MSCodec_XorWord95 & rCodec,SfxMedium & rMedium,WW8Fib * pWwFib)4921     uno::Sequence< beans::NamedValue > InitXorWord95Codec( ::msfilter::MSCodec_XorWord95& rCodec, SfxMedium& rMedium, WW8Fib* pWwFib )
4922     {
4923         uno::Sequence< beans::NamedValue > aEncryptionData;
4924         SFX_ITEMSET_ARG( rMedium.GetItemSet(), pEncryptionData, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
4925         if ( pEncryptionData && ( pEncryptionData->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
4926             aEncryptionData.realloc( 0 );
4927 
4928         if ( !aEncryptionData.getLength() )
4929         {
4930             String sUniPassword = QueryPasswordForMedium( rMedium );
4931 
4932             ByteString sPassword(sUniPassword, WW8Fib::GetFIBCharset( pWwFib->chseTables ) );
4933 
4934             xub_StrLen nLen = sPassword.Len();
4935             if( nLen <= 15 )
4936             {
4937                 sal_uInt8 pPassword[16];
4938                 memset( pPassword, 0, sizeof( pPassword ) );
4939 
4940                 for (xub_StrLen nChar = 0; nChar < sPassword.Len(); ++nChar )
4941                     pPassword[nChar] = sPassword.GetChar(nChar);
4942 
4943                 rCodec.InitKey( pPassword );
4944                 aEncryptionData = rCodec.GetEncryptionData();
4945 
4946                 // the export supports RC4 algorithm only, so we have to generate the related EncryptionData as well,
4947                 // so that Save can export the document without asking for a password;
4948                 // as result there will be EncryptionData for both algorithms in the MediaDescriptor
4949                 ::msfilter::MSCodec_Std97 aCodec97;
4950 
4951                 // Generate random number with a seed of time as salt.
4952                 TimeValue aTime;
4953                 osl_getSystemTime( &aTime );
4954                 rtlRandomPool aRandomPool = rtl_random_createPool();
4955                 rtl_random_addBytes ( aRandomPool, &aTime, 8 );
4956 
4957                 sal_uInt8 pDocId[ 16 ];
4958                 rtl_random_getBytes( aRandomPool, pDocId, 16 );
4959 
4960                 rtl_random_destroyPool( aRandomPool );
4961 
4962                 sal_uInt16 pStd97Pass[16];
4963                 memset( pStd97Pass, 0, sizeof( pStd97Pass ) );
4964                 for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
4965                     pStd97Pass[nChar] = sUniPassword.GetChar(nChar);
4966 
4967                 aCodec97.InitKey( pStd97Pass, pDocId );
4968 
4969                 // merge the EncryptionData, there should be no conflicts
4970                 ::comphelper::SequenceAsHashMap aEncryptionHash( aEncryptionData );
4971                 aEncryptionHash.update( ::comphelper::SequenceAsHashMap( aCodec97.GetEncryptionData() ) );
4972                 aEncryptionHash >> aEncryptionData;
4973             }
4974         }
4975 
4976         return aEncryptionData;
4977     }
4978 
InitStd97Codec(::msfilter::MSCodec_Std97 & rCodec,sal_uInt8 pDocId[16],SfxMedium & rMedium)4979     uno::Sequence< beans::NamedValue > InitStd97Codec( ::msfilter::MSCodec_Std97& rCodec, sal_uInt8 pDocId[16], SfxMedium& rMedium )
4980     {
4981         uno::Sequence< beans::NamedValue > aEncryptionData;
4982         SFX_ITEMSET_ARG( rMedium.GetItemSet(), pEncryptionData, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
4983         if ( pEncryptionData && ( pEncryptionData->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
4984             aEncryptionData.realloc( 0 );
4985 
4986         if ( !aEncryptionData.getLength() )
4987         {
4988             String sUniPassword = QueryPasswordForMedium( rMedium );
4989 
4990             xub_StrLen nLen = sUniPassword.Len();
4991             if ( nLen <= 15 )
4992             {
4993                 sal_Unicode pPassword[16];
4994                 memset( pPassword, 0, sizeof( pPassword ) );
4995                 for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
4996                     pPassword[nChar] = sUniPassword.GetChar(nChar);
4997 
4998                 rCodec.InitKey( pPassword, pDocId );
4999                 aEncryptionData = rCodec.GetEncryptionData();
5000             }
5001         }
5002 
5003         return aEncryptionData;
5004     }
5005 }
5006 
LoadThroughDecryption(SwPaM & rPaM,WW8Glossary * pGloss)5007 sal_uLong SwWW8ImplReader::LoadThroughDecryption(SwPaM& rPaM ,WW8Glossary *pGloss)
5008 {
5009     sal_uLong nErrRet = 0;
5010     if (pGloss)
5011         pWwFib = pGloss->GetFib();
5012     else
5013         pWwFib = new WW8Fib(*pStrm, nWantedVersion);
5014 
5015     if (pWwFib->nFibError)
5016         nErrRet = ERR_SWG_READ_ERROR;
5017 
5018     SvStorageStreamRef xTableStream, xDataStream;
5019 
5020     if (!nErrRet)
5021         nErrRet = SetSubStreams(xTableStream, xDataStream);
5022 
5023     utl::TempFile *pTempMain = 0;
5024     utl::TempFile *pTempTable = 0;
5025     utl::TempFile *pTempData = 0;
5026     SvFileStream aDecryptMain;
5027     SvFileStream aDecryptTable;
5028     SvFileStream aDecryptData;
5029 
5030     bool bDecrypt = false;
5031     enum {RC4, XOR, Other} eAlgo = Other;
5032     if (pWwFib->fEncrypted && !nErrRet)
5033     {
5034         if (!pGloss)
5035         {
5036             bDecrypt = true;
5037             if (8 != pWwFib->nVersion)
5038                 eAlgo = XOR;
5039             else
5040             {
5041                 if (pWwFib->nKey != 0)
5042                     eAlgo = XOR;
5043                 else
5044                 {
5045                     pTableStream->Seek(0);
5046                     sal_uInt32 nEncType;
5047                     *pTableStream >> nEncType;
5048                     if (nEncType == 0x10001)
5049                         eAlgo = RC4;
5050                 }
5051             }
5052         }
5053     }
5054 
5055     if (bDecrypt)
5056     {
5057         nErrRet = ERRCODE_SVX_WRONGPASS;
5058         SfxMedium* pMedium = mpDocShell->GetMedium();
5059 
5060         if ( pMedium )
5061         {
5062             switch (eAlgo)
5063             {
5064                 default:
5065                     nErrRet = ERRCODE_SVX_READ_FILTER_CRYPT;
5066                     break;
5067                 case XOR:
5068                 {
5069                     msfilter::MSCodec_XorWord95 aCtx;
5070                     uno::Sequence< beans::NamedValue > aEncryptionData = InitXorWord95Codec( aCtx, *pMedium, pWwFib );
5071 
5072                     // if initialization has failed the EncryptionData should be empty
5073                     if ( aEncryptionData.getLength() && aCtx.VerifyKey( pWwFib->nKey, pWwFib->nHash ) )
5074                     {
5075                         nErrRet = 0;
5076                         pTempMain = MakeTemp(aDecryptMain);
5077 
5078                         pStrm->Seek(0);
5079                         size_t nUnencryptedHdr =
5080                             (8 == pWwFib->nVersion) ? 0x44 : 0x34;
5081                         sal_uInt8 *pIn = new sal_uInt8[nUnencryptedHdr];
5082                         pStrm->Read(pIn, nUnencryptedHdr);
5083                         aDecryptMain.Write(pIn, nUnencryptedHdr);
5084                         delete [] pIn;
5085 
5086                         DecryptXOR(aCtx, *pStrm, aDecryptMain);
5087 
5088                         if (!pTableStream || pTableStream == pStrm)
5089                             pTableStream = &aDecryptMain;
5090                         else
5091                         {
5092                             pTempTable = MakeTemp(aDecryptTable);
5093                             DecryptXOR(aCtx, *pTableStream, aDecryptTable);
5094                             pTableStream = &aDecryptTable;
5095                         }
5096 
5097                         if (!pDataStream || pDataStream == pStrm)
5098                             pDataStream = &aDecryptMain;
5099                         else
5100                         {
5101                             pTempData = MakeTemp(aDecryptData);
5102                             DecryptXOR(aCtx, *pDataStream, aDecryptData);
5103                             pDataStream = &aDecryptData;
5104                         }
5105 
5106                         pMedium->GetItemSet()->ClearItem( SID_PASSWORD );
5107                         pMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
5108                     }
5109                 }
5110                 break;
5111                 case RC4:
5112                 {
5113                     msfilter::MSCodec_Std97 aCtx;
5114 
5115                     sal_uInt8 aDocId[ 16 ];
5116                     pTableStream->Read(aDocId, 16);
5117                     sal_uInt8 aSaltData[ 16 ];
5118                     pTableStream->Read(aSaltData, 16);
5119                     sal_uInt8 aSaltHash[ 16 ];
5120                     pTableStream->Read(aSaltHash, 16);
5121 
5122                     // if initialization has failed the EncryptionData should be empty
5123                     uno::Sequence< beans::NamedValue > aEncryptionData = InitStd97Codec( aCtx, aDocId, *pMedium );
5124                     if ( aEncryptionData.getLength() && aCtx.VerifyKey( aSaltData, aSaltHash ) )
5125                     {
5126                         nErrRet = 0;
5127 
5128                         pTempTable = MakeTemp(aDecryptTable);
5129                         DecryptRC4(aCtx, *pTableStream, aDecryptTable);
5130                         pTableStream = &aDecryptTable;
5131 
5132                         pTempMain = MakeTemp(aDecryptMain);
5133                         DecryptRC4(aCtx, *pStrm, aDecryptMain);
5134 
5135                         if (!pDataStream || pDataStream == pStrm)
5136                             pDataStream = &aDecryptMain;
5137                         else
5138                         {
5139                             pTempData = MakeTemp(aDecryptData);
5140                             DecryptRC4(aCtx, *pDataStream, aDecryptData);
5141                             pDataStream = &aDecryptData;
5142                         }
5143 
5144                         pMedium->GetItemSet()->ClearItem( SID_PASSWORD );
5145                         pMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
5146                     }
5147                 }
5148                 break;
5149             }
5150         }
5151 
5152         if (nErrRet == 0)
5153         {
5154             pStrm = &aDecryptMain;
5155 
5156             delete pWwFib;
5157             pWwFib = new WW8Fib(*pStrm, nWantedVersion);
5158             if (pWwFib->nFibError)
5159                 nErrRet = ERR_SWG_READ_ERROR;
5160         }
5161     }
5162 
5163     if (!nErrRet)
5164         nErrRet = CoreLoad(pGloss, *rPaM.GetPoint());
5165 
5166     delete pTempMain;
5167     delete pTempTable;
5168     delete pTempData;
5169 
5170     if (!pGloss)
5171         delete pWwFib;
5172     return nErrRet;
5173 }
5174 
5175 class outlineeq : public std::unary_function<const SwTxtFmtColl*, bool>
5176 {
5177 private:
5178     sal_uInt8 mnNum;
5179 public:
outlineeq(sal_uInt8 nNum)5180     outlineeq(sal_uInt8 nNum) : mnNum(nNum) {}
operator ()(const SwTxtFmtColl * pTest) const5181     bool operator()(const SwTxtFmtColl *pTest) const
5182     {
5183         //return pTest->GetOutlineLevel() == mnNum;	//#outline level,zhaojianwei
5184 		return pTest->IsAssignedToListLevelOfOutlineStyle() && pTest->GetAssignedOutlineStyleLevel() == mnNum;	//<-end,zhaojianwei
5185     }
5186 };
5187 
5188 
SetOutlineStyles()5189 void SwWW8ImplReader::SetOutlineStyles()
5190 {
5191 
5192     // If we are inserted into a document then don't clobber existing outline levels.
5193     sal_uInt16 nOutlineStyleListLevelWithAssignment = 0;
5194     if ( !mbNewDoc )
5195     {
5196         sw::ParaStyles aOutLined( sw::util::GetParaStyles( rDoc ) );
5197         sw::util::SortByAssignedOutlineStyleListLevel( aOutLined );
5198         sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend();
5199         for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter )
5200         {
5201             if ( ( *aIter )->IsAssignedToListLevelOfOutlineStyle() )
5202                 nOutlineStyleListLevelWithAssignment |= 1 << ( *aIter )->GetAssignedOutlineStyleLevel();
5203             else
5204                 break;
5205         }
5206     }
5207 
5208     // Check applied WW8 list styles at WW8 Built-In Heading Styles
5209     // - Choose the list style which occurs most often as the one which provides
5210     //   the list level properties for the Outline Style.
5211     // - Populate temporary list of WW8 Built-In Heading Styles for further iteration
5212     std::vector< SwWW8StyInf* > aWW8BuiltInHeadingStyles;
5213     const SwNumRule* pChosenWW8ListStyle = NULL;
5214     {
5215         std::map< const SwNumRule*, int > aWW8ListStyleCounts;
5216         for ( sal_uInt16 nI = 0; nI < nColls; ++nI )
5217         {
5218             SwWW8StyInf& rSI = pCollA[nI];
5219 
5220             if ( !rSI.IsWW8BuiltInHeadingStyle()
5221                  || !rSI.HasWW8OutlineLevel() )
5222             {
5223                 continue;
5224             }
5225 
5226             aWW8BuiltInHeadingStyles.push_back( &rSI );
5227 
5228             const SwNumRule* pWW8ListStyle = rSI.GetOutlineNumrule();
5229             if ( pWW8ListStyle != NULL )
5230             {
5231                 std::map< const SwNumRule*, int >::iterator aCountIter =
5232                         aWW8ListStyleCounts.find( pWW8ListStyle );
5233                 if ( aCountIter == aWW8ListStyleCounts.end() )
5234                 {
5235                     aWW8ListStyleCounts[pWW8ListStyle] = 1;
5236                 }
5237                 else
5238                 {
5239                     ++(aCountIter->second);
5240                 }
5241             }
5242         }
5243 
5244         int nCurrentMaxCount = 0;
5245         std::map< const SwNumRule*, int >::iterator aCountIterEnd =
5246             aWW8ListStyleCounts.end();
5247         for ( std::map< const SwNumRule*, int >::iterator aIter = aWW8ListStyleCounts.begin();
5248               aIter != aCountIterEnd;
5249               ++aIter )
5250         {
5251             if ( aIter->second > nCurrentMaxCount )
5252             {
5253                 nCurrentMaxCount = aIter->second;
5254                 pChosenWW8ListStyle = aIter->first;
5255             }
5256         }
5257     }
5258 
5259     // - set list level properties of Outline Style - ODF's list style applied by default to headings
5260     // - assign corresponding Heading Paragraph Styles to the Outline Style
5261     // - If a heading Paragraph Styles is not applying the WW8 list style which had been chosen as
5262     //   the one which provides the list level properties for the Outline Style, its assignment to
5263     //   the Outline Style is removed. A potential applied WW8 list style is assigned directly and
5264     //   its default outline level is applied.
5265     SwNumRule aOutlineRule( *rDoc.GetOutlineNumRule() );
5266     bool bAppliedChangedOutlineStyle = false;
5267     std::vector< SwWW8StyInf* >::iterator aStylesIterEnd =
5268         aWW8BuiltInHeadingStyles.end();
5269     for ( std::vector< SwWW8StyInf* >::iterator aStyleIter = aWW8BuiltInHeadingStyles.begin();
5270           aStyleIter != aStylesIterEnd;
5271           ++aStyleIter )
5272     {
5273         SwWW8StyInf* pStyleInf = (*aStyleIter);
5274 
5275         const sal_uInt16 nOutlineStyleListLevelOfWW8BuiltInHeadingStyle = 1 << pStyleInf->mnWW8OutlineLevel;
5276         if ( nOutlineStyleListLevelOfWW8BuiltInHeadingStyle & nOutlineStyleListLevelWithAssignment )
5277         {
5278             continue;
5279         }
5280 
5281         if ( pChosenWW8ListStyle != NULL
5282              && pStyleInf->mnWW8OutlineLevel == pStyleInf->nListLevel )
5283         {
5284             const SwNumFmt& rRule = pChosenWW8ListStyle->Get( pStyleInf->mnWW8OutlineLevel );
5285             aOutlineRule.Set( pStyleInf->mnWW8OutlineLevel, rRule );
5286             bAppliedChangedOutlineStyle = true;
5287         }
5288 
5289         // in case that there are more styles on this level ignore them
5290         nOutlineStyleListLevelWithAssignment |= nOutlineStyleListLevelOfWW8BuiltInHeadingStyle;
5291 
5292         SwTxtFmtColl* pTxtFmtColl = static_cast<SwTxtFmtColl*>(pStyleInf->pFmt);
5293         if ( pStyleInf->GetOutlineNumrule() != pChosenWW8ListStyle
5294              || ( pStyleInf->nListLevel < WW8ListManager::nMaxLevel
5295                   && pStyleInf->mnWW8OutlineLevel != pStyleInf->nListLevel ) )
5296         {
5297             // WW8 Built-In Heading Style does not apply the chosen one.
5298             // --> delete assignment to OutlineStyle, but keep its current outline level
5299             pTxtFmtColl->DeleteAssignmentToListLevelOfOutlineStyle( false );
5300             // Apply existing WW8 list style a normal list style at the Paragraph Style
5301             if ( pStyleInf->GetOutlineNumrule() != NULL )
5302             {
5303                 pTxtFmtColl->SetFmtAttr( SwNumRuleItem( pStyleInf->GetOutlineNumrule()->GetName() ) );
5304             }
5305             // apply default outline level of WW8 Built-in Heading Style
5306             const sal_uInt8 nOutlineLevel =
5307                     SwWW8StyInf::WW8OutlineLevelToOutlinelevel( pStyleInf->mnWW8OutlineLevel );
5308             pTxtFmtColl->SetFmtAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL, nOutlineLevel ) );
5309         }
5310         else
5311         {
5312             pTxtFmtColl->AssignToListLevelOfOutlineStyle( pStyleInf->mnWW8OutlineLevel );
5313         }
5314     }
5315 
5316     if ( bAppliedChangedOutlineStyle )
5317     {
5318         rDoc.SetOutlineNumRule(aOutlineRule);
5319     }
5320 }
5321 
GetAnnotationAuthor(sal_uInt16 nIdx)5322 const String* SwWW8ImplReader::GetAnnotationAuthor(sal_uInt16 nIdx)
5323 {
5324     if (!mpAtnNames && pWwFib->lcbGrpStAtnOwners)
5325     {
5326         // Authoren bestimmen: steht im TableStream
5327         mpAtnNames = new ::std::vector<String>;
5328         SvStream& rStrm = *pTableStream;
5329 
5330         long nOldPos = rStrm.Tell();
5331         rStrm.Seek( pWwFib->fcGrpStAtnOwners );
5332 
5333         long nRead = 0, nCount = pWwFib->lcbGrpStAtnOwners;
5334         while (nRead < nCount)
5335         {
5336             if( bVer67 )
5337             {
5338                 mpAtnNames->push_back(WW8ReadPString(rStrm, false));
5339                 nRead += mpAtnNames->rbegin()->Len() + 1;   // Laenge + sal_uInt8 Count
5340             }
5341             else
5342             {
5343                 mpAtnNames->push_back(WW8Read_xstz(rStrm, 0, false));
5344                 // UNICode: doppelte Laenge + sal_uInt16 Count
5345                 nRead += mpAtnNames->rbegin()->Len() * 2 + 2;
5346             }
5347         }
5348         rStrm.Seek( nOldPos );
5349     }
5350 
5351     const String *pRet = 0;
5352     if (mpAtnNames && nIdx < mpAtnNames->size())
5353         pRet = &((*mpAtnNames)[nIdx]);
5354     return pRet;
5355 }
5356 
LoadDoc(SwPaM & rPaM,WW8Glossary * pGloss)5357 sal_uLong SwWW8ImplReader::LoadDoc( SwPaM& rPaM,WW8Glossary *pGloss)
5358 {
5359     sal_uLong nErrRet = 0;
5360 
5361     {
5362         static const sal_Char* aNames[ 13 ] = {
5363             "WinWord/WW", "WinWord/WW8", "WinWord/WWFT",
5364             "WinWord/WWFLX", "WinWord/WWFLY",
5365             "WinWord/WWF",
5366             "WinWord/WWFA0", "WinWord/WWFA1", "WinWord/WWFA2",
5367             "WinWord/WWFB0", "WinWord/WWFB1", "WinWord/WWFB2",
5368             "WinWord/RegardHindiDigits"
5369         };
5370         sal_uInt32 aVal[ 13 ];
5371 
5372         SwFilterOptions aOpt( 13, aNames, aVal );
5373 
5374         nIniFlags = aVal[ 0 ];
5375         nIniFlags1= aVal[ 1 ];
5376         // schiebt Flys um x twips nach rechts o. links
5377         nIniFlyDx = aVal[ 3 ];
5378         nIniFlyDy = aVal[ 4 ];
5379 
5380         nFieldFlags = aVal[ 5 ];
5381         nFieldTagAlways[0] = aVal[ 6 ];
5382         nFieldTagAlways[1] = aVal[ 7 ];
5383         nFieldTagAlways[2] = aVal[ 8 ];
5384         nFieldTagBad[0] = aVal[ 9 ];
5385         nFieldTagBad[1] = aVal[ 10 ];
5386         nFieldTagBad[2] = aVal[ 11 ];
5387         m_bRegardHindiDigits = aVal[ 12 ] > 0;
5388     }
5389 
5390     sal_uInt16 nMagic;
5391     *pStrm >> nMagic;
5392 
5393     // beachte: 6 steht fuer "6 ODER 7",  7 steht fuer "NUR 7"
5394     switch (nWantedVersion)
5395     {
5396         case 6:
5397         case 7:
5398             if (
5399                 (0xa5dc != nMagic && 0xa5db != nMagic) &&
5400                 (nMagic < 0xa697 || nMagic > 0xa699)
5401                )
5402             {
5403                 //JP 06.05.99: teste auf eigenen 97-Fake!
5404                 if (pStg && 0xa5ec == nMagic)
5405                 {
5406                     sal_uLong nCurPos = pStrm->Tell();
5407                     if (pStrm->Seek(nCurPos + 22))
5408                     {
5409                         sal_uInt32 nfcMin;
5410                         *pStrm >> nfcMin;
5411                         if (0x300 != nfcMin)
5412                             nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
5413                     }
5414                     pStrm->Seek( nCurPos );
5415                 }
5416                 else
5417                     nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
5418             }
5419             break;
5420         case 8:
5421             if (0xa5ec != nMagic)
5422                 nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
5423             break;
5424         default:
5425             nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
5426             ASSERT( sal_False, "It was forgotten to encode nVersion!" );
5427             break;
5428     }
5429 
5430     if (!nErrRet)
5431         nErrRet = LoadThroughDecryption(rPaM ,pGloss);
5432 
5433     rDoc.PropagateOutlineRule();
5434 
5435     return nErrRet;
5436 }
5437 
ImportDOC()5438 extern "C" SAL_DLLPUBLIC_EXPORT Reader* SAL_CALL ImportDOC()
5439 {
5440     return new WW8Reader();
5441 }
5442 
Read(SwDoc & rDoc,const String & rBaseURL,SwPaM & rPam,const String &)5443 sal_uLong WW8Reader::Read(SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & /* FileName */)
5444 {
5445     sal_uInt16 nOldBuffSize = 32768;
5446     bool bNew = !bInsertMode;               // Neues Doc ( kein Einfuegen )
5447 
5448 
5449     SvStorageStreamRef refStrm;         // damit uns keiner den Stream klaut
5450     SvStream* pIn = pStrm;
5451 
5452     sal_uLong nRet = 0;
5453     sal_uInt8 nVersion = 8;
5454 
5455     String sFltName = GetFltName();
5456     if( sFltName.EqualsAscii( "WW6" ) )
5457     {
5458         if (pStrm)
5459             nVersion = 6;
5460         else
5461         {
5462             ASSERT(sal_False, "WinWord 95 Reader-Read without stream");
5463             nRet = ERR_SWG_READ_ERROR;
5464         }
5465     }
5466     else
5467     {
5468         if( sFltName.EqualsAscii( "CWW6" ) )
5469             nVersion = 6;
5470         else if( sFltName.EqualsAscii( "CWW7" ) )
5471             nVersion = 7;
5472 
5473         if( pStg )
5474         {
5475             nRet = OpenMainStream( refStrm, nOldBuffSize );
5476             pIn = &refStrm;
5477         }
5478         else
5479         {
5480             ASSERT(sal_False, "WinWord 95/97 Reader-Read without storage");
5481             nRet = ERR_SWG_READ_ERROR;
5482         }
5483     }
5484 
5485     if( !nRet )
5486     {
5487         //JP 18.01.96: Alle Ueberschriften sind normalerweise ohne
5488         //              Kapitelnummer. Darum hier explizit abschalten
5489         //              weil das Default jetzt wieder auf AN ist.
5490         if (bNew)
5491         {
5492             Reader::SetNoOutlineNum( rDoc );
5493             // MIB 27.09.96: Umrandung uns Abstaende aus Frm-Vorlagen entf.
5494             Reader::ResetFrmFmts( rDoc );
5495         }
5496         SwWW8ImplReader* pRdr = new SwWW8ImplReader(nVersion, pStg, pIn, rDoc,
5497             rBaseURL, bNew);
5498         try
5499         {
5500             nRet = pRdr->LoadDoc( rPam );
5501         }
5502         catch( const std::exception& )
5503         {
5504             nRet = ERR_WW8_NO_WW8_FILE_ERR;
5505         }
5506         delete pRdr;
5507 
5508         if( refStrm.Is() )
5509         {
5510             refStrm->SetBufferSize( nOldBuffSize );
5511             refStrm.Clear();
5512         }
5513         else if (pIn)
5514             pIn->ResetError();
5515 
5516     }
5517     return nRet;
5518 }
5519 
GetReaderType()5520 int WW8Reader::GetReaderType()
5521 {
5522     return SW_STORAGE_READER | SW_STREAM_READER;
5523 }
5524 
HasGlossaries() const5525 sal_Bool WW8Reader::HasGlossaries() const
5526 {
5527     return true;
5528 }
5529 
ReadGlossaries(SwTextBlocks & rBlocks,sal_Bool bSaveRelFiles) const5530 sal_Bool WW8Reader::ReadGlossaries(SwTextBlocks& rBlocks, sal_Bool bSaveRelFiles) const
5531 {
5532     bool bRet=false;
5533 
5534     WW8Reader *pThis = const_cast<WW8Reader *>(this);
5535 
5536     sal_uInt16 nOldBuffSize = 32768;
5537     SvStorageStreamRef refStrm;
5538     if (!pThis->OpenMainStream(refStrm, nOldBuffSize))
5539     {
5540         WW8Glossary aGloss( refStrm, 8, pStg );
5541         bRet = aGloss.Load( rBlocks, bSaveRelFiles ? true : false);
5542     }
5543     return bRet ? true : false;
5544 }
5545 
GetOLEStorageName(long nOLEId,String & rStorageName,SvStorageRef & rSrcStorage,uno::Reference<embed::XStorage> & rDestStorage) const5546 sal_Bool SwMSDffManager::GetOLEStorageName(long nOLEId, String& rStorageName,
5547     SvStorageRef& rSrcStorage, uno::Reference < embed::XStorage >& rDestStorage) const
5548 {
5549     bool bRet = false;
5550 
5551     long nPictureId = 0;
5552     if (rReader.pStg)
5553     {
5554         // dann holen wir uns mal ueber den TextBox-PLCF die richtigen
5555         // Char Start-/End-Positionen. In dem Bereich sollte dann
5556         // das EinbettenFeld und die entsprechenden Sprms zu finden
5557         // sein. Wir brauchen hier aber nur das Sprm fuer die Picture Id
5558         long nOldPos = rReader.pStrm->Tell();
5559         {
5560             // #i32596# - consider return value of method
5561             // <rReader.GetTxbxTextSttEndCp(..)>. If it returns false, method
5562             // wasn't successful. Thus, continue in this case.
5563             // Note: Ask MM for initialization of <nStartCp> and <nEndCp>.
5564             // Note: Ask MM about assertions in method <rReader.GetTxbxTextSttEndCp(..)>.
5565             WW8_CP nStartCp, nEndCp;
5566             if ( rReader.GetTxbxTextSttEndCp(nStartCp, nEndCp,
5567                             static_cast<sal_uInt16>((nOLEId >> 16) & 0xFFFF),
5568                             static_cast<sal_uInt16>(nOLEId & 0xFFFF)) )
5569             {
5570                 WW8PLCFxSaveAll aSave;
5571                 memset( &aSave, 0, sizeof( aSave ) );
5572                 rReader.pPlcxMan->SaveAllPLCFx( aSave );
5573 
5574                 nStartCp += rReader.nDrawCpO;
5575                 nEndCp   += rReader.nDrawCpO;
5576                 WW8PLCFx_Cp_FKP* pChp = rReader.pPlcxMan->GetChpPLCF();
5577                 wwSprmParser aSprmParser(rReader.pWwFib->GetFIBVersion());
5578                 while (nStartCp <= nEndCp && !nPictureId)
5579                 {
5580                     WW8PLCFxDesc aDesc;
5581                     pChp->SeekPos( nStartCp );
5582                     pChp->GetSprms( &aDesc );
5583 
5584                     if (aDesc.nSprmsLen && aDesc.pMemPos)   // Attribut(e) vorhanden
5585                     {
5586                         long nLen = aDesc.nSprmsLen;
5587                         const sal_uInt8* pSprm = aDesc.pMemPos;
5588 
5589                         while (nLen >= 2 && !nPictureId)
5590                         {
5591                             sal_uInt16 nId = aSprmParser.GetSprmId(pSprm);
5592                             sal_uInt16 nSL = aSprmParser.GetSprmSize(nId, pSprm);
5593 
5594                             if( nLen < nSL )
5595                                 break;              // nicht mehr genug Bytes uebrig
5596 
5597                             if( 0x6A03 == nId && 0 < nLen )
5598                             {
5599                                 nPictureId = SVBT32ToUInt32(pSprm +
5600                                     aSprmParser.DistanceToData(nId));
5601                                 bRet = true;
5602                             }
5603                             pSprm += nSL;
5604                             nLen -= nSL;
5605                         }
5606                     }
5607                     nStartCp = aDesc.nEndPos;
5608                 }
5609 
5610                 rReader.pPlcxMan->RestoreAllPLCFx( aSave );
5611             }
5612         }
5613         rReader.pStrm->Seek( nOldPos );
5614     }
5615 
5616     if( bRet )
5617     {
5618         rStorageName = '_';
5619         rStorageName += String::CreateFromInt32(nPictureId);
5620         rSrcStorage = rReader.pStg->OpenSotStorage(CREATE_CONST_ASC(
5621             SL::aObjectPool));
5622         if (!rReader.mpDocShell)
5623             bRet=false;
5624         else
5625             rDestStorage = rReader.mpDocShell->GetStorage();
5626     }
5627     return bRet;
5628 }
5629 
ShapeHasText(sal_uLong,sal_uLong) const5630 sal_Bool SwMSDffManager::ShapeHasText(sal_uLong, sal_uLong) const
5631 {
5632     // Zur Zeit des Einlesens einer einzelnen Box, die womoeglich Teil einer
5633     // Gruppe ist, liegen noch nicht genuegend Informationen vor, um
5634     // entscheiden zu koennen, ob wir sie nicht doch als Textfeld benoetigen.
5635     // Also vorsichtshalber mal alle umwandeln:
5636     return true;
5637 }
5638 
InEqualOrHigherApo(int nLvl) const5639 bool SwWW8ImplReader::InEqualOrHigherApo(int nLvl) const
5640 {
5641     if (nLvl)
5642         --nLvl;
5643     // #i60827# - check size of <maApos> to assure that <maApos.begin() + nLvl> can be performed.
5644     if ( sal::static_int_cast< sal_Int32>(nLvl) >= sal::static_int_cast< sal_Int32>(maApos.size()) )
5645     {
5646         return false;
5647     }
5648     mycApoIter aIter = std::find(maApos.begin() + nLvl, maApos.end(), true);
5649     if (aIter != maApos.end())
5650         return true;
5651     else
5652         return false;
5653 }
5654 
InEqualApo(int nLvl) const5655 bool SwWW8ImplReader::InEqualApo(int nLvl) const
5656 {
5657     //If we are in a table, see if an apo was inserted at the level below
5658     //the table.
5659     if (nLvl)
5660         --nLvl;
5661     return maApos[nLvl];
5662 }
5663 
5664 namespace sw
5665 {
5666     namespace hack
5667     {
Position(const SwPosition & rPos)5668         Position::Position(const SwPosition &rPos)
5669             : maPtNode(rPos.nNode), mnPtCntnt(rPos.nContent.GetIndex())
5670         {
5671         }
5672 
Position(const Position & rPos)5673         Position::Position(const Position &rPos)
5674             : maPtNode(rPos.maPtNode), mnPtCntnt(rPos.mnPtCntnt)
5675         {
5676         }
5677 
operator SwPosition() const5678         Position::operator SwPosition() const
5679         {
5680             SwPosition aRet(maPtNode);
5681             aRet.nContent.Assign(maPtNode.GetNode().GetCntntNode(), mnPtCntnt);
5682             return aRet;
5683         }
5684     }
5685 }
5686 
5687 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
5688 
SwMacroInfo()5689 SwMacroInfo::SwMacroInfo() :
5690     SdrObjUserData( SW_DRAWLAYER, SW_UD_IMAPDATA, 0 )
5691 {
5692 }
5693 
~SwMacroInfo()5694 SwMacroInfo::~SwMacroInfo()
5695 {
5696 }
5697 
Clone(SdrObject *) const5698 SdrObjUserData* SwMacroInfo::Clone( SdrObject* /*pObj*/ ) const
5699 {
5700    return new SwMacroInfo( *this );
5701 }
5702 
5703 
5704 
5705