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