xref: /aoo4110/main/sw/source/filter/ww8/ww8par.cxx (revision b1cdbd2c)
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 chararcter.
223 	const sal_uInt16 WW8_NUL                    = WW8_NUL_C;    /// NUL chararcter (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(!this, "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(!this, "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(!this, "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(!this, "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 compatability 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 postion 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         similiar 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     , mbLoadingTOCCache(false)
3728     , mbLoadingTOCHyperlink(false)
3729     , mpPosAfterTOC(0)
3730     , mbCareFirstParaEndInToc(false)
3731     , mbCareLastParaEndInToc(false)
3732     , maTOXEndCps()
3733 	//Modify here for #119405, by easyfan, 2012-05-24
3734 	,maCurrAttrCP(-1),
3735 	mbOnLoadingMain(false)
3736 	//End of modification, by easyfan
3737 {
3738     pStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
3739     nWantedVersion = nVersionPara;
3740     pCtrlStck   = 0;
3741     mpRedlineStack = 0;
3742     pReffedStck = 0;
3743     pReffingStck = 0;
3744     pAnchorStck = 0;
3745     pFonts = 0;
3746     pSBase = 0;
3747     pPlcxMan = 0;
3748     pStyles = 0;
3749     pAktColl = 0;
3750     pLstManager = 0;
3751     pAktItemSet = 0;
3752     pCollA = 0;
3753     pDfltTxtFmtColl = 0;
3754     pStandardFmtColl = 0;
3755     pHdFt = 0;
3756     pWFlyPara = 0;
3757     pSFlyPara = 0;
3758     pFlyFmtOfJustInsertedGraphic   = 0;
3759     pFmtOfJustInsertedApo = 0;
3760     pPreviousNumPaM = 0;
3761     pPrevNumRule = 0;
3762     nColls = nAktColl = 0;
3763     nObjLocFc = nPicLocFc = 0;
3764     nInTable=0;
3765     bReadNoTbl = bPgSecBreak = bSpec = bObj = bTxbxFlySection
3766                = bHasBorder = bSymbol = bIgnoreText
3767                = bWasTabRowEnd = bWasTabCellEnd = false;
3768     bShdTxtCol = bCharShdTxtCol = bAnl = bHdFtFtnEdn = bFtnEdn
3769                = bIsHeader = bIsFooter = bIsUnicode = bCpxStyle = bStyNormal =
3770                  bWWBugNormal  = false;
3771 
3772     mpPostProcessAttrsInfo = 0;
3773 
3774     bNoAttrImport = bPgChpLevel = bEmbeddObj = false;
3775     bAktAND_fNumberAcross = false;
3776     bNoLnNumYet = true;
3777     bInHyperlink = false;
3778     bWasParaEnd = false;
3779     bDropCap = false;
3780     bFirstPara = true;
3781 	  bFirstParaOfPage = false;//xushanchuan add for issue106569
3782     bParaAutoBefore = false;
3783     bParaAutoAfter = false;
3784     nProgress = 0;
3785     nSwNumLevel = nWwNumType = 0xff;
3786     pTableDesc = 0;
3787     pNumOlst = 0;
3788     pNode_FLY_AT_PARA = 0;
3789     pDrawModel = 0;
3790     pDrawPg = 0;
3791     mpDrawEditEngine = 0;
3792     pWWZOrder = 0;
3793     pFormImpl = 0;
3794     pNumFldType = 0;
3795     nFldNum = 0;
3796 
3797     nLFOPosition = USHRT_MAX;
3798     nListLevel = WW8ListManager::nMaxLevel;
3799     eHardCharSet = RTL_TEXTENCODING_DONTKNOW;
3800 
3801     nPgChpDelim = nPgChpLevel = 0;
3802 
3803     maApos.push_back(false);
3804 }
3805 
DeleteStk(SwFltControlStack * pStck)3806 void SwWW8ImplReader::DeleteStk(SwFltControlStack* pStck)
3807 {
3808     if( pStck )
3809     {
3810         pStck->SetAttr( *pPaM->GetPoint(), 0, false);
3811         pStck->SetAttr( *pPaM->GetPoint(), 0, false);
3812         delete pStck;
3813     }
3814     else
3815     {
3816         ASSERT( !this, "WW-Stack bereits geloescht" );
3817     }
3818 }
3819 
SetSegmentToPageDesc(const wwSection & rSection,bool bTitlePage,bool bIgnoreCols)3820 void wwSectionManager::SetSegmentToPageDesc(const wwSection &rSection,
3821     bool bTitlePage, bool bIgnoreCols)
3822 {
3823     SwPageDesc &rPage = bTitlePage ? *rSection.mpTitlePage : *rSection.mpPage;
3824 
3825     SetNumberingType(rSection, rPage);
3826 
3827     SwFrmFmt &rFmt = rPage.GetMaster();
3828 
3829     if(mrReader.pWDop->fUseBackGroundInAllmodes)  // #i56806# Make sure mrReader is initialized
3830 		mrReader.GrafikCtor();
3831 
3832 
3833     if (mrReader.pWDop->fUseBackGroundInAllmodes && mrReader.pMSDffManager)
3834     {
3835         Rectangle aRect(0, 0, 100, 100); //A dummy, we don't care about the size
3836         SvxMSDffImportData aData(aRect);
3837         SdrObject* pObject = 0;
3838         if (mrReader.pMSDffManager->GetShape(0x401, pObject, aData))
3839         {
3840             SvxMSDffImportRec * pRec = aData.GetRecord(0);
3841 
3842             // Only handle shape if it is a background shape
3843             if ((pRec->nFlags & 0x400) != 0)
3844             {
3845                 SfxItemSet aSet(rFmt.GetAttrSet());
3846                 mrReader.MatchSdrItemsIntoFlySet(pObject, aSet, mso_lineSimple,
3847                                                  mso_sptRectangle, aRect);
3848                 rFmt.SetFmtAttr(aSet.Get(RES_BACKGROUND));
3849             }
3850         }
3851     }
3852     wwULSpaceData aULData;
3853     GetPageULData(rSection, bTitlePage, aULData);
3854     SetPageULSpaceItems(rFmt, aULData, rSection);
3855 
3856     SetPage(rPage, rFmt, rSection, bIgnoreCols);
3857 
3858     bool bSetBorder = false;
3859     switch (rSection.maSep.pgbApplyTo)
3860     {
3861         case 0:
3862         case 3:
3863             bSetBorder = true;
3864             break;
3865         case 1:
3866             bSetBorder = bTitlePage;
3867             break;
3868         case 2:
3869             bSetBorder = !bTitlePage;
3870             break;
3871     }
3872     if (bSetBorder)
3873         mrReader.SetPageBorder(rFmt, rSection);
3874 
3875     mrReader.SetDocumentGrid(rFmt, rSection);
3876 }
3877 
SetUseOn(wwSection & rSection)3878 void wwSectionManager::SetUseOn(wwSection &rSection)
3879 {
3880     bool bEven = (rSection.maSep.grpfIhdt & (WW8_HEADER_EVEN|WW8_FOOTER_EVEN)) ?
3881         true : false;
3882 
3883     bool bMirror = mrReader.pWDop->fMirrorMargins ||
3884         mrReader.pWDop->doptypography.f2on1;
3885 
3886     UseOnPage eUseBase = bMirror ? nsUseOnPage::PD_MIRROR : nsUseOnPage::PD_ALL;
3887     UseOnPage eUse = eUseBase;
3888     if (!bEven)
3889         eUse = (UseOnPage)(eUse | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE);
3890 
3891     ASSERT(rSection.mpPage, "Makes no sense to call me with no pages to set");
3892     if (rSection.mpPage)
3893         rSection.mpPage->WriteUseOn(eUse);
3894     if (rSection.mpTitlePage)
3895     {
3896         rSection.mpTitlePage->WriteUseOn(
3897             (UseOnPage) (eUseBase | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE));
3898     }
3899 }
3900 
3901 //Set the page descriptor on this node, handle the different cases for a text
3902 //node or a table
GiveNodePageDesc(SwNodeIndex & rIdx,const SwFmtPageDesc & rPgDesc,SwDoc & rDoc)3903 void GiveNodePageDesc(SwNodeIndex &rIdx, const SwFmtPageDesc &rPgDesc,
3904     SwDoc &rDoc)
3905 {
3906     /*
3907     If its a table here, apply the pagebreak to the table
3908     properties, otherwise we add it to the para at this
3909     position
3910     */
3911     if (rIdx.GetNode().IsTableNode())
3912     {
3913         SwTable& rTable =
3914             rIdx.GetNode().GetTableNode()->GetTable();
3915         SwFrmFmt* pApply = rTable.GetFrmFmt();
3916         ASSERT(pApply, "impossible");
3917         if (pApply)
3918             pApply->SetFmtAttr(rPgDesc);
3919     }
3920     else
3921     {
3922         SwPosition aPamStart(rIdx);
3923         aPamStart.nContent.Assign(
3924             rIdx.GetNode().GetCntntNode(), 0);
3925         SwPaM aPage(aPamStart);
3926 
3927         rDoc.InsertPoolItem(aPage, rPgDesc, 0);
3928     }
3929 }
3930 
3931 //Map a word section with to either one or two writer page descriptors
3932 //depending on if the word section has a title page
SetSwFmtPageDesc(mySegIter & rIter,mySegIter & rStart,bool bIgnoreCols)3933 SwFmtPageDesc wwSectionManager::SetSwFmtPageDesc(mySegIter &rIter,
3934     mySegIter &rStart, bool bIgnoreCols)
3935 {
3936     SwFmtPageDesc aEmpty;
3937     // Always read title page header/footer data - it could be used by following sections
3938     {
3939         if (IsNewDoc() && rIter == rStart)
3940         {
3941             rIter->mpTitlePage =
3942                 mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_FIRST);
3943         }
3944         else
3945         {
3946             sal_uInt16 nPos = mrReader.rDoc.MakePageDesc(
3947                 ViewShell::GetShellRes()->GetPageDescName(mnDesc)
3948                 , 0, false);
3949             rIter->mpTitlePage = &mrReader.rDoc._GetPageDesc(nPos);
3950         }
3951         ASSERT(rIter->mpTitlePage, "no page!");
3952         if (!rIter->mpTitlePage)
3953             return aEmpty;
3954 
3955         SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
3956     }
3957 
3958     if (IsNewDoc() && rIter == rStart)
3959     {
3960         rIter->mpPage =
3961             mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_STANDARD);
3962     }
3963     else
3964     {
3965         sal_uInt16 nPos = mrReader.rDoc.MakePageDesc(
3966             ViewShell::GetShellRes()->GetPageDescName(mnDesc,
3967                 false, rIter->HasTitlePage()),
3968                 rIter->mpTitlePage, false);
3969         rIter->mpPage = &mrReader.rDoc._GetPageDesc(nPos);
3970     }
3971     ASSERT(rIter->mpPage, "no page!");
3972     if (!rIter->mpPage)
3973         return aEmpty;
3974 
3975     //Set page before hd/ft
3976     const wwSection *pPrevious = 0;
3977 
3978     mySegIter aPrev = rIter;
3979     while( aPrev!= rStart )
3980     {
3981         aPrev--;
3982         pPrevious = &(*(aPrev));
3983         if( aPrev->IsContinous())
3984             continue;
3985         else{
3986             break;
3987         }
3988     }
3989 
3990     SetHdFt(*rIter, std::distance(rStart, rIter), pPrevious);
3991     SetUseOn(*rIter);
3992 
3993     //Set hd/ft after set page
3994     if (rIter->mpTitlePage)
3995         SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
3996     SetSegmentToPageDesc(*rIter, false, bIgnoreCols);
3997 
3998     SwFmtPageDesc aRet(rIter->HasTitlePage() ?
3999         rIter->mpTitlePage : rIter->mpPage);
4000 
4001     rIter->mpPage->SetFollow(rIter->mpPage);
4002 
4003     if (rIter->mpTitlePage)
4004         rIter->mpTitlePage->SetFollow(rIter->mpPage);
4005 
4006     if (rIter->PageRestartNo())
4007         aRet.SetNumOffset(rIter->PageStartAt());
4008 
4009     ++mnDesc;
4010     return aRet;
4011 }
4012 
IsNewDoc() const4013 bool wwSectionManager::IsNewDoc() const
4014 {
4015     return mrReader.mbNewDoc;
4016 }
4017 
InsertSegments()4018 void wwSectionManager::InsertSegments()
4019 {
4020     const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
4021     sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
4022     mySegIter aEnd = maSegments.end();
4023     mySegIter aStart = maSegments.begin();
4024     for (mySegIter aIter = aStart; aIter != aEnd; ++aIter)
4025     {
4026         mySegIter aNext = aIter+1;
4027         mySegIter aPrev = (aIter == aStart) ? aIter : aIter-1;
4028 
4029         // If two following sections are different in following properties, Word will interprete a continuous
4030         // section break between them as if it was a section break next page.
4031         bool bThisAndPreviousAreCompatible = ((aIter->GetPageWidth() == aPrev->GetPageWidth()) &&
4032             (aIter->GetPageHeight() == aPrev->GetPageHeight()) && (aIter->IsLandScape() == aPrev->IsLandScape()));
4033 
4034         bool bInsertSection = (aIter != aStart) ? (aIter->IsContinous() &&  bThisAndPreviousAreCompatible): false;
4035         bool bInsertPageDesc = !bInsertSection;
4036         bool bProtected = SectionIsProtected(*aIter); // do we really  need this ?? I guess I have a different logic in editshell which disales this...
4037         if (bUseEnhFields && mrReader.pWDop->fProtEnabled && aIter->IsNotProtected())
4038         {
4039             // here we have the special case that the whole document is protected, with the execption of this section.
4040             // I want to address this when I do the section rework, so for the moment we disable the overall protection then...
4041             mrReader.rDoc.set(IDocumentSettingAccess::PROTECT_FORM, false );
4042         }
4043 
4044 
4045         if (bInsertPageDesc)
4046         {
4047             /*
4048              If a cont section follows this section then we won't be
4049              creating a page desc with 2+ cols as we cannot host a one
4050              col section in a 2+ col pagedesc and make it look like
4051              word. But if the current section actually has columns then
4052              we are forced to insert a section here as well as a page
4053              descriptor.
4054             */
4055 
4056             bool bIgnoreCols = false;
4057             bool bThisAndNextAreCompatible = (aNext != aEnd) ? ((aIter->GetPageWidth() == aNext->GetPageWidth()) &&
4058                 (aIter->GetPageHeight() == aNext->GetPageHeight()) && (aIter->IsLandScape() == aNext->IsLandScape())) : true;
4059 
4060             if (((aNext != aEnd && aNext->IsContinous() && bThisAndNextAreCompatible) || bProtected))
4061             {
4062                 bIgnoreCols = true;
4063                 if ((aIter->NoCols() > 1) || bProtected)
4064                     bInsertSection = true;
4065             }
4066 
4067             SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, bIgnoreCols));
4068             if (!aDesc.GetPageDesc())
4069                 continue;
4070             GiveNodePageDesc(aIter->maStart, aDesc, mrReader.rDoc);
4071         }
4072 
4073         SwTxtNode* pTxtNd = 0;
4074         if (bInsertSection)
4075         {
4076             //Start getting the bounds of this section
4077             SwPaM aSectPaM(*mrReader.pPaM);
4078             SwNodeIndex aAnchor(aSectPaM.GetPoint()->nNode);
4079             if (aNext != aEnd)
4080             {
4081                 aAnchor = aNext->maStart;
4082                 aSectPaM.GetPoint()->nNode = aAnchor;
4083                 aSectPaM.GetPoint()->nContent.Assign(
4084                     aNext->maStart.GetNode().GetCntntNode(), 0);
4085                 aSectPaM.Move(fnMoveBackward);
4086             }
4087 
4088             const SwPosition* pPos  = aSectPaM.GetPoint();
4089             SwTxtNode const*const pSttNd = pPos->nNode.GetNode().GetTxtNode();
4090             const SwTableNode* pTableNd = pSttNd ? pSttNd->FindTableNode() : 0;
4091             if (pTableNd)
4092             {
4093                 pTxtNd =
4094                     mrReader.rDoc.GetNodes().MakeTxtNode(aAnchor,
4095                     mrReader.rDoc.GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
4096 
4097                 aSectPaM.GetPoint()->nNode = SwNodeIndex(*pTxtNd);
4098                 aSectPaM.GetPoint()->nContent.Assign(
4099                     aSectPaM.GetCntntNode(), 0);
4100             }
4101 
4102             aSectPaM.SetMark();
4103 
4104             aSectPaM.GetPoint()->nNode = aIter->maStart;
4105             aSectPaM.GetPoint()->nContent.Assign(
4106                 aSectPaM.GetCntntNode(), 0);
4107             //End getting the bounds of this section, quite a job eh ?
4108 
4109             SwSectionFmt *pRet = InsertSection(aSectPaM, *aIter);
4110             //The last section if continous is always unbalanced
4111             if (pRet)
4112             {
4113                 //Set the columns to be UnBalanced if that compatability option
4114                 //is set
4115                 if (mrReader.pWDop->fNoColumnBalance)
4116                     pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
4117                 else
4118                 {
4119                     //Otherwise set to unbalanced if the following section is
4120                     //not continuous, (which also means that the last section
4121                     //is unbalanced)
4122                     if (aNext == aEnd || !aNext->IsContinous())
4123                         pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
4124                 }
4125             }
4126 
4127             bool bHasOwnHdFt = false;
4128             /*
4129              In this nightmare scenario the continuous section has its own
4130              headers and footers so we will try and find a hard page break
4131              between here and the end of the section and put the headers and
4132              footers there.
4133             */
4134             if (!bInsertPageDesc)
4135             {
4136                bHasOwnHdFt =
4137                 mrReader.HasOwnHeaderFooter(
4138                  aIter->maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST),
4139                  aIter->maSep.grpfIhdt, std::distance(aStart, aIter)
4140                 );
4141             }
4142             if (bHasOwnHdFt)
4143             {
4144 				// #i40766# Need to cache the page descriptor in case there is
4145 				// no page break in the section
4146 				SwPageDesc *pOrig = aIter->mpPage;
4147 				SwPageDesc *pOrigTitle = aIter->mpTitlePage;
4148 				bool bFailed = true;
4149                 SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, true));
4150                 if (aDesc.GetPageDesc())
4151                 {
4152                     sal_uLong nStart = aSectPaM.Start()->nNode.GetIndex();
4153                     sal_uLong nEnd   = aSectPaM.End()->nNode.GetIndex();
4154                     for(; nStart <= nEnd; ++nStart)
4155                     {
4156                         SwNode* pNode = mrReader.rDoc.GetNodes()[nStart];
4157                         if (!pNode)
4158                             continue;
4159                         if (sw::util::HasPageBreak(*pNode))
4160                         {
4161                             SwNodeIndex aIdx(*pNode);
4162                             GiveNodePageDesc(aIdx, aDesc, mrReader.rDoc);
4163 							bFailed = false;
4164                             break;
4165                         }
4166                     }
4167                 }
4168 				if(bFailed)
4169 				{
4170 					aIter->mpPage = pOrig;
4171 					aIter->mpTitlePage = pOrigTitle;
4172 				}
4173             }
4174         }
4175 
4176         if (pTxtNd)
4177         {
4178             SwNodeIndex aIdx(*pTxtNd);
4179             SwPosition aPos(aIdx);
4180             SwPaM aTest(aPos);
4181             mrReader.rDoc.DelFullPara(aTest);
4182             pTxtNd = 0;
4183         }
4184     }
4185 }
4186 
StoreMacroCmds()4187 void SwWW8ImplReader::StoreMacroCmds()
4188 {
4189     if (pWwFib->lcbCmds)
4190     {
4191         maTracer.Log(sw::log::eContainsWordBasic);
4192 
4193         pTableStream->Seek(pWwFib->fcCmds);
4194 
4195         uno::Reference < embed::XStorage > xRoot(mpDocShell->GetStorage());
4196         try
4197         {
4198             uno::Reference < io::XStream > xStream =
4199                     xRoot->openStreamElement( CREATE_CONST_ASC(SL::aMSMacroCmds), embed::ElementModes::READWRITE );
4200             SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xStream );
4201 
4202             sal_uInt8 *pBuffer = new sal_uInt8[pWwFib->lcbCmds];
4203             pTableStream->Read(pBuffer, pWwFib->lcbCmds);
4204             pStream->Write(pBuffer, pWwFib->lcbCmds);
4205             delete[] pBuffer;
4206             delete pStream;
4207         }
4208         catch ( uno::Exception& )
4209         {
4210         }
4211     }
4212 }
4213 
ReadDocVars()4214 void SwWW8ImplReader::ReadDocVars()
4215 {
4216     std::vector<String> aDocVarStrings;
4217     std::vector<ww::bytes> aDocVarStringIds;
4218     std::vector<String> aDocValueStrings;
4219     WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcStwUser,
4220         pWwFib->lcbStwUser, bVer67 ? 2 : 0, eStructCharSet,
4221         aDocVarStrings, &aDocVarStringIds, &aDocValueStrings);
4222     if (!bVer67) {
4223         using namespace ::com::sun::star;
4224 
4225         uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
4226             mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
4227         uno::Reference<document::XDocumentProperties> xDocProps(
4228             xDPS->getDocumentProperties());
4229         DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
4230         uno::Reference<beans::XPropertyContainer> xUserDefinedProps =
4231             xDocProps->getUserDefinedProperties();
4232         DBG_ASSERT(xUserDefinedProps.is(), "UserDefinedProperties is null");
4233 
4234         for(size_t i=0; i<aDocVarStrings.size(); i++)
4235         {
4236             uno::Any aDefaultValue;
4237             ::rtl::OUString name(aDocVarStrings[i]);
4238             uno::Any aValue;
4239             aValue <<= ::rtl::OUString(aDocValueStrings[i]);
4240             try {
4241                 xUserDefinedProps->addProperty( name,
4242                     beans::PropertyAttribute::REMOVEABLE,
4243                     aValue );
4244             } catch (uno::Exception &) {
4245                 // ignore
4246             }
4247         }
4248 	}
4249 }
4250 
4251 //-----------------------------------------
4252 //      Document Info
4253 //-----------------------------------------
4254 
ReadDocInfo()4255 void SwWW8ImplReader::ReadDocInfo()
4256 {
4257     if( pStg )
4258     {
4259         uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
4260             mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
4261         uno::Reference<document::XDocumentProperties> xDocProps(
4262             xDPS->getDocumentProperties());
4263         DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
4264 
4265         if (xDocProps.is()) {
4266             sfx2::LoadOlePropertySet(xDocProps, pStg);
4267         }
4268     }
4269 }
4270 
CoreLoad(WW8Glossary * pGloss,const SwPosition & rPos)4271 sal_uLong SwWW8ImplReader::CoreLoad(WW8Glossary *pGloss, const SwPosition &rPos)
4272 {
4273     sal_uLong nErrRet = 0;
4274 
4275 	rDoc.SetDocumentType( SwDoc::DOCTYPE_MSWORD );
4276     if (mbNewDoc && pStg && !pGloss)
4277         ReadDocInfo();
4278 
4279     ::ww8::WW8FibData * pFibData = new ::ww8::WW8FibData();
4280 
4281     if (pWwFib->fReadOnlyRecommended)
4282         pFibData->setReadOnlyRecommended(true);
4283     else
4284         pFibData->setReadOnlyRecommended(false);
4285 
4286     if (pWwFib->fWriteReservation)
4287         pFibData->setWriteReservation(true);
4288     else
4289         pFibData->setWriteReservation(false);
4290 
4291     ::sw::tExternalDataPointer pExternalFibData(pFibData);
4292 
4293     rDoc.setExternalData(::sw::FIB, pExternalFibData);
4294 
4295     ::sw::tExternalDataPointer pSttbfAsoc
4296           (new ::ww8::WW8Sttb<ww8::WW8Struct>(*pTableStream, pWwFib->fcSttbfAssoc, pWwFib->lcbSttbfAssoc));
4297 
4298     rDoc.setExternalData(::sw::STTBF_ASSOC, pSttbfAsoc);
4299 
4300     if (pWwFib->fWriteReservation || pWwFib->fReadOnlyRecommended)
4301     {
4302         SwDocShell * pDocShell = rDoc.GetDocShell();
4303         if (pDocShell)
4304             pDocShell->SetReadOnlyUI(sal_True);
4305     }
4306 
4307     pPaM = new SwPaM(rPos);
4308 
4309     pCtrlStck = new SwWW8FltControlStack( &rDoc, nFieldFlags, *this );
4310 
4311     mpRedlineStack = new sw::util::RedlineStack(rDoc);
4312 
4313     /*
4314         RefFldStck: Keeps track of bookmarks which may be inserted as
4315         variables intstead.
4316     */
4317     pReffedStck = new SwWW8ReferencedFltEndStack(&rDoc, nFieldFlags);
4318     pReffingStck = new SwWW8FltRefStack(&rDoc, nFieldFlags);
4319 
4320     pAnchorStck = new SwWW8FltAnchorStack(&rDoc, nFieldFlags);
4321 
4322     sal_uInt16 nPageDescOffset = rDoc.GetPageDescCnt();
4323 
4324     SwNodeIndex aSttNdIdx( rDoc.GetNodes() );
4325     SwRelNumRuleSpaces aRelNumRule(rDoc, mbNewDoc);
4326 
4327     sal_uInt16 eMode = nsRedlineMode_t::REDLINE_SHOW_INSERT;
4328 
4329     mpSprmParser = new wwSprmParser(pWwFib->GetFIBVersion());
4330 
4331     // praktische Hilfsvariablen besetzen:
4332     bVer6  = (6 == pWwFib->nVersion);
4333     bVer7  = (7 == pWwFib->nVersion);
4334     bVer67 = bVer6 || bVer7;
4335     bVer8  = (8 == pWwFib->nVersion);
4336 
4337     eTextCharSet = WW8Fib::GetFIBCharset(pWwFib->chse);
4338     eStructCharSet = WW8Fib::GetFIBCharset(pWwFib->chseTables);
4339 
4340     bWWBugNormal = pWwFib->nProduct == 0xc03d;
4341 
4342     if (!mbNewDoc)
4343         aSttNdIdx = pPaM->GetPoint()->nNode;
4344 
4345     ::StartProgress(STR_STATSTR_W4WREAD, 0, 100, mpDocShell);
4346 
4347 #ifdef DEBUGDUMP
4348     //experimental embedded ttf dumper
4349     if (pWwFib->lcbSttbttmbd && (7 < pWwFib->nVersion))
4350     {
4351         pTableStream->Seek(pWwFib->fcSttbttmbd);
4352         sal_uInt16 nZeros;
4353         *pTableStream >> nZeros;
4354         sal_uInt16 nNoEntries;
4355         *pTableStream >> nNoEntries;
4356         sal_uInt32 nUnknown1;
4357         *pTableStream >> nUnknown1;
4358         sal_uInt16 nUnknown2;
4359         *pTableStream >> nUnknown2;
4360         std::vector<sal_uInt32> aOffsets;
4361         for (sal_uInt16 nI = 0; nI < nNoEntries; ++nI)
4362         {
4363             sal_uInt32 nOffset;
4364             *pTableStream >> nOffset;
4365             aOffsets.push_back(nOffset);
4366             sal_uInt32 nUnknown3;
4367             *pTableStream >> nUnknown3;
4368             sal_uInt32 nUnknown4;
4369             *pTableStream >> nUnknown4;
4370         }
4371         typedef std::vector<sal_uInt32>::iterator myIter;
4372         myIter aEnd = aOffsets.end();
4373         myIter aIter = aOffsets.begin();
4374         while (aIter != aEnd)
4375         {
4376             sal_uInt32 nOffset = *aIter;
4377             sal_uInt32 nLen = STREAM_SEEK_TO_END;
4378             ++aIter;
4379             pStrm->Seek(nOffset);
4380             if (aIter != aEnd)
4381                 nLen = *aIter - nOffset;
4382             SvStream *pDbg = sw::hack::CreateDebuggingStream(CREATE_CONST_ASC(".ttf.dump"));
4383             sw::hack::DumpStream(*pStrm, *pDbg, nLen);
4384             delete pDbg;
4385         }
4386     }
4387 #endif
4388 
4389     // read Font Table
4390     pFonts = new WW8Fonts( *pTableStream, *pWwFib );
4391 
4392     // Document Properties
4393     pWDop = new WW8Dop( *pTableStream, pWwFib->nFib, pWwFib->fcDop,
4394         pWwFib->lcbDop );
4395 
4396     if (mbNewDoc)
4397         ImportDop();
4398 
4399     /*
4400         Import revisioning data: author names
4401     */
4402     if( pWwFib->lcbSttbfRMark )
4403     {
4404         ReadRevMarkAuthorStrTabl( *pTableStream,
4405                                     pWwFib->fcSttbfRMark,
4406                                     pWwFib->lcbSttbfRMark, rDoc );
4407     }
4408 
4409     // M.M. Initialize our String/ID map for Linked Sections
4410     std::vector<String> aLinkStrings;
4411     std::vector<ww::bytes> aStringIds;
4412 
4413     WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcSttbFnm,
4414         pWwFib->lcbSttbFnm, bVer67 ? 2 : 0, eStructCharSet,
4415         aLinkStrings, &aStringIds);
4416 
4417     for (size_t i=0; i < aLinkStrings.size(); ++i)
4418     {
4419         ww::bytes stringId = aStringIds[i];
4420         WW8_STRINGID *stringIdStruct = (WW8_STRINGID*)(&stringId[0]);
4421         aLinkStringMap[SVBT16ToShort(stringIdStruct->nStringId)] =
4422             aLinkStrings[i];
4423     }
4424 
4425 	ReadDocVars(); // import document variables as meta information.
4426 
4427     ::SetProgressState(nProgress, mpDocShell);    // Update
4428 
4429     pLstManager = new WW8ListManager( *pTableStream, *this );
4430 
4431     /*
4432         zuerst(!) alle Styles importieren   (siehe WW8PAR2.CXX)
4433             VOR dem Import der Listen !!
4434     */
4435     ::SetProgressState(nProgress, mpDocShell);    // Update
4436     pStyles = new WW8RStyle( *pWwFib, this );   // Styles
4437     pStyles->Import();
4438 
4439     /*
4440         zu guter Letzt: (siehe ebenfalls WW8PAR3.CXX)
4441         ===============
4442         alle Styles durchgehen und ggfs. zugehoeriges Listen-Format
4443         anhaengen NACH dem Import der Styles und NACH dem Import der
4444         Listen !!
4445     */
4446     ::SetProgressState(nProgress, mpDocShell);    // Update
4447     pStyles->PostProcessStyles();
4448 
4449     if (pCollA)
4450         SetOutlineStyles();
4451 
4452     pSBase = new WW8ScannerBase(pStrm,pTableStream,pDataStream,pWwFib);
4453 
4454     if ( !pSBase->IsValid() )
4455     {
4456         return ERR_SWG_READ_ERROR;
4457     }
4458 
4459     static const SvxExtNumType eNumTA[16] =
4460     {
4461         SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,
4462         SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N,
4463         SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
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
4467     };
4468 
4469     if (pSBase->AreThereFootnotes())
4470     {
4471         static const SwFtnNum eNumA[4] =
4472         {
4473             FTNNUM_DOC, FTNNUM_CHAPTER, FTNNUM_PAGE, FTNNUM_DOC
4474         };
4475 
4476         SwFtnInfo aInfo;
4477         aInfo = rDoc.GetFtnInfo();      // Copy-Ctor privat
4478 
4479         aInfo.ePos = FTNPOS_PAGE;
4480         aInfo.eNum = eNumA[pWDop->rncFtn];
4481         aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcFtnRef]) );
4482         if( pWDop->nFtn )
4483             aInfo.nFtnOffset = pWDop->nFtn - 1;
4484         rDoc.SetFtnInfo( aInfo );
4485     }
4486     if( pSBase->AreThereEndnotes() )
4487     {
4488         SwEndNoteInfo aInfo;
4489         aInfo = rDoc.GetEndNoteInfo();  // parallel zu Ftn
4490 
4491         // Ich kann nicht setzen, wann neu nummerieren...
4492         //  aInfo.eNum = eNumA[pWDop->pDop->rncEdn];
4493         aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcEdnRef]) );
4494         if( pWDop->nEdn )
4495             aInfo.nFtnOffset = pWDop->nEdn - 1;
4496         rDoc.SetEndNoteInfo( aInfo );
4497     }
4498 
4499     if( pWwFib->lcbPlcfhdd )
4500         pHdFt = new WW8PLCF_HdFt( pTableStream, *pWwFib, *pWDop );
4501 
4502     if (!mbNewDoc)
4503     {
4504         // inserting into an existing document:
4505         // As only complete paragraphs are inserted, the current one
4506         // needs to be splitted - once or even twice.
4507         const SwPosition* pPos = pPaM->GetPoint();
4508 
4509         // split current paragraph to get new paragraph for the insertion
4510         rDoc.SplitNode( *pPos, false );
4511 
4512         // another split, if insertion position was not at the end of the current paragraph.
4513         SwTxtNode const*const pTxtNd = pPos->nNode.GetNode().GetTxtNode();
4514         if ( pTxtNd->GetTxt().Len() )
4515         {
4516             rDoc.SplitNode( *pPos, false );
4517             // move PaM back to the newly empty paragraph
4518             pPaM->Move( fnMoveBackward );
4519         }
4520 
4521         // suppress insertion of tables inside footnotes.
4522         const sal_uLong nNd = pPos->nNode.GetIndex();
4523         bReadNoTbl = ( nNd < rDoc.GetNodes().GetEndOfInserts().GetIndex() &&
4524                        rDoc.GetNodes().GetEndOfInserts().StartOfSectionIndex() < nNd );
4525 
4526     }
4527 
4528     ::SetProgressState(nProgress, mpDocShell);    // Update
4529 
4530     // loop for each glossary entry and add dummy section node
4531     if (pGloss)
4532     {
4533         WW8PLCF aPlc(pTableStream, pWwFib->fcPlcfglsy, pWwFib->lcbPlcfglsy, 0);
4534         if ( aPlc.IsValid() )
4535         {
4536             WW8_CP nStart, nEnd;
4537             void* pDummy;
4538 
4539             for (int i=0; i<pGloss->GetNoStrings(); i++,aPlc++)
4540             {
4541                 SwNodeIndex aIdx( rDoc.GetNodes().GetEndOfContent());
4542                 SwTxtFmtColl* pColl =
4543                     rDoc.GetTxtCollFromPool(RES_POOLCOLL_STANDARD,
4544                     false);
4545                 SwStartNode *pNode =
4546                     rDoc.GetNodes().MakeTextSection(aIdx,
4547                     SwNormalStartNode,pColl);
4548                 pPaM->GetPoint()->nNode = pNode->GetIndex()+1;
4549                 pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(),0);
4550                 aPlc.Get( nStart, nEnd, pDummy );
4551                 ReadText(nStart,nEnd-nStart-1,MAN_MAINTEXT);
4552             }
4553         }
4554     }
4555     else //ordinary case
4556     {
4557         //Modify here for #119405, by easyfan, 2012-05-24
4558         mbOnLoadingMain = true;
4559         //End of modification, by easyfan
4560         ReadText( 0, pWwFib->ccpText, MAN_MAINTEXT );
4561         //Modify here for #119405, by easyfan, 2012-05-24
4562         mbOnLoadingMain = false;
4563         //End of modification, by easyfan
4564     }
4565 
4566     ::SetProgressState(nProgress, mpDocShell);    // Update
4567 
4568     if (pDrawPg && pMSDffManager && pMSDffManager->GetShapeOrders())
4569     {
4570         // Hilfsarray zum Verketten der (statt SdrTxtObj) eingefuegten
4571         // Rahmen
4572         SvxMSDffShapeTxBxSort aTxBxSort;
4573 
4574         // korrekte Z-Order der eingelesen Escher-Objekte sicherstellen
4575         sal_uInt16 nShapeCount = pMSDffManager->GetShapeOrders()->Count();
4576 
4577         for (sal_uInt16 nShapeNum=0; nShapeNum < nShapeCount; nShapeNum++)
4578         {
4579             SvxMSDffShapeOrder *pOrder =
4580                 pMSDffManager->GetShapeOrders()->GetObject(nShapeNum);
4581             // Pointer in neues Sort-Array einfuegen
4582             if (pOrder->nTxBxComp && pOrder->pFly)
4583                 aTxBxSort.Insert(pOrder);
4584         }
4585         // zu verkettende Rahmen jetzt verketten
4586         sal_uInt16 nTxBxCount = aTxBxSort.Count();
4587         if( nTxBxCount )
4588         {
4589             SwFmtChain aChain;
4590             for (sal_uInt16 nTxBxNum=0; nTxBxNum < nTxBxCount; nTxBxNum++)
4591             {
4592                 SvxMSDffShapeOrder *pOrder =
4593                     aTxBxSort.GetObject(nTxBxNum);
4594 
4595                 // Fly-Frame-Formate initialisieren
4596                 SwFlyFrmFmt* pFlyFmt     = pOrder->pFly;
4597                 SwFlyFrmFmt* pNextFlyFmt = 0;
4598                 SwFlyFrmFmt* pPrevFlyFmt = 0;
4599                 // ggfs. Nachfolger ermitteln
4600                 if( 1+nTxBxNum < nTxBxCount )
4601                 {
4602                     SvxMSDffShapeOrder *pNextOrder =
4603                         aTxBxSort.GetObject(nTxBxNum+1);
4604                     if ((0xFFFF0000 & pOrder->nTxBxComp)
4605                            == (0xFFFF0000 & pNextOrder->nTxBxComp))
4606                         pNextFlyFmt = pNextOrder->pFly;
4607                 }
4608                 // ggfs. Vorgaenger ermitteln
4609                 if( nTxBxNum )
4610                 {
4611                     SvxMSDffShapeOrder *pPrevOrder =
4612                         aTxBxSort.GetObject(nTxBxNum-1);
4613                     if ((0xFFFF0000 & pOrder->nTxBxComp)
4614                            == (0xFFFF0000 & pPrevOrder->nTxBxComp))
4615                         pPrevFlyFmt = pPrevOrder->pFly;
4616                 }
4617                 // Falls Nachfolger oder Vorgaenger vorhanden,
4618                 // die Verkettung am Fly-Frame-Format eintragen
4619                 if (pNextFlyFmt || pPrevFlyFmt)
4620                 {
4621                     aChain.SetNext( pNextFlyFmt );
4622                     aChain.SetPrev( pPrevFlyFmt );
4623                     pFlyFmt->SetFmtAttr( aChain );
4624                 }
4625             }
4626 
4627         }
4628 
4629     }
4630 
4631     if (mbNewDoc)
4632     {
4633         if( pWDop->fRevMarking )
4634             eMode |= nsRedlineMode_t::REDLINE_ON;
4635         if( pWDop->fRMView )
4636             eMode |= nsRedlineMode_t::REDLINE_SHOW_DELETE;
4637         if (pStg && !pGloss) /*meaningless for a glossary, cmc*/
4638         {
4639             const SvtFilterOptions* pVBAFlags = SvtFilterOptions::Get();
4640             maTracer.EnterEnvironment(sw::log::eMacros);
4641             SvxImportMSVBasic aVBasic(*mpDocShell, *pStg,
4642                             pVBAFlags->IsLoadWordBasicCode(),
4643                             pVBAFlags->IsLoadWordBasicStorage() );
4644             String s1(CREATE_CONST_ASC("Macros"));
4645             String s2(CREATE_CONST_ASC("VBA"));
4646             int nRet = aVBasic.Import( s1, s2 );
4647             if( 2 & nRet )
4648             {
4649                 maTracer.Log(sw::log::eContainsVisualBasic);
4650                 rDoc.SetContainsMSVBasic(true);
4651             }
4652 
4653             StoreMacroCmds();
4654 
4655             maTracer.LeaveEnvironment(sw::log::eMacros);
4656         }
4657     }
4658 
4659     maInsertedTables.DelAndMakeTblFrms();
4660     maSectionManager.InsertSegments();
4661 
4662     if (pCollA)
4663         delete[] pCollA;
4664 
4665     DELETEZ( pStyles );
4666 
4667     if( pFormImpl )
4668         DeleteFormImpl();
4669     GrafikDtor();
4670     DELETEZ( pMSDffManager );
4671     DELETEZ( pHdFt );
4672     //For i120928,delay the destruct action
4673     //DELETEZ( pLstManager );
4674     DELETEZ( pSBase );
4675     delete pWDop;
4676     DELETEZ( pFonts );
4677     delete mpAtnNames;
4678     DELETEZ( pAuthorInfos );
4679     delete mpSprmParser;
4680     ::EndProgress(mpDocShell);
4681 
4682     pDataStream = 0;
4683     pTableStream = 0;
4684 
4685     DeleteCtrlStk();
4686     mpRedlineStack->closeall(*pPaM->GetPoint());
4687     delete mpRedlineStack;
4688     DeleteAnchorStk();
4689     DeleteRefStks();
4690 
4691     //For i120928,achieve the graphics from the special bookmark with is for graphic bullet
4692     {
4693         std::vector<const SwGrfNode*> vecBulletGrf;
4694         std::vector<SwFrmFmt*> vecFrmFmt;
4695 
4696         IDocumentMarkAccess* const pMarkAccess =
4697             rDoc.getIDocumentMarkAccess();
4698         if ( pMarkAccess )
4699         {
4700             IDocumentMarkAccess::const_iterator_t ppBkmk =
4701                 pMarkAccess->findBookmark( C2U("_PictureBullets") );
4702             if ( ppBkmk != pMarkAccess->getBookmarksEnd()
4703                  && IDocumentMarkAccess::GetType( *(ppBkmk->get()) ) == IDocumentMarkAccess::BOOKMARK )
4704             {
4705                 SwTxtNode* pTxtNode = ppBkmk->get()->GetMarkStart().nNode.GetNode().GetTxtNode();
4706                 if ( pTxtNode )
4707                 {
4708                     const SwpHints* pHints = pTxtNode->GetpSwpHints();
4709                     for( sal_uInt16 nHintPos = 0; pHints && nHintPos < pHints->Count(); ++nHintPos)
4710                     {
4711                         const SwTxtAttr *pHt = (*pHints)[nHintPos];
4712                         const xub_StrLen st = *(pHt->GetStart());
4713                         if( pHt
4714                             && pHt->Which() == RES_TXTATR_FLYCNT
4715                             && (st >= ppBkmk->get()->GetMarkStart().nContent.GetIndex()) )
4716                         {
4717                             SwFrmFmt* pFrmFmt = pHt->GetFlyCnt().GetFrmFmt();
4718                             vecFrmFmt.push_back(pFrmFmt);
4719                             const SwNodeIndex* pNdIdx = pFrmFmt->GetCntnt().GetCntntIdx();
4720                             const SwNodes* pNodesArray = (pNdIdx != NULL)
4721                                                          ? &(pNdIdx->GetNodes())
4722                                                          : NULL;
4723                             const SwGrfNode *pGrf = (pNodesArray != NULL)
4724                                                     ? dynamic_cast<const SwGrfNode*>((*pNodesArray)[pNdIdx->GetIndex() + 1])
4725                                                     : NULL;
4726                             vecBulletGrf.push_back(pGrf);
4727                         }
4728                     }
4729                     // update graphic bullet information
4730                     sal_uInt16 nCount = pLstManager->GetWW8LSTInfoNum();
4731                     for (sal_uInt16 i = 0; i < nCount; ++i)
4732                     {
4733                         SwNumRule* pRule = pLstManager->GetNumRule(i);
4734                         for (sal_uInt16 j = 0; j < MAXLEVEL; ++j)
4735                         {
4736                             SwNumFmt aNumFmt(pRule->Get(j));
4737                             const sal_Int16 nType = aNumFmt.GetNumberingType();
4738                             const sal_uInt16 nGrfBulletCP = aNumFmt.GetGrfBulletCP();
4739                             if ( nType == SVX_NUM_BITMAP
4740                                  && vecBulletGrf.size() > nGrfBulletCP
4741                                  && vecBulletGrf[nGrfBulletCP] != NULL )
4742                             {
4743                                 Graphic aGraphic = vecBulletGrf[nGrfBulletCP]->GetGrf();
4744                                 SvxBrushItem aBrush(aGraphic, GPOS_AREA, SID_ATTR_BRUSH);
4745                                 Font aFont = numfunc::GetDefBulletFont();
4746                                 int nHeight = aFont.GetHeight() * 12;
4747                                 Size aPrefSize( aGraphic.GetPrefSize());
4748                                 if (aPrefSize.Height() * aPrefSize.Width() != 0 )
4749                                 {
4750                                     int nWidth = (nHeight * aPrefSize.Width()) / aPrefSize.Height();
4751                                     Size aSize(nWidth, nHeight);
4752                                     aNumFmt.SetGraphicBrush(&aBrush, &aSize);
4753                                 }
4754                                 else
4755                                 {
4756                                     aNumFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
4757                                     aNumFmt.SetBulletChar(0x2190);
4758                                 }
4759                                 pRule->Set( j, aNumFmt );
4760                             }
4761                         }
4762                     }
4763                     // Remove additional pictures
4764                     for (sal_uInt16 i = 0; i < vecFrmFmt.size(); ++i)
4765                     {
4766                         rDoc.DelLayoutFmt(vecFrmFmt[i]);
4767                     }
4768                 }
4769             }
4770             DELETEZ( pLstManager );
4771         }
4772     }
4773 
4774     UpdateFields();
4775 
4776     // delete the pam before the call for hide all redlines (Bug 73683)
4777     if (mbNewDoc)
4778       rDoc.SetRedlineMode((RedlineMode_t)( eMode ));
4779 
4780     UpdatePageDescs(rDoc, nPageDescOffset);
4781 
4782     delete pPaM, pPaM = 0;
4783     return nErrRet;
4784 }
4785 
SetSubStreams(SvStorageStreamRef & rTableStream,SvStorageStreamRef & rDataStream)4786 sal_uLong SwWW8ImplReader::SetSubStreams(SvStorageStreamRef &rTableStream,
4787     SvStorageStreamRef &rDataStream)
4788 {
4789     sal_uLong nErrRet = 0;
4790     // 6 stands for "6 OR 7",  7 stand for "ONLY 7"
4791     switch (pWwFib->nVersion)
4792     {
4793         case 6:
4794         case 7:
4795             pTableStream = pStrm;
4796             pDataStream = pStrm;
4797             break;
4798         case 8:
4799             if(!pStg)
4800             {
4801                 ASSERT( pStg, "Version 8 muss immer einen Storage haben!" );
4802                 nErrRet = ERR_SWG_READ_ERROR;
4803                 break;
4804             }
4805 
4806             rTableStream = pStg->OpenSotStream( String::CreateFromAscii(
4807                 pWwFib->fWhichTblStm ? SL::a1Table : SL::a0Table),
4808                 STREAM_STD_READ);
4809 
4810             pTableStream = &rTableStream;
4811             pTableStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
4812 
4813             rDataStream = pStg->OpenSotStream(CREATE_CONST_ASC(SL::aData),
4814                 STREAM_STD_READ | STREAM_NOCREATE );
4815 
4816             if (rDataStream.Is() && SVSTREAM_OK == rDataStream->GetError())
4817             {
4818                 pDataStream = &rDataStream;
4819                 pDataStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
4820             }
4821             else
4822                 pDataStream = pStrm;
4823             break;
4824         default:
4825             // Programm-Fehler!
4826             ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
4827             nErrRet = ERR_SWG_READ_ERROR;
4828             break;
4829     }
4830     return nErrRet;
4831 }
4832 
4833 namespace
4834 {
MakeTemp(SvFileStream & rSt)4835     utl::TempFile *MakeTemp(SvFileStream &rSt)
4836     {
4837         utl::TempFile *pT = new utl::TempFile;
4838         pT->EnableKillingFile();
4839         rSt.Open(pT->GetFileName(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE);
4840         return pT;
4841     }
4842 
4843 #define WW_BLOCKSIZE 0x200
4844 
DecryptRC4(msfilter::MSCodec_Std97 & rCtx,SvStream & rIn,SvStream & rOut)4845     void DecryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
4846     {
4847         rIn.Seek(STREAM_SEEK_TO_END);
4848         sal_uLong nLen = rIn.Tell();
4849         rIn.Seek(0);
4850 
4851         sal_uInt8 in[WW_BLOCKSIZE];
4852         for (sal_uLong nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
4853         {
4854             sal_uLong nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI;
4855             rIn.Read(in, nBS);
4856             rCtx.InitCipher(nBlock);
4857             rCtx.Decode(in, nBS, in, nBS);
4858             rOut.Write(in, nBS);
4859         }
4860     }
4861 
DecryptXOR(msfilter::MSCodec_XorWord95 & rCtx,SvStream & rIn,SvStream & rOut)4862     void DecryptXOR(msfilter::MSCodec_XorWord95 &rCtx, SvStream &rIn, SvStream &rOut)
4863     {
4864         sal_uLong nSt = rIn.Tell();
4865         rIn.Seek(STREAM_SEEK_TO_END);
4866         sal_uLong nLen = rIn.Tell();
4867         rIn.Seek(nSt);
4868 
4869         rCtx.InitCipher();
4870         rCtx.Skip(nSt);
4871 
4872         sal_uInt8 in[0x4096];
4873         for (sal_uLong nI = nSt; nI < nLen; nI += 0x4096)
4874         {
4875             sal_uLong nBS = (nLen - nI > 0x4096 ) ? 0x4096 : nLen - nI;
4876             rIn.Read(in, nBS);
4877             rCtx.Decode(in, nBS);
4878             rOut.Write(in, nBS);
4879         }
4880     }
4881 
4882     //moan, copy and paste :-(
QueryPasswordForMedium(SfxMedium & rMedium)4883     String QueryPasswordForMedium(SfxMedium& rMedium)
4884     {
4885         String aPassw;
4886 
4887         using namespace com::sun::star;
4888 
4889         const SfxItemSet* pSet = rMedium.GetItemSet();
4890         const SfxPoolItem *pPasswordItem;
4891 
4892         if(pSet && SFX_ITEM_SET == pSet->GetItemState(SID_PASSWORD, sal_True, &pPasswordItem))
4893             aPassw = ((const SfxStringItem *)pPasswordItem)->GetValue();
4894         else
4895         {
4896             try
4897             {
4898                 uno::Reference< task::XInteractionHandler > xHandler( rMedium.GetInteractionHandler() );
4899                 if( xHandler.is() )
4900                 {
4901                     ::comphelper::DocPasswordRequest* pRequest = new ::comphelper::DocPasswordRequest(
4902                         ::comphelper::DocPasswordRequestType_MS, task::PasswordRequestMode_PASSWORD_ENTER,
4903                         INetURLObject( rMedium.GetOrigURL() ).GetName( INetURLObject::DECODE_WITH_CHARSET ) );
4904                     uno::Reference< task::XInteractionRequest > xRequest( pRequest );
4905 
4906                     xHandler->handle( xRequest );
4907 
4908                     if( pRequest->isPassword() )
4909                         aPassw = pRequest->getPassword();
4910                 }
4911             }
4912             catch( uno::Exception& )
4913             {
4914             }
4915         }
4916 
4917         return aPassw;
4918     }
4919 
InitXorWord95Codec(::msfilter::MSCodec_XorWord95 & rCodec,SfxMedium & rMedium,WW8Fib * pWwFib)4920     uno::Sequence< beans::NamedValue > InitXorWord95Codec( ::msfilter::MSCodec_XorWord95& rCodec, SfxMedium& rMedium, WW8Fib* pWwFib )
4921     {
4922         uno::Sequence< beans::NamedValue > aEncryptionData;
4923         SFX_ITEMSET_ARG( rMedium.GetItemSet(), pEncryptionData, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
4924         if ( pEncryptionData && ( pEncryptionData->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
4925             aEncryptionData.realloc( 0 );
4926 
4927         if ( !aEncryptionData.getLength() )
4928         {
4929             String sUniPassword = QueryPasswordForMedium( rMedium );
4930 
4931             ByteString sPassword(sUniPassword, WW8Fib::GetFIBCharset( pWwFib->chseTables ) );
4932 
4933             xub_StrLen nLen = sPassword.Len();
4934             if( nLen <= 15 )
4935             {
4936                 sal_uInt8 pPassword[16];
4937                 memset( pPassword, 0, sizeof( pPassword ) );
4938 
4939                 for (xub_StrLen nChar = 0; nChar < sPassword.Len(); ++nChar )
4940                     pPassword[nChar] = sPassword.GetChar(nChar);
4941 
4942                 rCodec.InitKey( pPassword );
4943                 aEncryptionData = rCodec.GetEncryptionData();
4944 
4945                 // the export supports RC4 algorithm only, so we have to generate the related EncryptionData as well,
4946                 // so that Save can export the document without asking for a password;
4947                 // as result there will be EncryptionData for both algorithms in the MediaDescriptor
4948                 ::msfilter::MSCodec_Std97 aCodec97;
4949 
4950                 // Generate random number with a seed of time as salt.
4951                 TimeValue aTime;
4952                 osl_getSystemTime( &aTime );
4953                 rtlRandomPool aRandomPool = rtl_random_createPool();
4954                 rtl_random_addBytes ( aRandomPool, &aTime, 8 );
4955 
4956                 sal_uInt8 pDocId[ 16 ];
4957                 rtl_random_getBytes( aRandomPool, pDocId, 16 );
4958 
4959                 rtl_random_destroyPool( aRandomPool );
4960 
4961                 sal_uInt16 pStd97Pass[16];
4962                 memset( pStd97Pass, 0, sizeof( pStd97Pass ) );
4963                 for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
4964                     pStd97Pass[nChar] = sUniPassword.GetChar(nChar);
4965 
4966                 aCodec97.InitKey( pStd97Pass, pDocId );
4967 
4968                 // merge the EncryptionData, there should be no conflicts
4969                 ::comphelper::SequenceAsHashMap aEncryptionHash( aEncryptionData );
4970                 aEncryptionHash.update( ::comphelper::SequenceAsHashMap( aCodec97.GetEncryptionData() ) );
4971                 aEncryptionHash >> aEncryptionData;
4972             }
4973         }
4974 
4975         return aEncryptionData;
4976     }
4977 
InitStd97Codec(::msfilter::MSCodec_Std97 & rCodec,sal_uInt8 pDocId[16],SfxMedium & rMedium)4978     uno::Sequence< beans::NamedValue > InitStd97Codec( ::msfilter::MSCodec_Std97& rCodec, sal_uInt8 pDocId[16], SfxMedium& rMedium )
4979     {
4980         uno::Sequence< beans::NamedValue > aEncryptionData;
4981         SFX_ITEMSET_ARG( rMedium.GetItemSet(), pEncryptionData, SfxUnoAnyItem, SID_ENCRYPTIONDATA, sal_False );
4982         if ( pEncryptionData && ( pEncryptionData->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
4983             aEncryptionData.realloc( 0 );
4984 
4985         if ( !aEncryptionData.getLength() )
4986         {
4987             String sUniPassword = QueryPasswordForMedium( rMedium );
4988 
4989             xub_StrLen nLen = sUniPassword.Len();
4990             if ( nLen <= 15 )
4991             {
4992                 sal_Unicode pPassword[16];
4993                 memset( pPassword, 0, sizeof( pPassword ) );
4994                 for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
4995                     pPassword[nChar] = sUniPassword.GetChar(nChar);
4996 
4997                 rCodec.InitKey( pPassword, pDocId );
4998                 aEncryptionData = rCodec.GetEncryptionData();
4999             }
5000         }
5001 
5002         return aEncryptionData;
5003     }
5004 }
5005 
LoadThroughDecryption(SwPaM & rPaM,WW8Glossary * pGloss)5006 sal_uLong SwWW8ImplReader::LoadThroughDecryption(SwPaM& rPaM ,WW8Glossary *pGloss)
5007 {
5008     sal_uLong nErrRet = 0;
5009     if (pGloss)
5010         pWwFib = pGloss->GetFib();
5011     else
5012         pWwFib = new WW8Fib(*pStrm, nWantedVersion);
5013 
5014     if (pWwFib->nFibError)
5015         nErrRet = ERR_SWG_READ_ERROR;
5016 
5017     SvStorageStreamRef xTableStream, xDataStream;
5018 
5019     if (!nErrRet)
5020         nErrRet = SetSubStreams(xTableStream, xDataStream);
5021 
5022     utl::TempFile *pTempMain = 0;
5023     utl::TempFile *pTempTable = 0;
5024     utl::TempFile *pTempData = 0;
5025     SvFileStream aDecryptMain;
5026     SvFileStream aDecryptTable;
5027     SvFileStream aDecryptData;
5028 
5029     bool bDecrypt = false;
5030     enum {RC4, XOR, Other} eAlgo = Other;
5031     if (pWwFib->fEncrypted && !nErrRet)
5032     {
5033         if (!pGloss)
5034         {
5035             bDecrypt = true;
5036             if (8 != pWwFib->nVersion)
5037                 eAlgo = XOR;
5038             else
5039             {
5040                 if (pWwFib->nKey != 0)
5041                     eAlgo = XOR;
5042                 else
5043                 {
5044                     pTableStream->Seek(0);
5045                     sal_uInt32 nEncType;
5046                     *pTableStream >> nEncType;
5047                     if (nEncType == 0x10001)
5048                         eAlgo = RC4;
5049                 }
5050             }
5051         }
5052     }
5053 
5054     if (bDecrypt)
5055     {
5056         nErrRet = ERRCODE_SVX_WRONGPASS;
5057         SfxMedium* pMedium = mpDocShell->GetMedium();
5058 
5059         if ( pMedium )
5060         {
5061             switch (eAlgo)
5062             {
5063                 default:
5064                     nErrRet = ERRCODE_SVX_READ_FILTER_CRYPT;
5065                     break;
5066                 case XOR:
5067                 {
5068                     msfilter::MSCodec_XorWord95 aCtx;
5069                     uno::Sequence< beans::NamedValue > aEncryptionData = InitXorWord95Codec( aCtx, *pMedium, pWwFib );
5070 
5071                     // if initialization has failed the EncryptionData should be empty
5072                     if ( aEncryptionData.getLength() && aCtx.VerifyKey( pWwFib->nKey, pWwFib->nHash ) )
5073                     {
5074                         nErrRet = 0;
5075                         pTempMain = MakeTemp(aDecryptMain);
5076 
5077                         pStrm->Seek(0);
5078                         size_t nUnencryptedHdr =
5079                             (8 == pWwFib->nVersion) ? 0x44 : 0x34;
5080                         sal_uInt8 *pIn = new sal_uInt8[nUnencryptedHdr];
5081                         pStrm->Read(pIn, nUnencryptedHdr);
5082                         aDecryptMain.Write(pIn, nUnencryptedHdr);
5083                         delete [] pIn;
5084 
5085                         DecryptXOR(aCtx, *pStrm, aDecryptMain);
5086 
5087                         if (!pTableStream || pTableStream == pStrm)
5088                             pTableStream = &aDecryptMain;
5089                         else
5090                         {
5091                             pTempTable = MakeTemp(aDecryptTable);
5092                             DecryptXOR(aCtx, *pTableStream, aDecryptTable);
5093                             pTableStream = &aDecryptTable;
5094                         }
5095 
5096                         if (!pDataStream || pDataStream == pStrm)
5097                             pDataStream = &aDecryptMain;
5098                         else
5099                         {
5100                             pTempData = MakeTemp(aDecryptData);
5101                             DecryptXOR(aCtx, *pDataStream, aDecryptData);
5102                             pDataStream = &aDecryptData;
5103                         }
5104 
5105                         pMedium->GetItemSet()->ClearItem( SID_PASSWORD );
5106                         pMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
5107                     }
5108                 }
5109                 break;
5110                 case RC4:
5111                 {
5112                     msfilter::MSCodec_Std97 aCtx;
5113 
5114                     sal_uInt8 aDocId[ 16 ];
5115                     pTableStream->Read(aDocId, 16);
5116                     sal_uInt8 aSaltData[ 16 ];
5117                     pTableStream->Read(aSaltData, 16);
5118                     sal_uInt8 aSaltHash[ 16 ];
5119                     pTableStream->Read(aSaltHash, 16);
5120 
5121                     // if initialization has failed the EncryptionData should be empty
5122                     uno::Sequence< beans::NamedValue > aEncryptionData = InitStd97Codec( aCtx, aDocId, *pMedium );
5123                     if ( aEncryptionData.getLength() && aCtx.VerifyKey( aSaltData, aSaltHash ) )
5124                     {
5125                         nErrRet = 0;
5126 
5127                         pTempTable = MakeTemp(aDecryptTable);
5128                         DecryptRC4(aCtx, *pTableStream, aDecryptTable);
5129                         pTableStream = &aDecryptTable;
5130 
5131                         pTempMain = MakeTemp(aDecryptMain);
5132                         DecryptRC4(aCtx, *pStrm, aDecryptMain);
5133 
5134                         if (!pDataStream || pDataStream == pStrm)
5135                             pDataStream = &aDecryptMain;
5136                         else
5137                         {
5138                             pTempData = MakeTemp(aDecryptData);
5139                             DecryptRC4(aCtx, *pDataStream, aDecryptData);
5140                             pDataStream = &aDecryptData;
5141                         }
5142 
5143                         pMedium->GetItemSet()->ClearItem( SID_PASSWORD );
5144                         pMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
5145                     }
5146                 }
5147                 break;
5148             }
5149         }
5150 
5151         if (nErrRet == 0)
5152         {
5153             pStrm = &aDecryptMain;
5154 
5155             delete pWwFib;
5156             pWwFib = new WW8Fib(*pStrm, nWantedVersion);
5157             if (pWwFib->nFibError)
5158                 nErrRet = ERR_SWG_READ_ERROR;
5159         }
5160     }
5161 
5162     if (!nErrRet)
5163         nErrRet = CoreLoad(pGloss, *rPaM.GetPoint());
5164 
5165     delete pTempMain;
5166     delete pTempTable;
5167     delete pTempData;
5168 
5169     if (!pGloss)
5170         delete pWwFib;
5171     return nErrRet;
5172 }
5173 
5174 class outlineeq : public std::unary_function<const SwTxtFmtColl*, bool>
5175 {
5176 private:
5177     sal_uInt8 mnNum;
5178 public:
outlineeq(sal_uInt8 nNum)5179     outlineeq(sal_uInt8 nNum) : mnNum(nNum) {}
operator ()(const SwTxtFmtColl * pTest) const5180     bool operator()(const SwTxtFmtColl *pTest) const
5181     {
5182         //return pTest->GetOutlineLevel() == mnNum;	//#outline level,zhaojianwei
5183 		return pTest->IsAssignedToListLevelOfOutlineStyle() && pTest->GetAssignedOutlineStyleLevel() == mnNum;	//<-end,zhaojianwei
5184     }
5185 };
5186 
5187 
SetOutlineStyles()5188 void SwWW8ImplReader::SetOutlineStyles()
5189 {
5190 
5191     // If we are inserted into a document then don't clobber existing outline levels.
5192     sal_uInt16 nOutlineStyleListLevelWithAssignment = 0;
5193     if ( !mbNewDoc )
5194     {
5195         sw::ParaStyles aOutLined( sw::util::GetParaStyles( rDoc ) );
5196         sw::util::SortByAssignedOutlineStyleListLevel( aOutLined );
5197         sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend();
5198         for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter )
5199         {
5200             if ( ( *aIter )->IsAssignedToListLevelOfOutlineStyle() )
5201                 nOutlineStyleListLevelWithAssignment |= 1 << ( *aIter )->GetAssignedOutlineStyleLevel();
5202             else
5203                 break;
5204         }
5205     }
5206 
5207     // Check applied WW8 list styles at WW8 Built-In Heading Styles
5208     // - Choose the list style which occurs most often as the one which provides
5209     //   the list level properties for the Outline Style.
5210     // - Populate temporary list of WW8 Built-In Heading Styles for further iteration
5211     std::vector< SwWW8StyInf* > aWW8BuiltInHeadingStyles;
5212     const SwNumRule* pChosenWW8ListStyle = NULL;
5213     {
5214         std::map< const SwNumRule*, int > aWW8ListStyleCounts;
5215         for ( sal_uInt16 nI = 0; nI < nColls; ++nI )
5216         {
5217             SwWW8StyInf& rSI = pCollA[nI];
5218 
5219             if ( !rSI.IsWW8BuiltInHeadingStyle()
5220                  || !rSI.HasWW8OutlineLevel() )
5221             {
5222                 continue;
5223             }
5224 
5225             aWW8BuiltInHeadingStyles.push_back( &rSI );
5226 
5227             const SwNumRule* pWW8ListStyle = rSI.GetOutlineNumrule();
5228             if ( pWW8ListStyle != NULL )
5229             {
5230                 std::map< const SwNumRule*, int >::iterator aCountIter =
5231                         aWW8ListStyleCounts.find( pWW8ListStyle );
5232                 if ( aCountIter == aWW8ListStyleCounts.end() )
5233                 {
5234                     aWW8ListStyleCounts[pWW8ListStyle] = 1;
5235                 }
5236                 else
5237                 {
5238                     ++(aCountIter->second);
5239                 }
5240             }
5241         }
5242 
5243         int nCurrentMaxCount = 0;
5244         std::map< const SwNumRule*, int >::iterator aCountIterEnd =
5245             aWW8ListStyleCounts.end();
5246         for ( std::map< const SwNumRule*, int >::iterator aIter = aWW8ListStyleCounts.begin();
5247               aIter != aCountIterEnd;
5248               ++aIter )
5249         {
5250             if ( aIter->second > nCurrentMaxCount )
5251             {
5252                 nCurrentMaxCount = aIter->second;
5253                 pChosenWW8ListStyle = aIter->first;
5254             }
5255         }
5256     }
5257 
5258     // - set list level properties of Outline Style - ODF's list style applied by default to headings
5259     // - assign corresponding Heading Paragraph Styles to the Outline Style
5260     // - If a heading Paragraph Styles is not applying the WW8 list style which had been chosen as
5261     //   the one which provides the list level properties for the Outline Style, its assignment to
5262     //   the Outline Style is removed. A potential applied WW8 list style is assigned directly and
5263     //   its default outline level is applied.
5264     SwNumRule aOutlineRule( *rDoc.GetOutlineNumRule() );
5265     bool bAppliedChangedOutlineStyle = false;
5266     std::vector< SwWW8StyInf* >::iterator aStylesIterEnd =
5267         aWW8BuiltInHeadingStyles.end();
5268     for ( std::vector< SwWW8StyInf* >::iterator aStyleIter = aWW8BuiltInHeadingStyles.begin();
5269           aStyleIter != aStylesIterEnd;
5270           ++aStyleIter )
5271     {
5272         SwWW8StyInf* pStyleInf = (*aStyleIter);
5273 
5274         const sal_uInt16 nOutlineStyleListLevelOfWW8BuiltInHeadingStyle = 1 << pStyleInf->mnWW8OutlineLevel;
5275         if ( nOutlineStyleListLevelOfWW8BuiltInHeadingStyle & nOutlineStyleListLevelWithAssignment )
5276         {
5277             continue;
5278         }
5279 
5280         if ( pChosenWW8ListStyle != NULL
5281              && pStyleInf->mnWW8OutlineLevel == pStyleInf->nListLevel )
5282         {
5283             const SwNumFmt& rRule = pChosenWW8ListStyle->Get( pStyleInf->mnWW8OutlineLevel );
5284             aOutlineRule.Set( pStyleInf->mnWW8OutlineLevel, rRule );
5285             bAppliedChangedOutlineStyle = true;
5286         }
5287 
5288         // in case that there are more styles on this level ignore them
5289         nOutlineStyleListLevelWithAssignment |= nOutlineStyleListLevelOfWW8BuiltInHeadingStyle;
5290 
5291         SwTxtFmtColl* pTxtFmtColl = static_cast<SwTxtFmtColl*>(pStyleInf->pFmt);
5292         if ( pStyleInf->GetOutlineNumrule() != pChosenWW8ListStyle
5293              || ( pStyleInf->nListLevel < WW8ListManager::nMaxLevel
5294                   && pStyleInf->mnWW8OutlineLevel != pStyleInf->nListLevel ) )
5295         {
5296             // WW8 Built-In Heading Style does not apply the chosen one.
5297             // --> delete assignment to OutlineStyle, but keep its current outline level
5298             pTxtFmtColl->DeleteAssignmentToListLevelOfOutlineStyle( false );
5299             // Apply existing WW8 list style a normal list style at the Paragraph Style
5300             if ( pStyleInf->GetOutlineNumrule() != NULL )
5301             {
5302                 pTxtFmtColl->SetFmtAttr( SwNumRuleItem( pStyleInf->GetOutlineNumrule()->GetName() ) );
5303             }
5304             // apply default outline level of WW8 Built-in Heading Style
5305             const sal_uInt8 nOutlineLevel =
5306                     SwWW8StyInf::WW8OutlineLevelToOutlinelevel( pStyleInf->mnWW8OutlineLevel );
5307             pTxtFmtColl->SetFmtAttr( SfxUInt16Item( RES_PARATR_OUTLINELEVEL, nOutlineLevel ) );
5308         }
5309         else
5310         {
5311             pTxtFmtColl->AssignToListLevelOfOutlineStyle( pStyleInf->mnWW8OutlineLevel );
5312         }
5313     }
5314 
5315     if ( bAppliedChangedOutlineStyle )
5316     {
5317         rDoc.SetOutlineNumRule(aOutlineRule);
5318     }
5319 }
5320 
GetAnnotationAuthor(sal_uInt16 nIdx)5321 const String* SwWW8ImplReader::GetAnnotationAuthor(sal_uInt16 nIdx)
5322 {
5323     if (!mpAtnNames && pWwFib->lcbGrpStAtnOwners)
5324     {
5325         // Authoren bestimmen: steht im TableStream
5326         mpAtnNames = new ::std::vector<String>;
5327         SvStream& rStrm = *pTableStream;
5328 
5329         long nOldPos = rStrm.Tell();
5330         rStrm.Seek( pWwFib->fcGrpStAtnOwners );
5331 
5332         long nRead = 0, nCount = pWwFib->lcbGrpStAtnOwners;
5333         while (nRead < nCount)
5334         {
5335             if( bVer67 )
5336             {
5337                 mpAtnNames->push_back(WW8ReadPString(rStrm, false));
5338                 nRead += mpAtnNames->rbegin()->Len() + 1;   // Laenge + sal_uInt8 Count
5339             }
5340             else
5341             {
5342                 mpAtnNames->push_back(WW8Read_xstz(rStrm, 0, false));
5343                 // UNICode: doppelte Laenge + sal_uInt16 Count
5344                 nRead += mpAtnNames->rbegin()->Len() * 2 + 2;
5345             }
5346         }
5347         rStrm.Seek( nOldPos );
5348     }
5349 
5350     const String *pRet = 0;
5351     if (mpAtnNames && nIdx < mpAtnNames->size())
5352         pRet = &((*mpAtnNames)[nIdx]);
5353     return pRet;
5354 }
5355 
LoadDoc(SwPaM & rPaM,WW8Glossary * pGloss)5356 sal_uLong SwWW8ImplReader::LoadDoc( SwPaM& rPaM,WW8Glossary *pGloss)
5357 {
5358     sal_uLong nErrRet = 0;
5359 
5360     {
5361         static const sal_Char* aNames[ 13 ] = {
5362             "WinWord/WW", "WinWord/WW8", "WinWord/WWFT",
5363             "WinWord/WWFLX", "WinWord/WWFLY",
5364             "WinWord/WWF",
5365             "WinWord/WWFA0", "WinWord/WWFA1", "WinWord/WWFA2",
5366             "WinWord/WWFB0", "WinWord/WWFB1", "WinWord/WWFB2",
5367             "WinWord/RegardHindiDigits"
5368         };
5369         sal_uInt32 aVal[ 13 ];
5370 
5371         SwFilterOptions aOpt( 13, aNames, aVal );
5372 
5373         nIniFlags = aVal[ 0 ];
5374         nIniFlags1= aVal[ 1 ];
5375         // schiebt Flys um x twips nach rechts o. links
5376         nIniFlyDx = aVal[ 3 ];
5377         nIniFlyDy = aVal[ 4 ];
5378 
5379         nFieldFlags = aVal[ 5 ];
5380         nFieldTagAlways[0] = aVal[ 6 ];
5381         nFieldTagAlways[1] = aVal[ 7 ];
5382         nFieldTagAlways[2] = aVal[ 8 ];
5383         nFieldTagBad[0] = aVal[ 9 ];
5384         nFieldTagBad[1] = aVal[ 10 ];
5385         nFieldTagBad[2] = aVal[ 11 ];
5386         m_bRegardHindiDigits = aVal[ 12 ] > 0;
5387     }
5388 
5389     sal_uInt16 nMagic;
5390     *pStrm >> nMagic;
5391 
5392     // beachte: 6 steht fuer "6 ODER 7",  7 steht fuer "NUR 7"
5393     switch (nWantedVersion)
5394     {
5395         case 6:
5396         case 7:
5397             if (
5398                 (0xa5dc != nMagic && 0xa5db != nMagic) &&
5399                 (nMagic < 0xa697 || nMagic > 0xa699)
5400                )
5401             {
5402                 //JP 06.05.99: teste auf eigenen 97-Fake!
5403                 if (pStg && 0xa5ec == nMagic)
5404                 {
5405                     sal_uLong nCurPos = pStrm->Tell();
5406                     if (pStrm->Seek(nCurPos + 22))
5407                     {
5408                         sal_uInt32 nfcMin;
5409                         *pStrm >> nfcMin;
5410                         if (0x300 != nfcMin)
5411                             nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
5412                     }
5413                     pStrm->Seek( nCurPos );
5414                 }
5415                 else
5416                     nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
5417             }
5418             break;
5419         case 8:
5420             if (0xa5ec != nMagic)
5421                 nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
5422             break;
5423         default:
5424             nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
5425             ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
5426             break;
5427     }
5428 
5429     if (!nErrRet)
5430         nErrRet = LoadThroughDecryption(rPaM ,pGloss);
5431 
5432     rDoc.PropagateOutlineRule();
5433 
5434     return nErrRet;
5435 }
5436 
ImportDOC()5437 extern "C" SAL_DLLPUBLIC_EXPORT Reader* SAL_CALL ImportDOC()
5438 {
5439     return new WW8Reader();
5440 }
5441 
Read(SwDoc & rDoc,const String & rBaseURL,SwPaM & rPam,const String &)5442 sal_uLong WW8Reader::Read(SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & /* FileName */)
5443 {
5444     sal_uInt16 nOldBuffSize = 32768;
5445     bool bNew = !bInsertMode;               // Neues Doc ( kein Einfuegen )
5446 
5447 
5448     SvStorageStreamRef refStrm;         // damit uns keiner den Stream klaut
5449     SvStream* pIn = pStrm;
5450 
5451     sal_uLong nRet = 0;
5452     sal_uInt8 nVersion = 8;
5453 
5454     String sFltName = GetFltName();
5455     if( sFltName.EqualsAscii( "WW6" ) )
5456     {
5457         if (pStrm)
5458             nVersion = 6;
5459         else
5460         {
5461             ASSERT(!this, "WinWord 95 Reader-Read ohne Stream");
5462             nRet = ERR_SWG_READ_ERROR;
5463         }
5464     }
5465     else
5466     {
5467         if( sFltName.EqualsAscii( "CWW6" ) )
5468             nVersion = 6;
5469         else if( sFltName.EqualsAscii( "CWW7" ) )
5470             nVersion = 7;
5471 
5472         if( pStg )
5473         {
5474             nRet = OpenMainStream( refStrm, nOldBuffSize );
5475             pIn = &refStrm;
5476         }
5477         else
5478         {
5479             ASSERT(!this, "WinWord 95/97 Reader-Read ohne Storage");
5480             nRet = ERR_SWG_READ_ERROR;
5481         }
5482     }
5483 
5484     if( !nRet )
5485     {
5486         //JP 18.01.96: Alle Ueberschriften sind normalerweise ohne
5487         //              Kapitelnummer. Darum hier explizit abschalten
5488         //              weil das Default jetzt wieder auf AN ist.
5489         if (bNew)
5490         {
5491             Reader::SetNoOutlineNum( rDoc );
5492             // MIB 27.09.96: Umrandung uns Abstaende aus Frm-Vorlagen entf.
5493             Reader::ResetFrmFmts( rDoc );
5494         }
5495         SwWW8ImplReader* pRdr = new SwWW8ImplReader(nVersion, pStg, pIn, rDoc,
5496             rBaseURL, bNew);
5497         try
5498         {
5499             nRet = pRdr->LoadDoc( rPam );
5500         }
5501         catch( const std::exception& )
5502         {
5503             nRet = ERR_WW8_NO_WW8_FILE_ERR;
5504         }
5505         delete pRdr;
5506 
5507         if( refStrm.Is() )
5508         {
5509             refStrm->SetBufferSize( nOldBuffSize );
5510             refStrm.Clear();
5511         }
5512         else if (pIn)
5513             pIn->ResetError();
5514 
5515     }
5516     return nRet;
5517 }
5518 
GetReaderType()5519 int WW8Reader::GetReaderType()
5520 {
5521     return SW_STORAGE_READER | SW_STREAM_READER;
5522 }
5523 
HasGlossaries() const5524 sal_Bool WW8Reader::HasGlossaries() const
5525 {
5526     return true;
5527 }
5528 
ReadGlossaries(SwTextBlocks & rBlocks,sal_Bool bSaveRelFiles) const5529 sal_Bool WW8Reader::ReadGlossaries(SwTextBlocks& rBlocks, sal_Bool bSaveRelFiles) const
5530 {
5531     bool bRet=false;
5532 
5533     WW8Reader *pThis = const_cast<WW8Reader *>(this);
5534 
5535     sal_uInt16 nOldBuffSize = 32768;
5536     SvStorageStreamRef refStrm;
5537     if (!pThis->OpenMainStream(refStrm, nOldBuffSize))
5538     {
5539         WW8Glossary aGloss( refStrm, 8, pStg );
5540         bRet = aGloss.Load( rBlocks, bSaveRelFiles ? true : false);
5541     }
5542     return bRet ? true : false;
5543 }
5544 
GetOLEStorageName(long nOLEId,String & rStorageName,SvStorageRef & rSrcStorage,uno::Reference<embed::XStorage> & rDestStorage) const5545 sal_Bool SwMSDffManager::GetOLEStorageName(long nOLEId, String& rStorageName,
5546     SvStorageRef& rSrcStorage, uno::Reference < embed::XStorage >& rDestStorage) const
5547 {
5548     bool bRet = false;
5549 
5550     long nPictureId = 0;
5551     if (rReader.pStg)
5552     {
5553         // dann holen wir uns mal ueber den TextBox-PLCF die richtigen
5554         // Char Start-/End-Positionen. In dem Bereich sollte dann
5555         // das EinbettenFeld und die entsprechenden Sprms zu finden
5556         // sein. Wir brauchen hier aber nur das Sprm fuer die Picture Id
5557         long nOldPos = rReader.pStrm->Tell();
5558         {
5559             // #i32596# - consider return value of method
5560             // <rReader.GetTxbxTextSttEndCp(..)>. If it returns false, method
5561             // wasn't successful. Thus, continue in this case.
5562             // Note: Ask MM for initialization of <nStartCp> and <nEndCp>.
5563             // Note: Ask MM about assertions in method <rReader.GetTxbxTextSttEndCp(..)>.
5564             WW8_CP nStartCp, nEndCp;
5565             if ( rReader.GetTxbxTextSttEndCp(nStartCp, nEndCp,
5566                             static_cast<sal_uInt16>((nOLEId >> 16) & 0xFFFF),
5567                             static_cast<sal_uInt16>(nOLEId & 0xFFFF)) )
5568             {
5569                 WW8PLCFxSaveAll aSave;
5570                 memset( &aSave, 0, sizeof( aSave ) );
5571                 rReader.pPlcxMan->SaveAllPLCFx( aSave );
5572 
5573                 nStartCp += rReader.nDrawCpO;
5574                 nEndCp   += rReader.nDrawCpO;
5575                 WW8PLCFx_Cp_FKP* pChp = rReader.pPlcxMan->GetChpPLCF();
5576                 wwSprmParser aSprmParser(rReader.pWwFib->GetFIBVersion());
5577                 while (nStartCp <= nEndCp && !nPictureId)
5578                 {
5579                     WW8PLCFxDesc aDesc;
5580                     pChp->SeekPos( nStartCp );
5581                     pChp->GetSprms( &aDesc );
5582 
5583                     if (aDesc.nSprmsLen && aDesc.pMemPos)   // Attribut(e) vorhanden
5584                     {
5585                         long nLen = aDesc.nSprmsLen;
5586                         const sal_uInt8* pSprm = aDesc.pMemPos;
5587 
5588                         while (nLen >= 2 && !nPictureId)
5589                         {
5590                             sal_uInt16 nId = aSprmParser.GetSprmId(pSprm);
5591                             sal_uInt16 nSL = aSprmParser.GetSprmSize(nId, pSprm);
5592 
5593                             if( nLen < nSL )
5594                                 break;              // nicht mehr genug Bytes uebrig
5595 
5596                             if( 0x6A03 == nId && 0 < nLen )
5597                             {
5598                                 nPictureId = SVBT32ToUInt32(pSprm +
5599                                     aSprmParser.DistanceToData(nId));
5600                                 bRet = true;
5601                             }
5602                             pSprm += nSL;
5603                             nLen -= nSL;
5604                         }
5605                     }
5606                     nStartCp = aDesc.nEndPos;
5607                 }
5608 
5609                 rReader.pPlcxMan->RestoreAllPLCFx( aSave );
5610             }
5611         }
5612         rReader.pStrm->Seek( nOldPos );
5613     }
5614 
5615     if( bRet )
5616     {
5617         rStorageName = '_';
5618         rStorageName += String::CreateFromInt32(nPictureId);
5619         rSrcStorage = rReader.pStg->OpenSotStorage(CREATE_CONST_ASC(
5620             SL::aObjectPool));
5621         if (!rReader.mpDocShell)
5622             bRet=false;
5623         else
5624             rDestStorage = rReader.mpDocShell->GetStorage();
5625     }
5626     return bRet;
5627 }
5628 
ShapeHasText(sal_uLong,sal_uLong) const5629 sal_Bool SwMSDffManager::ShapeHasText(sal_uLong, sal_uLong) const
5630 {
5631     // Zur Zeit des Einlesens einer einzelnen Box, die womoeglich Teil einer
5632     // Gruppe ist, liegen noch nicht genuegend Informationen vor, um
5633     // entscheiden zu koennen, ob wir sie nicht doch als Textfeld benoetigen.
5634     // Also vorsichtshalber mal alle umwandeln:
5635     return true;
5636 }
5637 
InEqualOrHigherApo(int nLvl) const5638 bool SwWW8ImplReader::InEqualOrHigherApo(int nLvl) const
5639 {
5640     if (nLvl)
5641         --nLvl;
5642     // #i60827# - check size of <maApos> to assure that <maApos.begin() + nLvl> can be performed.
5643     if ( sal::static_int_cast< sal_Int32>(nLvl) >= sal::static_int_cast< sal_Int32>(maApos.size()) )
5644     {
5645         return false;
5646     }
5647     mycApoIter aIter = std::find(maApos.begin() + nLvl, maApos.end(), true);
5648     if (aIter != maApos.end())
5649         return true;
5650     else
5651         return false;
5652 }
5653 
InEqualApo(int nLvl) const5654 bool SwWW8ImplReader::InEqualApo(int nLvl) const
5655 {
5656     //If we are in a table, see if an apo was inserted at the level below
5657     //the table.
5658     if (nLvl)
5659         --nLvl;
5660     return maApos[nLvl];
5661 }
5662 
5663 namespace sw
5664 {
5665     namespace hack
5666     {
Position(const SwPosition & rPos)5667         Position::Position(const SwPosition &rPos)
5668             : maPtNode(rPos.nNode), mnPtCntnt(rPos.nContent.GetIndex())
5669         {
5670         }
5671 
Position(const Position & rPos)5672         Position::Position(const Position &rPos)
5673             : maPtNode(rPos.maPtNode), mnPtCntnt(rPos.mnPtCntnt)
5674         {
5675         }
5676 
operator SwPosition() const5677         Position::operator SwPosition() const
5678         {
5679             SwPosition aRet(maPtNode);
5680             aRet.nContent.Assign(maPtNode.GetNode().GetCntntNode(), mnPtCntnt);
5681             return aRet;
5682         }
5683     }
5684 }
5685 
5686 /* vi:set tabstop=4 shiftwidth=4 expandtab: */
5687 
SwMacroInfo()5688 SwMacroInfo::SwMacroInfo() :
5689     SdrObjUserData( SW_DRAWLAYER, SW_UD_IMAPDATA, 0 )
5690 {
5691 }
5692 
~SwMacroInfo()5693 SwMacroInfo::~SwMacroInfo()
5694 {
5695 }
5696 
Clone(SdrObject *) const5697 SdrObjUserData* SwMacroInfo::Clone( SdrObject* /*pObj*/ ) const
5698 {
5699    return new SwMacroInfo( *this );
5700 }
5701 
5702 
5703 
5704