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