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