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