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