Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <config_features.h>
21 :
22 : #include <sal/config.h>
23 :
24 : #include <boost/noncopyable.hpp>
25 : #include <boost/unordered_set.hpp>
26 : #include <com/sun/star/embed/ElementModes.hpp>
27 :
28 : #include <i18nlangtag/languagetag.hxx>
29 :
30 : #include <unotools/ucbstreamhelper.hxx>
31 : #include <rtl/random.h>
32 : #include <rtl/ustring.hxx>
33 : #include <rtl/ustrbuf.hxx>
34 :
35 : #include <sfx2/docinf.hxx>
36 : #include <sfx2/request.hxx>
37 : #include <sfx2/frame.hxx>
38 : #include <tools/urlobj.hxx>
39 : #include <unotools/tempfile.hxx>
40 :
41 : #include <comphelper/docpasswordrequest.hxx>
42 : #include <comphelper/string.hxx>
43 :
44 : #include <editeng/brushitem.hxx>
45 : #include <editeng/tstpitem.hxx>
46 : #include <editeng/ulspitem.hxx>
47 : #include <editeng/langitem.hxx>
48 : #include <editeng/opaqitem.hxx>
49 : #include <editeng/charhiddenitem.hxx>
50 : #include <editeng/fontitem.hxx>
51 : #include <svx/unoapi.hxx>
52 : #include <svx/svdoole2.hxx>
53 : #include <svx/svdoashp.hxx>
54 : #include <svx/svxerr.hxx>
55 : #include <filter/msfilter/mscodec.hxx>
56 : #include <svx/svdmodel.hxx>
57 : #include <svx/xflclit.hxx>
58 :
59 : #include <unotools/fltrcfg.hxx>
60 : #include <fmtfld.hxx>
61 : #include <fmturl.hxx>
62 : #include <fmtinfmt.hxx>
63 : #include <reffld.hxx>
64 : #include <fmthdft.hxx>
65 : #include <fmtcntnt.hxx>
66 : #include <fmtcnct.hxx>
67 : #include <fmtanchr.hxx>
68 : #include <fmtpdsc.hxx>
69 : #include <ftninfo.hxx>
70 : #include <fmtftn.hxx>
71 : #include <txtftn.hxx>
72 : #include <ndtxt.hxx>
73 : #include <pagedesc.hxx>
74 : #include <paratr.hxx>
75 : #include <fmtclbl.hxx>
76 : #include <section.hxx>
77 : #include <docsh.hxx>
78 : #include <IDocumentFieldsAccess.hxx>
79 : #include <IDocumentLayoutAccess.hxx>
80 : #include <IDocumentStylePoolAccess.hxx>
81 : #include <IDocumentExternalData.hxx>
82 : #include <docufld.hxx>
83 : #include <swfltopt.hxx>
84 : #include <viewsh.hxx>
85 : #include <shellres.hxx>
86 : #include <mdiexp.hxx>
87 : #include <statstr.hrc>
88 : #include <swerror.h>
89 : #include <swtable.hxx>
90 : #include <fchrfmt.hxx>
91 : #include <charfmt.hxx>
92 : #include <unocrsr.hxx>
93 : #include <IDocumentSettingAccess.hxx>
94 :
95 : #include <fltini.hxx>
96 :
97 : #include "writerwordglue.hxx"
98 :
99 : #include "ndgrf.hxx"
100 : #include <editeng/editids.hrc>
101 : #include <txtflcnt.hxx>
102 : #include <fmtflcnt.hxx>
103 : #include <txatbase.hxx>
104 :
105 : #include "ww8par2.hxx"
106 :
107 : #include <com/sun/star/beans/PropertyAttribute.hpp>
108 : #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
109 : #include <com/sun/star/document/XViewDataSupplier.hpp>
110 : #include <com/sun/star/document/IndexedPropertyValues.hpp>
111 : #include <svl/itemiter.hxx>
112 :
113 : #include <comphelper/processfactory.hxx>
114 : #include <basic/basmgr.hxx>
115 :
116 : #include "ww8toolbar.hxx"
117 : #include <osl/file.hxx>
118 :
119 : #include <breakit.hxx>
120 :
121 : #if OSL_DEBUG_LEVEL > 1
122 : #include <iostream>
123 : #include <dbgoutsw.hxx>
124 : #endif
125 : #include <unotools/localfilehelper.hxx>
126 :
127 : #include <svx/hlnkitem.hxx>
128 : #include "WW8Sttbf.hxx"
129 : #include "WW8FibData.hxx"
130 :
131 : using namespace ::com::sun::star;
132 : using namespace sw::util;
133 : using namespace sw::types;
134 : using namespace nsHdFtFlags;
135 :
136 : #include <com/sun/star/i18n/ScriptType.hpp>
137 : #include <unotools/pathoptions.hxx>
138 : #include <com/sun/star/ucb/SimpleFileAccess.hpp>
139 :
140 : #include <com/sun/star/script/vba/XVBACompatibility.hpp>
141 : #include <comphelper/sequenceashashmap.hxx>
142 : #include <oox/ole/vbaproject.hxx>
143 : #include <oox/ole/olestorage.hxx>
144 :
145 : //#define VT_EMPTY 0
146 : //#define VT_I4 3
147 : //#define VT_LPSTR 30
148 : //#define VT_LPWSTR 31
149 : //#define VT_BLOB 65
150 : //#define VT_TYPEMASK 0xFFF
151 : /** Expands to a pointer behind the last element of a STATIC data array (like STL end()). */
152 : //#define STATIC_TABLE_END( array ) ((array)+STATIC_TABLE_SIZE(array))
153 : /** Expands to the size of a STATIC data array. */
154 : //#define STATIC_TABLE_SIZE( array ) (sizeof(array)/sizeof(*(array)))
155 :
156 2 : SwMacroInfo* GetMacroInfo( SdrObject* pObj, bool bCreate ) // static
157 : {
158 2 : if ( pObj )
159 : {
160 2 : sal_uInt16 nCount = pObj->GetUserDataCount();
161 2 : for( sal_uInt16 i = 0; i < nCount; i++ )
162 : {
163 0 : SdrObjUserData* pData = pObj->GetUserData( i );
164 0 : if( pData && pData->GetInventor() == SW_DRAWLAYER
165 0 : && pData->GetId() == SW_UD_IMAPDATA)
166 : {
167 0 : return dynamic_cast<SwMacroInfo*>(pData);
168 : }
169 : }
170 2 : if ( bCreate )
171 : {
172 2 : SwMacroInfo* pData = new SwMacroInfo;
173 2 : pObj->AppendUserData(pData);
174 2 : return pData;
175 : }
176 : }
177 :
178 0 : return 0;
179 : };
180 :
181 2 : void lclGetAbsPath(OUString& rPath, sal_uInt16 nLevel, SwDocShell* pDocShell)
182 : {
183 2 : OUString aTmpStr;
184 4 : while( nLevel )
185 : {
186 0 : aTmpStr += "../";
187 0 : --nLevel;
188 : }
189 2 : if (!aTmpStr.isEmpty())
190 0 : aTmpStr += rPath;
191 : else
192 2 : aTmpStr = rPath;
193 :
194 2 : if (!aTmpStr.isEmpty())
195 : {
196 2 : bool bWasAbs = false;
197 2 : rPath = pDocShell->GetMedium()->GetURLObject().smartRel2Abs( aTmpStr, bWasAbs ).GetMainURL( INetURLObject::NO_DECODE );
198 : // full path as stored in SvxURLField must be encoded
199 2 : }
200 2 : }
201 :
202 0 : void lclIgnoreString32( SvMemoryStream& rStrm, bool b16Bit )
203 : {
204 0 : sal_uInt32 nChars(0);
205 0 : rStrm.ReadUInt32( nChars );
206 0 : if( b16Bit )
207 0 : nChars *= 2;
208 0 : rStrm.SeekRel( nChars );
209 0 : }
210 :
211 4 : OUString SwWW8ImplReader::ReadRawUniString(SvMemoryStream& rStrm, sal_uInt16 nChars, bool b16Bit)
212 : {
213 : // Fixed-size characters
214 4 : const sal_uInt8 WW8_NUL_C = '\x00'; /// NUL chararcter.
215 4 : const sal_uInt16 WW8_NUL = WW8_NUL_C; /// NUL chararcter (unicode).
216 4 : sal_Unicode mcNulSubst = '\0';
217 :
218 4 : sal_uInt16 nCharsLeft = nChars;
219 4 : sal_Unicode* pcBuffer = new sal_Unicode[ nCharsLeft + 1 ];
220 :
221 4 : sal_Unicode* pcUniChar = pcBuffer;
222 4 : sal_Unicode* pcEndChar = pcBuffer + nCharsLeft;
223 :
224 4 : if( b16Bit )
225 : {
226 : sal_uInt16 nReadChar;
227 16 : for( ; (pcUniChar < pcEndChar); ++pcUniChar )
228 : {
229 14 : rStrm.ReadUInt16( nReadChar );
230 14 : (*pcUniChar) = (nReadChar == WW8_NUL) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar );
231 : }
232 : }
233 : else
234 : {
235 : sal_uInt8 nReadChar;
236 18 : for( ; (pcUniChar < pcEndChar); ++pcUniChar )
237 : {
238 16 : rStrm.ReadUChar( nReadChar ) ;
239 16 : (*pcUniChar) = (nReadChar == WW8_NUL_C) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar );
240 : }
241 : }
242 :
243 4 : *pcEndChar = '\0';
244 4 : OUString aRet(pcBuffer);
245 4 : delete[] pcBuffer;
246 4 : return aRet;
247 : }
248 :
249 4 : void lclAppendString32(OUString& rString, SvMemoryStream& rStrm, sal_uInt32 nChars, bool b16Bit)
250 : {
251 4 : sal_uInt16 nReadChars = ulimit_cast< sal_uInt16 >( nChars );
252 4 : OUString urlStr = SwWW8ImplReader::ReadRawUniString( rStrm, nReadChars, b16Bit );
253 4 : rString += urlStr;
254 4 : }
255 :
256 2 : void lclAppendString32(OUString& rString, SvMemoryStream& rStrm, bool b16Bit)
257 : {
258 2 : sal_uInt32 nValue(0);
259 2 : rStrm.ReadUInt32( nValue );
260 2 : lclAppendString32(rString, rStrm, nValue, b16Bit);
261 2 : }
262 :
263 2 : void SwWW8ImplReader::ReadEmbeddedData( SvMemoryStream& rStrm, SwDocShell* pDocShell, struct HyperLinksTable& hlStr)
264 : {
265 : // (0x01B8) HLINK
266 : // const sal_uInt16 WW8_ID_HLINK = 0x01B8;
267 2 : const sal_uInt32 WW8_HLINK_BODY = 0x00000001; /// Contains file link or URL.
268 2 : const sal_uInt32 WW8_HLINK_ABS = 0x00000002; /// Absolute path.
269 2 : const sal_uInt32 WW8_HLINK_DESCR = 0x00000014; /// Description.
270 2 : const sal_uInt32 WW8_HLINK_MARK = 0x00000008; /// Text mark.
271 2 : const sal_uInt32 WW8_HLINK_FRAME = 0x00000080; /// Target frame.
272 2 : const sal_uInt32 WW8_HLINK_UNC = 0x00000100; /// UNC path.
273 :
274 : //sal_uInt8 maGuidStdLink[ 16 ] ={
275 : // 0xD0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
276 :
277 : sal_uInt8 maGuidUrlMoniker[ 16 ] = {
278 2 : 0xE0, 0xC9, 0xEA, 0x79, 0xF9, 0xBA, 0xCE, 0x11, 0x8C, 0x82, 0x00, 0xAA, 0x00, 0x4B, 0xA9, 0x0B };
279 :
280 : sal_uInt8 maGuidFileMoniker[ 16 ] = {
281 2 : 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 };
282 :
283 : sal_uInt8 aGuid[16];
284 2 : sal_uInt32 nFlags(0);
285 :
286 2 : rStrm.Read(aGuid, 16);
287 2 : rStrm.SeekRel( 4 );
288 2 : rStrm.ReadUInt32( nFlags );
289 :
290 2 : sal_uInt16 nLevel = 0; // counter for level to climb down in path
291 2 : boost::scoped_ptr< OUString > xLongName; // link / file name
292 4 : boost::scoped_ptr< OUString > xShortName; // 8.3-representation of file name
293 4 : boost::scoped_ptr< OUString > xTextMark; // text mark
294 :
295 : // description (ignore)
296 2 : if( ::get_flag( nFlags, WW8_HLINK_DESCR ) )
297 0 : lclIgnoreString32( rStrm, true );
298 :
299 : // target frame
300 2 : if( ::get_flag( nFlags, WW8_HLINK_FRAME ) )
301 : {
302 0 : OUString sFrmName;
303 0 : lclAppendString32(sFrmName, rStrm, true);
304 0 : hlStr.tarFrm = sFrmName;
305 : }
306 :
307 : // UNC path
308 2 : if( ::get_flag( nFlags, WW8_HLINK_UNC ) )
309 : {
310 0 : xLongName.reset( new OUString );
311 0 : lclAppendString32( *xLongName, rStrm, true );
312 0 : lclGetAbsPath( *xLongName, 0 , pDocShell);
313 : }
314 : // file link or URL
315 2 : else if( ::get_flag( nFlags, WW8_HLINK_BODY ) )
316 : {
317 2 : rStrm.Read( aGuid, 16);
318 :
319 2 : if( (memcmp(aGuid, maGuidFileMoniker, 16) == 0) )
320 : {
321 2 : rStrm.ReadUInt16( nLevel );
322 2 : xShortName.reset( new OUString );
323 2 : lclAppendString32( *xShortName,rStrm, false );
324 2 : rStrm.SeekRel( 24 );
325 :
326 2 : sal_uInt32 nStrLen(0);
327 2 : rStrm.ReadUInt32( nStrLen );
328 2 : if( nStrLen )
329 : {
330 2 : nStrLen = 0;
331 2 : rStrm.ReadUInt32( nStrLen );
332 2 : nStrLen /= 2;
333 2 : rStrm.SeekRel( 2 );
334 2 : xLongName.reset( new OUString );
335 2 : lclAppendString32( *xLongName, rStrm,nStrLen, true );
336 2 : lclGetAbsPath( *xLongName, nLevel, pDocShell);
337 : }
338 : else
339 0 : lclGetAbsPath( *xShortName, nLevel, pDocShell);
340 : }
341 0 : else if( (memcmp(aGuid, maGuidUrlMoniker, 16) == 0) )
342 : {
343 0 : sal_uInt32 nStrLen(0);
344 0 : rStrm.ReadUInt32( nStrLen );
345 0 : nStrLen /= 2;
346 0 : xLongName.reset( new OUString );
347 0 : lclAppendString32( *xLongName,rStrm, nStrLen, true );
348 0 : if( !::get_flag( nFlags, WW8_HLINK_ABS ) )
349 0 : lclGetAbsPath( *xLongName, 0 ,pDocShell);
350 : }
351 : else
352 : {
353 : SAL_INFO("sw.ww8", "WW8Hyperlink::ReadEmbeddedData - unknown content GUID");
354 : }
355 : }
356 :
357 : // text mark
358 2 : if( ::get_flag( nFlags, WW8_HLINK_MARK ) )
359 : {
360 0 : xTextMark.reset( new OUString );
361 0 : lclAppendString32( *xTextMark, rStrm, true );
362 : }
363 :
364 2 : if( !xLongName.get() && xShortName.get() )
365 : {
366 0 : xLongName.reset( new OUString );
367 0 : *xLongName = xLongName->concat(*xShortName);
368 : }
369 2 : else if( !xLongName.get() && xTextMark.get() )
370 0 : xLongName.reset( new OUString );
371 :
372 2 : if( xLongName.get() )
373 : {
374 2 : if( xTextMark.get() )
375 : {
376 0 : if (xLongName->isEmpty())
377 0 : *xTextMark = xTextMark->replace('!', '.');
378 0 : *xLongName = xLongName->concat("#");
379 0 : *xLongName = xLongName->concat(*xTextMark);
380 : }
381 2 : hlStr.hLinkAddr = *xLongName;
382 2 : }
383 2 : }
384 :
385 182 : class BasicProjImportHelper
386 : {
387 : SwDocShell& mrDocShell;
388 : uno::Reference< uno::XComponentContext > mxCtx;
389 : public:
390 182 : BasicProjImportHelper( SwDocShell& rShell ) : mrDocShell( rShell )
391 : {
392 182 : mxCtx = comphelper::getProcessComponentContext();
393 182 : }
394 : bool import( const uno::Reference< io::XInputStream >& rxIn );
395 : OUString getProjectName();
396 : };
397 :
398 182 : bool BasicProjImportHelper::import( const uno::Reference< io::XInputStream >& rxIn )
399 : {
400 182 : bool bRet = false;
401 : try
402 : {
403 182 : oox::ole::OleStorage root( mxCtx, rxIn, false );
404 364 : oox::StorageRef vbaStg = root.openSubStorage( "Macros" , false );
405 182 : if ( vbaStg.get() )
406 : {
407 2 : oox::ole::VbaProject aVbaPrj( mxCtx, mrDocShell.GetModel(), OUString("Writer") );
408 2 : bRet = aVbaPrj.importVbaProject( *vbaStg );
409 182 : }
410 : }
411 0 : catch( const uno::Exception& )
412 : {
413 0 : bRet = false;
414 : }
415 182 : return bRet;
416 : }
417 :
418 182 : OUString BasicProjImportHelper::getProjectName()
419 : {
420 182 : OUString sProjName( "Standard" );
421 364 : uno::Reference< beans::XPropertySet > xProps( mrDocShell.GetModel(), uno::UNO_QUERY );
422 182 : if ( xProps.is() )
423 : {
424 : try
425 : {
426 238 : uno::Reference< script::vba::XVBACompatibility > xVBA( xProps->getPropertyValue( "BasicLibraries" ), uno::UNO_QUERY_THROW );
427 126 : sProjName = xVBA->getProjectName();
428 :
429 : }
430 56 : catch( const uno::Exception& )
431 : {
432 : }
433 : }
434 364 : return sProjName;
435 : }
436 :
437 : class Sttb : TBBase, private boost::noncopyable
438 : {
439 16008 : struct SBBItem
440 : {
441 : sal_uInt16 cchData;
442 : OUString data;
443 2484 : SBBItem() : cchData(0){}
444 : };
445 : sal_uInt16 fExtend;
446 : sal_uInt16 cData;
447 : sal_uInt16 cbExtra;
448 :
449 : std::vector< SBBItem > dataItems;
450 :
451 : public:
452 : Sttb();
453 : virtual ~Sttb();
454 : bool Read(SvStream &rS) SAL_OVERRIDE;
455 : #if OSL_DEBUG_LEVEL > 1
456 : virtual void Print( FILE* fp ) SAL_OVERRIDE;
457 : #endif
458 : OUString getStringAtIndex( sal_uInt32 );
459 : };
460 :
461 144 : Sttb::Sttb()
462 : : fExtend(0)
463 : , cData(0)
464 144 : , cbExtra(0)
465 : {
466 144 : }
467 :
468 144 : Sttb::~Sttb()
469 : {
470 144 : }
471 :
472 144 : bool Sttb::Read( SvStream& rS )
473 : {
474 : OSL_TRACE("Sttb::Read() stream pos 0x%x", rS.Tell() );
475 144 : nOffSet = rS.Tell();
476 144 : rS.ReadUInt16( fExtend ).ReadUInt16( cData ).ReadUInt16( cbExtra );
477 144 : if ( cData )
478 : {
479 : //if they are all going to be empty strings, how many could there be
480 140 : const size_t nMaxPossibleRecords = rS.remainingSize() / sizeof(sal_uInt16);
481 140 : if (cData > nMaxPossibleRecords)
482 2 : return false;
483 2622 : for ( sal_Int32 index = 0; index < cData; ++index )
484 : {
485 2484 : SBBItem aItem;
486 2484 : rS.ReadUInt16( aItem.cchData );
487 2484 : aItem.data = read_uInt16s_ToOUString(rS, aItem.cchData);
488 2484 : dataItems.push_back( aItem );
489 2484 : }
490 : }
491 142 : return true;
492 : }
493 :
494 : #if OSL_DEBUG_LEVEL > 1
495 : void Sttb::Print( FILE* fp )
496 : {
497 : fprintf( fp, "[ 0x%" SAL_PRIxUINT32 " ] Sttb - dump\n", nOffSet);
498 : fprintf( fp, " fExtend 0x%x [expected 0xFFFF ]\n", fExtend );
499 : fprintf( fp, " cData no. or string data items %d (0x%x)\n", cData, cData );
500 :
501 : if ( cData )
502 : {
503 : for (sal_uInt16 index = 0; index < cData; ++index)
504 : {
505 : if (index >= dataItems.size())
506 : {
507 : fprintf(fp, " Sttb truncated at entry %d(0x%x)\n", static_cast< int >( index ), static_cast< unsigned int >( index ));
508 : break;
509 : }
510 : fprintf(fp," string dataItem[ %d(0x%x) ] has name %s\n", static_cast< int >( index ), static_cast< unsigned int >( index ), OUStringToOString( dataItems[ index ].data, RTL_TEXTENCODING_UTF8 ).getStr() );
511 : }
512 : }
513 : }
514 : #endif
515 :
516 : OUString
517 144 : Sttb::getStringAtIndex( sal_uInt32 index )
518 : {
519 144 : OUString aRet;
520 144 : if ( index < dataItems.size() )
521 138 : aRet = dataItems[ index ].data;
522 144 : return aRet;
523 :
524 : }
525 :
526 106 : SwMSDffManager::SwMSDffManager( SwWW8ImplReader& rRdr )
527 106 : : SvxMSDffManager(*rRdr.pTableStream, rRdr.GetBaseURL(), rRdr.pWwFib->fcDggInfo,
528 : rRdr.pDataStream, 0, 0, COL_WHITE, 12, rRdr.pStrm),
529 212 : rReader(rRdr), pFallbackStream(0)
530 : {
531 106 : SetSvxMSDffSettings( GetSvxMSDffSettings() );
532 106 : nSvxMSDffOLEConvFlags = SwMSDffManager::GetFilterFlags();
533 106 : }
534 :
535 116 : sal_uInt32 SwMSDffManager::GetFilterFlags()
536 : {
537 116 : sal_uInt32 nFlags(0);
538 116 : const SvtFilterOptions& rOpt = SvtFilterOptions::Get();
539 116 : if (rOpt.IsMathType2Math())
540 116 : nFlags |= OLE_MATHTYPE_2_STARMATH;
541 116 : if (rOpt.IsExcel2Calc())
542 116 : nFlags |= OLE_EXCEL_2_STARCALC;
543 116 : if (rOpt.IsPowerPoint2Impress())
544 116 : nFlags |= OLE_POWERPOINT_2_STARIMPRESS;
545 116 : if (rOpt.IsWinWord2Writer())
546 116 : nFlags |= OLE_WINWORD_2_STARWRITER;
547 116 : return nFlags;
548 : }
549 :
550 : /*
551 : * I would like to override the default OLE importing to add a test
552 : * and conversion of OCX controls from their native OLE type into our
553 : * native nonOLE Form Control Objects.
554 : *
555 : * cmc
556 : */
557 : // #i32596# - consider new parameter <_nCalledByGroup>
558 24 : SdrObject* SwMSDffManager::ImportOLE( long nOLEId,
559 : const Graphic& rGrf,
560 : const Rectangle& rBoundRect,
561 : const Rectangle& rVisArea,
562 : const int _nCalledByGroup,
563 : sal_Int64 nAspect ) const
564 : {
565 : // #i32596# - no import of OLE object, if it's inside a group.
566 : // NOTE: This can be undone, if grouping of Writer fly frames is possible or
567 : // if drawing OLE objects are allowed in Writer.
568 24 : if ( _nCalledByGroup > 0 )
569 : {
570 0 : return 0L;
571 : }
572 :
573 24 : SdrObject* pRet = 0;
574 24 : OUString sStorageName;
575 48 : SotStorageRef xSrcStg;
576 48 : uno::Reference < embed::XStorage > xDstStg;
577 24 : if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg ))
578 : {
579 : SvStorageRef xSrc = xSrcStg->OpenSotStorage( sStorageName,
580 24 : STREAM_READWRITE| STREAM_SHARE_DENYALL );
581 : OSL_ENSURE(rReader.pFormImpl, "No Form Implementation!");
582 48 : ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > xShape;
583 48 : if ( (!(rReader.bIsHeader || rReader.bIsFooter)) &&
584 24 : rReader.pFormImpl->ReadOCXStream(xSrc,&xShape,true))
585 : {
586 2 : pRet = GetSdrObjectFromXShape(xShape);
587 : }
588 : else
589 : {
590 22 : ErrCode nError = ERRCODE_NONE;
591 : pRet = CreateSdrOLEFromStorage( sStorageName, xSrcStg, xDstStg,
592 22 : rGrf, rBoundRect, rVisArea, pStData, nError, nSvxMSDffOLEConvFlags, nAspect );
593 24 : }
594 : }
595 48 : return pRet;
596 : }
597 :
598 50 : void SwMSDffManager::DisableFallbackStream()
599 : {
600 : OSL_ENSURE(!pFallbackStream,
601 : "if you're recursive, you're broken");
602 50 : pFallbackStream = pStData2;
603 50 : aOldEscherBlipCache = aEscherBlipCache;
604 50 : aEscherBlipCache.clear();
605 50 : pStData2 = 0;
606 50 : }
607 :
608 50 : void SwMSDffManager::EnableFallbackStream()
609 : {
610 50 : pStData2 = pFallbackStream;
611 50 : aEscherBlipCache = aOldEscherBlipCache;
612 50 : aOldEscherBlipCache.clear();
613 50 : pFallbackStream = 0;
614 50 : }
615 :
616 4438 : sal_uInt16 SwWW8ImplReader::GetToggleAttrFlags() const
617 : {
618 4438 : return pCtrlStck ? pCtrlStck->GetToggleAttrFlags() : 0;
619 : }
620 :
621 4438 : sal_uInt16 SwWW8ImplReader::GetToggleBiDiAttrFlags() const
622 : {
623 4438 : return pCtrlStck ? pCtrlStck->GetToggleBiDiAttrFlags() : 0;
624 : }
625 :
626 4438 : void SwWW8ImplReader::SetToggleAttrFlags(sal_uInt16 nFlags)
627 : {
628 4438 : if (pCtrlStck)
629 4438 : pCtrlStck->SetToggleAttrFlags(nFlags);
630 4438 : }
631 :
632 4438 : void SwWW8ImplReader::SetToggleBiDiAttrFlags(sal_uInt16 nFlags)
633 : {
634 4438 : if (pCtrlStck)
635 4438 : pCtrlStck->SetToggleBiDiAttrFlags(nFlags);
636 4438 : }
637 :
638 626 : SdrObject* SwMSDffManager::ProcessObj(SvStream& rSt,
639 : DffObjData& rObjData,
640 : void* pData,
641 : Rectangle& rTextRect,
642 : SdrObject* pObj
643 : )
644 : {
645 626 : if( !rTextRect.IsEmpty() )
646 : {
647 626 : SvxMSDffImportData& rImportData = *(SvxMSDffImportData*)pData;
648 626 : SvxMSDffImportRec* pImpRec = new SvxMSDffImportRec;
649 :
650 : // fill Import Record with data
651 626 : pImpRec->nShapeId = rObjData.nShapeId;
652 626 : pImpRec->eShapeType = rObjData.eShapeType;
653 :
654 : rObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt,
655 : DFF_msofbtClientAnchor,
656 626 : SEEK_FROM_CURRENT_AND_RESTART );
657 626 : if( rObjData.bClientAnchor )
658 : ProcessClientAnchor( rSt,
659 200 : maShapeRecords.Current()->nRecLen,
660 400 : pImpRec->pClientAnchorBuffer, pImpRec->nClientAnchorLen );
661 :
662 : rObjData.bClientData = maShapeRecords.SeekToContent( rSt,
663 : DFF_msofbtClientData,
664 626 : SEEK_FROM_CURRENT_AND_RESTART );
665 626 : if( rObjData.bClientData )
666 : ProcessClientData( rSt,
667 540 : maShapeRecords.Current()->nRecLen,
668 1080 : pImpRec->pClientDataBuffer, pImpRec->nClientDataLen );
669 :
670 : // process user (== Winword) defined parameters in 0xF122 record
671 : // #i84783# - set special value to determine, if property is provided or not.
672 626 : pImpRec->nLayoutInTableCell = 0xFFFFFFFF;
673 :
674 626 : if( maShapeRecords.SeekToContent( rSt,
675 : DFF_msofbtUDefProp,
676 626 : SEEK_FROM_CURRENT_AND_RESTART )
677 626 : && maShapeRecords.Current()->nRecLen )
678 : {
679 244 : sal_uInt32 nBytesLeft = maShapeRecords.Current()->nRecLen;
680 : sal_uInt32 nUDData;
681 : sal_uInt16 nPID;
682 20928 : while( 5 < nBytesLeft )
683 : {
684 20440 : rSt.ReadUInt16( nPID );
685 20440 : if ( rSt.GetError() != 0 )
686 0 : break;
687 20440 : rSt.ReadUInt32( nUDData );
688 20440 : switch( nPID )
689 : {
690 94 : case 0x038F: pImpRec->nXAlign = nUDData; break;
691 : case 0x0390:
692 72 : delete pImpRec->pXRelTo;
693 72 : pImpRec->pXRelTo = new sal_uInt32;
694 72 : *(pImpRec->pXRelTo) = nUDData;
695 72 : break;
696 94 : case 0x0391: pImpRec->nYAlign = nUDData; break;
697 : case 0x0392:
698 72 : delete pImpRec->pYRelTo;
699 72 : pImpRec->pYRelTo = new sal_uInt32;
700 72 : *(pImpRec->pYRelTo) = nUDData;
701 72 : break;
702 96 : case 0x03BF: pImpRec->nLayoutInTableCell = nUDData; break;
703 : case 0x0393:
704 : // This seems to correspond to o:hrpct from .docx (even including
705 : // the difference that it's in 0.1% even though the .docx spec
706 : // says it's in 1%).
707 6 : pImpRec->relativeHorizontalWidth = nUDData;
708 6 : break;
709 : case 0x0394:
710 : // And this is really just a guess, but a mere presence of this
711 : // flag makes a horizontal rule be as wide as the page (unless
712 : // overridden by something), so it probably matches o:hr from .docx.
713 8 : pImpRec->isHorizontalRule = true;
714 8 : break;
715 : }
716 20440 : if ( rSt.GetError() != 0 )
717 0 : break;
718 20440 : nBytesLeft -= 6;
719 : }
720 : }
721 :
722 : // Text Frame also Title or Outline
723 626 : sal_uInt32 nTextId = GetPropertyValue( DFF_Prop_lTxid, 0 );
724 626 : if( nTextId )
725 : {
726 148 : SfxItemSet aSet( pSdrModel->GetItemPool() );
727 :
728 : // Originally anything that as a mso_sptTextBox was created as a
729 : // textbox, this was changed to be created as a simple
730 : // rect to keep impress happy. For the rest of us we'd like to turn
731 : // it back into a textbox again.
732 148 : bool bIsSimpleDrawingTextBox = (pImpRec->eShapeType == mso_sptTextBox);
733 148 : if (!bIsSimpleDrawingTextBox)
734 : {
735 : // Either
736 : // a) it's a simple text object or
737 : // b) it's a rectangle with text and square wrapping.
738 : bIsSimpleDrawingTextBox =
739 : (
740 320 : (pImpRec->eShapeType == mso_sptTextSimple) ||
741 : (
742 112 : (pImpRec->eShapeType == mso_sptRectangle)
743 96 : && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() )
744 : )
745 112 : );
746 : }
747 :
748 : // Distance of Textbox to it's surrounding Autoshape
749 148 : sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 91440L);
750 148 : sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 91440L );
751 148 : sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 45720L );
752 148 : sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 45720L );
753 :
754 148 : ScaleEmu( nTextLeft );
755 148 : ScaleEmu( nTextRight );
756 148 : ScaleEmu( nTextTop );
757 148 : ScaleEmu( nTextBottom );
758 :
759 148 : sal_Int32 nTextRotationAngle=0;
760 148 : bool bVerticalText = false;
761 148 : if ( IsProperty( DFF_Prop_txflTextFlow ) )
762 : {
763 : MSO_TextFlow eTextFlow = (MSO_TextFlow)(GetPropertyValue(
764 6 : DFF_Prop_txflTextFlow) & 0xFFFF);
765 6 : switch( eTextFlow )
766 : {
767 : case mso_txflBtoT:
768 0 : nTextRotationAngle = 9000;
769 0 : break;
770 : case mso_txflVertN:
771 : case mso_txflTtoBN:
772 0 : nTextRotationAngle = 27000;
773 0 : break;
774 : case mso_txflTtoBA:
775 0 : bVerticalText = true;
776 0 : break;
777 : case mso_txflHorzA:
778 0 : bVerticalText = true;
779 0 : nTextRotationAngle = 9000;
780 : case mso_txflHorzN:
781 : default :
782 6 : break;
783 : }
784 : }
785 :
786 148 : if (nTextRotationAngle)
787 : {
788 0 : if (nTextRotationAngle == 9000)
789 : {
790 0 : long nWidth = rTextRect.GetWidth();
791 0 : rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight();
792 0 : rTextRect.Bottom() = rTextRect.Top() + nWidth;
793 :
794 0 : sal_Int32 nOldTextLeft = nTextLeft;
795 0 : sal_Int32 nOldTextRight = nTextRight;
796 0 : sal_Int32 nOldTextTop = nTextTop;
797 0 : sal_Int32 nOldTextBottom = nTextBottom;
798 :
799 0 : nTextLeft = nOldTextBottom;
800 0 : nTextRight = nOldTextTop;
801 0 : nTextTop = nOldTextLeft;
802 0 : nTextBottom = nOldTextRight;
803 : }
804 0 : else if (nTextRotationAngle == 27000)
805 : {
806 0 : long nWidth = rTextRect.GetWidth();
807 0 : rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight();
808 0 : rTextRect.Bottom() = rTextRect.Top() + nWidth;
809 :
810 0 : sal_Int32 nOldTextLeft = nTextLeft;
811 0 : sal_Int32 nOldTextRight = nTextRight;
812 0 : sal_Int32 nOldTextTop = nTextTop;
813 0 : sal_Int32 nOldTextBottom = nTextBottom;
814 :
815 0 : nTextLeft = nOldTextTop;
816 0 : nTextRight = nOldTextBottom;
817 0 : nTextTop = nOldTextRight;
818 0 : nTextBottom = nOldTextLeft;
819 : }
820 : }
821 :
822 148 : if (bIsSimpleDrawingTextBox)
823 : {
824 132 : SdrObject::Free( pObj );
825 132 : pObj = new SdrRectObj(OBJ_TEXT, rTextRect);
826 : }
827 :
828 : // The vertical paragraph justification are contained within the
829 : // BoundRect so calculate it here
830 148 : Rectangle aNewRect(rTextRect);
831 148 : aNewRect.Bottom() -= nTextTop + nTextBottom;
832 148 : aNewRect.Right() -= nTextLeft + nTextRight;
833 :
834 : // Only if it's a simple Textbox, Writer can replace the Object
835 : // with a Frame, else
836 148 : if( bIsSimpleDrawingTextBox )
837 : {
838 : ::boost::shared_ptr<SvxMSDffShapeInfo> const pTmpRec(
839 132 : new SvxMSDffShapeInfo(0, pImpRec->nShapeId));
840 :
841 : SvxMSDffShapeInfos_ById::const_iterator const it =
842 132 : GetShapeInfos()->find(pTmpRec);
843 132 : if (it != GetShapeInfos()->end())
844 : {
845 132 : SvxMSDffShapeInfo& rInfo = **it;
846 132 : pImpRec->bReplaceByFly = rInfo.bReplaceByFly;
847 132 : }
848 : }
849 :
850 148 : if( bIsSimpleDrawingTextBox )
851 132 : ApplyAttributes( rSt, aSet, rObjData );
852 :
853 148 : if (GetPropertyValue(DFF_Prop_FitTextToShape) & 2)
854 : {
855 0 : aSet.Put( makeSdrTextAutoGrowHeightItem( true ) );
856 : aSet.Put( makeSdrTextMinFrameHeightItem(
857 0 : aNewRect.Bottom() - aNewRect.Top() ) );
858 : aSet.Put( makeSdrTextMinFrameWidthItem(
859 0 : aNewRect.Right() - aNewRect.Left() ) );
860 : }
861 : else
862 : {
863 148 : aSet.Put( makeSdrTextAutoGrowHeightItem( false ) );
864 148 : aSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
865 : }
866 :
867 148 : switch ( (MSO_WrapMode)
868 148 : GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) )
869 : {
870 : case mso_wrapNone :
871 0 : aSet.Put( makeSdrTextAutoGrowWidthItem( true ) );
872 0 : pImpRec->bAutoWidth = true;
873 0 : break;
874 : case mso_wrapByPoints :
875 0 : aSet.Put( makeSdrTextContourFrameItem( true ) );
876 0 : break;
877 : default:
878 : ;
879 : }
880 :
881 : // Set distances on Textbox's margins
882 148 : aSet.Put( makeSdrTextLeftDistItem( nTextLeft ) );
883 148 : aSet.Put( makeSdrTextRightDistItem( nTextRight ) );
884 148 : aSet.Put( makeSdrTextUpperDistItem( nTextTop ) );
885 148 : aSet.Put( makeSdrTextLowerDistItem( nTextBottom ) );
886 148 : pImpRec->nDxTextLeft = nTextLeft;
887 148 : pImpRec->nDyTextTop = nTextTop;
888 148 : pImpRec->nDxTextRight = nTextRight;
889 148 : pImpRec->nDyTextBottom = nTextBottom;
890 :
891 : // Taking the correct default (which is mso_anchorTop)
892 : MSO_Anchor eTextAnchor =
893 148 : (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop );
894 :
895 : SdrTextVertAdjust eTVA = bVerticalText
896 : ? SDRTEXTVERTADJUST_BLOCK
897 148 : : SDRTEXTVERTADJUST_CENTER;
898 : SdrTextHorzAdjust eTHA = bVerticalText
899 : ? SDRTEXTHORZADJUST_CENTER
900 148 : : SDRTEXTHORZADJUST_BLOCK;
901 :
902 148 : switch( eTextAnchor )
903 : {
904 : case mso_anchorTop:
905 : {
906 132 : if ( bVerticalText )
907 0 : eTHA = SDRTEXTHORZADJUST_RIGHT;
908 : else
909 132 : eTVA = SDRTEXTVERTADJUST_TOP;
910 : }
911 132 : break;
912 : case mso_anchorTopCentered:
913 : {
914 0 : if ( bVerticalText )
915 0 : eTHA = SDRTEXTHORZADJUST_RIGHT;
916 : else
917 0 : eTVA = SDRTEXTVERTADJUST_TOP;
918 : }
919 0 : break;
920 : case mso_anchorMiddle:
921 16 : break;
922 : case mso_anchorMiddleCentered:
923 0 : break;
924 : case mso_anchorBottom:
925 : {
926 0 : if ( bVerticalText )
927 0 : eTHA = SDRTEXTHORZADJUST_LEFT;
928 : else
929 0 : eTVA = SDRTEXTVERTADJUST_BOTTOM;
930 : }
931 0 : break;
932 : case mso_anchorBottomCentered:
933 : {
934 0 : if ( bVerticalText )
935 0 : eTHA = SDRTEXTHORZADJUST_LEFT;
936 : else
937 0 : eTVA = SDRTEXTVERTADJUST_BOTTOM;
938 : }
939 0 : break;
940 : default:
941 : ;
942 : }
943 :
944 148 : aSet.Put( SdrTextVertAdjustItem( eTVA ) );
945 148 : aSet.Put( SdrTextHorzAdjustItem( eTHA ) );
946 :
947 148 : if (pObj != NULL)
948 : {
949 148 : pObj->SetMergedItemSet(aSet);
950 148 : pObj->SetModel(pSdrModel);
951 :
952 148 : if (bVerticalText)
953 : {
954 0 : SdrTextObj *pTextObj = dynamic_cast< SdrTextObj* >(pObj);
955 0 : if (pTextObj)
956 0 : pTextObj->SetVerticalWriting(true);
957 : }
958 :
959 148 : if ( bIsSimpleDrawingTextBox )
960 : {
961 132 : if ( nTextRotationAngle )
962 : {
963 0 : long nMinWH = rTextRect.GetWidth() < rTextRect.GetHeight() ?
964 0 : rTextRect.GetWidth() : rTextRect.GetHeight();
965 0 : nMinWH /= 2;
966 0 : Point aPivot(rTextRect.TopLeft());
967 0 : aPivot.X() += nMinWH;
968 0 : aPivot.Y() += nMinWH;
969 0 : double a = nTextRotationAngle * nPi180;
970 0 : pObj->NbcRotate(aPivot, nTextRotationAngle, sin(a), cos(a));
971 : }
972 : }
973 :
974 148 : if ( ( ( rObjData.nSpFlags & SP_FFLIPV ) || mnFix16Angle || nTextRotationAngle ) && dynamic_cast< SdrObjCustomShape* >( pObj ) )
975 : {
976 0 : SdrObjCustomShape* pCustomShape = dynamic_cast< SdrObjCustomShape* >( pObj );
977 0 : if (pCustomShape)
978 : {
979 0 : double fExtraTextRotation = 0.0;
980 0 : if ( mnFix16Angle && !( GetPropertyValue( DFF_Prop_FitTextToShape ) & 4 ) )
981 : { // text is already rotated, we have to take back the object rotation if DFF_Prop_RotateText is false
982 0 : fExtraTextRotation = -mnFix16Angle;
983 : }
984 0 : if ( rObjData.nSpFlags & SP_FFLIPV ) // sj: in ppt the text is flipped, whereas in word the text
985 : { // remains unchanged, so we have to take back the flipping here
986 0 : fExtraTextRotation += 18000.0; // because our core will flip text if the shape is flipped.
987 : }
988 0 : fExtraTextRotation += nTextRotationAngle;
989 0 : if ( !::basegfx::fTools::equalZero( fExtraTextRotation ) )
990 : {
991 0 : fExtraTextRotation /= 100.0;
992 0 : SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
993 0 : const OUString sTextRotateAngle( "TextRotateAngle" );
994 0 : com::sun::star::beans::PropertyValue aPropVal;
995 0 : aPropVal.Name = sTextRotateAngle;
996 0 : aPropVal.Value <<= fExtraTextRotation;
997 0 : aGeometryItem.SetPropertyValue( aPropVal );
998 0 : pCustomShape->SetMergedItem( aGeometryItem );
999 : }
1000 : }
1001 : }
1002 148 : else if ( mnFix16Angle )
1003 : {
1004 : // rotate text with shape ?
1005 0 : double a = mnFix16Angle * nPi180;
1006 0 : pObj->NbcRotate( rObjData.aBoundRect.Center(), mnFix16Angle,
1007 0 : sin( a ), cos( a ) );
1008 : }
1009 148 : }
1010 : }
1011 478 : else if( !pObj )
1012 : {
1013 : // simple rectangular objects are ignored by ImportObj() :-(
1014 : // this is OK for Draw but not for Calc and Writer
1015 : // cause here these objects have a default border
1016 4 : pObj = new SdrRectObj(rTextRect);
1017 4 : pObj->SetModel( pSdrModel );
1018 4 : SfxItemSet aSet( pSdrModel->GetItemPool() );
1019 4 : ApplyAttributes( rSt, aSet, rObjData );
1020 :
1021 4 : const SfxPoolItem* pPoolItem=NULL;
1022 : SfxItemState eState = aSet.GetItemState( XATTR_FILLCOLOR,
1023 4 : false, &pPoolItem );
1024 4 : if( SfxItemState::DEFAULT == eState )
1025 : aSet.Put( XFillColorItem( OUString(),
1026 0 : Color( mnDefaultColor ) ) );
1027 4 : pObj->SetMergedItemSet(aSet);
1028 : }
1029 :
1030 : // Means that fBehindDocument is set
1031 626 : if (GetPropertyValue(DFF_Prop_fPrint) & 0x20)
1032 0 : pImpRec->bDrawHell = true;
1033 : else
1034 626 : pImpRec->bDrawHell = false;
1035 626 : if (GetPropertyValue(DFF_Prop_fPrint) & 0x02)
1036 0 : pImpRec->bHidden = true;
1037 626 : pImpRec->nNextShapeId = GetPropertyValue( DFF_Prop_hspNext, 0 );
1038 :
1039 626 : if ( nTextId )
1040 : {
1041 148 : pImpRec->aTextId.nTxBxS = (sal_uInt16)( nTextId >> 16 );
1042 148 : pImpRec->aTextId.nSequence = (sal_uInt16)nTextId;
1043 : }
1044 :
1045 : pImpRec->nDxWrapDistLeft = GetPropertyValue(
1046 626 : DFF_Prop_dxWrapDistLeft, 114935L ) / 635L;
1047 : pImpRec->nDyWrapDistTop = GetPropertyValue(
1048 626 : DFF_Prop_dyWrapDistTop, 0 ) / 635L;
1049 : pImpRec->nDxWrapDistRight = GetPropertyValue(
1050 626 : DFF_Prop_dxWrapDistRight, 114935L ) / 635L;
1051 : pImpRec->nDyWrapDistBottom = GetPropertyValue(
1052 626 : DFF_Prop_dyWrapDistBottom, 0 ) / 635L;
1053 : // 16.16 fraction times total image width or height, as appropriate.
1054 :
1055 626 : if (SeekToContent(DFF_Prop_pWrapPolygonVertices, rSt))
1056 : {
1057 0 : delete pImpRec->pWrapPolygon;
1058 0 : pImpRec->pWrapPolygon = NULL;
1059 :
1060 0 : sal_uInt16 nNumElemVert(0), nNumElemMemVert(0), nElemSizeVert(0);
1061 0 : rSt.ReadUInt16( nNumElemVert ).ReadUInt16( nNumElemMemVert ).ReadUInt16( nElemSizeVert );
1062 0 : bool bOk = false;
1063 0 : if (nNumElemVert && ((nElemSizeVert == 8) || (nElemSizeVert == 4)))
1064 : {
1065 : //check if there is enough data in the file to make the
1066 : //record sane
1067 0 : bOk = rSt.remainingSize() / nElemSizeVert >= nNumElemVert;
1068 : }
1069 0 : if (bOk)
1070 : {
1071 0 : pImpRec->pWrapPolygon = new Polygon(nNumElemVert);
1072 0 : for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
1073 : {
1074 0 : sal_Int32 nX(0), nY(0);
1075 0 : if (nElemSizeVert == 8)
1076 0 : rSt.ReadInt32( nX ).ReadInt32( nY );
1077 : else
1078 : {
1079 0 : sal_Int16 nSmallX(0), nSmallY(0);
1080 0 : rSt.ReadInt16( nSmallX ).ReadInt16( nSmallY );
1081 0 : nX = nSmallX;
1082 0 : nY = nSmallY;
1083 : }
1084 0 : (*(pImpRec->pWrapPolygon))[i].X() = nX;
1085 0 : (*(pImpRec->pWrapPolygon))[i].Y() = nY;
1086 : }
1087 : }
1088 : }
1089 :
1090 : pImpRec->nCropFromTop = GetPropertyValue(
1091 626 : DFF_Prop_cropFromTop, 0 );
1092 : pImpRec->nCropFromBottom = GetPropertyValue(
1093 626 : DFF_Prop_cropFromBottom, 0 );
1094 : pImpRec->nCropFromLeft = GetPropertyValue(
1095 626 : DFF_Prop_cropFromLeft, 0 );
1096 : pImpRec->nCropFromRight = GetPropertyValue(
1097 626 : DFF_Prop_cropFromRight, 0 );
1098 :
1099 626 : sal_uInt32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash );
1100 :
1101 778 : if ( !IsHardAttribute( DFF_Prop_fLine ) &&
1102 152 : pImpRec->eShapeType == mso_sptPictureFrame )
1103 : {
1104 0 : nLineFlags &= ~0x08;
1105 : }
1106 :
1107 626 : pImpRec->eLineStyle = (nLineFlags & 8)
1108 : ? (MSO_LineStyle)GetPropertyValue(
1109 : DFF_Prop_lineStyle,
1110 422 : mso_lineSimple )
1111 1048 : : (MSO_LineStyle)USHRT_MAX;
1112 : pImpRec->eLineDashing = (MSO_LineDashing)GetPropertyValue(
1113 626 : DFF_Prop_lineDashing, mso_lineSolid );
1114 :
1115 626 : pImpRec->nFlags = rObjData.nSpFlags;
1116 :
1117 626 : if( pImpRec->nShapeId )
1118 : {
1119 : // Complement Import Record List
1120 624 : pImpRec->pObj = pObj;
1121 624 : rImportData.aRecords.insert( pImpRec );
1122 :
1123 : // Complement entry in Z Order List with a pointer to this Object
1124 : // Only store objects which are not deep inside the tree
1125 624 : if( ( rObjData.nCalledByGroup == 0 )
1126 398 : ||
1127 398 : ( (rObjData.nSpFlags & SP_FGROUP)
1128 30 : && (rObjData.nCalledByGroup < 2) )
1129 : )
1130 : StoreShapeOrder( pImpRec->nShapeId,
1131 256 : ( ( (sal_uLong)pImpRec->aTextId.nTxBxS ) << 16 )
1132 512 : + pImpRec->aTextId.nSequence, pObj );
1133 : }
1134 : else
1135 2 : delete pImpRec;
1136 : }
1137 :
1138 626 : sal_uInt32 nBufferSize = GetPropertyValue( DFF_Prop_pihlShape );
1139 626 : if( (0 < nBufferSize) && (nBufferSize <= 0xFFFF) && SeekToContent( DFF_Prop_pihlShape, rSt ) )
1140 : {
1141 2 : SvMemoryStream aMemStream;
1142 4 : struct HyperLinksTable hlStr;
1143 : sal_uInt16 mnRawRecId,mnRawRecSize;
1144 2 : aMemStream.WriteUInt16( 0 ).WriteUInt16( nBufferSize );
1145 :
1146 : // copy from DFF stream to memory stream
1147 4 : ::std::vector< sal_uInt8 > aBuffer( nBufferSize );
1148 2 : sal_uInt8* pnData = &aBuffer.front();
1149 : sal_uInt8 mnStreamSize;
1150 2 : if( pnData && rSt.Read( pnData, nBufferSize ) == nBufferSize )
1151 : {
1152 2 : aMemStream.Write( pnData, nBufferSize );
1153 2 : aMemStream.Seek( STREAM_SEEK_TO_END );
1154 2 : mnStreamSize = aMemStream.Tell();
1155 2 : aMemStream.Seek( STREAM_SEEK_TO_BEGIN );
1156 2 : bool bRet = 4 <= mnStreamSize;
1157 2 : if( bRet )
1158 2 : aMemStream.ReadUInt16( mnRawRecId ).ReadUInt16( mnRawRecSize );
1159 2 : SwDocShell* pDocShell = rReader.mpDocShell;
1160 2 : if(pDocShell)
1161 : {
1162 2 : SwWW8ImplReader::ReadEmbeddedData( aMemStream, pDocShell, hlStr);
1163 : }
1164 : }
1165 :
1166 2 : if (pObj && !hlStr.hLinkAddr.isEmpty())
1167 : {
1168 2 : SwMacroInfo* pInfo = GetMacroInfo( pObj, true );
1169 2 : if( pInfo )
1170 : {
1171 2 : pInfo->SetShapeId( rObjData.nShapeId );
1172 2 : pInfo->SetHlink( hlStr.hLinkAddr );
1173 2 : if (!hlStr.tarFrm.isEmpty())
1174 0 : pInfo->SetTarFrm( hlStr.tarFrm );
1175 2 : OUString aNameStr = GetPropertyString( DFF_Prop_wzName, rSt );
1176 2 : if (!aNameStr.isEmpty())
1177 0 : pInfo->SetName( aNameStr );
1178 : }
1179 2 : }
1180 : }
1181 :
1182 626 : return pObj;
1183 : }
1184 :
1185 : /**
1186 : * Special FastSave - Attributes
1187 : */
1188 0 : void SwWW8ImplReader::Read_StyleCode( sal_uInt16, const sal_uInt8* pData, short nLen )
1189 : {
1190 0 : if (nLen < 0)
1191 : {
1192 0 : bCpxStyle = false;
1193 0 : return;
1194 : }
1195 0 : sal_uInt16 nColl = 0;
1196 0 : if (pWwFib->GetFIBVersion() <= ww::eWW2)
1197 0 : nColl = *pData;
1198 : else
1199 0 : nColl = SVBT16ToShort(pData);
1200 0 : if (nColl < vColl.size())
1201 : {
1202 0 : SetTxtFmtCollAndListLevel( *pPaM, vColl[nColl] );
1203 0 : bCpxStyle = true;
1204 : }
1205 : }
1206 :
1207 : /**
1208 : * Read_Majority is for Majority (103) and Majority50 (108)
1209 : */
1210 0 : void SwWW8ImplReader::Read_Majority( sal_uInt16, const sal_uInt8* , short )
1211 : {
1212 0 : }
1213 :
1214 : /**
1215 : * Stack
1216 : */
1217 52372 : void SwWW8FltControlStack::NewAttr(const SwPosition& rPos,
1218 : const SfxPoolItem& rAttr)
1219 : {
1220 : OSL_ENSURE(RES_TXTATR_FIELD != rAttr.Which(), "probably don't want to put"
1221 : "fields into the control stack");
1222 : OSL_ENSURE(RES_TXTATR_INPUTFIELD != rAttr.Which(), "probably don't want to put"
1223 : "input fields into the control stack");
1224 : OSL_ENSURE(RES_TXTATR_ANNOTATION != rAttr.Which(), "probably don't want to put"
1225 : "annotations into the control stack");
1226 : OSL_ENSURE(RES_FLTR_REDLINE != rAttr.Which(), "probably don't want to put"
1227 : "redlines into the control stack");
1228 52372 : SwFltControlStack::NewAttr(rPos, rAttr);
1229 52372 : }
1230 :
1231 104362 : SwFltStackEntry* SwWW8FltControlStack::SetAttr(const SwPosition& rPos, sal_uInt16 nAttrId,
1232 : bool bTstEnde, long nHand, bool )
1233 : {
1234 104362 : SwFltStackEntry *pRet = NULL;
1235 : // Doing a textbox, and using the control stack only as a temporary
1236 : // collection point for properties which will are not to be set into
1237 : // the real document
1238 104362 : if (rReader.pPlcxMan && rReader.pPlcxMan->GetDoingDrawTextBox())
1239 : {
1240 2690 : size_t nCnt = size();
1241 12712 : for (size_t i=0; i < nCnt; ++i)
1242 : {
1243 10022 : SwFltStackEntry& rEntry = (*this)[i];
1244 10022 : if (nAttrId == rEntry.pAttr->Which())
1245 : {
1246 808 : DeleteAndDestroy(i--);
1247 808 : --nCnt;
1248 : }
1249 : }
1250 : }
1251 : else // Normal case, set the attribute into the document
1252 101672 : pRet = SwFltControlStack::SetAttr(rPos, nAttrId, bTstEnde, nHand);
1253 104362 : return pRet;
1254 : }
1255 :
1256 0 : long GetListFirstLineIndent(const SwNumFmt &rFmt)
1257 : {
1258 : OSL_ENSURE( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
1259 : "<GetListFirstLineIndent> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
1260 :
1261 0 : SvxAdjust eAdj = rFmt.GetNumAdjust();
1262 : long nReverseListIndented;
1263 0 : if (eAdj == SVX_ADJUST_RIGHT)
1264 0 : nReverseListIndented = -rFmt.GetCharTextDistance();
1265 0 : else if (eAdj == SVX_ADJUST_CENTER)
1266 0 : nReverseListIndented = rFmt.GetFirstLineOffset()/2;
1267 : else
1268 0 : nReverseListIndented = rFmt.GetFirstLineOffset();
1269 0 : return nReverseListIndented;
1270 : }
1271 :
1272 0 : static long lcl_GetTrueMargin(const SvxLRSpaceItem &rLR, const SwNumFmt &rFmt,
1273 : long &rFirstLinePos)
1274 : {
1275 : OSL_ENSURE( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
1276 : "<lcl_GetTrueMargin> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
1277 :
1278 0 : const long nBodyIndent = rLR.GetTxtLeft();
1279 0 : const long nFirstLineDiff = rLR.GetTxtFirstLineOfst();
1280 0 : rFirstLinePos = nBodyIndent + nFirstLineDiff;
1281 :
1282 0 : const long nPseudoListBodyIndent = rFmt.GetAbsLSpace();
1283 0 : const long nReverseListIndented = GetListFirstLineIndent(rFmt);
1284 0 : long nExtraListIndent = nPseudoListBodyIndent + nReverseListIndented;
1285 :
1286 0 : return nExtraListIndent > 0 ? nExtraListIndent : 0;
1287 : }
1288 :
1289 : // #i103711#
1290 : // #i105414#
1291 184 : void SyncIndentWithList( SvxLRSpaceItem &rLR,
1292 : const SwNumFmt &rFmt,
1293 : const bool bFirstLineOfstSet,
1294 : const bool bLeftIndentSet )
1295 : {
1296 184 : if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1297 : {
1298 : long nWantedFirstLinePos;
1299 0 : long nExtraListIndent = lcl_GetTrueMargin(rLR, rFmt, nWantedFirstLinePos);
1300 0 : rLR.SetTxtLeft(nWantedFirstLinePos - nExtraListIndent);
1301 0 : rLR.SetTxtFirstLineOfst(0);
1302 : }
1303 184 : else if ( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT )
1304 : {
1305 280 : if ( !bFirstLineOfstSet && bLeftIndentSet &&
1306 96 : rFmt.GetFirstLineIndent() != 0 )
1307 : {
1308 0 : rLR.SetTxtFirstLineOfst( rFmt.GetFirstLineIndent() );
1309 : }
1310 184 : else if ( bFirstLineOfstSet && !bLeftIndentSet &&
1311 0 : rFmt.GetIndentAt() != 0 )
1312 : {
1313 0 : rLR.SetTxtLeft( rFmt.GetIndentAt() );
1314 : }
1315 184 : else if (!bFirstLineOfstSet && !bLeftIndentSet )
1316 : {
1317 10 : if ( rFmt.GetFirstLineIndent() != 0 )
1318 : {
1319 10 : rLR.SetTxtFirstLineOfst( rFmt.GetFirstLineIndent() );
1320 : }
1321 10 : if ( rFmt.GetIndentAt() != 0 )
1322 : {
1323 10 : rLR.SetTxtLeft( rFmt.GetIndentAt() );
1324 : }
1325 : }
1326 : }
1327 184 : }
1328 :
1329 2204 : const SwNumFmt* SwWW8FltControlStack::GetNumFmtFromStack(const SwPosition &rPos,
1330 : const SwTxtNode &rTxtNode)
1331 : {
1332 2204 : const SwNumFmt *pRet = 0;
1333 2204 : const SfxPoolItem *pItem = GetStackAttr(rPos, RES_FLTR_NUMRULE);
1334 2204 : if (pItem && rTxtNode.GetNumRule())
1335 : {
1336 0 : if (rTxtNode.IsCountedInList())
1337 : {
1338 0 : OUString sName(((SfxStringItem*)pItem)->GetValue());
1339 0 : const SwNumRule *pRule = pDoc->FindNumRulePtr(sName);
1340 0 : if (pRule)
1341 0 : pRet = GetNumFmtFromSwNumRuleLevel(*pRule, rTxtNode.GetActualListLevel());
1342 : }
1343 : }
1344 2204 : return pRet;
1345 : }
1346 :
1347 101360 : sal_Int32 SwWW8FltControlStack::GetCurrAttrCP() const
1348 : {
1349 101360 : return rReader.GetCurrAttrCP();
1350 : }
1351 :
1352 45148 : bool SwWW8FltControlStack::IsParaEndInCPs(sal_Int32 nStart,sal_Int32 nEnd,bool bSdOD) const
1353 : {
1354 45148 : return rReader.IsParaEndInCPs(nStart,nEnd,bSdOD);
1355 : }
1356 :
1357 : /**
1358 : * Clear the para end position recorded in reader intermittently
1359 : * for the least impact on loading performance.
1360 : */
1361 274 : void SwWW8FltControlStack::ClearParaEndPosition()
1362 : {
1363 274 : if ( !empty() )
1364 274 : return;
1365 :
1366 274 : rReader.ClearParaEndPosition();
1367 : }
1368 :
1369 412 : bool SwWW8FltControlStack::CheckSdOD(sal_Int32 nStart,sal_Int32 nEnd)
1370 : {
1371 412 : return rReader.IsParaEndInCPs(nStart,nEnd);
1372 : }
1373 :
1374 48 : void SwWW8ReferencedFltEndStack::SetAttrInDoc( const SwPosition& rTmpPos,
1375 : SwFltStackEntry& rEntry )
1376 : {
1377 48 : switch( rEntry.pAttr->Which() )
1378 : {
1379 : case RES_FLTR_BOOKMARK:
1380 : {
1381 : // suppress insertion of bookmark, which is recognized as an internal bookmark used for table-of-content
1382 : // and which is not referenced.
1383 48 : bool bInsertBookmarkIntoDoc = true;
1384 :
1385 48 : SwFltBookmark* pFltBookmark = dynamic_cast<SwFltBookmark*>(rEntry.pAttr);
1386 48 : if ( pFltBookmark != 0 && pFltBookmark->IsTOCBookmark() )
1387 : {
1388 0 : const OUString& rName = pFltBookmark->GetName();
1389 0 : ::std::set< OUString, SwWW8::ltstr >::const_iterator aResult = aReferencedTOCBookmarks.find(rName);
1390 0 : if ( aResult == aReferencedTOCBookmarks.end() )
1391 : {
1392 0 : bInsertBookmarkIntoDoc = false;
1393 : }
1394 : }
1395 48 : if ( bInsertBookmarkIntoDoc )
1396 : {
1397 48 : SwFltEndStack::SetAttrInDoc( rTmpPos, rEntry );
1398 : }
1399 48 : break;
1400 : }
1401 : default:
1402 0 : SwFltEndStack::SetAttrInDoc( rTmpPos, rEntry );
1403 0 : break;
1404 : }
1405 :
1406 48 : }
1407 :
1408 48504 : void SwWW8FltControlStack::SetAttrInDoc(const SwPosition& rTmpPos,
1409 : SwFltStackEntry& rEntry)
1410 : {
1411 48504 : switch (rEntry.pAttr->Which())
1412 : {
1413 : case RES_LR_SPACE:
1414 : {
1415 : /*
1416 : Loop over the affected nodes and
1417 : a) convert the word style absolute indent to indent relative
1418 : to any numbering indent active on the nodes
1419 : b) adjust the writer style tabstops relative to the old
1420 : paragraph indent to be relative to the new paragraph indent
1421 : */
1422 : using namespace sw::util;
1423 3342 : SwPaM aRegion(rTmpPos);
1424 3342 : if (rEntry.MakeRegion(pDoc, aRegion, false))
1425 : {
1426 2204 : SvxLRSpaceItem aNewLR( *(SvxLRSpaceItem*)rEntry.pAttr );
1427 2204 : sal_uLong nStart = aRegion.Start()->nNode.GetIndex();
1428 2204 : sal_uLong nEnd = aRegion.End()->nNode.GetIndex();
1429 4408 : for(; nStart <= nEnd; ++nStart)
1430 : {
1431 2204 : SwNode* pNode = pDoc->GetNodes()[ nStart ];
1432 2204 : if (!pNode || !pNode->IsTxtNode())
1433 210 : continue;
1434 :
1435 2204 : SwCntntNode* pNd = (SwCntntNode*)pNode;
1436 2204 : SvxLRSpaceItem aOldLR = (const SvxLRSpaceItem&)pNd->GetAttr(RES_LR_SPACE);
1437 :
1438 2204 : SwTxtNode *pTxtNode = (SwTxtNode*)pNode;
1439 :
1440 2204 : const SwNumFmt *pNum = 0;
1441 2204 : pNum = GetNumFmtFromStack( *aRegion.GetPoint(), *pTxtNode );
1442 2204 : if (!pNum)
1443 : {
1444 2204 : pNum = GetNumFmtFromTxtNode(*pTxtNode);
1445 : }
1446 :
1447 2204 : if ( pNum )
1448 : {
1449 : // #i103711#
1450 : const bool bFirstLineIndentSet =
1451 368 : ( rReader.maTxtNodesHavingFirstLineOfstSet.end() !=
1452 552 : rReader.maTxtNodesHavingFirstLineOfstSet.find( pNode ) );
1453 : // #i105414#
1454 : const bool bLeftIndentSet =
1455 368 : ( rReader.maTxtNodesHavingLeftIndentSet.end() !=
1456 552 : rReader.maTxtNodesHavingLeftIndentSet.find( pNode ) );
1457 : SyncIndentWithList( aNewLR, *pNum,
1458 : bFirstLineIndentSet,
1459 184 : bLeftIndentSet );
1460 : }
1461 :
1462 2204 : if (aNewLR == aOldLR)
1463 210 : continue;
1464 :
1465 1994 : pNd->SetAttr(aNewLR);
1466 :
1467 4198 : }
1468 3342 : }
1469 : }
1470 3342 : break;
1471 :
1472 : case RES_TXTATR_FIELD:
1473 : OSL_ENSURE(false, "What is a field doing in the control stack,"
1474 : "probably should have been in the endstack");
1475 0 : break;
1476 :
1477 : case RES_TXTATR_ANNOTATION:
1478 : OSL_ENSURE(false, "What is a annotation doing in the control stack,"
1479 : "probably should have been in the endstack");
1480 0 : break;
1481 :
1482 : case RES_TXTATR_INPUTFIELD:
1483 : OSL_ENSURE(false, "What is a input field doing in the control stack,"
1484 : "probably should have been in the endstack");
1485 0 : break;
1486 :
1487 : case RES_TXTATR_INETFMT:
1488 : {
1489 14 : SwPaM aRegion(rTmpPos);
1490 14 : if (rEntry.MakeRegion(pDoc, aRegion, false))
1491 : {
1492 : SwFrmFmt *pFrm;
1493 : // If we have just one single inline graphic then
1494 : // don't insert a field for the single frame, set
1495 : // the frames hyperlink field attribute directly.
1496 14 : if (0 != (pFrm = rReader.ContainsSingleInlineGraphic(aRegion)))
1497 : {
1498 : const SwFmtINetFmt *pAttr = (const SwFmtINetFmt *)
1499 0 : rEntry.pAttr;
1500 0 : SwFmtURL aURL;
1501 0 : aURL.SetURL(pAttr->GetValue(), false);
1502 0 : aURL.SetTargetFrameName(pAttr->GetTargetFrame());
1503 0 : pFrm->SetFmtAttr(aURL);
1504 : }
1505 : else
1506 : {
1507 14 : pDoc->getIDocumentContentOperations().InsertPoolItem(aRegion, *rEntry.pAttr, 0);
1508 : }
1509 14 : }
1510 : }
1511 14 : break;
1512 : default:
1513 45148 : SwFltControlStack::SetAttrInDoc(rTmpPos, rEntry);
1514 45148 : break;
1515 : }
1516 48504 : }
1517 :
1518 34850 : const SfxPoolItem* SwWW8FltControlStack::GetFmtAttr(const SwPosition& rPos,
1519 : sal_uInt16 nWhich)
1520 : {
1521 34850 : const SfxPoolItem *pItem = GetStackAttr(rPos, nWhich);
1522 34850 : if (!pItem)
1523 : {
1524 26832 : SwCntntNode const*const pNd = rPos.nNode.GetNode().GetCntntNode();
1525 26832 : if (!pNd)
1526 0 : pItem = &pDoc->GetAttrPool().GetDefaultItem(nWhich);
1527 : else
1528 : {
1529 : /*
1530 : If we're hunting for the indent on a paragraph and need to use the
1531 : parent style indent, then return the indent in msword format, and
1532 : not writer format, because that's the style that the filter works
1533 : in (naturally)
1534 : */
1535 26832 : if (nWhich == RES_LR_SPACE)
1536 : {
1537 1790 : SfxItemState eState = SfxItemState::DEFAULT;
1538 1790 : if (const SfxItemSet *pSet = pNd->GetpSwAttrSet())
1539 634 : eState = pSet->GetItemState(RES_LR_SPACE, false);
1540 1790 : if (eState != SfxItemState::SET && rReader.nAktColl < rReader.vColl.size())
1541 1790 : pItem = &(rReader.vColl[rReader.nAktColl].maWordLR);
1542 : }
1543 :
1544 : /*
1545 : If we're hunting for a character property, try and exact position
1546 : within the text node for lookup
1547 : */
1548 26832 : if (pNd->IsTxtNode())
1549 : {
1550 26832 : const sal_Int32 nPos = rPos.nContent.GetIndex();
1551 26832 : SfxItemSet aSet(pDoc->GetAttrPool(), nWhich, nWhich);
1552 26832 : if (static_cast<const SwTxtNode*>(pNd)->GetAttr(aSet, nPos, nPos))
1553 18632 : pItem = aSet.GetItem(nWhich);
1554 : }
1555 :
1556 26832 : if (!pItem)
1557 6724 : pItem = &pNd->GetAttr(nWhich);
1558 : }
1559 : }
1560 34850 : return pItem;
1561 : }
1562 :
1563 40202 : const SfxPoolItem* SwWW8FltControlStack::GetStackAttr(const SwPosition& rPos,
1564 : sal_uInt16 nWhich)
1565 : {
1566 40202 : SwFltPosition aFltPos(rPos);
1567 :
1568 40202 : size_t nSize = size();
1569 760676 : while (nSize)
1570 : {
1571 689768 : const SwFltStackEntry& rEntry = (*this)[ --nSize ];
1572 689768 : if (rEntry.pAttr->Which() == nWhich)
1573 : {
1574 54456 : if ( (rEntry.bOpen) ||
1575 : (
1576 35464 : (rEntry.m_aMkPos.m_nNode <= aFltPos.m_nNode) &&
1577 34608 : (rEntry.m_aPtPos.m_nNode >= aFltPos.m_nNode) &&
1578 33726 : (rEntry.m_aMkPos.m_nCntnt <= aFltPos.m_nCntnt) &&
1579 16850 : (rEntry.m_aPtPos.m_nCntnt > aFltPos.m_nCntnt)
1580 : )
1581 : )
1582 : /*
1583 : * e.g. half-open range [0-3) so asking for properties at 3
1584 : * means props that end at 3 are not included
1585 : */
1586 : {
1587 9496 : return rEntry.pAttr;
1588 : }
1589 : }
1590 : }
1591 30706 : return 0;
1592 : }
1593 :
1594 0 : bool SwWW8FltRefStack::IsFtnEdnBkmField(
1595 : const SwFmtFld& rFmtFld,
1596 : sal_uInt16& rBkmNo)
1597 : {
1598 0 : const SwField* pFld = rFmtFld.GetField();
1599 : sal_uInt16 nSubType;
1600 0 : if(pFld && (RES_GETREFFLD == pFld->Which())
1601 0 : && ((REF_FOOTNOTE == (nSubType = pFld->GetSubType())) || (REF_ENDNOTE == nSubType))
1602 0 : && !((SwGetRefField*)pFld)->GetSetRefName().isEmpty())
1603 : {
1604 0 : const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1605 : IDocumentMarkAccess::const_iterator_t ppBkmk =
1606 0 : pMarkAccess->findMark( ((SwGetRefField*)pFld)->GetSetRefName() );
1607 0 : if(ppBkmk != pMarkAccess->getAllMarksEnd())
1608 : {
1609 : // find Sequence No of corresponding Foot-/Endnote
1610 0 : rBkmNo = ppBkmk - pMarkAccess->getAllMarksBegin();
1611 0 : return true;
1612 : }
1613 : }
1614 0 : return false;
1615 : }
1616 :
1617 0 : void SwWW8FltRefStack::SetAttrInDoc(const SwPosition& rTmpPos,
1618 : SwFltStackEntry& rEntry)
1619 : {
1620 0 : switch (rEntry.pAttr->Which())
1621 : {
1622 : /*
1623 : Look up these in our lists of bookmarks that were changed to
1624 : variables, and replace the ref field with a var field, otherwise
1625 : do normal (?) strange stuff
1626 : */
1627 : case RES_TXTATR_FIELD:
1628 : case RES_TXTATR_ANNOTATION:
1629 : case RES_TXTATR_INPUTFIELD:
1630 : {
1631 0 : SwNodeIndex aIdx(rEntry.m_aMkPos.m_nNode, 1);
1632 0 : SwPaM aPaM(aIdx, rEntry.m_aMkPos.m_nCntnt);
1633 :
1634 0 : SwFmtFld& rFmtFld = *(SwFmtFld*)rEntry.pAttr;
1635 0 : SwField* pFld = rFmtFld.GetField();
1636 :
1637 0 : if (!RefToVar(pFld, rEntry))
1638 : {
1639 : sal_uInt16 nBkmNo;
1640 0 : if( IsFtnEdnBkmField(rFmtFld, nBkmNo) )
1641 : {
1642 0 : ::sw::mark::IMark const * const pMark = (pDoc->getIDocumentMarkAccess()->getAllMarksBegin() + nBkmNo)->get();
1643 :
1644 0 : const SwPosition& rBkMrkPos = pMark->GetMarkPos();
1645 :
1646 0 : SwTxtNode* pTxt = rBkMrkPos.nNode.GetNode().GetTxtNode();
1647 0 : if( pTxt && rBkMrkPos.nContent.GetIndex() )
1648 : {
1649 : SwTxtAttr* const pFtn = pTxt->GetTxtAttrForCharAt(
1650 0 : rBkMrkPos.nContent.GetIndex()-1, RES_TXTATR_FTN );
1651 0 : if( pFtn )
1652 : {
1653 0 : sal_uInt16 nRefNo = ((SwTxtFtn*)pFtn)->GetSeqRefNo();
1654 :
1655 0 : ((SwGetRefField*)pFld)->SetSeqNo( nRefNo );
1656 :
1657 0 : if( pFtn->GetFtn().IsEndNote() )
1658 0 : ((SwGetRefField*)pFld)->SetSubType(REF_ENDNOTE);
1659 : }
1660 : }
1661 : }
1662 : }
1663 :
1664 0 : pDoc->getIDocumentContentOperations().InsertPoolItem(aPaM, *rEntry.pAttr, 0);
1665 0 : MoveAttrs(*aPaM.GetPoint());
1666 : }
1667 0 : break;
1668 : case RES_FLTR_TOX:
1669 0 : SwFltEndStack::SetAttrInDoc(rTmpPos, rEntry);
1670 0 : break;
1671 : default:
1672 : case RES_FLTR_BOOKMARK:
1673 : OSL_ENSURE(false, "EndStck used with non field, not what we want");
1674 0 : SwFltEndStack::SetAttrInDoc(rTmpPos, rEntry);
1675 0 : break;
1676 : }
1677 0 : }
1678 :
1679 : /*
1680 : For styles we will do our tabstop arithmetic in word style and adjust them to
1681 : writer style after all the styles have been finished and the dust settles as
1682 : to what affects what.
1683 :
1684 : For explicit attributes we turn the adjusted writer tabstops back into 0 based
1685 : word indexes and we'll turn them back into writer indexes when setting them
1686 : into the document. If explicit left indent exist which affects them, then this
1687 : is handled when the explicit left indent is set into the document
1688 : */
1689 984 : void SwWW8ImplReader::Read_Tab(sal_uInt16 , const sal_uInt8* pData, short nLen)
1690 : {
1691 984 : if (nLen < 0)
1692 : {
1693 388 : pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_TABSTOP);
1694 1372 : return;
1695 : }
1696 :
1697 596 : sal_uInt8 nDel = (nLen > 0) ? pData[0] : 0;
1698 596 : const sal_uInt8* pDel = pData + 1; // Del - Array
1699 :
1700 596 : sal_uInt8 nIns = (nLen > nDel*2+1) ? pData[nDel*2+1] : 0;
1701 596 : const sal_uInt8* pIns = pData + 2*nDel + 2; // Ins - Array
1702 :
1703 596 : short nRequiredLength = 2 + 2*nDel + 2*nIns + 1*nIns;
1704 596 : if (nRequiredLength > nLen)
1705 : {
1706 : // would require more data than available to describe!
1707 : // discard invalid record
1708 0 : nIns = 0;
1709 0 : nDel = 0;
1710 : }
1711 :
1712 596 : WW8_TBD* pTyp = (WW8_TBD*)(pData + 2*nDel + 2*nIns + 2); // Type Array
1713 :
1714 596 : SvxTabStopItem aAttr(0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP);
1715 :
1716 596 : const SwTxtFmtColl* pSty = 0;
1717 : sal_uInt16 nTabBase;
1718 596 : if (pAktColl && nAktColl < vColl.size()) // StyleDef
1719 : {
1720 208 : nTabBase = vColl[nAktColl].nBase;
1721 208 : if (nTabBase < vColl.size()) // Based On
1722 194 : pSty = (const SwTxtFmtColl*)vColl[nTabBase].pFmt;
1723 : }
1724 : else
1725 : { // Text
1726 388 : nTabBase = nAktColl;
1727 388 : if (nAktColl < vColl.size())
1728 388 : pSty = (const SwTxtFmtColl*)vColl[nAktColl].pFmt;
1729 : //TODO: figure out else here
1730 : }
1731 :
1732 596 : bool bFound = false;
1733 1192 : ::boost::unordered_set<size_t> aLoopWatch;
1734 1892 : while (pSty && !bFound)
1735 : {
1736 : const SfxPoolItem* pTabs;
1737 700 : bFound = pSty->GetAttrSet().GetItemState(RES_PARATR_TABSTOP, false,
1738 700 : &pTabs) == SfxItemState::SET;
1739 700 : if( bFound )
1740 74 : aAttr = *((const SvxTabStopItem*)pTabs);
1741 : else
1742 : {
1743 626 : sal_uInt16 nOldTabBase = nTabBase;
1744 : // If based on another
1745 626 : if (nTabBase < vColl.size())
1746 626 : nTabBase = vColl[nTabBase].nBase;
1747 :
1748 626 : if (
1749 798 : nTabBase < vColl.size() &&
1750 798 : nOldTabBase != nTabBase &&
1751 : nTabBase != ww::stiNil
1752 : )
1753 : {
1754 : // #i61789: Stop searching when next style is the same as the
1755 : // current one (prevent loop)
1756 172 : aLoopWatch.insert(reinterpret_cast<size_t>(pSty));
1757 172 : if (nTabBase < vColl.size())
1758 172 : pSty = (const SwTxtFmtColl*)vColl[nTabBase].pFmt;
1759 : //TODO figure out the else branch
1760 :
1761 172 : if (aLoopWatch.find(reinterpret_cast<size_t>(pSty)) !=
1762 : aLoopWatch.end())
1763 0 : pSty = 0;
1764 : }
1765 : else
1766 454 : pSty = 0; // Give up on the search
1767 : }
1768 : }
1769 :
1770 596 : SvxTabStop aTabStop;
1771 932 : for (short i=0; i < nDel; ++i)
1772 : {
1773 336 : sal_uInt16 nPos = aAttr.GetPos(SVBT16ToShort(pDel + i*2));
1774 336 : if( nPos != SVX_TAB_NOTFOUND )
1775 116 : aAttr.Remove( nPos, 1 );
1776 : }
1777 :
1778 1862 : for (short i=0; i < nIns; ++i)
1779 : {
1780 1266 : short nPos = SVBT16ToShort(pIns + i*2);
1781 1266 : aTabStop.GetTabPos() = nPos;
1782 1266 : switch( pTyp[i].aBits1 & 0x7 ) // pTyp[i].jc
1783 : {
1784 : case 0:
1785 658 : aTabStop.GetAdjustment() = SVX_TAB_ADJUST_LEFT;
1786 658 : break;
1787 : case 1:
1788 204 : aTabStop.GetAdjustment() = SVX_TAB_ADJUST_CENTER;
1789 204 : break;
1790 : case 2:
1791 286 : aTabStop.GetAdjustment() = SVX_TAB_ADJUST_RIGHT;
1792 286 : break;
1793 : case 3:
1794 0 : aTabStop.GetAdjustment() = SVX_TAB_ADJUST_DECIMAL;
1795 0 : break;
1796 : case 4:
1797 0 : continue; // Ignore Bar
1798 : }
1799 :
1800 1266 : switch( pTyp[i].aBits1 >> 3 & 0x7 )
1801 : {
1802 : case 0:
1803 1242 : aTabStop.GetFill() = ' ';
1804 1242 : break;
1805 : case 1:
1806 24 : aTabStop.GetFill() = '.';
1807 24 : break;
1808 : case 2:
1809 0 : aTabStop.GetFill() = '-';
1810 0 : break;
1811 : case 3:
1812 : case 4:
1813 0 : aTabStop.GetFill() = '_';
1814 0 : break;
1815 : }
1816 :
1817 1266 : sal_uInt16 nPos2 = aAttr.GetPos( nPos );
1818 1266 : if (nPos2 != SVX_TAB_NOTFOUND)
1819 0 : aAttr.Remove(nPos2, 1); // Or else Insert() refuses
1820 1266 : aAttr.Insert(aTabStop);
1821 : }
1822 :
1823 596 : if (nIns || nDel)
1824 596 : NewAttr(aAttr);
1825 : else
1826 : {
1827 : // Here we have a tab definition which inserts no extra tabs, or deletes
1828 : // no existing tabs. An older version of writer is probably the creater
1829 : // of the document :-( . So if we are importing a style we can just
1830 : // ignore it. But if we are importing into text we cannot as during
1831 : // text SwWW8ImplReader::Read_Tab is called at the begin and end of
1832 : // the range the attrib affects, and ignoring it would upset the
1833 : // balance
1834 0 : if (!pAktColl) // not importing into a style
1835 : {
1836 : using namespace sw::util;
1837 : SvxTabStopItem aOrig = pSty ?
1838 0 : ItemGet<SvxTabStopItem>(*pSty, RES_PARATR_TABSTOP) :
1839 0 : DefaultItemGet<SvxTabStopItem>(rDoc, RES_PARATR_TABSTOP);
1840 0 : NewAttr(aOrig);
1841 : }
1842 596 : }
1843 : }
1844 :
1845 : /**
1846 : * DOP
1847 : */
1848 186 : void SwWW8ImplReader::ImportDop()
1849 : {
1850 : // correct the LastPrinted date in DocumentProperties
1851 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1852 186 : mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
1853 : uno::Reference<document::XDocumentProperties> xDocuProps(
1854 372 : xDPS->getDocumentProperties());
1855 : OSL_ENSURE(xDocuProps.is(), "DocumentProperties is null");
1856 186 : if (xDocuProps.is())
1857 : {
1858 : DateTime aLastPrinted(
1859 186 : msfilter::util::DTTM2DateTime(pWDop->dttmLastPrint));
1860 186 : ::util::DateTime uDT(aLastPrinted.GetNanoSec(),
1861 372 : aLastPrinted.GetSec(), aLastPrinted.GetMin(),
1862 372 : aLastPrinted.GetHour(), aLastPrinted.GetDay(),
1863 1116 : aLastPrinted.GetMonth(), aLastPrinted.GetYear(), false);
1864 186 : xDocuProps->setPrintDate(uDT);
1865 : }
1866 :
1867 : // COMPATIBILITY FLAGS START
1868 :
1869 : // #i78951# - remember the unknown compatibility options
1870 : // so as to export them out
1871 186 : rDoc.getIDocumentSettingAccess().Setn32DummyCompatibilityOptions1( pWDop->GetCompatibilityOptions());
1872 186 : rDoc.getIDocumentSettingAccess().Setn32DummyCompatibilityOptions2( pWDop->GetCompatibilityOptions2());
1873 :
1874 : // The distance between two paragraphs is the sum of the bottom distance of
1875 : // the first paragraph and the top distance of the second one
1876 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::PARA_SPACE_MAX, pWDop->fDontUseHTMLAutoSpacing);
1877 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES, true );
1878 : // move tabs on alignment
1879 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::TAB_COMPAT, true);
1880 : // #i24363# tab stops relative to indent
1881 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT, false);
1882 :
1883 : // Import Default Tabs
1884 186 : long nDefTabSiz = pWDop->dxaTab;
1885 186 : if( nDefTabSiz < 56 )
1886 2 : nDefTabSiz = 709;
1887 :
1888 : // We want exactly one DefaultTab
1889 372 : SvxTabStopItem aNewTab( 1, sal_uInt16(nDefTabSiz), SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
1890 186 : ((SvxTabStop&)aNewTab[0]).GetAdjustment() = SVX_TAB_ADJUST_DEFAULT;
1891 :
1892 186 : rDoc.GetAttrPool().SetPoolDefaultItem( aNewTab );
1893 :
1894 : // Import zoom factor
1895 186 : if (pWDop->wScaleSaved)
1896 : {
1897 182 : uno::Sequence<beans::PropertyValue> aViewProps(3);
1898 182 : aViewProps[0].Name = "ZoomFactor";
1899 182 : aViewProps[0].Value <<= sal_Int16(pWDop->wScaleSaved);
1900 182 : aViewProps[1].Name = "VisibleBottom";
1901 182 : aViewProps[1].Value <<= sal_Int32(0);
1902 182 : aViewProps[2].Name = "ZoomType";
1903 182 : aViewProps[2].Value <<= sal_Int16(0);
1904 :
1905 364 : uno::Reference< uno::XComponentContext > xComponentContext(comphelper::getProcessComponentContext());
1906 364 : uno::Reference<container::XIndexContainer> xBox = document::IndexedPropertyValues::create(xComponentContext);
1907 182 : xBox->insertByIndex(sal_Int32(0), uno::makeAny(aViewProps));
1908 364 : uno::Reference<container::XIndexAccess> xIndexAccess(xBox, uno::UNO_QUERY);
1909 364 : uno::Reference<document::XViewDataSupplier> xViewDataSupplier(mpDocShell->GetModel(), uno::UNO_QUERY);
1910 364 : xViewDataSupplier->setViewData(xIndexAccess);
1911 : }
1912 :
1913 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, !pWDop->fUsePrinterMetrics);
1914 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, true);
1915 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::ADD_FLY_OFFSETS, true );
1916 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::ADD_EXT_LEADING, !pWDop->fNoLeading);
1917 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::OLD_NUMBERING, false);
1918 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, false); // #i47448#
1919 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, !pWDop->fExpShRtn); // #i49277#, #i56856#
1920 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, false); // #i53199#
1921 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::OLD_LINE_SPACING, false);
1922 :
1923 : // #i25901# - set new compatibility option
1924 : // 'Add paragraph and table spacing at bottom of table cells'
1925 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS, true);
1926 :
1927 : // #i11860# - set new compatibility option
1928 : // 'Use former object positioning' to <sal_False>
1929 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::USE_FORMER_OBJECT_POS, false);
1930 :
1931 : // #i27767# - set new compatibility option
1932 : // 'Conder Wrapping mode when positioning object' to <sal_True>
1933 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION, true);
1934 :
1935 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING, false); // #i13832#, #i24135#
1936 :
1937 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::TABLE_ROW_KEEP, true); //SetTableRowKeep( true );
1938 :
1939 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, true); // #i3952#
1940 :
1941 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::INVERT_BORDER_SPACING, true);
1942 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::COLLAPSE_EMPTY_CELL_PARA, true);
1943 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::TAB_OVERFLOW, true);
1944 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::UNBREAKABLE_NUMBERINGS, true);
1945 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::CLIPPED_PICTURES, true);
1946 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::TAB_OVER_MARGIN, true);
1947 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::SURROUND_TEXT_WRAP_SMALL, true);
1948 186 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::PROP_LINE_SPACING_SHRINKS_FIRST_LINE, true);
1949 :
1950 : // COMPATIBILITY FLAGS END
1951 :
1952 : // Import magic doptypography information, if its there
1953 186 : if (pWwFib->nFib > 105)
1954 182 : ImportDopTypography(pWDop->doptypography);
1955 :
1956 : // disable form design mode to be able to use imported controls directly
1957 : // #i31239# always disable form design mode, not only in protected docs
1958 : {
1959 : using namespace com::sun::star;
1960 :
1961 : uno::Reference<lang::XComponent> xModelComp(mpDocShell->GetModel(),
1962 186 : uno::UNO_QUERY);
1963 : uno::Reference<beans::XPropertySet> xDocProps(xModelComp,
1964 372 : uno::UNO_QUERY);
1965 186 : if (xDocProps.is())
1966 : {
1967 : uno::Reference<beans::XPropertySetInfo> xInfo =
1968 186 : xDocProps->getPropertySetInfo();
1969 186 : bool bValue = false;
1970 186 : if (xInfo.is())
1971 : {
1972 186 : if (xInfo->hasPropertyByName("ApplyFormDesignMode"))
1973 : {
1974 186 : xDocProps->setPropertyValue("ApplyFormDesignMode", css::uno::makeAny(bValue));
1975 : }
1976 186 : }
1977 186 : }
1978 : }
1979 :
1980 : // Still allow editing of form fields.
1981 186 : if (!pWDop->fProtEnabled)
1982 182 : mpDocShell->SetModifyPasswordHash(pWDop->lKeyProtDoc);
1983 :
1984 186 : const SvtFilterOptions& rOpt = SvtFilterOptions::Get();
1985 186 : if (rOpt.IsUseEnhancedFields())
1986 372 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::PROTECT_FORM, pWDop->fProtEnabled );
1987 186 : }
1988 :
1989 182 : void SwWW8ImplReader::ImportDopTypography(const WW8DopTypography &rTypo)
1990 : {
1991 : using namespace com::sun::star;
1992 182 : switch (rTypo.iLevelOfKinsoku)
1993 : {
1994 : case 2: // custom
1995 : {
1996 : i18n::ForbiddenCharacters aForbidden(rTypo.rgxchFPunct,
1997 0 : rTypo.rgxchLPunct);
1998 0 : rDoc.getIDocumentSettingAccess().setForbiddenCharacters(rTypo.GetConvertedLang(),
1999 0 : aForbidden);
2000 : // Obviously cannot set the standard level 1 for japanese, so
2001 : // bail out now while we can.
2002 0 : if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESE)
2003 182 : return;
2004 : }
2005 0 : break;
2006 : default:
2007 182 : break;
2008 : }
2009 :
2010 : /*
2011 : This MS hack means that level 2 of japanese is not in operation, so we put
2012 : in what we know are the MS defaults, there is a complementary reverse
2013 : hack in the writer. Its our default as well, but we can set it anyway
2014 : as a flag for later.
2015 : */
2016 182 : if (!rTypo.reserved2)
2017 : {
2018 : i18n::ForbiddenCharacters aForbidden(WW8DopTypography::GetJapanNotBeginLevel1(),
2019 144 : WW8DopTypography::GetJapanNotEndLevel1());
2020 144 : rDoc.getIDocumentSettingAccess().setForbiddenCharacters(LANGUAGE_JAPANESE,aForbidden);
2021 : }
2022 :
2023 182 : rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION, rTypo.fKerningPunct);
2024 182 : rDoc.getIDocumentSettingAccess().setCharacterCompressionType(static_cast<SwCharCompressType>(rTypo.iJustification));
2025 : }
2026 :
2027 : /**
2028 : * Footnotes and Endnotes
2029 : */
2030 488 : WW8ReaderSave::WW8ReaderSave(SwWW8ImplReader* pRdr ,WW8_CP nStartCp) :
2031 488 : maTmpPos(*pRdr->pPaM->GetPoint()),
2032 : mpOldStck(pRdr->pCtrlStck),
2033 : mpOldAnchorStck(pRdr->pAnchorStck),
2034 : mpOldRedlines(pRdr->mpRedlineStack),
2035 : mpOldPlcxMan(pRdr->pPlcxMan),
2036 : mpWFlyPara(pRdr->pWFlyPara),
2037 : mpSFlyPara(pRdr->pSFlyPara),
2038 : mpPreviousNumPaM(pRdr->pPreviousNumPaM),
2039 : mpPrevNumRule(pRdr->pPrevNumRule),
2040 : mpTableDesc(pRdr->pTableDesc),
2041 : mnInTable(pRdr->nInTable),
2042 : mnAktColl(pRdr->nAktColl),
2043 : mcSymbol(pRdr->cSymbol),
2044 : mbIgnoreText(pRdr->bIgnoreText),
2045 : mbSymbol(pRdr->bSymbol),
2046 : mbHdFtFtnEdn(pRdr->bHdFtFtnEdn),
2047 : mbTxbxFlySection(pRdr->bTxbxFlySection),
2048 : mbAnl(pRdr->bAnl),
2049 : mbInHyperlink(pRdr->bInHyperlink),
2050 : mbPgSecBreak(pRdr->bPgSecBreak),
2051 : mbWasParaEnd(pRdr->bWasParaEnd),
2052 : mbHasBorder(pRdr->bHasBorder),
2053 976 : mbFirstPara(pRdr->bFirstPara)
2054 : {
2055 488 : pRdr->bSymbol = false;
2056 488 : pRdr->bHdFtFtnEdn = true;
2057 : pRdr->bTxbxFlySection = pRdr->bAnl = pRdr->bPgSecBreak = pRdr->bWasParaEnd
2058 488 : = pRdr->bHasBorder = false;
2059 488 : pRdr->bFirstPara = true;
2060 488 : pRdr->nInTable = 0;
2061 488 : pRdr->pWFlyPara = 0;
2062 488 : pRdr->pSFlyPara = 0;
2063 488 : pRdr->pPreviousNumPaM = 0;
2064 488 : pRdr->pPrevNumRule = 0;
2065 488 : pRdr->pTableDesc = 0;
2066 488 : pRdr->nAktColl = 0;
2067 :
2068 : pRdr->pCtrlStck = new SwWW8FltControlStack(&pRdr->rDoc, pRdr->nFieldFlags,
2069 488 : *pRdr);
2070 :
2071 488 : pRdr->mpRedlineStack = new sw::util::RedlineStack(pRdr->rDoc);
2072 :
2073 488 : pRdr->pAnchorStck = new SwWW8FltAnchorStack(&pRdr->rDoc, pRdr->nFieldFlags);
2074 :
2075 : // Save the attribute manager: we need this as the newly created PLCFx Manager
2076 : // access the same FKPs as the old one and their Start-End position changes.
2077 488 : if (pRdr->pPlcxMan)
2078 202 : pRdr->pPlcxMan->SaveAllPLCFx(maPLCFxSave);
2079 :
2080 488 : if (nStartCp != -1)
2081 : {
2082 : pRdr->pPlcxMan = new WW8PLCFMan(pRdr->pSBase,
2083 14 : mpOldPlcxMan->GetManType(), nStartCp);
2084 : }
2085 :
2086 488 : maOldApos.push_back(false);
2087 488 : maOldApos.swap(pRdr->maApos);
2088 488 : maOldFieldStack.swap(pRdr->maFieldStack);
2089 488 : }
2090 :
2091 488 : void WW8ReaderSave::Restore( SwWW8ImplReader* pRdr )
2092 : {
2093 488 : pRdr->pWFlyPara = mpWFlyPara;
2094 488 : pRdr->pSFlyPara = mpSFlyPara;
2095 488 : pRdr->pPreviousNumPaM = mpPreviousNumPaM;
2096 488 : pRdr->pPrevNumRule = mpPrevNumRule;
2097 488 : pRdr->pTableDesc = mpTableDesc;
2098 488 : pRdr->cSymbol = mcSymbol;
2099 488 : pRdr->bSymbol = mbSymbol;
2100 488 : pRdr->bIgnoreText = mbIgnoreText;
2101 488 : pRdr->bHdFtFtnEdn = mbHdFtFtnEdn;
2102 488 : pRdr->bTxbxFlySection = mbTxbxFlySection;
2103 488 : pRdr->nInTable = mnInTable;
2104 488 : pRdr->bAnl = mbAnl;
2105 488 : pRdr->bInHyperlink = mbInHyperlink;
2106 488 : pRdr->bWasParaEnd = mbWasParaEnd;
2107 488 : pRdr->bPgSecBreak = mbPgSecBreak;
2108 488 : pRdr->nAktColl = mnAktColl;
2109 488 : pRdr->bHasBorder = mbHasBorder;
2110 488 : pRdr->bFirstPara = mbFirstPara;
2111 :
2112 : // Close all attributes as attributes could be created that extend the Fly
2113 488 : pRdr->DeleteCtrlStk();
2114 488 : pRdr->pCtrlStck = mpOldStck;
2115 :
2116 488 : pRdr->mpRedlineStack->closeall(*pRdr->pPaM->GetPoint());
2117 488 : delete pRdr->mpRedlineStack;
2118 488 : pRdr->mpRedlineStack = mpOldRedlines;
2119 :
2120 488 : pRdr->DeleteAnchorStk();
2121 488 : pRdr->pAnchorStck = mpOldAnchorStck;
2122 :
2123 488 : *pRdr->pPaM->GetPoint() = maTmpPos;
2124 :
2125 488 : if (mpOldPlcxMan != pRdr->pPlcxMan)
2126 : {
2127 202 : delete pRdr->pPlcxMan;
2128 202 : pRdr->pPlcxMan = mpOldPlcxMan;
2129 : }
2130 488 : if (pRdr->pPlcxMan)
2131 202 : pRdr->pPlcxMan->RestoreAllPLCFx(maPLCFxSave);
2132 488 : pRdr->maApos.swap(maOldApos);
2133 488 : pRdr->maFieldStack.swap(maOldFieldStack);
2134 488 : }
2135 :
2136 288 : void SwWW8ImplReader::Read_HdFtFtnText( const SwNodeIndex* pSttIdx,
2137 : long nStartCp, long nLen, ManTypes nType )
2138 : {
2139 : // Saves Flags (amongst other things) and resets them
2140 288 : WW8ReaderSave aSave( this );
2141 :
2142 288 : pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1;
2143 288 : pPaM->GetPoint()->nContent.Assign( pPaM->GetCntntNode(), 0 );
2144 :
2145 : // Read Text for Header, Footer or Footnote
2146 288 : ReadText( nStartCp, nLen, nType ); // Ignore Sepx when doing so
2147 288 : aSave.Restore( this );
2148 288 : }
2149 :
2150 : /**
2151 : * Use authornames, if not available fall back to initials.
2152 : */
2153 30 : long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes)
2154 : {
2155 30 : WW8PLCFx_SubDoc* pSD = pPlcxMan->GetAtn();
2156 30 : if( !pSD )
2157 0 : return 0;
2158 :
2159 30 : OUString sAuthor;
2160 60 : OUString sInitials;
2161 30 : if( bVer67 )
2162 : {
2163 0 : const WW67_ATRD* pDescri = (const WW67_ATRD*)pSD->GetData();
2164 0 : const OUString* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst));
2165 0 : if (pA)
2166 0 : sAuthor = *pA;
2167 : else
2168 0 : sAuthor = OUString(pDescri->xstUsrInitl + 1, pDescri->xstUsrInitl[0],
2169 0 : RTL_TEXTENCODING_MS_1252);
2170 : }
2171 : else
2172 : {
2173 30 : const WW8_ATRD* pDescri = (const WW8_ATRD*)pSD->GetData();
2174 :
2175 : {
2176 30 : const sal_uInt16 nLen = SVBT16ToShort(pDescri->xstUsrInitl[0]);
2177 30 : OUStringBuffer aBuf;
2178 30 : aBuf.setLength(nLen);
2179 48 : for(sal_uInt16 nIdx = 1; nIdx <= nLen; ++nIdx)
2180 18 : aBuf[nIdx-1] = SVBT16ToShort(pDescri->xstUsrInitl[nIdx]);
2181 30 : sInitials = aBuf.makeStringAndClear();
2182 : }
2183 :
2184 30 : if (const OUString* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst)))
2185 30 : sAuthor = *pA;
2186 : else
2187 0 : sAuthor = sInitials;
2188 :
2189 : // If there is a bookmark tag, a text range should be commented.
2190 30 : sal_uInt32 nTagBkmk = SVBT32ToUInt32(pDescri->ITagBkmk);
2191 30 : if (nTagBkmk != 0xFFFFFFFF)
2192 : {
2193 24 : int nAtnIndex = GetAnnotationIndex(nTagBkmk);
2194 24 : if (nAtnIndex != -1)
2195 : {
2196 24 : WW8_CP nStart = GetAnnotationStart(nAtnIndex);
2197 24 : WW8_CP nEnd = GetAnnotationEnd(GetAnnotationEndIndex(nAtnIndex));
2198 : //It is unfortunately fragile and wrong to assume that two
2199 : //character positions in the original word document, which is
2200 : //what nStart and nEnd are, will equate to the same length in
2201 : //the destination writer document.
2202 : //
2203 : //Better would be, while writing the content into the writer
2204 : //document to store the equivalent writer document positions
2205 : //that relate to each annotation index as the parser passes
2206 : //those points.
2207 24 : sal_Int32 nLen = nEnd - nStart;
2208 : // the start and end positions are apparently stored in
2209 : // different arrays, so in an invalid file only one could exist
2210 24 : if(SAL_MAX_INT32 != nEnd && SAL_MAX_INT32 != nStart && nLen > 0)
2211 : {
2212 24 : if (pPaM->GetPoint()->nContent.GetIndex() >= nLen)
2213 : {
2214 18 : pPaM->SetMark();
2215 18 : pPaM->GetPoint()->nContent -= nLen;
2216 : }
2217 6 : else if (pPaM->GetPoint()->nNode.GetNode().IsTxtNode() )
2218 : {
2219 6 : pPaM->SetMark();
2220 6 : nLen -= pPaM->GetPoint()->nContent.GetIndex();
2221 :
2222 6 : SwTxtNode* pTxtNode = 0;
2223 :
2224 : // Find first text node which is affected by the comment
2225 12 : while (nLen > 0)
2226 : {
2227 : // Move to previous content node
2228 6 : bool bSuccess = pPaM->Move(fnMoveBackward, fnGoNode);
2229 :
2230 6 : if (!bSuccess)
2231 : {
2232 0 : nLen = 0;
2233 0 : break;
2234 : }
2235 :
2236 6 : --nLen; // End line character
2237 :
2238 6 : SwNode& rNode = pPaM->GetPoint()->nNode.GetNode();
2239 :
2240 : // Subtract previous text node's length
2241 6 : if (rNode.IsTxtNode())
2242 : {
2243 6 : pTxtNode = rNode.GetTxtNode();
2244 6 : if (nLen < pTxtNode->Len())
2245 6 : break;
2246 : else
2247 0 : nLen -= pTxtNode->Len();
2248 : }
2249 : }
2250 :
2251 : // Set position of the text range's first character
2252 6 : if( pTxtNode )
2253 : {
2254 6 : pTxtNode->MakeStartIndex(&pPaM->GetPoint()->nContent);
2255 6 : pPaM->GetPoint()->nContent += pTxtNode->Len() - nLen;
2256 : }
2257 : }
2258 : }
2259 : }
2260 : }
2261 : }
2262 :
2263 30 : sal_uInt32 nDateTime = 0;
2264 :
2265 30 : if (sal_uInt8 * pExtended = pPlcxMan->GetExtendedAtrds()) // Word < 2002 has no date data for comments
2266 : {
2267 30 : sal_uLong nIndex = pSD->GetIdx() & 0xFFFF; // Index is (stupidly) multiplexed for WW8PLCFx_SubDocs
2268 30 : if (pWwFib->lcbAtrdExtra/18 > nIndex)
2269 30 : nDateTime = SVBT32ToUInt32(*(SVBT32*)(pExtended+(nIndex*18)));
2270 : }
2271 :
2272 30 : DateTime aDate = msfilter::util::DTTM2DateTime(nDateTime);
2273 :
2274 60 : OUString sTxt;
2275 : OutlinerParaObject *pOutliner = ImportAsOutliner( sTxt, pRes->nCp2OrIdx,
2276 30 : pRes->nCp2OrIdx + pRes->nMemLen, MAN_AND );
2277 :
2278 30 : this->pFmtOfJustInsertedApo = 0;
2279 : SwPostItField aPostIt(
2280 30 : (SwPostItFieldType*)rDoc.getIDocumentFieldsAccess().GetSysFldType(RES_POSTITFLD), sAuthor,
2281 90 : sTxt, sInitials, OUString(), aDate );
2282 30 : aPostIt.SetTextObject(pOutliner);
2283 :
2284 60 : SwPaM aEnd(*pPaM->End(), *pPaM->End());
2285 30 : pCtrlStck->NewAttr(*aEnd.GetPoint(), SvxCharHiddenItem(false, RES_CHRATR_HIDDEN));
2286 30 : rDoc.getIDocumentContentOperations().InsertPoolItem(aEnd, SwFmtFld(aPostIt), 0);
2287 30 : pCtrlStck->SetAttr(*aEnd.GetPoint(), RES_CHRATR_HIDDEN);
2288 :
2289 : // If this is a range, create the associated fieldmark.
2290 30 : if (pPaM->HasMark())
2291 : {
2292 24 : IDocumentMarkAccess* pMarksAccess = rDoc.getIDocumentMarkAccess();
2293 24 : pMarksAccess->makeAnnotationMark(*pPaM, aPostIt.GetName());
2294 24 : pPaM->Exchange();
2295 24 : pPaM->DeleteMark();
2296 : }
2297 :
2298 60 : return 0;
2299 : }
2300 :
2301 0 : void SwWW8ImplReader::Read_HdFtTextAsHackedFrame(long nStart, long nLen,
2302 : SwFrmFmt &rHdFtFmt, sal_uInt16 nPageWidth)
2303 : {
2304 0 : const SwNodeIndex* pSttIdx = rHdFtFmt.GetCntnt().GetCntntIdx();
2305 : OSL_ENSURE(pSttIdx, "impossible");
2306 0 : if (!pSttIdx)
2307 0 : return;
2308 :
2309 0 : SwPosition aTmpPos(*pPaM->GetPoint());
2310 :
2311 0 : pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1;
2312 0 : pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(), 0);
2313 :
2314 0 : SwFlyFrmFmt *pFrame = rDoc.MakeFlySection(FLY_AT_PARA, pPaM->GetPoint());
2315 :
2316 0 : SwFmtAnchor aAnch( pFrame->GetAnchor() );
2317 0 : aAnch.SetType( FLY_AT_PARA );
2318 0 : pFrame->SetFmtAttr( aAnch );
2319 0 : SwFmtFrmSize aSz(ATT_MIN_SIZE, nPageWidth, MINLAY);
2320 0 : SwFrmSize eFrmSize = ATT_MIN_SIZE;
2321 0 : if( eFrmSize != aSz.GetWidthSizeType() )
2322 0 : aSz.SetWidthSizeType( eFrmSize );
2323 0 : pFrame->SetFmtAttr(aSz);
2324 0 : pFrame->SetFmtAttr(SwFmtSurround(SURROUND_THROUGHT));
2325 0 : pFrame->SetFmtAttr(SwFmtHoriOrient(0, text::HoriOrientation::LEFT)); //iFOO
2326 :
2327 : // #i43427# - send frame for header/footer into background.
2328 0 : pFrame->SetFmtAttr( SvxOpaqueItem( RES_OPAQUE, false ) );
2329 0 : SdrObject* pFrmObj = CreateContactObject( pFrame );
2330 : OSL_ENSURE( pFrmObj,
2331 : "<SwWW8ImplReader::Read_HdFtTextAsHackedFrame(..)> - missing SdrObject instance" );
2332 0 : if ( pFrmObj )
2333 : {
2334 0 : pFrmObj->SetOrdNum( 0L );
2335 : }
2336 0 : MoveInsideFly(pFrame);
2337 :
2338 0 : const SwNodeIndex* pHackIdx = pFrame->GetCntnt().GetCntntIdx();
2339 :
2340 0 : Read_HdFtFtnText(pHackIdx, nStart, nLen - 1, MAN_HDFT);
2341 :
2342 0 : MoveOutsideFly(pFrame, aTmpPos);
2343 : }
2344 :
2345 286 : void SwWW8ImplReader::Read_HdFtText(long nStart, long nLen, SwFrmFmt* pHdFtFmt)
2346 : {
2347 286 : const SwNodeIndex* pSttIdx = pHdFtFmt->GetCntnt().GetCntntIdx();
2348 286 : if (!pSttIdx)
2349 286 : return;
2350 :
2351 286 : SwPosition aTmpPos( *pPaM->GetPoint() ); // Remember old cursor position
2352 :
2353 286 : Read_HdFtFtnText(pSttIdx, nStart, nLen - 1, MAN_HDFT);
2354 :
2355 286 : *pPaM->GetPoint() = aTmpPos;
2356 : }
2357 :
2358 282 : bool SwWW8ImplReader::isValid_HdFt_CP(WW8_CP nHeaderCP) const
2359 : {
2360 : // Each CP of Plcfhdd MUST be less than FibRgLw97.ccpHdd
2361 282 : return (nHeaderCP < pWwFib->ccpHdr);
2362 : }
2363 :
2364 0 : bool SwWW8ImplReader::HasOwnHeaderFooter(sal_uInt8 nWhichItems, sal_uInt8 grpfIhdt,
2365 : int nSect)
2366 : {
2367 0 : if (pHdFt)
2368 : {
2369 : WW8_CP start;
2370 : long nLen;
2371 0 : sal_uInt8 nNumber = 5;
2372 :
2373 0 : for( sal_uInt8 nI = 0x20; nI; nI >>= 1, nNumber-- )
2374 : {
2375 0 : if (nI & nWhichItems)
2376 : {
2377 0 : bool bOk = true;
2378 0 : if( bVer67 )
2379 0 : bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 );
2380 : else
2381 : {
2382 0 : pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen);
2383 0 : bOk = ( 2 <= nLen ) && isValid_HdFt_CP(start);
2384 : }
2385 :
2386 0 : if (bOk)
2387 0 : return true;
2388 : }
2389 : }
2390 : }
2391 0 : return false;
2392 : }
2393 :
2394 86 : void SwWW8ImplReader::Read_HdFt(int nSect, const SwPageDesc *pPrev,
2395 : const wwSection &rSection)
2396 : {
2397 86 : sal_uInt8 grpfIhdt = rSection.maSep.grpfIhdt;
2398 86 : SwPageDesc *pPD = rSection.mpPage;
2399 :
2400 86 : if( pHdFt )
2401 : {
2402 : WW8_CP start;
2403 : long nLen;
2404 86 : sal_uInt8 nNumber = 5;
2405 :
2406 : // This loops through the 6 flags WW8_{FOOTER,HEADER}_{ODD,EVEN,FIRST}
2407 : // corresponding to bit fields in grpfIhdt indicating which
2408 : // header/footer(s) are present in this section
2409 602 : for( sal_uInt8 nI = 0x20; nI; nI >>= 1, nNumber-- )
2410 : {
2411 516 : if (nI & grpfIhdt)
2412 : {
2413 318 : bool bOk = true;
2414 318 : if( bVer67 )
2415 4 : bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 );
2416 : else
2417 : {
2418 314 : pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen);
2419 314 : bOk = ( 2 <= nLen ) && isValid_HdFt_CP(start);
2420 : }
2421 :
2422 : bool bUseLeft
2423 318 : = (nI & ( WW8_HEADER_EVEN | WW8_FOOTER_EVEN )) ? true: false;
2424 : bool bUseFirst
2425 318 : = (nI & ( WW8_HEADER_FIRST | WW8_FOOTER_FIRST )) ? true: false;
2426 :
2427 : // If we are loading a first-page header/footer which is not
2428 : // actually enabled in this section (it still needs to be
2429 : // loaded as it may be inherited by a later section)
2430 318 : bool bDisabledFirst = bUseFirst && !rSection.HasTitlePage();
2431 :
2432 : bool bFooter
2433 318 : = (nI & ( WW8_FOOTER_EVEN | WW8_FOOTER_ODD | WW8_FOOTER_FIRST )) ? true: false;
2434 :
2435 : SwFrmFmt& rFmt = bUseLeft ? pPD->GetLeft()
2436 : : bUseFirst ? pPD->GetFirstMaster()
2437 318 : : pPD->GetMaster();
2438 :
2439 : SwFrmFmt* pHdFtFmt;
2440 : // If we have empty first page header and footer.
2441 318 : bool bNoFirst = !(grpfIhdt & WW8_HEADER_FIRST) && !(grpfIhdt & WW8_FOOTER_FIRST);
2442 318 : if (bFooter)
2443 : {
2444 158 : bIsFooter = true;
2445 : //#i17196# Cannot have left without right
2446 316 : if (!bDisabledFirst
2447 158 : && !pPD->GetMaster().GetFooter().GetFooterFmt())
2448 74 : pPD->GetMaster().SetFmtAttr(SwFmtFooter(true));
2449 158 : if (bUseLeft)
2450 26 : pPD->GetLeft().SetFmtAttr(SwFmtFooter(true));
2451 158 : if (bUseFirst || (rSection.maSep.fTitlePage && bNoFirst))
2452 62 : pPD->GetFirstMaster().SetFmtAttr(SwFmtFooter(true));
2453 158 : pHdFtFmt = const_cast<SwFrmFmt*>(rFmt.GetFooter().GetFooterFmt());
2454 : }
2455 : else
2456 : {
2457 160 : bIsHeader = true;
2458 : //#i17196# Cannot have left without right
2459 320 : if (!bDisabledFirst
2460 160 : && !pPD->GetMaster().GetHeader().GetHeaderFmt())
2461 72 : pPD->GetMaster().SetFmtAttr(SwFmtHeader(true));
2462 160 : if (bUseLeft)
2463 24 : pPD->GetLeft().SetFmtAttr(SwFmtHeader(true));
2464 160 : if (bUseFirst || (rSection.maSep.fTitlePage && bNoFirst))
2465 68 : pPD->GetFirstMaster().SetFmtAttr(SwFmtHeader(true));
2466 160 : pHdFtFmt = const_cast<SwFrmFmt*>(rFmt.GetHeader().GetHeaderFmt());
2467 : }
2468 :
2469 318 : if (bOk)
2470 : {
2471 286 : bool bHackRequired = false;
2472 286 : if (bIsHeader && rSection.IsFixedHeightHeader())
2473 0 : bHackRequired = true;
2474 286 : else if (bIsFooter && rSection.IsFixedHeightFooter())
2475 0 : bHackRequired = true;
2476 :
2477 286 : if (bHackRequired)
2478 : {
2479 : Read_HdFtTextAsHackedFrame(start, nLen, *pHdFtFmt,
2480 0 : static_cast< sal_uInt16 >(rSection.GetTextAreaWidth()) );
2481 : }
2482 : else
2483 286 : Read_HdFtText(start, nLen, pHdFtFmt);
2484 : }
2485 32 : else if (!bOk && pPrev)
2486 32 : CopyPageDescHdFt(pPrev, pPD, nI);
2487 :
2488 318 : bIsHeader = bIsFooter = false;
2489 : }
2490 : }
2491 : }
2492 86 : }
2493 :
2494 228 : bool wwSectionManager::SectionIsProtected(const wwSection &rSection) const
2495 : {
2496 228 : return (mrReader.pWwFib->fReadOnlyRecommended && !rSection.IsNotProtected());
2497 : }
2498 :
2499 220 : void wwSectionManager::SetHdFt(wwSection &rSection, int nSect,
2500 : const wwSection *pPrevious)
2501 : {
2502 : // Header/Footer not present
2503 220 : if (!rSection.maSep.grpfIhdt)
2504 354 : return;
2505 :
2506 : OSL_ENSURE(rSection.mpPage, "makes no sense to call with a main page");
2507 86 : if (rSection.mpPage)
2508 : {
2509 : mrReader.Read_HdFt(nSect, pPrevious ? pPrevious->mpPage : 0,
2510 86 : rSection);
2511 : }
2512 :
2513 : // Header/Footer - Update Index
2514 : // So that the index is still valid later on
2515 86 : if (mrReader.pHdFt)
2516 86 : mrReader.pHdFt->UpdateIndex(rSection.maSep.grpfIhdt);
2517 :
2518 : }
2519 :
2520 5542 : void SwWW8ImplReader::AppendTxtNode(SwPosition& rPos)
2521 : {
2522 5542 : SwTxtNode* pTxt = pPaM->GetNode().GetTxtNode();
2523 :
2524 5542 : const SwNumRule* pRule = NULL;
2525 :
2526 5542 : if (pTxt != NULL)
2527 5542 : pRule = sw::util::GetNumRuleFromTxtNode(*pTxt);
2528 :
2529 5542 : if (
2530 674 : pRule && !pWDop->fDontUseHTMLAutoSpacing &&
2531 224 : (bParaAutoBefore || bParaAutoAfter)
2532 : )
2533 : {
2534 : // If after spacing is set to auto, set the after space to 0
2535 0 : if (bParaAutoAfter)
2536 0 : SetLowerSpacing(*pPaM, 0);
2537 :
2538 : // If the previous textnode had numbering and
2539 : // and before spacing is set to auto, set before space to 0
2540 0 : if(pPrevNumRule && bParaAutoBefore)
2541 0 : SetUpperSpacing(*pPaM, 0);
2542 :
2543 : // If the previous numbering rule was different we need
2544 : // to insert a space after the previous paragraph
2545 0 : if((pRule != pPrevNumRule) && pPreviousNumPaM)
2546 0 : SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
2547 :
2548 : // cache current paragraph
2549 0 : if(pPreviousNumPaM)
2550 0 : delete pPreviousNumPaM, pPreviousNumPaM = 0;
2551 :
2552 0 : pPreviousNumPaM = new SwPaM(*pPaM);
2553 0 : pPrevNumRule = pRule;
2554 : }
2555 5542 : else if(!pRule && pPreviousNumPaM)
2556 : {
2557 : // If the previous paragraph has numbering but the current one does not
2558 : // we need to add a space after the previous paragraph
2559 0 : SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
2560 0 : delete pPreviousNumPaM, pPreviousNumPaM = 0;
2561 0 : pPrevNumRule = 0;
2562 : }
2563 : else
2564 : {
2565 : // clear paragraph cache
2566 5542 : if(pPreviousNumPaM)
2567 0 : delete pPreviousNumPaM, pPreviousNumPaM = 0;
2568 5542 : pPrevNumRule = pRule;
2569 : }
2570 :
2571 : // If this is the first paragraph in the document and
2572 : // Auto-spacing before paragraph is set,
2573 : // set the upper spacing value to 0
2574 5542 : if(bParaAutoBefore && bFirstPara && !pWDop->fDontUseHTMLAutoSpacing)
2575 0 : SetUpperSpacing(*pPaM, 0);
2576 :
2577 5542 : bFirstPara = false;
2578 :
2579 5542 : rDoc.getIDocumentContentOperations().AppendTxtNode(rPos);
2580 :
2581 : // We can flush all anchored graphics at the end of a paragraph.
2582 5542 : pAnchorStck->Flush();
2583 5542 : }
2584 :
2585 0 : bool SwWW8ImplReader::SetSpacing(SwPaM &rMyPam, int nSpace, bool bIsUpper )
2586 : {
2587 0 : bool bRet = false;
2588 0 : const SwPosition* pSpacingPos = rMyPam.GetPoint();
2589 :
2590 0 : const SvxULSpaceItem* pULSpaceItem = (const SvxULSpaceItem*)pCtrlStck->GetFmtAttr(*pSpacingPos, RES_UL_SPACE);
2591 :
2592 0 : if(pULSpaceItem != 0)
2593 : {
2594 0 : SvxULSpaceItem aUL(*pULSpaceItem);
2595 :
2596 0 : if(bIsUpper)
2597 0 : aUL.SetUpper( static_cast< sal_uInt16 >(nSpace) );
2598 : else
2599 0 : aUL.SetLower( static_cast< sal_uInt16 >(nSpace) );
2600 :
2601 0 : const sal_Int32 nEnd = pSpacingPos->nContent.GetIndex();
2602 0 : rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), 0);
2603 0 : pCtrlStck->NewAttr(*pSpacingPos, aUL);
2604 0 : rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), nEnd);
2605 0 : pCtrlStck->SetAttr(*pSpacingPos, RES_UL_SPACE);
2606 0 : bRet = true;
2607 : }
2608 0 : return bRet;
2609 : }
2610 :
2611 0 : bool SwWW8ImplReader::SetLowerSpacing(SwPaM &rMyPam, int nSpace)
2612 : {
2613 0 : return SetSpacing(rMyPam, nSpace, false);
2614 : }
2615 :
2616 0 : bool SwWW8ImplReader::SetUpperSpacing(SwPaM &rMyPam, int nSpace)
2617 : {
2618 0 : return SetSpacing(rMyPam, nSpace, true);
2619 : }
2620 :
2621 41258 : sal_uInt16 SwWW8ImplReader::TabRowSprm(int nLevel) const
2622 : {
2623 41258 : if (bVer67)
2624 0 : return 25;
2625 41258 : return nLevel ? 0x244C : 0x2417;
2626 : }
2627 :
2628 486 : void SwWW8ImplReader::EndSpecial()
2629 : {
2630 : // Frame/Table/Anl
2631 486 : if (bAnl)
2632 0 : StopAllAnl(); // -> bAnl = false
2633 :
2634 972 : while(maApos.size() > 1)
2635 : {
2636 0 : StopTable();
2637 0 : maApos.pop_back();
2638 0 : --nInTable;
2639 0 : if (maApos[nInTable] == true)
2640 0 : StopApo();
2641 : }
2642 :
2643 486 : if (maApos[0] == true)
2644 0 : StopApo();
2645 :
2646 : OSL_ENSURE(!nInTable, "unclosed table!");
2647 486 : }
2648 :
2649 7982 : bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync, WW8_CP nStartCp)
2650 : {
2651 : // Frame/Table/Anl
2652 7982 : if (bInHyperlink)
2653 0 : return false;
2654 :
2655 7982 : rbReSync = false;
2656 :
2657 : OSL_ENSURE(nInTable >= 0,"nInTable < 0!");
2658 :
2659 : // TabRowEnd
2660 7982 : bool bTableRowEnd = (pPlcxMan->HasParaSprm(bVer67 ? 25 : 0x2417) != 0 );
2661 :
2662 : // Unfortunately, for every paragraph we need to check first whether
2663 : // they contain a sprm 29 (0x261B), which starts an APO.
2664 : // All other sprms then refer to that APO and not to the normal text
2665 : // surrounding it.
2666 : // The same holds true for a Table (sprm 24 (0x2416)) and Anls (sprm 13).
2667 :
2668 : // WW: Table in APO is possible (Both Start-Ends occur at the same time)
2669 : // WW: APO in Table not possible
2670 :
2671 : // This mean that of a Table is the content of a APO, the APO start needs
2672 : // to be edited first, so that the Table remains in the APO and not the
2673 : // other way around.
2674 : // At the End, however, we need to edit the Table End first as the APO
2675 : // must end after that Table (or else we never find the APO End).
2676 :
2677 : // The same holds true for Fly / Anl, Tab / Anl, Fly / Tab / Anl.
2678 :
2679 : // If the Table is within an APO the TabRowEnd Area misses the
2680 : // APO settings.
2681 : // To not end the APO there, we do not call ProcessApo
2682 :
2683 : // KHZ: When there is a table inside the Apo the Apo-flags are also
2684 : // missing for the 2nd, 3rd... paragraphs of each cell.
2685 :
2686 : // 1st look for in-table flag, for 2000+ there is a subtable flag to
2687 : // be considered, the sprm 6649 gives the level of the table
2688 7982 : sal_uInt8 nCellLevel = 0;
2689 :
2690 7982 : if (bVer67)
2691 150 : nCellLevel = 0 != pPlcxMan->HasParaSprm(24);
2692 : else
2693 : {
2694 7832 : nCellLevel = 0 != pPlcxMan->HasParaSprm(0x2416);
2695 7832 : if (!nCellLevel)
2696 4650 : nCellLevel = 0 != pPlcxMan->HasParaSprm(0x244B);
2697 : }
2698 7988 : do
2699 : {
2700 7988 : WW8_TablePos *pTabPos=0;
2701 : WW8_TablePos aTabPos;
2702 7988 : if(nCellLevel && !bVer67)
2703 : {
2704 : WW8PLCFxSave1 aSave;
2705 3188 : pPlcxMan->GetPap()->Save( aSave );
2706 3188 : rbReSync = true;
2707 3188 : WW8PLCFx_Cp_FKP* pPap = pPlcxMan->GetPapPLCF();
2708 3188 : WW8_CP nMyStartCp=nStartCp;
2709 :
2710 3188 : if (const sal_uInt8 *pLevel = pPlcxMan->HasParaSprm(0x6649))
2711 3188 : nCellLevel = *pLevel;
2712 :
2713 3188 : bool bHasRowEnd = SearchRowEnd(pPap, nMyStartCp, (nInTable<nCellLevel?nInTable:nCellLevel-1));
2714 :
2715 : // Bad Table, remain unchanged in level, e.g. #i19667#
2716 3188 : if (!bHasRowEnd)
2717 2 : nCellLevel = static_cast< sal_uInt8 >(nInTable);
2718 :
2719 3188 : if (bHasRowEnd && ParseTabPos(&aTabPos,pPap))
2720 202 : pTabPos = &aTabPos;
2721 :
2722 3188 : pPlcxMan->GetPap()->Restore( aSave );
2723 : }
2724 :
2725 : // Then look if we are in an Apo
2726 :
2727 7988 : ApoTestResults aApo = TestApo(nCellLevel, bTableRowEnd, pTabPos);
2728 :
2729 : // Look to see if we are in a Table, but Table in foot/end note not allowed
2730 7988 : bool bStartTab = (nInTable < nCellLevel) && !bFtnEdn;
2731 :
2732 7988 : bool bStopTab = bWasTabRowEnd && (nInTable > nCellLevel) && !bFtnEdn;
2733 :
2734 7988 : bWasTabRowEnd = false; // must be deactivated right here to prevent next
2735 : // WW8TabDesc::TableCellEnd() from making nonsense
2736 :
2737 7988 : if (nInTable && !bTableRowEnd && !bStopTab && (nInTable == nCellLevel && aApo.HasStartStop()))
2738 2 : bStopTab = bStartTab = true; // Required to stop and start table
2739 :
2740 : // Test for Anl (Numbering) and process all events in the right order
2741 7988 : if( bAnl && !bTableRowEnd )
2742 : {
2743 0 : const sal_uInt8* pSprm13 = pPlcxMan->HasParaSprm( 13 );
2744 0 : if( pSprm13 )
2745 : { // Still Anl left?
2746 0 : sal_uInt8 nT = static_cast< sal_uInt8 >(GetNumType( *pSprm13 ));
2747 0 : if( ( nT != WW8_Pause && nT != nWwNumType ) // Anl change
2748 0 : || aApo.HasStartStop() // Forced Anl end
2749 0 : || bStopTab || bStartTab )
2750 : {
2751 0 : StopAnlToRestart(nT); // Anl-Restart (= change) over sprms
2752 : }
2753 : else
2754 : {
2755 0 : NextAnlLine( pSprm13 ); // Next Anl Line
2756 : }
2757 : }
2758 : else
2759 : { // Regular Anl end
2760 0 : StopAllAnl(); // Actual end
2761 : }
2762 : }
2763 7988 : if (bStopTab)
2764 : {
2765 140 : StopTable();
2766 140 : maApos.pop_back();
2767 140 : --nInTable;
2768 : }
2769 7988 : if (aApo.mbStopApo)
2770 : {
2771 24 : StopApo();
2772 24 : maApos[nInTable] = false;
2773 : }
2774 :
2775 : // So that SwWW8ImplReader::StartApo() can write into this, and
2776 : // WW8TabDesc::CreateSwTable() can read it, if necessary.
2777 7988 : SvxULSpaceItem aULSpaceItem(RES_UL_SPACE);
2778 :
2779 7988 : if (aApo.mbStartApo)
2780 : {
2781 24 : maApos[nInTable] = StartApo(aApo, pTabPos, &aULSpaceItem);
2782 : // We need an ReSync after StartApo
2783 : // (actually only if the Apo extends past a FKP border)
2784 24 : rbReSync = true;
2785 : }
2786 7988 : if (bStartTab)
2787 : {
2788 : WW8PLCFxSave1 aSave;
2789 140 : pPlcxMan->GetPap()->Save( aSave );
2790 :
2791 : // Numbering for cell borders causes a crash -> no Anls in Tables
2792 140 : if (bAnl)
2793 0 : StopAllAnl();
2794 :
2795 140 : if(nInTable < nCellLevel)
2796 : {
2797 140 : if (StartTable(nStartCp, &aULSpaceItem))
2798 140 : ++nInTable;
2799 : else
2800 0 : break;
2801 140 : maApos.push_back(false);
2802 : }
2803 :
2804 140 : if(nInTable >= nCellLevel)
2805 : {
2806 : // We need an ReSync after StartTable
2807 : // (actually only if the Apo extends past a FKP border)
2808 134 : rbReSync = true;
2809 134 : pPlcxMan->GetPap()->Restore( aSave );
2810 : }
2811 7988 : }
2812 15974 : } while (!bFtnEdn && (nInTable < nCellLevel));
2813 7982 : return bTableRowEnd;
2814 : }
2815 :
2816 622 : rtl_TextEncoding SwWW8ImplReader::GetCharSetFromLanguage()
2817 : {
2818 : /*
2819 : #i22206#/#i52786#
2820 : The (default) character set used for a run of text is the default
2821 : character set for the version of Word that last saved the document.
2822 :
2823 : This is a bit tentative, more might be required if the concept is correct.
2824 : When later version of word write older 6/95 documents the charset is
2825 : correctly set in the character runs involved, so its hard to reproduce
2826 : documents that require this to be sure of the process involved.
2827 : */
2828 622 : const SvxLanguageItem *pLang = (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
2829 622 : LanguageType eLang = pLang ? pLang->GetLanguage() : LANGUAGE_SYSTEM;
2830 622 : ::com::sun::star::lang::Locale aLocale(LanguageTag::convertToLocale(eLang));
2831 622 : return msfilter::util::getBestTextEncodingFromLocale(aLocale);
2832 : }
2833 :
2834 622 : rtl_TextEncoding SwWW8ImplReader::GetCJKCharSetFromLanguage()
2835 : {
2836 : /*
2837 : #i22206#/#i52786#
2838 : The (default) character set used for a run of text is the default
2839 : character set for the version of Word that last saved the document.
2840 :
2841 : This is a bit tentative, more might be required if the concept is correct.
2842 : When later version of word write older 6/95 documents the charset is
2843 : correctly set in the character runs involved, so its hard to reproduce
2844 : documents that require this to be sure of the process involved.
2845 : */
2846 622 : const SvxLanguageItem *pLang = (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_CJK_LANGUAGE);
2847 622 : LanguageType eLang = pLang ? pLang->GetLanguage() : LANGUAGE_SYSTEM;
2848 622 : ::com::sun::star::lang::Locale aLocale(LanguageTag::convertToLocale(eLang));
2849 622 : return msfilter::util::getBestTextEncodingFromLocale(aLocale);
2850 : }
2851 :
2852 800 : rtl_TextEncoding SwWW8ImplReader::GetCurrentCharSet()
2853 : {
2854 : /*
2855 : #i2015
2856 : If the hard charset is set use it, if not see if there is an open
2857 : character run that has set the charset, if not then fallback to the
2858 : current underlying paragraph style.
2859 : */
2860 800 : rtl_TextEncoding eSrcCharSet = eHardCharSet;
2861 800 : if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2862 : {
2863 800 : if (!maFontSrcCharSets.empty())
2864 130 : eSrcCharSet = maFontSrcCharSets.top();
2865 800 : if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && nCharFmt >= 0 && (size_t)nCharFmt < vColl.size() )
2866 0 : eSrcCharSet = vColl[nCharFmt].GetCharSet();
2867 800 : if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && StyleExists(nAktColl) && nAktColl < vColl.size())
2868 670 : eSrcCharSet = vColl[nAktColl].GetCharSet();
2869 800 : if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2870 622 : eSrcCharSet = GetCharSetFromLanguage();
2871 : }
2872 800 : return eSrcCharSet;
2873 : }
2874 :
2875 : //Takashi Ono for CJK
2876 622 : rtl_TextEncoding SwWW8ImplReader::GetCurrentCJKCharSet()
2877 : {
2878 : /*
2879 : #i2015
2880 : If the hard charset is set use it, if not see if there is an open
2881 : character run that has set the charset, if not then fallback to the
2882 : current underlying paragraph style.
2883 : */
2884 622 : rtl_TextEncoding eSrcCharSet = eHardCharSet;
2885 622 : if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2886 : {
2887 622 : if (!maFontSrcCJKCharSets.empty())
2888 0 : eSrcCharSet = maFontSrcCJKCharSets.top();
2889 622 : if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && nCharFmt >= 0 && (size_t)nCharFmt < vColl.size() )
2890 0 : eSrcCharSet = vColl[nCharFmt].GetCJKCharSet();
2891 622 : if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW && StyleExists(nAktColl) && nAktColl < vColl.size())
2892 622 : eSrcCharSet = vColl[nAktColl].GetCJKCharSet();
2893 622 : if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2894 622 : eSrcCharSet = GetCJKCharSetFromLanguage();
2895 : }
2896 622 : return eSrcCharSet;
2897 : }
2898 :
2899 0 : void SwWW8ImplReader::PostProcessAttrs()
2900 : {
2901 0 : if (mpPostProcessAttrsInfo != NULL)
2902 : {
2903 0 : SfxItemIter aIter(mpPostProcessAttrsInfo->mItemSet);
2904 :
2905 0 : const SfxPoolItem * pItem = aIter.GetCurItem();
2906 0 : if (pItem != NULL)
2907 : {
2908 0 : do
2909 : {
2910 0 : pCtrlStck->NewAttr(*mpPostProcessAttrsInfo->mPaM.GetPoint(),
2911 0 : *pItem);
2912 0 : pCtrlStck->SetAttr(*mpPostProcessAttrsInfo->mPaM.GetMark(),
2913 0 : pItem->Which(), true);
2914 : }
2915 0 : while (!aIter.IsAtEnd() && 0 != (pItem = aIter.NextItem()));
2916 : }
2917 :
2918 0 : delete mpPostProcessAttrsInfo;
2919 0 : mpPostProcessAttrsInfo = NULL;
2920 : }
2921 0 : }
2922 :
2923 : /*
2924 : #i9241#
2925 : It appears that some documents that are in a baltic 8 bit encoding which has
2926 : some undefined characters can have use made of those characters, in which
2927 : case they default to CP1252. If not then its perhaps that the font encoding
2928 : is only in use for 6/7 and for 8+ if we are in 8bit mode then the encoding
2929 : is always 1252.
2930 :
2931 : So a encoding converter that on an undefined character attempts to
2932 : convert from 1252 on the undefined character
2933 : */
2934 3904 : sal_Size Custom8BitToUnicode(rtl_TextToUnicodeConverter hConverter,
2935 : sal_Char *pIn, sal_Size nInLen, sal_Unicode *pOut, sal_Size nOutLen)
2936 : {
2937 : const sal_uInt32 nFlags =
2938 : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
2939 : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
2940 : RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE |
2941 3904 : RTL_TEXTTOUNICODE_FLAGS_FLUSH;
2942 :
2943 : const sal_uInt32 nFlags2 =
2944 : RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE |
2945 : RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_IGNORE |
2946 : RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE |
2947 3904 : RTL_TEXTTOUNICODE_FLAGS_FLUSH;
2948 :
2949 3904 : sal_Size nDestChars=0;
2950 3904 : sal_Size nConverted=0;
2951 :
2952 3904 : do
2953 : {
2954 3904 : sal_uInt32 nInfo = 0;
2955 3904 : sal_Size nThisConverted=0;
2956 :
2957 : nDestChars += rtl_convertTextToUnicode(hConverter, 0,
2958 : pIn+nConverted, nInLen-nConverted,
2959 : pOut+nDestChars, nOutLen-nDestChars,
2960 3904 : nFlags, &nInfo, &nThisConverted);
2961 :
2962 : OSL_ENSURE(nInfo == 0, "A character conversion failed!");
2963 :
2964 3904 : nConverted += nThisConverted;
2965 :
2966 3904 : if (
2967 7808 : nInfo & RTL_TEXTTOUNICODE_INFO_UNDEFINED ||
2968 3904 : nInfo & RTL_TEXTTOUNICODE_INFO_MBUNDEFINED
2969 : )
2970 : {
2971 : sal_Size nOtherConverted;
2972 : rtl_TextToUnicodeConverter hCP1252Converter =
2973 0 : rtl_createTextToUnicodeConverter(RTL_TEXTENCODING_MS_1252);
2974 : nDestChars += rtl_convertTextToUnicode(hCP1252Converter, 0,
2975 : pIn+nConverted, 1,
2976 : pOut+nDestChars, nOutLen-nDestChars,
2977 0 : nFlags2, &nInfo, &nOtherConverted);
2978 0 : rtl_destroyTextToUnicodeConverter(hCP1252Converter);
2979 0 : nConverted+=1;
2980 : }
2981 : } while (nConverted < nInLen);
2982 :
2983 3904 : return nDestChars;
2984 : }
2985 :
2986 0 : bool SwWW8ImplReader::LangUsesHindiNumbers(sal_uInt16 nLang)
2987 : {
2988 0 : bool bResult = false;
2989 :
2990 0 : switch (nLang)
2991 : {
2992 : case 0x1401: // Arabic(Algeria)
2993 : case 0x3c01: // Arabic(Bahrain)
2994 : case 0xc01: // Arabic(Egypt)
2995 : case 0x801: // Arabic(Iraq)
2996 : case 0x2c01: // Arabic (Jordan)
2997 : case 0x3401: // Arabic(Kuwait)
2998 : case 0x3001: // Arabic(Lebanon)
2999 : case 0x1001: // Arabic(Libya)
3000 : case 0x1801: // Arabic(Morocco)
3001 : case 0x2001: // Arabic(Oman)
3002 : case 0x4001: // Arabic(Qatar)
3003 : case 0x401: // Arabic(Saudi Arabia)
3004 : case 0x2801: // Arabic(Syria)
3005 : case 0x1c01: // Arabic(Tunisia)
3006 : case 0x3801: // Arabic(U.A.E)
3007 : case 0x2401: // Arabic(Yemen)
3008 0 : bResult = true;
3009 0 : break;
3010 : default:
3011 0 : break;
3012 : }
3013 :
3014 0 : return bResult;
3015 : }
3016 :
3017 0 : sal_Unicode SwWW8ImplReader::TranslateToHindiNumbers(sal_Unicode nChar)
3018 : {
3019 0 : if (nChar >= 0x0030 && nChar <= 0x0039)
3020 0 : return nChar + 0x0630;
3021 :
3022 0 : return nChar;
3023 : }
3024 :
3025 : /**
3026 : * Return value: true for non special chars
3027 : */
3028 16734 : bool SwWW8ImplReader::ReadPlainChars(WW8_CP& rPos, sal_Int32 nEnd, sal_Int32 nCpOfs)
3029 : {
3030 16734 : sal_Int32 nRequestedStrLen = nEnd - rPos;
3031 :
3032 : OSL_ENSURE(nRequestedStrLen, "String is 0");
3033 16734 : if (nRequestedStrLen <= 0)
3034 0 : return true;
3035 :
3036 16734 : sal_Int32 nRequestedPos = pSBase->WW8Cp2Fc(nCpOfs+rPos, &bIsUnicode);
3037 16734 : bool bValidPos = checkSeek(*pStrm, nRequestedPos);
3038 : OSL_ENSURE(bValidPos, "Document claimed to have more text than available");
3039 16734 : if (!bValidPos)
3040 : {
3041 : // Swallow missing range, e.g. #i95550#
3042 0 : rPos+=nRequestedStrLen;
3043 0 : return true;
3044 : }
3045 :
3046 16734 : sal_Size nAvailableStrLen = pStrm->remainingSize() / (bIsUnicode ? 2 : 1);
3047 : OSL_ENSURE(nAvailableStrLen, "Document claimed to have more text than available");
3048 16734 : if (!nAvailableStrLen)
3049 : {
3050 : // Swallow missing range, e.g. #i95550#
3051 0 : rPos+=nRequestedStrLen;
3052 0 : return true;
3053 : }
3054 :
3055 16734 : sal_Int32 nValidStrLen = std::min<sal_Size>(nRequestedStrLen, nAvailableStrLen);
3056 :
3057 : // Reset Unicode flag and correct FilePos if needed.
3058 : // Note: Seek is not expensive, as we're checking inline whether or not
3059 : // the correct FilePos has already been reached.
3060 16734 : const sal_Int32 nStrLen = std::min(nValidStrLen, SAL_MAX_INT32-1);
3061 :
3062 : rtl_TextEncoding eSrcCharSet = bVer67 ? GetCurrentCharSet() :
3063 16734 : RTL_TEXTENCODING_MS_1252;
3064 16734 : if (bVer67 && eSrcCharSet == RTL_TEXTENCODING_MS_932)
3065 : {
3066 : /*
3067 : fdo#82904
3068 :
3069 : Older documents exported as word 95 that use unicode aware fonts will
3070 : have the charset of those fonts set to RTL_TEXTENCODING_MS_932 on
3071 : export as the conversion from RTL_TEXTENCODING_UNICODE. This is a serious
3072 : pain.
3073 :
3074 : We will try and use a fallback encoding if the conversion from
3075 : RTL_TEXTENCODING_MS_932 fails, but you can get unlucky and get a document
3076 : which isn't really in RTL_TEXTENCODING_MS_932 but parts of it form
3077 : valid RTL_TEXTENCODING_MS_932 by chance :-(
3078 :
3079 : We're not the only ones that struggle with this: Here's the help from
3080 : MSOffice 2003 on the topic:
3081 :
3082 : <<
3083 : Earlier versions of Microsoft Word were sometimes used in conjunction with
3084 : third-party language-processing add-in programs designed to support Chinese or
3085 : Korean on English versions of Microsoft Windows. Use of these add-ins sometimes
3086 : results in incorrect text display in more recent versions of Word.
3087 :
3088 : However, you can set options to convert these documents so that text is
3089 : displayed correctly. On the Tools menu, click Options, and then click the
3090 : General tab. In the English Word 6.0/95 documents list, select Contain Asian
3091 : text (to have Word interpret the text as Asian code page data, regardless of
3092 : its font) or Automatically detect Asian text (to have Word attempt to determine
3093 : which parts of the text are meant to be Asian).
3094 : >>
3095 :
3096 : What we can try here is to ignore a RTL_TEXTENCODING_MS_932 codepage if
3097 : the language is not Japanese
3098 : */
3099 :
3100 0 : const SfxPoolItem * pItem = GetFmtAttr(RES_CHRATR_CJK_LANGUAGE);
3101 0 : if (pItem != NULL && LANGUAGE_JAPANESE != static_cast<const SvxLanguageItem *>(pItem)->GetLanguage())
3102 : {
3103 : SAL_WARN("sw.ww8", "discarding word95 RTL_TEXTENCODING_MS_932 encoding");
3104 0 : eSrcCharSet = GetCharSetFromLanguage();
3105 : }
3106 : }
3107 : const rtl_TextEncoding eSrcCJKCharSet = bVer67 ? GetCurrentCJKCharSet() :
3108 16734 : RTL_TEXTENCODING_MS_1252;
3109 :
3110 : // allocate unicode string data
3111 16734 : rtl_uString *pStr = rtl_uString_alloc(nStrLen);
3112 16734 : sal_Unicode* pBuffer = pStr->buffer;
3113 16734 : sal_Unicode* pWork = pBuffer;
3114 :
3115 16734 : sal_Char* p8Bits = NULL;
3116 :
3117 16734 : rtl_TextToUnicodeConverter hConverter = 0;
3118 16734 : if (!bIsUnicode || bVer67)
3119 10496 : hConverter = rtl_createTextToUnicodeConverter(eSrcCharSet);
3120 :
3121 16734 : if (!bIsUnicode)
3122 10496 : p8Bits = new sal_Char[nStrLen];
3123 :
3124 : // read the stream data
3125 16734 : sal_uInt8 nBCode = 0;
3126 : sal_uInt16 nUCode;
3127 :
3128 16734 : sal_uInt16 nCTLLang = 0;
3129 16734 : const SfxPoolItem * pItem = GetFmtAttr(RES_CHRATR_CTL_LANGUAGE);
3130 16734 : if (pItem != NULL)
3131 16734 : nCTLLang = static_cast<const SvxLanguageItem *>(pItem)->GetLanguage();
3132 :
3133 : sal_Int32 nL2;
3134 363528 : for( nL2 = 0; nL2 < nStrLen; ++nL2, ++pWork )
3135 : {
3136 357224 : if (bIsUnicode)
3137 35518 : pStrm->ReadUInt16( nUCode ); // unicode --> read 2 bytes
3138 : else
3139 : {
3140 321706 : pStrm->ReadUChar( nBCode ); // old code --> read 1 byte
3141 321706 : nUCode = nBCode;
3142 : }
3143 :
3144 357224 : if (pStrm->GetError())
3145 : {
3146 0 : rPos = WW8_CP_MAX-10; // -> eof or other error
3147 0 : rtl_freeMemory(pStr);
3148 0 : delete [] p8Bits;
3149 0 : return true;
3150 : }
3151 :
3152 357224 : if ((32 > nUCode) || (0xa0 == nUCode))
3153 : {
3154 10430 : pStrm->SeekRel( bIsUnicode ? -2 : -1 );
3155 10430 : break; // Special character < 32, == 0xa0 found
3156 : }
3157 :
3158 346794 : if (bIsUnicode)
3159 : {
3160 32148 : if (!bVer67)
3161 32148 : *pWork = nUCode;
3162 : else
3163 : {
3164 0 : if (nUCode >= 0x3000) //0x8000 ?
3165 : {
3166 : sal_Char aTest[2];
3167 0 : aTest[0] = static_cast< sal_Char >((nUCode & 0xFF00) >> 8);
3168 0 : aTest[1] = static_cast< sal_Char >(nUCode & 0x00FF);
3169 0 : OUString aTemp(aTest, 2, eSrcCJKCharSet);
3170 : OSL_ENSURE(aTemp.getLength() == 1, "so much for that theory");
3171 0 : *pWork = aTemp[0];
3172 : }
3173 : else
3174 : {
3175 0 : sal_Char cTest = static_cast< sal_Char >(nUCode & 0x00FF);
3176 0 : Custom8BitToUnicode(hConverter, &cTest, 1, pWork, 1);
3177 : }
3178 : }
3179 : }
3180 : else
3181 314646 : p8Bits[nL2] = nBCode;
3182 : }
3183 :
3184 16734 : if (nL2)
3185 : {
3186 6788 : const sal_Int32 nEndUsed = !bIsUnicode
3187 3904 : ? Custom8BitToUnicode(hConverter, p8Bits, nL2, pBuffer, nStrLen)
3188 10692 : : nL2;
3189 :
3190 402764 : for( sal_Int32 nI = 0; nI < nStrLen; ++nI, ++pBuffer )
3191 395976 : if (m_bRegardHindiDigits && bBidi && LangUsesHindiNumbers(nCTLLang))
3192 0 : *pBuffer = TranslateToHindiNumbers(*pBuffer);
3193 :
3194 6788 : pStr->buffer[nEndUsed] = 0;
3195 6788 : pStr->length = nEndUsed;
3196 :
3197 6788 : emulateMSWordAddTextToParagraph(OUString(pStr, SAL_NO_ACQUIRE));
3198 6788 : pStr = NULL;
3199 6788 : rPos += nL2;
3200 6788 : if (!maApos.back()) // a para end in apo doesn't count
3201 6778 : bWasParaEnd = false; // No CR
3202 : }
3203 :
3204 16734 : if (hConverter)
3205 10496 : rtl_destroyTextToUnicodeConverter(hConverter);
3206 16734 : if (pStr)
3207 9946 : rtl_uString_release(pStr);
3208 16734 : delete [] p8Bits;
3209 16734 : return nL2 >= nStrLen;
3210 : }
3211 :
3212 : #define MSASCII SAL_MAX_INT16
3213 :
3214 : namespace
3215 : {
3216 : // We want to force weak chars inside 0x0020 to 0x007F to LATIN
3217 544938 : sal_Int16 lcl_getScriptType(
3218 : const uno::Reference<i18n::XBreakIterator>& rBI,
3219 : const OUString &rString, sal_Int32 nPos)
3220 : {
3221 544938 : sal_Int16 nScript = rBI->getScriptType(rString, nPos);
3222 544938 : if (nScript == i18n::ScriptType::WEAK && rString[nPos] >= 0x0020 && rString[nPos] <= 0x007F)
3223 144548 : nScript = MSASCII;
3224 544938 : return nScript;
3225 : }
3226 :
3227 : // We want to know about WEAK segments, so endOfScript isn't
3228 : // useful, and see lcl_getScriptType anyway
3229 102466 : sal_Int32 lcl_endOfScript(
3230 : const uno::Reference<i18n::XBreakIterator>& rBI,
3231 : const OUString &rString, sal_Int32 nPos, sal_Int16 nScript)
3232 : {
3233 552676 : while (nPos < rString.getLength())
3234 : {
3235 442472 : sal_Int16 nNewScript = lcl_getScriptType(rBI, rString, nPos);
3236 442472 : if (nScript != nNewScript)
3237 94728 : break;
3238 347744 : ++nPos;
3239 : }
3240 102466 : return nPos;
3241 : }
3242 :
3243 48464 : sal_Int32 lcl_getWriterScriptType(
3244 : const uno::Reference<i18n::XBreakIterator>& rBI,
3245 : const OUString &rString, sal_Int32 nPos)
3246 : {
3247 48464 : sal_Int16 nScript = i18n::ScriptType::WEAK;
3248 :
3249 48464 : if (rString.isEmpty())
3250 0 : return nScript;
3251 :
3252 145764 : while (nPos >= 0)
3253 : {
3254 97210 : nScript = rBI->getScriptType(rString, nPos);
3255 97210 : if (nScript != i18n::ScriptType::WEAK)
3256 48374 : break;
3257 48836 : --nPos;
3258 : }
3259 :
3260 48464 : return nScript;
3261 : }
3262 :
3263 2 : bool samePitchIgnoreUnknown(FontPitch eA, FontPitch eB)
3264 : {
3265 2 : return (eA == eB || eA == PITCH_DONTKNOW || eB == PITCH_DONTKNOW);
3266 : }
3267 :
3268 1444 : bool sameFontIgnoringIrrelevantFields(const SvxFontItem &rA, const SvxFontItem &rB)
3269 : {
3270 : // Ignoring CharSet, and ignoring unknown pitch
3271 1446 : return rA.GetFamilyName() == rB.GetFamilyName() &&
3272 4 : rA.GetStyleName() == rB.GetStyleName() &&
3273 1448 : rA.GetFamily() == rB.GetFamily() &&
3274 1446 : samePitchIgnoreUnknown(rA.GetPitch(), rB.GetPitch());
3275 : }
3276 : }
3277 :
3278 : // In writer we categorize text into CJK, CTL and "Western" for everything else.
3279 : // Microsoft Word basically categorizes text into East Asian, Complex, ASCII,
3280 : // NonEastAsian/HighAnsi, with some shared characters and some properties to
3281 : // hint as to which way to bias those shared characters.
3282 :
3283 : // That's four categories, we however have three categories. Given that problem
3284 : // here we would ideally find out "what would word do" to see what font/language
3285 : // word would assign to characters based on the unicode range they fall into and
3286 : // hack the word one onto the range we use. However it's unclear what word's
3287 : // categorization is. So we don't do that here yet.
3288 :
3289 : // Additional to the categorization, when word encounters weak text for ambigious
3290 : // chars it uses idcthint to indicate which way to bias. We don't have a idcthint
3291 : // feature in writer.
3292 :
3293 : // So what we currently do here then is to split our text into non-weak/weak
3294 : // sections and uses word's idcthint to determine what font it would use and
3295 : // force that on for the segment. Following what we *do* know about word's
3296 : // categorization, we know that the range 0x0020 and 0x007F is sprmCRgFtc0 in
3297 : // word, something we map to LATIN, so we consider all weaks chars in that range
3298 : // to auto-bias to LATIN.
3299 :
3300 : // See https://bugs.libreoffice.org/show_bug.cgi?id=34319 for an example
3301 : //
3302 : // TO-DO: revisit this after the fix of #i119612# which retains the
3303 : // idcthint feature on import from word and has it available for reexport
3304 : // but we don't use it yet for the actual rendering and layout
3305 7738 : void SwWW8ImplReader::emulateMSWordAddTextToParagraph(const OUString& rAddString)
3306 : {
3307 7738 : if (rAddString.isEmpty())
3308 0 : return;
3309 :
3310 7738 : uno::Reference<i18n::XBreakIterator> xBI(g_pBreakIt->GetBreakIter());
3311 7738 : if (!xBI.is())
3312 : {
3313 0 : simpleAddTextToParagraph(rAddString);
3314 0 : return;
3315 : }
3316 :
3317 7738 : sal_Int16 nScript = lcl_getScriptType(xBI, rAddString, 0);
3318 7738 : sal_Int32 nLen = rAddString.getLength();
3319 :
3320 15476 : OUString sParagraphText;
3321 7738 : const SwCntntNode *pCntNd = pPaM->GetCntntNode();
3322 7738 : const SwTxtNode* pNd = pCntNd ? pCntNd->GetTxtNode() : NULL;
3323 7738 : if (pNd)
3324 7738 : sParagraphText = pNd->GetTxt();
3325 7738 : sal_Int32 nParaOffset = sParagraphText.getLength();
3326 7738 : sParagraphText = sParagraphText + rAddString;
3327 :
3328 7738 : sal_Int32 nPos = 0;
3329 117942 : while (nPos < nLen)
3330 : {
3331 102466 : sal_Int32 nEnd = lcl_endOfScript(xBI, rAddString, nPos, nScript);
3332 102466 : if (nEnd < 0)
3333 0 : break;
3334 :
3335 102466 : OUString sChunk(rAddString.copy(nPos, nEnd-nPos));
3336 102466 : const sal_uInt16 aIds[] = {RES_CHRATR_FONT, RES_CHRATR_CJK_FONT, RES_CHRATR_CTL_FONT};
3337 102466 : const SvxFontItem *pOverriddenItems[] = {NULL, NULL, NULL};
3338 102466 : bool aForced[] = {false, false, false};
3339 :
3340 102466 : int nLclIdctHint = 0xFF;
3341 102466 : if (nScript == i18n::ScriptType::WEAK)
3342 398 : nLclIdctHint = nIdctHint;
3343 102068 : else if (nScript == MSASCII) // Force weak chars in ascii range to use LATIN font
3344 48066 : nLclIdctHint = 0;
3345 :
3346 102466 : sal_uInt16 nForceFromFontId = 0;
3347 102466 : if (nLclIdctHint != 0xFF)
3348 : {
3349 48464 : switch (nLclIdctHint)
3350 : {
3351 : case 0:
3352 48464 : nForceFromFontId = RES_CHRATR_FONT;
3353 48464 : break;
3354 : case 1:
3355 0 : nForceFromFontId = RES_CHRATR_CJK_FONT;
3356 0 : break;
3357 : case 2:
3358 0 : nForceFromFontId = RES_CHRATR_CTL_FONT;
3359 0 : break;
3360 : default:
3361 0 : break;
3362 : }
3363 : }
3364 :
3365 102466 : if (nForceFromFontId != 0)
3366 : {
3367 : // Now we know that word would use the nForceFromFontId font for this range
3368 : // Try and determine what script writer would assign this range to
3369 :
3370 : sal_Int32 nWriterScript = lcl_getWriterScriptType(xBI, sParagraphText,
3371 48464 : nPos + nParaOffset);
3372 :
3373 48464 : bool bWriterWillUseSameFontAsWordAutomatically = false;
3374 :
3375 48464 : if (nWriterScript != i18n::ScriptType::WEAK)
3376 : {
3377 48374 : if (
3378 0 : (nWriterScript == i18n::ScriptType::ASIAN && nForceFromFontId == RES_CHRATR_CJK_FONT) ||
3379 1444 : (nWriterScript == i18n::ScriptType::COMPLEX && nForceFromFontId == RES_CHRATR_CTL_FONT) ||
3380 46930 : (nWriterScript == i18n::ScriptType::LATIN && nForceFromFontId == RES_CHRATR_FONT)
3381 : )
3382 : {
3383 46930 : bWriterWillUseSameFontAsWordAutomatically = true;
3384 : }
3385 : else
3386 : {
3387 1444 : const SvxFontItem *pSourceFont = (const SvxFontItem*)GetFmtAttr(nForceFromFontId);
3388 1444 : sal_uInt16 nDestId = aIds[nWriterScript-1];
3389 1444 : const SvxFontItem *pDestFont = (const SvxFontItem*)GetFmtAttr(nDestId);
3390 1444 : bWriterWillUseSameFontAsWordAutomatically = sameFontIgnoringIrrelevantFields(*pSourceFont, *pDestFont);
3391 : }
3392 : }
3393 :
3394 : // Writer won't use the same font as word, so force the issue
3395 48464 : if (!bWriterWillUseSameFontAsWordAutomatically)
3396 : {
3397 1532 : const SvxFontItem *pSourceFont = (const SvxFontItem*)GetFmtAttr(nForceFromFontId);
3398 :
3399 6128 : for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i)
3400 : {
3401 4596 : const SvxFontItem *pDestFont = (const SvxFontItem*)GetFmtAttr(aIds[i]);
3402 4596 : aForced[i] = aIds[i] != nForceFromFontId && *pSourceFont != *pDestFont;
3403 4596 : if (aForced[i])
3404 : {
3405 : pOverriddenItems[i] =
3406 2932 : (const SvxFontItem*)pCtrlStck->GetStackAttr(*pPaM->GetPoint(), aIds[i]);
3407 :
3408 2932 : SvxFontItem aForceFont(*pSourceFont);
3409 2932 : aForceFont.SetWhich(aIds[i]);
3410 2932 : pCtrlStck->NewAttr(*pPaM->GetPoint(), aForceFont);
3411 : }
3412 : }
3413 : }
3414 : }
3415 :
3416 102466 : simpleAddTextToParagraph(sChunk);
3417 :
3418 409864 : for (size_t i = 0; i < SAL_N_ELEMENTS(aIds); ++i)
3419 : {
3420 307398 : if (aForced[i])
3421 : {
3422 2932 : pCtrlStck->SetAttr(*pPaM->GetPoint(), aIds[i]);
3423 2932 : if (pOverriddenItems[i])
3424 1448 : pCtrlStck->NewAttr(*pPaM->GetPoint(), *(pOverriddenItems[i]));
3425 : }
3426 : }
3427 :
3428 102466 : nPos = nEnd;
3429 102466 : if (nPos < nLen)
3430 94728 : nScript = lcl_getScriptType(xBI, rAddString, nPos);
3431 110204 : }
3432 : }
3433 :
3434 102466 : void SwWW8ImplReader::simpleAddTextToParagraph(const OUString& rAddString)
3435 : {
3436 102466 : if (rAddString.isEmpty())
3437 0 : return;
3438 :
3439 : #if OSL_DEBUG_LEVEL > 1
3440 : {
3441 : OString sText(OUStringToOString(rAddString, RTL_TEXTENCODING_UTF8));
3442 : SAL_INFO("sw.ww8", "<addTextToParagraph>" << sText.getStr() << "</addTextToParagraph>");
3443 : }
3444 : #endif
3445 :
3446 102466 : const SwCntntNode *pCntNd = pPaM->GetCntntNode();
3447 102466 : const SwTxtNode* pNd = pCntNd ? pCntNd->GetTxtNode() : NULL;
3448 :
3449 : OSL_ENSURE(pNd, "What the hell, where's my text node");
3450 :
3451 102466 : if (!pNd)
3452 0 : return;
3453 :
3454 102466 : const sal_Int32 nCharsLeft = SAL_MAX_INT32 - pNd->GetTxt().getLength();
3455 102466 : if (nCharsLeft > 0)
3456 : {
3457 102466 : if (rAddString.getLength() <= nCharsLeft)
3458 : {
3459 102466 : rDoc.getIDocumentContentOperations().InsertString(*pPaM, rAddString);
3460 : }
3461 : else
3462 : {
3463 0 : rDoc.getIDocumentContentOperations().InsertString(*pPaM, rAddString.copy(0, nCharsLeft));
3464 0 : AppendTxtNode(*pPaM->GetPoint());
3465 0 : rDoc.getIDocumentContentOperations().InsertString(*pPaM, rAddString.copy(nCharsLeft));
3466 : }
3467 : }
3468 : else
3469 : {
3470 0 : AppendTxtNode(*pPaM->GetPoint());
3471 0 : rDoc.getIDocumentContentOperations().InsertString(*pPaM, rAddString);
3472 : }
3473 :
3474 102466 : bReadTable = false;
3475 : }
3476 :
3477 : /**
3478 : * Return value: true for para end
3479 : */
3480 15066 : bool SwWW8ImplReader::ReadChars(WW8_CP& rPos, WW8_CP nNextAttr, long nTextEnd,
3481 : long nCpOfs)
3482 : {
3483 15066 : long nEnd = ( nNextAttr < nTextEnd ) ? nNextAttr : nTextEnd;
3484 :
3485 15066 : if (bSymbol || bIgnoreText)
3486 : {
3487 8 : if( bSymbol ) // Insert special chars
3488 : {
3489 0 : for(sal_uInt16 nCh = 0; nCh < nEnd - rPos; ++nCh)
3490 : {
3491 0 : rDoc.getIDocumentContentOperations().InsertString( *pPaM, OUString(cSymbol) );
3492 : }
3493 0 : pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_FONT );
3494 : }
3495 8 : pStrm->SeekRel( nEnd- rPos );
3496 8 : rPos = nEnd; // Ignore until attribute end
3497 8 : return false;
3498 : }
3499 :
3500 : while (true)
3501 : {
3502 16734 : if (ReadPlainChars(rPos, nEnd, nCpOfs))
3503 6304 : return false; // Done
3504 :
3505 10430 : bool bStartLine = ReadChar(rPos, nCpOfs);
3506 10430 : rPos++;
3507 10430 : if (bPgSecBreak || bStartLine || rPos == nEnd) // CR or Done
3508 : {
3509 8754 : return bStartLine;
3510 : }
3511 1676 : }
3512 : }
3513 :
3514 124 : bool SwWW8ImplReader::HandlePageBreakChar()
3515 : {
3516 124 : bool bParaEndAdded = false;
3517 : // #i1909# section/page breaks should not occur in tables, word
3518 : // itself ignores them in this case.
3519 124 : if (!nInTable)
3520 : {
3521 124 : bool IsTemp=true;
3522 124 : SwTxtNode* pTemp = pPaM->GetNode().GetTxtNode();
3523 248 : if (pTemp && pTemp->GetTxt().isEmpty()
3524 232 : && (bFirstPara || bFirstParaOfPage))
3525 : {
3526 6 : IsTemp = false;
3527 6 : AppendTxtNode(*pPaM->GetPoint());
3528 6 : pTemp->SetAttr(*GetDfltAttr(RES_PARATR_NUMRULE));
3529 : }
3530 :
3531 124 : bPgSecBreak = true;
3532 124 : pCtrlStck->KillUnlockedAttrs(*pPaM->GetPoint());
3533 : /*
3534 : If it's a 0x0c without a paragraph end before it, act like a
3535 : paragraph end, but nevertheless, numbering (and perhaps other
3536 : similar constructs) do not exist on the para.
3537 : */
3538 124 : if (!bWasParaEnd && IsTemp)
3539 : {
3540 20 : bParaEndAdded = true;
3541 20 : if (0 >= pPaM->GetPoint()->nContent.GetIndex())
3542 : {
3543 4 : if (SwTxtNode* pTxtNode = pPaM->GetNode().GetTxtNode())
3544 : {
3545 : pTxtNode->SetAttr(
3546 4 : *GetDfltAttr(RES_PARATR_NUMRULE));
3547 : }
3548 : }
3549 : }
3550 : }
3551 124 : return bParaEndAdded;
3552 : }
3553 :
3554 10430 : bool SwWW8ImplReader::ReadChar(long nPosCp, long nCpOfs)
3555 : {
3556 10430 : bool bNewParaEnd = false;
3557 : // Reset Unicode flag and correct FilePos if needed.
3558 : // Note: Seek is not expensive, as we're checking inline whether or not
3559 : // the correct FilePos has already been reached.
3560 10430 : sal_Size nRequestedPos = pSBase->WW8Cp2Fc(nCpOfs+nPosCp, &bIsUnicode);
3561 10430 : if (!checkSeek(*pStrm, nRequestedPos))
3562 0 : return false;
3563 :
3564 10430 : sal_uInt8 nBCode(0);
3565 10430 : sal_uInt16 nWCharVal(0);
3566 10430 : if( bIsUnicode )
3567 3370 : pStrm->ReadUInt16( nWCharVal ); // unicode --> read 2 bytes
3568 : else
3569 : {
3570 7060 : pStrm -> ReadUChar( nBCode ); // old code --> read 1 byte
3571 7060 : nWCharVal = nBCode;
3572 : }
3573 :
3574 10430 : sal_Unicode cInsert = '\x0';
3575 10430 : bool bRet = false;
3576 :
3577 10430 : if ( 0xc != nWCharVal )
3578 10306 : bFirstParaOfPage = false;
3579 :
3580 10430 : switch (nWCharVal)
3581 : {
3582 : case 0:
3583 : {
3584 : // Page number
3585 : SwPageNumberField aFld(
3586 940 : (SwPageNumberFieldType*)rDoc.getIDocumentFieldsAccess().GetSysFldType(
3587 940 : RES_PAGENUMBERFLD ), PG_RANDOM, SVX_NUM_ARABIC);
3588 940 : rDoc.getIDocumentContentOperations().InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
3589 : }
3590 940 : break;
3591 : case 0xe:
3592 : // if there is only one column word treats a column break like a pagebreak.
3593 0 : if (maSectionManager.CurrentSectionColCount() < 2)
3594 0 : bRet = HandlePageBreakChar();
3595 0 : else if (!nInTable)
3596 : {
3597 : // Always insert a txtnode for a column break, e.g. ##
3598 0 : SwCntntNode *pCntNd=pPaM->GetCntntNode();
3599 0 : if (pCntNd!=NULL && pCntNd->Len()>0) // if par is empty not break is needed
3600 0 : AppendTxtNode(*pPaM->GetPoint());
3601 0 : rDoc.getIDocumentContentOperations().InsertPoolItem(*pPaM, SvxFmtBreakItem(SVX_BREAK_COLUMN_BEFORE, RES_BREAK), 0);
3602 : }
3603 0 : break;
3604 : case 0x7:
3605 2192 : bNewParaEnd = true;
3606 2192 : TabCellEnd(); // Table cell end (query flags!)
3607 2192 : break;
3608 : case 0xf:
3609 0 : if( !bSpec ) // "Satellite"
3610 0 : cInsert = sal_Unicode('\xa4');
3611 0 : break;
3612 : case 0x14:
3613 40 : if( !bSpec ) // "Para End" char
3614 0 : cInsert = sal_Unicode('\xb5');
3615 40 : break;
3616 : case 0x15:
3617 42 : if( !bSpec ) // Juristenparagraph
3618 : {
3619 0 : cp_set::iterator aItr = maTOXEndCps.find((WW8_CP)nPosCp);
3620 0 : if (aItr == maTOXEndCps.end())
3621 0 : cInsert = sal_Unicode('\xa7');
3622 : else
3623 0 : maTOXEndCps.erase(aItr);
3624 : }
3625 42 : break;
3626 : case 0x9:
3627 912 : cInsert = '\x9'; // Tab
3628 912 : break;
3629 : case 0xb:
3630 32 : cInsert = '\xa'; // Hard NewLine
3631 32 : break;
3632 : case 0xc:
3633 124 : bRet = HandlePageBreakChar();
3634 124 : break;
3635 : case 0x1e: // Non-breaking hyphen
3636 0 : rDoc.getIDocumentContentOperations().InsertString( *pPaM, OUString(CHAR_HARDHYPHEN) );
3637 0 : break;
3638 : case 0x1f: // Non-required hyphens
3639 0 : rDoc.getIDocumentContentOperations().InsertString( *pPaM, OUString(CHAR_SOFTHYPHEN) );
3640 0 : break;
3641 : case 0xa0: // Non-breaking spaces
3642 4 : rDoc.getIDocumentContentOperations().InsertString( *pPaM, OUString(CHAR_HARDBLANK) );
3643 4 : break;
3644 : case 0x1:
3645 : /*
3646 : Current thinking is that if bObj is set then we have a
3647 : straightforward "traditional" ole object, otherwise we have a
3648 : graphic preview of an associated ole2 object (or a simple
3649 : graphic of course)
3650 :
3651 : normally in the canvas field, the code is 0x8 0x1.
3652 : in a special case, the code is 0x1 0x1, which yields a simple picture
3653 : */
3654 : {
3655 50 : bool bReadObj = IsInlineEscherHack();
3656 50 : if( bReadObj )
3657 : {
3658 6 : long nCurPos = pStrm->Tell();
3659 6 : sal_uInt16 nWordCode(0);
3660 :
3661 6 : if( bIsUnicode )
3662 4 : pStrm->ReadUInt16( nWordCode );
3663 : else
3664 : {
3665 2 : sal_uInt8 nByteCode(0);
3666 2 : pStrm->ReadUChar( nByteCode );
3667 2 : nWordCode = nByteCode;
3668 : }
3669 6 : if( nWordCode == 0x1 )
3670 0 : bReadObj = false;
3671 6 : pStrm->Seek( nCurPos );
3672 : }
3673 50 : if( !bReadObj )
3674 : {
3675 44 : SwFrmFmt *pResult = 0;
3676 44 : if (bObj)
3677 0 : pResult = ImportOle();
3678 44 : else if (bSpec)
3679 42 : pResult = ImportGraf();
3680 :
3681 : // If we have a bad 0x1 insert a space instead.
3682 44 : if (!pResult)
3683 : {
3684 2 : cInsert = ' ';
3685 : OSL_ENSURE(!bObj && !bEmbeddObj && !nObjLocFc,
3686 : "WW8: Please report this document, it may have a "
3687 : "missing graphic");
3688 : }
3689 : else
3690 : {
3691 : // reset the flags.
3692 42 : bObj = bEmbeddObj = false;
3693 42 : nObjLocFc = 0;
3694 : }
3695 : }
3696 : }
3697 50 : break;
3698 : case 0x8:
3699 184 : if( !bObj )
3700 184 : Read_GrafLayer( nPosCp );
3701 184 : break;
3702 : case 0xd:
3703 5728 : bNewParaEnd = bRet = true;
3704 5728 : if (nInTable > 1)
3705 : {
3706 : /*
3707 : #i9666#/#i23161#
3708 : Yes complex, if there is an entry in the undocumented PLCF
3709 : which I believe to be a record of cell and row boundaries
3710 : see if the magic bit which I believe to mean cell end is
3711 : set. I also think btw that the third byte of the 4 byte
3712 : value is the level of the cell
3713 : */
3714 216 : WW8PLCFspecial* pTest = pPlcxMan->GetMagicTables();
3715 432 : if (pTest && pTest->SeekPosExact(nPosCp+1+nCpOfs) &&
3716 216 : pTest->Where() == nPosCp+1+nCpOfs)
3717 : {
3718 : WW8_FC nPos;
3719 : void *pData;
3720 216 : pTest->Get(nPos, pData);
3721 216 : sal_uInt32 nData = SVBT32ToUInt32(*(SVBT32*)pData);
3722 216 : if (nData & 0x2) // Might be how it works
3723 : {
3724 216 : TabCellEnd();
3725 216 : bRet = false;
3726 : }
3727 : }
3728 0 : else if (bWasTabCellEnd)
3729 : {
3730 0 : TabCellEnd();
3731 0 : bRet = false;
3732 : }
3733 : }
3734 :
3735 5728 : bWasTabCellEnd = false;
3736 :
3737 5728 : break; // line end
3738 : case 0x5: // Annotation reference
3739 : case 0x13:
3740 32 : break;
3741 : case 0x2: // TODO: Auto-Footnote-Number, should be replaced by SwWW8ImplReader::End_Ftn later
3742 4 : if (!maFtnStack.empty())
3743 4 : cInsert = 0x2;
3744 4 : break;
3745 : default:
3746 : SAL_INFO( "sw.ww8.level2", "<unknownValue val=\"" << nWCharVal << "\">" );
3747 146 : break;
3748 : }
3749 :
3750 10430 : if( '\x0' != cInsert )
3751 : {
3752 950 : OUString sInsert(cInsert);
3753 950 : emulateMSWordAddTextToParagraph(sInsert);
3754 : }
3755 10430 : if (!maApos.back()) // a para end in apo doesn't count
3756 10418 : bWasParaEnd = bNewParaEnd;
3757 10430 : return bRet;
3758 : }
3759 :
3760 13064 : void SwWW8ImplReader::ProcessAktCollChange(WW8PLCFManResult& rRes,
3761 : bool* pStartAttr, bool bCallProcessSpecial)
3762 : {
3763 13064 : sal_uInt16 nOldColl = nAktColl;
3764 13064 : nAktColl = pPlcxMan->GetColl();
3765 :
3766 : // Invalid Style-Id
3767 13064 : if (nAktColl >= vColl.size() || !vColl[nAktColl].pFmt || !vColl[nAktColl].bColl)
3768 : {
3769 0 : nAktColl = 0;
3770 0 : bParaAutoBefore = false;
3771 0 : bParaAutoAfter = false;
3772 : }
3773 : else
3774 : {
3775 13064 : bParaAutoBefore = vColl[nAktColl].bParaAutoBefore;
3776 13064 : bParaAutoAfter = vColl[nAktColl].bParaAutoAfter;
3777 : }
3778 :
3779 13064 : if (nOldColl >= vColl.size())
3780 0 : nOldColl = 0; // guess! TODO make sure this is what we want
3781 :
3782 13064 : bool bTabRowEnd = false;
3783 13064 : if( pStartAttr && bCallProcessSpecial && !bInHyperlink )
3784 : {
3785 : bool bReSync;
3786 : // Frame/Table/Autonumbering List Level
3787 7982 : bTabRowEnd = ProcessSpecial(bReSync, rRes.nAktCp+pPlcxMan->GetCpOfs());
3788 7982 : if( bReSync )
3789 3190 : *pStartAttr = pPlcxMan->Get( &rRes ); // Get Attribut-Pos again
3790 : }
3791 :
3792 13064 : if (!bTabRowEnd && StyleExists(nAktColl))
3793 : {
3794 12520 : SetTxtFmtCollAndListLevel( *pPaM, vColl[ nAktColl ]);
3795 12520 : ChkToggleAttr(vColl[ nOldColl ].n81Flags, vColl[ nAktColl ].n81Flags);
3796 12520 : ChkToggleBiDiAttr(vColl[nOldColl].n81BiDiFlags,
3797 25040 : vColl[nAktColl].n81BiDiFlags);
3798 : }
3799 13064 : }
3800 :
3801 189870 : long SwWW8ImplReader::ReadTextAttr(WW8_CP& rTxtPos, bool& rbStartLine)
3802 : {
3803 189870 : long nSkipChars = 0;
3804 : WW8PLCFManResult aRes;
3805 :
3806 : OSL_ENSURE(pPaM->GetNode().GetTxtNode(), "Missing txtnode");
3807 189870 : bool bStartAttr = pPlcxMan->Get(&aRes); // Get Attribute position again
3808 189870 : aRes.nAktCp = rTxtPos; // Current Cp position
3809 :
3810 189870 : bool bNewSection = (aRes.nFlags & MAN_MASK_NEW_SEP) && !bIgnoreText;
3811 189870 : if ( bNewSection ) // New Section
3812 : {
3813 : OSL_ENSURE(pPaM->GetNode().GetTxtNode(), "Missing txtnode");
3814 : // Create PageDesc and fill it
3815 222 : maSectionManager.CreateSep(rTxtPos, bPgSecBreak);
3816 : // -> 0xc was a Sectionbreak, but not a Pagebreak;
3817 : // Create PageDesc and fill it
3818 222 : bPgSecBreak = false;
3819 : OSL_ENSURE(pPaM->GetNode().GetTxtNode(), "Missing txtnode");
3820 : }
3821 :
3822 : // New paragraph over Plcx.Fkp.papx
3823 189870 : if ( (aRes.nFlags & MAN_MASK_NEW_PAP)|| rbStartLine )
3824 : {
3825 : ProcessAktCollChange( aRes, &bStartAttr,
3826 21046 : MAN_MASK_NEW_PAP == (aRes.nFlags & MAN_MASK_NEW_PAP) &&
3827 21046 : !bIgnoreText );
3828 13064 : rbStartLine = false;
3829 : }
3830 :
3831 : // position of last CP that's to be ignored
3832 189870 : long nSkipPos = -1;
3833 :
3834 189870 : if( 0 < aRes.nSprmId ) // Ignore empty Attrs
3835 : {
3836 158372 : if( ( eFTN > aRes.nSprmId ) || ( 0x0800 <= aRes.nSprmId ) )
3837 : {
3838 315788 : if( bStartAttr ) // WW attributes
3839 : {
3840 79940 : if( aRes.nMemLen >= 0 )
3841 79940 : ImportSprm(aRes.pMemPos, aRes.nSprmId);
3842 : }
3843 : else
3844 77954 : EndSprm( aRes.nSprmId ); // Switch off Attr
3845 : }
3846 478 : else if( aRes.nSprmId < 0x800 ) // Own helper attributes
3847 : {
3848 478 : if (bStartAttr)
3849 : {
3850 288 : nSkipChars = ImportExtSprm(&aRes);
3851 288 : if (
3852 860 : (aRes.nSprmId == eFTN) || (aRes.nSprmId == eEDN) ||
3853 412 : (aRes.nSprmId == eFLD) || (aRes.nSprmId == eAND)
3854 : )
3855 : {
3856 : // Skip Field/Ftn-/End-Note here
3857 192 : rTxtPos += nSkipChars;
3858 192 : nSkipPos = rTxtPos-1;
3859 : }
3860 : }
3861 : else
3862 190 : EndExtSprm( aRes.nSprmId );
3863 : }
3864 : }
3865 :
3866 189870 : pStrm->Seek(pSBase->WW8Cp2Fc( pPlcxMan->GetCpOfs() + rTxtPos, &bIsUnicode));
3867 :
3868 : // Find next Attr position (and Skip attributes of field contents if needed)
3869 189870 : if (nSkipChars && !bIgnoreText)
3870 68 : pCtrlStck->MarkAllAttrsOld();
3871 189870 : bool bOldIgnoreText = bIgnoreText;
3872 189870 : bIgnoreText = true;
3873 189870 : sal_uInt16 nOldColl = nAktColl;
3874 189870 : bool bDoPlcxManPlusPLus = true;
3875 : long nNext;
3876 192110 : do
3877 : {
3878 192110 : if( bDoPlcxManPlusPLus )
3879 189870 : pPlcxMan->advance();
3880 192110 : nNext = pPlcxMan->Where();
3881 :
3882 192110 : if (mpPostProcessAttrsInfo &&
3883 0 : mpPostProcessAttrsInfo->mnCpStart == nNext)
3884 : {
3885 0 : mpPostProcessAttrsInfo->mbCopy = true;
3886 : }
3887 :
3888 192110 : if( (0 <= nNext) && (nSkipPos >= nNext) )
3889 : {
3890 2330 : nNext = ReadTextAttr( rTxtPos, rbStartLine );
3891 2330 : bDoPlcxManPlusPLus = false;
3892 2330 : bIgnoreText = true;
3893 : }
3894 :
3895 192110 : if (mpPostProcessAttrsInfo &&
3896 0 : nNext > mpPostProcessAttrsInfo->mnCpEnd)
3897 : {
3898 0 : mpPostProcessAttrsInfo->mbCopy = false;
3899 : }
3900 : }
3901 : while( nSkipPos >= nNext );
3902 189870 : bIgnoreText = bOldIgnoreText;
3903 189870 : if( nSkipChars )
3904 : {
3905 68 : pCtrlStck->KillUnlockedAttrs( *pPaM->GetPoint() );
3906 68 : if( nOldColl != pPlcxMan->GetColl() )
3907 0 : ProcessAktCollChange(aRes, 0, false);
3908 : }
3909 :
3910 189870 : return nNext;
3911 : }
3912 :
3913 : //Revised 2012.8.16 for the complex attribute presentation of 0x0D in MS
3914 45560 : bool SwWW8ImplReader::IsParaEndInCPs(sal_Int32 nStart, sal_Int32 nEnd,bool bSdOD) const
3915 : {
3916 : //Revised for performance consideration
3917 45560 : if (nStart == -1 || nEnd == -1 || nEnd < nStart )
3918 0 : return false;
3919 :
3920 1669214 : for (cp_vector::const_reverse_iterator aItr = maEndParaPos.rbegin(); aItr!= maEndParaPos.rend(); ++aItr)
3921 : {
3922 : //Revised 2012.8.16,to the 0x0D,the attribute will have two situations
3923 : //*********within***********exact******
3924 : //*********but also sample with only left and the position of 0x0d is the edge of the right side***********
3925 1629540 : if ( bSdOD && ( (nStart < *aItr && nEnd > *aItr) || ( nStart == nEnd && *aItr == nStart)) )
3926 7250 : return true;
3927 1628176 : else if ( !bSdOD && (nStart < *aItr && nEnd >= *aItr) )
3928 4522 : return true;
3929 : }
3930 :
3931 39674 : return false;
3932 : }
3933 :
3934 : //Clear the para end position recorded in reader intermittently for the least impact on loading performance
3935 274 : void SwWW8ImplReader::ClearParaEndPosition()
3936 : {
3937 274 : if ( maEndParaPos.size() > 0 )
3938 22 : maEndParaPos.clear();
3939 274 : }
3940 :
3941 15066 : void SwWW8ImplReader::ReadAttrs(WW8_CP& rNext, WW8_CP& rTxtPos, bool& rbStartLine)
3942 : {
3943 : // Dow we have attributes?
3944 15066 : if( rTxtPos >= rNext )
3945 : {
3946 187540 : do
3947 : {
3948 187540 : maCurrAttrCP = rTxtPos;
3949 187540 : rNext = ReadTextAttr( rTxtPos, rbStartLine );
3950 : }
3951 187540 : while( rTxtPos >= rNext );
3952 :
3953 : }
3954 78 : else if ( rbStartLine )
3955 : {
3956 : /* No attributes, but still a new line.
3957 : * If a line ends with a line break and paragraph attributes or paragraph templates
3958 : * do NOT change the line end was not added to the Plcx.Fkp.papx i.e. (nFlags & MAN_MASK_NEW_PAP)
3959 : * is false.
3960 : * Due to this we need to set the template here as a kind of special treatment.
3961 : */
3962 48 : if (!bCpxStyle && nAktColl < vColl.size())
3963 48 : SetTxtFmtCollAndListLevel(*pPaM, vColl[nAktColl]);
3964 48 : rbStartLine = false;
3965 : }
3966 15066 : }
3967 :
3968 : /**
3969 : * CloseAttrEnds to only read the attribute ends at the end of a text or a
3970 : * text area (Header, Footnote, ...).
3971 : * We ignore attribute starts and fields.
3972 : */
3973 486 : void SwWW8ImplReader::CloseAttrEnds()
3974 : {
3975 : // If there are any unclosed sprms then copy them to
3976 : // another stack and close the ones that must be closed
3977 486 : std::stack<sal_uInt16> aStack;
3978 486 : pPlcxMan->TransferOpenSprms(aStack);
3979 :
3980 3646 : while (!aStack.empty())
3981 : {
3982 2674 : sal_uInt16 nSprmId = aStack.top();
3983 2674 : if ((0 < nSprmId) && (( eFTN > nSprmId) || (0x0800 <= nSprmId)))
3984 1986 : EndSprm(nSprmId);
3985 2674 : aStack.pop();
3986 : }
3987 :
3988 486 : EndSpecial();
3989 486 : }
3990 :
3991 486 : bool SwWW8ImplReader::ReadText(long nStartCp, long nTextLen, ManTypes nType)
3992 : {
3993 486 : bool bJoined=false;
3994 :
3995 486 : bool bStartLine = true;
3996 486 : short nCrCount = 0;
3997 486 : short nDistance = 0;
3998 :
3999 486 : bWasParaEnd = false;
4000 486 : nAktColl = 0;
4001 486 : pAktItemSet = 0;
4002 486 : nCharFmt = -1;
4003 486 : bSpec = false;
4004 486 : bPgSecBreak = false;
4005 :
4006 486 : pPlcxMan = new WW8PLCFMan( pSBase, nType, nStartCp );
4007 486 : long nCpOfs = pPlcxMan->GetCpOfs(); // Offset for Header/Footer, Footnote
4008 :
4009 486 : WW8_CP nNext = pPlcxMan->Where();
4010 486 : SwTxtNode* pPreviousNode = 0;
4011 486 : sal_uInt8 nDropLines = 0;
4012 486 : SwCharFmt* pNewSwCharFmt = 0;
4013 486 : const SwCharFmt* pFmt = 0;
4014 486 : pStrm->Seek( pSBase->WW8Cp2Fc( nStartCp + nCpOfs, &bIsUnicode ) );
4015 :
4016 486 : WW8_CP l = nStartCp;
4017 16038 : while ( l<nStartCp+nTextLen )
4018 : {
4019 15066 : ReadAttrs( nNext, l, bStartLine );// Takes SectionBreaks into account, too
4020 : OSL_ENSURE(pPaM->GetNode().GetTxtNode(), "Missing txtnode");
4021 :
4022 15066 : if (mpPostProcessAttrsInfo != NULL)
4023 0 : PostProcessAttrs();
4024 :
4025 15066 : if( l>= nStartCp + nTextLen )
4026 0 : break;
4027 :
4028 15066 : bStartLine = ReadChars(l, nNext, nStartCp+nTextLen, nCpOfs);
4029 :
4030 : // If the previous paragraph was a dropcap then do not
4031 : // create a new txtnode and join the two paragraphs together
4032 15066 : if (bStartLine && !pPreviousNode) // Line end
4033 : {
4034 5532 : bool bSplit = true;
4035 5532 : if (mbCareFirstParaEndInToc)
4036 : {
4037 0 : mbCareFirstParaEndInToc = false;
4038 0 : if (pPaM->End() && pPaM->End()->nNode.GetNode().GetTxtNode() && pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0)
4039 0 : bSplit = false;
4040 : }
4041 5532 : if (mbCareLastParaEndInToc)
4042 : {
4043 0 : mbCareLastParaEndInToc = false;
4044 0 : if (pPaM->End() && pPaM->End()->nNode.GetNode().GetTxtNode() && pPaM->End()->nNode.GetNode().GetTxtNode()->Len() == 0)
4045 0 : bSplit = false;
4046 : }
4047 5532 : if (bSplit)
4048 : {
4049 : // We will record the CP of a paragraph end ('0x0D'), if current loading contents is from main stream;
4050 5532 : if (mbOnLoadingMain)
4051 5204 : maEndParaPos.push_back(l-1);
4052 5532 : AppendTxtNode(*pPaM->GetPoint());
4053 : }
4054 : }
4055 :
4056 15066 : if (pPreviousNode && bStartLine)
4057 : {
4058 0 : SwTxtNode* pEndNd = pPaM->GetNode().GetTxtNode();
4059 0 : const sal_Int32 nDropCapLen = pPreviousNode->GetTxt().getLength();
4060 :
4061 : // Need to reset the font size and text position for the dropcap
4062 : {
4063 0 : SwPaM aTmp(*pEndNd, 0, *pEndNd, nDropCapLen+1);
4064 0 : pCtrlStck->Delete(aTmp);
4065 : }
4066 :
4067 : // Get the default document dropcap which we can use as our template
4068 : const SwFmtDrop* defaultDrop =
4069 0 : (const SwFmtDrop*) GetFmtAttr(RES_PARATR_DROP);
4070 0 : SwFmtDrop aDrop(*defaultDrop);
4071 :
4072 0 : aDrop.GetLines() = nDropLines;
4073 0 : aDrop.GetDistance() = nDistance;
4074 0 : aDrop.GetChars() = writer_cast<sal_uInt8>(nDropCapLen);
4075 : // Word has no concept of a "whole word dropcap"
4076 0 : aDrop.GetWholeWord() = false;
4077 :
4078 0 : if (pFmt)
4079 0 : aDrop.SetCharFmt(const_cast<SwCharFmt*>(pFmt));
4080 0 : else if(pNewSwCharFmt)
4081 0 : aDrop.SetCharFmt(const_cast<SwCharFmt*>(pNewSwCharFmt));
4082 :
4083 0 : SwPosition aStart(*pEndNd);
4084 0 : pCtrlStck->NewAttr(aStart, aDrop);
4085 0 : pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_DROP);
4086 0 : pPreviousNode = 0;
4087 : }
4088 15066 : else if (bDropCap)
4089 : {
4090 : // If we have found a dropcap store the textnode
4091 0 : pPreviousNode = pPaM->GetNode().GetTxtNode();
4092 :
4093 : const sal_uInt8 *pDCS;
4094 :
4095 0 : if (bVer67)
4096 0 : pDCS = pPlcxMan->GetPapPLCF()->HasSprm(46);
4097 : else
4098 0 : pDCS = pPlcxMan->GetPapPLCF()->HasSprm(0x442C);
4099 :
4100 0 : if (pDCS)
4101 0 : nDropLines = (*pDCS) >> 3;
4102 : else // There is no Drop Cap Specifier hence no dropcap
4103 0 : pPreviousNode = 0;
4104 :
4105 0 : if (const sal_uInt8 *pDistance = pPlcxMan->GetPapPLCF()->HasSprm(0x842F))
4106 0 : nDistance = SVBT16ToShort( pDistance );
4107 : else
4108 0 : nDistance = 0;
4109 :
4110 0 : const SwFmtCharFmt *pSwFmtCharFmt = 0;
4111 :
4112 0 : if(pAktItemSet)
4113 0 : pSwFmtCharFmt = &(ItemGet<SwFmtCharFmt>(*pAktItemSet, RES_TXTATR_CHARFMT));
4114 :
4115 0 : if(pSwFmtCharFmt)
4116 0 : pFmt = pSwFmtCharFmt->GetCharFmt();
4117 :
4118 0 : if(pAktItemSet && !pFmt)
4119 : {
4120 0 : OUString sPrefix(OUStringBuffer("WW8Dropcap").append(nDropCap++).makeStringAndClear());
4121 0 : pNewSwCharFmt = rDoc.MakeCharFmt(sPrefix, (SwCharFmt*)rDoc.GetDfltCharFmt());
4122 0 : pAktItemSet->ClearItem(RES_CHRATR_ESCAPEMENT);
4123 0 : pNewSwCharFmt->SetFmtAttr( *pAktItemSet );
4124 : }
4125 :
4126 0 : delete pAktItemSet;
4127 0 : pAktItemSet = 0;
4128 0 : bDropCap=false;
4129 : }
4130 :
4131 15066 : if (bStartLine || bWasTabRowEnd)
4132 : {
4133 : // Call all 64 CRs; not for Header and the like
4134 6112 : if ((nCrCount++ & 0x40) == 0 && nType == MAN_MAINTEXT)
4135 : {
4136 3710 : nProgress = (sal_uInt16)( l * 100 / nTextLen );
4137 3710 : ::SetProgressState(nProgress, mpDocShell); // Update
4138 : }
4139 : }
4140 :
4141 : // If we have encountered a 0x0c which indicates either section of
4142 : // pagebreak then look it up to see if it is a section break, and
4143 : // if it is not then insert a page break. If it is a section break
4144 : // it will be handled as such in the ReadAttrs of the next loop
4145 15066 : if (bPgSecBreak)
4146 : {
4147 : // We need only to see if a section is ending at this cp,
4148 : // the plcf will already be sitting on the correct location
4149 : // if it is there.
4150 124 : WW8PLCFxDesc aTemp;
4151 124 : aTemp.nStartPos = aTemp.nEndPos = WW8_CP_MAX;
4152 124 : if (pPlcxMan->GetSepPLCF())
4153 124 : pPlcxMan->GetSepPLCF()->GetSprms(&aTemp);
4154 124 : if ((aTemp.nStartPos != l) && (aTemp.nEndPos != l))
4155 : {
4156 : // #i39251# - insert text node for page break, if no one inserted.
4157 : // #i43118# - refine condition: the anchor
4158 : // control stack has to have entries, otherwise it's not needed
4159 : // to insert a text node.
4160 86 : if (!bStartLine && !pAnchorStck->empty())
4161 : {
4162 0 : AppendTxtNode(*pPaM->GetPoint());
4163 : }
4164 86 : rDoc.getIDocumentContentOperations().InsertPoolItem(*pPaM,
4165 86 : SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK), 0);
4166 86 : bFirstParaOfPage = true;
4167 86 : bPgSecBreak = false;
4168 : }
4169 : }
4170 : }
4171 :
4172 486 : if (pPaM->GetPoint()->nContent.GetIndex())
4173 2 : AppendTxtNode(*pPaM->GetPoint());
4174 :
4175 486 : if (!bInHyperlink)
4176 486 : bJoined = JoinNode(*pPaM);
4177 :
4178 486 : CloseAttrEnds();
4179 :
4180 486 : delete pPlcxMan, pPlcxMan = 0;
4181 486 : return bJoined;
4182 : }
4183 :
4184 190 : SwWW8ImplReader::SwWW8ImplReader(sal_uInt8 nVersionPara, SvStorage* pStorage,
4185 : SvStream* pSt, SwDoc& rD, const OUString& rBaseURL, bool bNewDoc)
4186 190 : : mpDocShell(rD.GetDocShell())
4187 : , pStg(pStorage)
4188 : , pStrm(pSt)
4189 : , pTableStream(0)
4190 : , pDataStream(0)
4191 : , rDoc(rD)
4192 : , pPaM(0)
4193 : , pCtrlStck(0)
4194 : , mpRedlineStack(0)
4195 : , pReffedStck(0)
4196 : , pReffingStck(0)
4197 : , pAnchorStck(0)
4198 : , maSectionManager(*this)
4199 : , m_aExtraneousParas(rD)
4200 : , maInsertedTables(rD)
4201 : , maSectionNameGenerator(rD, OUString("WW"))
4202 : , mpSprmParser(NULL)
4203 : , maGrfNameGenerator(bNewDoc, OUString('G'))
4204 : , maParaStyleMapper(rD)
4205 : , maCharStyleMapper(rD)
4206 : , pFormImpl(0)
4207 : , pFlyFmtOfJustInsertedGraphic(0)
4208 : , pFmtOfJustInsertedApo(0)
4209 : , pPreviousNumPaM(0)
4210 : , pPrevNumRule(0)
4211 : , mpPostProcessAttrsInfo(0)
4212 : , pWwFib(0)
4213 : , pFonts(0)
4214 : , pWDop(0)
4215 : , pLstManager(0)
4216 : , pSBase(0)
4217 : , pPlcxMan(0)
4218 : , maTxtNodesHavingFirstLineOfstSet()
4219 : , maTxtNodesHavingLeftIndentSet()
4220 : , pStyles(0)
4221 : , pAktColl(0)
4222 : , pAktItemSet(0)
4223 : , pDfltTxtFmtColl(0)
4224 : , pStandardFmtColl(0)
4225 : , pHdFt(0)
4226 : , pWFlyPara(0)
4227 : , pSFlyPara(0)
4228 : , pTableDesc(0)
4229 : , pNumOlst(0)
4230 : , pNode_FLY_AT_PARA(0)
4231 : , pDrawModel(0)
4232 : , pDrawPg(0)
4233 : , mpDrawEditEngine(0)
4234 : , pWWZOrder(0)
4235 : , pNumFldType(0)
4236 : , pMSDffManager(0)
4237 : , mpAtnNames(0)
4238 : , sBaseURL(rBaseURL)
4239 : , nIniFlags(0)
4240 : , nIniFlags1(0)
4241 : , nFieldFlags(0)
4242 : , m_bRegardHindiDigits( false )
4243 : , nDrawCpO(0)
4244 : , nPicLocFc(0)
4245 : , nObjLocFc(0)
4246 : , nIniFlyDx(0)
4247 : , nIniFlyDy(0)
4248 : , eTextCharSet(RTL_TEXTENCODING_ASCII_US)
4249 : , eStructCharSet(RTL_TEXTENCODING_ASCII_US)
4250 : , eHardCharSet(RTL_TEXTENCODING_DONTKNOW)
4251 : , nProgress(0)
4252 : , nAktColl(0)
4253 : , nFldNum(0)
4254 : , nLFOPosition(USHRT_MAX)
4255 : , nCharFmt(0)
4256 : , nDrawXOfs(0)
4257 : , nDrawYOfs(0)
4258 : , nDrawXOfs2(0)
4259 : , nDrawYOfs2(0)
4260 : , cSymbol(0)
4261 : , nWantedVersion(nVersionPara)
4262 : , nSwNumLevel(0xff)
4263 : , nWwNumType(0xff)
4264 : , nListLevel(WW8ListManager::nMaxLevel)
4265 : , nPgChpDelim(0)
4266 : , nPgChpLevel(0)
4267 : , mbNewDoc(bNewDoc)
4268 : , bReadNoTbl(false)
4269 : , bPgSecBreak(false)
4270 : , bSpec(false)
4271 : , bObj(false)
4272 : , bTxbxFlySection(false)
4273 : , bHasBorder(false)
4274 : , bSymbol(false)
4275 : , bIgnoreText(false)
4276 : , nInTable(0)
4277 : , bWasTabRowEnd(false)
4278 : , bWasTabCellEnd(false)
4279 : , bShdTxtCol(false)
4280 : , bCharShdTxtCol(false)
4281 : , bAnl(false)
4282 : , bHdFtFtnEdn(false)
4283 : , bFtnEdn(false)
4284 : , bIsHeader(false)
4285 : , bIsFooter(false)
4286 : , bIsUnicode(false)
4287 : , bCpxStyle(false)
4288 : , bStyNormal(false)
4289 : , bWWBugNormal(false)
4290 : , bNoAttrImport(false)
4291 : , bInHyperlink(false)
4292 : , bWasParaEnd(false)
4293 : , bVer67(false)
4294 : , bVer6(false)
4295 : , bVer7(false)
4296 : , bVer8(false)
4297 : , bEmbeddObj(false)
4298 : , bAktAND_fNumberAcross(false)
4299 : , bNoLnNumYet(true)
4300 : , bFirstPara(true)
4301 : , bFirstParaOfPage(false)
4302 : , bParaAutoBefore(false)
4303 : , bParaAutoAfter(false)
4304 : , bDropCap(false)
4305 : , nDropCap(0)
4306 : , nIdctHint(0)
4307 : , bBidi(false)
4308 : , bReadTable(false)
4309 : , mbLoadingTOXCache(false)
4310 : , mnEmbeddedTOXLevel(0)
4311 : , mbLoadingTOXHyperlink(false)
4312 : , mpPosAfterTOC(0)
4313 : , mbCareFirstParaEndInToc(false)
4314 : , mbCareLastParaEndInToc(false)
4315 : , maTOXEndCps()
4316 : , maCurrAttrCP(-1)
4317 190 : , mbOnLoadingMain(false)
4318 : {
4319 190 : pStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
4320 190 : maApos.push_back(false);
4321 190 : }
4322 :
4323 1744 : void SwWW8ImplReader::DeleteStk(SwFltControlStack* pStck)
4324 : {
4325 1744 : if( pStck )
4326 : {
4327 1744 : pStck->SetAttr( *pPaM->GetPoint(), 0, false);
4328 1744 : pStck->SetAttr( *pPaM->GetPoint(), 0, false);
4329 1744 : delete pStck;
4330 : }
4331 : else
4332 : {
4333 : OSL_ENSURE( false, "WW-Stack bereits geloescht" );
4334 : }
4335 1744 : }
4336 :
4337 220 : void wwSectionManager::SetSegmentToPageDesc(const wwSection &rSection,
4338 : bool bIgnoreCols)
4339 : {
4340 220 : SwPageDesc &rPage = *rSection.mpPage;
4341 :
4342 220 : SetNumberingType(rSection, rPage);
4343 :
4344 220 : SwFrmFmt &rFmt = rPage.GetMaster();
4345 :
4346 220 : if(mrReader.pWDop->fUseBackGroundInAllmodes) // #i56806# Make sure mrReader is initialized
4347 68 : mrReader.GrafikCtor();
4348 :
4349 220 : if (mrReader.pWDop->fUseBackGroundInAllmodes && mrReader.pMSDffManager)
4350 : {
4351 68 : Rectangle aRect(0, 0, 100, 100); // A dummy, we don't care about the size
4352 68 : SvxMSDffImportData aData(aRect);
4353 68 : SdrObject* pObject = 0;
4354 68 : if (mrReader.pMSDffManager->GetShape(0x401, pObject, aData))
4355 : {
4356 : // Only handle shape if it is a background shape
4357 24 : if ((aData.begin()->nFlags & 0x400) != 0)
4358 : {
4359 22 : SfxItemSet aSet(rFmt.GetAttrSet());
4360 : mrReader.MatchSdrItemsIntoFlySet(pObject, aSet, mso_lineSimple,
4361 22 : mso_lineSolid, mso_sptRectangle, aRect);
4362 22 : rFmt.SetFmtAttr(aSet.Get(RES_BACKGROUND));
4363 : }
4364 : }
4365 68 : SdrObject::Free(pObject);
4366 : }
4367 220 : wwULSpaceData aULData;
4368 220 : GetPageULData(rSection, aULData);
4369 220 : SetPageULSpaceItems(rFmt, aULData, rSection);
4370 :
4371 220 : SetPage(rPage, rFmt, rSection, bIgnoreCols);
4372 :
4373 220 : if (!(rSection.maSep.pgbApplyTo & 1))
4374 220 : mrReader.SetPageBorder(rFmt, rSection);
4375 220 : if (!(rSection.maSep.pgbApplyTo & 2))
4376 220 : mrReader.SetPageBorder(rPage.GetFirstMaster(), rSection);
4377 :
4378 220 : mrReader.SetDocumentGrid(rFmt, rSection);
4379 220 : }
4380 :
4381 220 : void wwSectionManager::SetUseOn(wwSection &rSection)
4382 : {
4383 220 : bool bMirror = mrReader.pWDop->fMirrorMargins ||
4384 220 : mrReader.pWDop->doptypography.f2on1;
4385 :
4386 220 : UseOnPage eUseBase = bMirror ? nsUseOnPage::PD_MIRROR : nsUseOnPage::PD_ALL;
4387 220 : UseOnPage eUse = eUseBase;
4388 220 : if (!mrReader.pWDop->fFacingPages)
4389 184 : eUse = (UseOnPage)(eUse | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE);
4390 220 : if (!rSection.HasTitlePage())
4391 196 : eUse = (UseOnPage)(eUse | nsUseOnPage::PD_FIRSTSHARE);
4392 :
4393 : OSL_ENSURE(rSection.mpPage, "Makes no sense to call me with no pages to set");
4394 220 : if (rSection.mpPage)
4395 220 : rSection.mpPage->WriteUseOn(eUse);
4396 220 : }
4397 :
4398 : /**
4399 : * Set the page descriptor on this node, handle the different cases for a text
4400 : * node or a table
4401 : */
4402 220 : void GiveNodePageDesc(SwNodeIndex &rIdx, const SwFmtPageDesc &rPgDesc,
4403 : SwDoc &rDoc)
4404 : {
4405 : /*
4406 : If it's a table here, apply the pagebreak to the table
4407 : properties, otherwise we add it to the para at this
4408 : position
4409 : */
4410 220 : if (rIdx.GetNode().IsTableNode())
4411 : {
4412 : SwTable& rTable =
4413 30 : rIdx.GetNode().GetTableNode()->GetTable();
4414 30 : SwFrmFmt* pApply = rTable.GetFrmFmt();
4415 : OSL_ENSURE(pApply, "impossible");
4416 30 : if (pApply)
4417 30 : pApply->SetFmtAttr(rPgDesc);
4418 : }
4419 : else
4420 : {
4421 190 : SwPosition aPamStart(rIdx);
4422 : aPamStart.nContent.Assign(
4423 190 : rIdx.GetNode().GetCntntNode(), 0);
4424 380 : SwPaM aPage(aPamStart);
4425 :
4426 380 : rDoc.getIDocumentContentOperations().InsertPoolItem(aPage, rPgDesc, 0);
4427 : }
4428 220 : }
4429 :
4430 : /**
4431 : * Map a word section to a writer page descriptor
4432 : */
4433 220 : SwFmtPageDesc wwSectionManager::SetSwFmtPageDesc(mySegIter &rIter,
4434 : mySegIter &rStart, bool bIgnoreCols)
4435 : {
4436 220 : if (IsNewDoc() && rIter == rStart)
4437 : {
4438 184 : rIter->mpPage =
4439 184 : mrReader.rDoc.getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_STANDARD);
4440 : }
4441 : else
4442 : {
4443 36 : rIter->mpPage = mrReader.rDoc.MakePageDesc(
4444 : SwViewShell::GetShellRes()->GetPageDescName(mnDesc, ShellResource::NORMAL_PAGE),
4445 36 : 0, false);
4446 : }
4447 : OSL_ENSURE(rIter->mpPage, "no page!");
4448 220 : if (!rIter->mpPage)
4449 0 : return SwFmtPageDesc();
4450 :
4451 : // Set page before hd/ft
4452 220 : const wwSection *pPrevious = 0;
4453 220 : if (rIter != rStart)
4454 36 : pPrevious = &(*(rIter-1));
4455 220 : SetHdFt(*rIter, std::distance(rStart, rIter), pPrevious);
4456 220 : SetUseOn(*rIter);
4457 :
4458 : // Set hd/ft after set page
4459 220 : SetSegmentToPageDesc(*rIter, bIgnoreCols);
4460 :
4461 220 : SwFmtPageDesc aRet(rIter->mpPage);
4462 :
4463 220 : rIter->mpPage->SetFollow(rIter->mpPage);
4464 :
4465 220 : if (rIter->PageRestartNo())
4466 10 : aRet.SetNumOffset(rIter->PageStartAt());
4467 :
4468 220 : ++mnDesc;
4469 220 : return aRet;
4470 : }
4471 :
4472 220 : bool wwSectionManager::IsNewDoc() const
4473 : {
4474 220 : return mrReader.mbNewDoc;
4475 : }
4476 :
4477 186 : void wwSectionManager::InsertSegments()
4478 : {
4479 186 : const SvtFilterOptions& rOpt = SvtFilterOptions::Get();
4480 186 : bool bUseEnhFields = rOpt.IsUseEnhancedFields();
4481 186 : mySegIter aEnd = maSegments.end();
4482 186 : mySegIter aStart = maSegments.begin();
4483 408 : for (mySegIter aIter = aStart; aIter != aEnd; ++aIter)
4484 : {
4485 : // If the section is of type "New column" (0x01), then simply insert a column break.
4486 : // But only if there actually are columns on the page, otherwise a column break
4487 : // seems to be handled like a page break by MSO.
4488 222 : if ( aIter->maSep.bkc == 1 && aIter->maSep.ccolM1 > 0 )
4489 : {
4490 2 : SwPaM start( aIter->maStart );
4491 2 : mrReader.rDoc.getIDocumentContentOperations().InsertPoolItem( start, SvxFmtBreakItem(SVX_BREAK_COLUMN_BEFORE, RES_BREAK), 0);
4492 2 : continue;
4493 : }
4494 :
4495 220 : mySegIter aNext = aIter+1;
4496 220 : mySegIter aPrev = (aIter == aStart) ? aIter : aIter-1;
4497 :
4498 : // If two following sections are different in following properties, Word will interprete a continuous
4499 : // section break between them as if it was a section break next page.
4500 438 : bool bThisAndPreviousAreCompatible = ((aIter->GetPageWidth() == aPrev->GetPageWidth()) &&
4501 438 : (aIter->GetPageHeight() == aPrev->GetPageHeight()) && (aIter->IsLandScape() == aPrev->IsLandScape()));
4502 :
4503 220 : bool bInsertSection = (aIter != aStart) && aIter->IsContinuous() && bThisAndPreviousAreCompatible;
4504 220 : bool bInsertPageDesc = !bInsertSection;
4505 : // HACK Force new pagedesc if margins change, otherwise e.g. floating tables may be anchored improperly.
4506 646 : if( aIter->maSep.dyaTop != aPrev->maSep.dyaTop || aIter->maSep.dyaBottom != aPrev->maSep.dyaBottom
4507 426 : || aIter->maSep.dxaLeft != aPrev->maSep.dxaLeft || aIter->maSep.dxaRight != aPrev->maSep.dxaRight )
4508 14 : bInsertPageDesc = true;
4509 220 : bool bProtected = SectionIsProtected(*aIter); // do we really need this ?? I guess I have a different logic in editshell which disables this...
4510 220 : if (bUseEnhFields && mrReader.pWDop->fProtEnabled && aIter->IsNotProtected())
4511 : {
4512 : // here we have the special case that the whole document is protected, with the exception of this section.
4513 : // I want to address this when I do the section rework, so for the moment we disable the overall protection then...
4514 0 : mrReader.rDoc.getIDocumentSettingAccess().set(IDocumentSettingAccess::PROTECT_FORM, false );
4515 : }
4516 :
4517 220 : if (bInsertPageDesc)
4518 : {
4519 : /*
4520 : If a cont section follows this section then we won't be
4521 : creating a page desc with 2+ cols as we cannot host a one
4522 : col section in a 2+ col pagedesc and make it look like
4523 : word. But if the current section actually has columns then
4524 : we are forced to insert a section here as well as a page
4525 : descriptor.
4526 : */
4527 :
4528 220 : bool bIgnoreCols = false;
4529 294 : bool bThisAndNextAreCompatible = (aNext != aEnd) ? ((aIter->GetPageWidth() == aNext->GetPageWidth()) &&
4530 294 : (aIter->GetPageHeight() == aNext->GetPageHeight()) && (aIter->IsLandScape() == aNext->IsLandScape())) : true;
4531 :
4532 220 : if (((aNext != aEnd && aNext->IsContinuous() && bThisAndNextAreCompatible) || bProtected))
4533 : {
4534 6 : bIgnoreCols = true;
4535 6 : if ((aIter->NoCols() > 1) || bProtected)
4536 2 : bInsertSection = true;
4537 : }
4538 :
4539 220 : SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, bIgnoreCols));
4540 220 : if (!aDesc.GetPageDesc())
4541 0 : continue;
4542 :
4543 : // special case handling for odd/even section break
4544 : // a) as before create a new page style for the section break
4545 : // b) set Layout of generated page style to right/left ( according
4546 : // to section break odd/even )
4547 : // c) create a new style to follow the break page style
4548 220 : if ( aIter->maSep.bkc == 3 || aIter->maSep.bkc == 4 )
4549 : {
4550 : // SetSwFmtPageDesc calls some methods that could
4551 : // modify aIter (e.g. wwSection ).
4552 : // Since we call SetSwFmtPageDesc below to generate the
4553 : // 'Following' style of the Break style, it is safer
4554 : // to take a copy of the contents of aIter.
4555 0 : wwSection aTmpSection = *aIter;
4556 : // create a new following page style
4557 0 : SwFmtPageDesc aFollow(SetSwFmtPageDesc(aIter, aStart, bIgnoreCols));
4558 : // restore any contents of aIter trashed by SetSwFmtPageDesc
4559 0 : *aIter = aTmpSection;
4560 :
4561 : // Handle the section break
4562 0 : UseOnPage eUseOnPage = nsUseOnPage::PD_LEFT;
4563 0 : if ( aIter->maSep.bkc == 4 ) // Odd ( right ) Section break
4564 0 : eUseOnPage = nsUseOnPage::PD_RIGHT;
4565 :
4566 0 : aDesc.GetPageDesc()->WriteUseOn( eUseOnPage );
4567 0 : aDesc.GetPageDesc()->SetFollow( aFollow.GetPageDesc() );
4568 : }
4569 :
4570 220 : GiveNodePageDesc(aIter->maStart, aDesc, mrReader.rDoc);
4571 : }
4572 :
4573 220 : SwTxtNode* pTxtNd = 0;
4574 220 : if (bInsertSection)
4575 : {
4576 : // Start getting the bounds of this section
4577 8 : SwPaM aSectPaM(*mrReader.pPaM);
4578 16 : SwNodeIndex aAnchor(aSectPaM.GetPoint()->nNode);
4579 8 : if (aNext != aEnd)
4580 : {
4581 2 : aAnchor = aNext->maStart;
4582 2 : aSectPaM.GetPoint()->nNode = aAnchor;
4583 2 : aSectPaM.GetPoint()->nContent.Assign(
4584 4 : aNext->maStart.GetNode().GetCntntNode(), 0);
4585 2 : aSectPaM.Move(fnMoveBackward);
4586 : }
4587 :
4588 8 : const SwPosition* pPos = aSectPaM.GetPoint();
4589 8 : SwTxtNode const*const pSttNd = pPos->nNode.GetNode().GetTxtNode();
4590 8 : const SwTableNode* pTableNd = pSttNd ? pSttNd->FindTableNode() : 0;
4591 8 : if (pTableNd)
4592 : {
4593 : pTxtNd =
4594 0 : mrReader.rDoc.GetNodes().MakeTxtNode(aAnchor,
4595 0 : mrReader.rDoc.getIDocumentStylePoolAccess().GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
4596 :
4597 0 : aSectPaM.GetPoint()->nNode = SwNodeIndex(*pTxtNd);
4598 0 : aSectPaM.GetPoint()->nContent.Assign(
4599 0 : aSectPaM.GetCntntNode(), 0);
4600 : }
4601 :
4602 8 : aSectPaM.SetMark();
4603 :
4604 8 : aSectPaM.GetPoint()->nNode = aIter->maStart;
4605 8 : aSectPaM.GetPoint()->nContent.Assign(
4606 16 : aSectPaM.GetCntntNode(), 0);
4607 :
4608 8 : bool bHasOwnHdFt = false;
4609 : /*
4610 : In this nightmare scenario the continuous section has its own
4611 : headers and footers so we will try and find a hard page break
4612 : between here and the end of the section and put the headers and
4613 : footers there.
4614 : */
4615 8 : if (!bInsertPageDesc)
4616 : {
4617 : bHasOwnHdFt =
4618 : mrReader.HasOwnHeaderFooter(
4619 0 : aIter->maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST),
4620 0 : aIter->maSep.grpfIhdt, std::distance(aStart, aIter)
4621 0 : );
4622 : }
4623 8 : if (bHasOwnHdFt)
4624 : {
4625 : // #i40766# Need to cache the page descriptor in case there is
4626 : // no page break in the section
4627 0 : SwPageDesc *pOrig = aIter->mpPage;
4628 0 : bool bFailed = true;
4629 0 : SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, true));
4630 0 : if (aDesc.GetPageDesc())
4631 : {
4632 0 : sal_uLong nStart = aSectPaM.Start()->nNode.GetIndex();
4633 0 : sal_uLong nEnd = aSectPaM.End()->nNode.GetIndex();
4634 0 : for(; nStart <= nEnd; ++nStart)
4635 : {
4636 0 : SwNode* pNode = mrReader.rDoc.GetNodes()[nStart];
4637 0 : if (!pNode)
4638 0 : continue;
4639 0 : if (sw::util::HasPageBreak(*pNode))
4640 : {
4641 0 : SwNodeIndex aIdx(*pNode);
4642 0 : GiveNodePageDesc(aIdx, aDesc, mrReader.rDoc);
4643 0 : bFailed = false;
4644 0 : break;
4645 : }
4646 : }
4647 : }
4648 0 : if(bFailed)
4649 : {
4650 0 : aIter->mpPage = pOrig;
4651 0 : }
4652 : }
4653 :
4654 : // End getting the bounds of this section, quite a job eh?
4655 8 : SwSectionFmt *pRet = InsertSection(aSectPaM, *aIter);
4656 : // The last section if continuous is always unbalanced
4657 8 : if (pRet)
4658 : {
4659 : // Set the columns to be UnBalanced if that compatibility option is set
4660 8 : if (mrReader.pWDop->fNoColumnBalance)
4661 0 : pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
4662 : else
4663 : {
4664 : // Otherwise set to unbalanced if the following section is
4665 : // not continuous, (which also means that the last section
4666 : // is unbalanced)
4667 8 : if (aNext == aEnd || !aNext->IsContinuous())
4668 6 : pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
4669 : }
4670 8 : }
4671 : }
4672 :
4673 220 : if (pTxtNd)
4674 : {
4675 0 : SwNodeIndex aIdx(*pTxtNd);
4676 0 : SwPaM aTest(aIdx);
4677 0 : mrReader.rDoc.getIDocumentContentOperations().DelFullPara(aTest);
4678 0 : pTxtNd = 0;
4679 : }
4680 : }
4681 186 : }
4682 :
4683 376 : void wwExtraneousParas::delete_all_from_doc()
4684 : {
4685 : typedef std::vector<SwTxtNode*>::iterator myParaIter;
4686 376 : myParaIter aEnd = m_aTxtNodes.end();
4687 382 : for (myParaIter aI = m_aTxtNodes.begin(); aI != aEnd; ++aI)
4688 : {
4689 6 : SwTxtNode *pTxtNode = *aI;
4690 6 : SwNodeIndex aIdx(*pTxtNode);
4691 12 : SwPaM aTest(aIdx);
4692 6 : m_rDoc.getIDocumentContentOperations().DelFullPara(aTest);
4693 6 : }
4694 376 : m_aTxtNodes.clear();
4695 376 : }
4696 :
4697 182 : void SwWW8ImplReader::StoreMacroCmds()
4698 : {
4699 182 : if (pWwFib->lcbCmds)
4700 : {
4701 142 : pTableStream->Seek(pWwFib->fcCmds);
4702 :
4703 142 : uno::Reference < embed::XStorage > xRoot(mpDocShell->GetStorage());
4704 :
4705 142 : if (!xRoot.is())
4706 238 : return;
4707 :
4708 : try
4709 : {
4710 : uno::Reference < io::XStream > xStream =
4711 86 : xRoot->openStreamElement( OUString(SL::aMSMacroCmds), embed::ElementModes::READWRITE );
4712 86 : SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xStream );
4713 :
4714 86 : sal_uInt8 *pBuffer = new sal_uInt8[pWwFib->lcbCmds];
4715 86 : pWwFib->lcbCmds = pTableStream->Read(pBuffer, pWwFib->lcbCmds);
4716 86 : pStream->Write(pBuffer, pWwFib->lcbCmds);
4717 86 : delete[] pBuffer;
4718 86 : delete pStream;
4719 : }
4720 0 : catch ( const uno::Exception& )
4721 : {
4722 86 : }
4723 : }
4724 : }
4725 :
4726 186 : void SwWW8ImplReader::ReadDocVars()
4727 : {
4728 186 : std::vector<OUString> aDocVarStrings;
4729 372 : std::vector<ww::bytes> aDocVarStringIds;
4730 372 : std::vector<OUString> aDocValueStrings;
4731 186 : WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcStwUser,
4732 : pWwFib->lcbStwUser, bVer67 ? 2 : 0, eStructCharSet,
4733 372 : aDocVarStrings, &aDocVarStringIds, &aDocValueStrings);
4734 186 : if (!bVer67) {
4735 : using namespace ::com::sun::star;
4736 :
4737 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
4738 182 : mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
4739 : uno::Reference<document::XDocumentProperties> xDocProps(
4740 364 : xDPS->getDocumentProperties());
4741 : OSL_ENSURE(xDocProps.is(), "DocumentProperties is null");
4742 : uno::Reference<beans::XPropertyContainer> xUserDefinedProps =
4743 364 : xDocProps->getUserDefinedProperties();
4744 : OSL_ENSURE(xUserDefinedProps.is(), "UserDefinedProperties is null");
4745 :
4746 222 : for(size_t i=0; i<aDocVarStrings.size(); i++)
4747 : {
4748 40 : const OUString &rName = aDocVarStrings[i];
4749 40 : uno::Any aValue;
4750 40 : aValue <<= OUString(aDocValueStrings[i]);
4751 : try {
4752 40 : xUserDefinedProps->addProperty( rName,
4753 : beans::PropertyAttribute::REMOVABLE,
4754 40 : aValue );
4755 0 : } catch (const uno::Exception &) {
4756 : // ignore
4757 : }
4758 222 : }
4759 186 : }
4760 186 : }
4761 :
4762 : /**
4763 : * Document Info
4764 : */
4765 182 : void SwWW8ImplReader::ReadDocInfo()
4766 : {
4767 182 : if( pStg )
4768 : {
4769 : uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
4770 182 : mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
4771 : uno::Reference<document::XDocumentProperties> xDocProps(
4772 364 : xDPS->getDocumentProperties());
4773 : OSL_ENSURE(xDocProps.is(), "DocumentProperties is null");
4774 :
4775 182 : if (xDocProps.is()) {
4776 182 : if ( pWwFib->fDot )
4777 : {
4778 0 : OUString sTemplateURL;
4779 0 : SfxMedium* pMedium = mpDocShell->GetMedium();
4780 0 : if ( pMedium )
4781 : {
4782 0 : OUString aName = pMedium->GetName();
4783 0 : INetURLObject aURL( aName );
4784 0 : sTemplateURL = aURL.GetMainURL(INetURLObject::DECODE_TO_IURI);
4785 0 : if ( !sTemplateURL.isEmpty() )
4786 0 : xDocProps->setTemplateURL( sTemplateURL );
4787 0 : }
4788 : }
4789 182 : else if (pWwFib->lcbSttbfAssoc) // not a template, and has a SttbfAssoc
4790 : {
4791 144 : long nCur = pTableStream->Tell();
4792 144 : Sttb aSttb;
4793 144 : pTableStream->Seek( pWwFib->fcSttbfAssoc ); // point at tgc record
4794 144 : if (!aSttb.Read( *pTableStream ) )
4795 : OSL_TRACE("** Read of SttbAssoc data failed!!!! ");
4796 144 : pTableStream->Seek( nCur ); // return to previous position, is that necessary?
4797 : #if OSL_DEBUG_LEVEL > 1
4798 : aSttb.Print( stderr );
4799 : #endif
4800 288 : OUString sPath = aSttb.getStringAtIndex( 0x1 );
4801 288 : OUString aURL;
4802 : // attempt to convert to url (won't work for obvious reasons on linux)
4803 144 : if ( !sPath.isEmpty() )
4804 2 : ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sPath, aURL );
4805 144 : if (aURL.isEmpty())
4806 142 : xDocProps->setTemplateURL( aURL );
4807 : else
4808 146 : xDocProps->setTemplateURL( sPath );
4809 :
4810 : }
4811 182 : sfx2::LoadOlePropertySet(xDocProps, pStg);
4812 182 : }
4813 : }
4814 182 : }
4815 :
4816 182 : static void lcl_createTemplateToProjectEntry( const uno::Reference< container::XNameContainer >& xPrjNameCache, const OUString& sTemplatePathOrURL, const OUString& sVBAProjName )
4817 : {
4818 182 : if ( xPrjNameCache.is() )
4819 : {
4820 134 : INetURLObject aObj;
4821 134 : aObj.SetURL( sTemplatePathOrURL );
4822 134 : bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
4823 268 : OUString aURL;
4824 134 : if ( bIsURL )
4825 0 : aURL = sTemplatePathOrURL;
4826 : else
4827 : {
4828 134 : osl::FileBase::getFileURLFromSystemPath( sTemplatePathOrURL, aURL );
4829 134 : aObj.SetURL( aURL );
4830 : }
4831 : try
4832 : {
4833 134 : OUString templateNameWithExt = aObj.GetLastName();
4834 268 : OUString templateName;
4835 134 : sal_Int32 nIndex = templateNameWithExt.lastIndexOf( '.' );
4836 134 : if ( nIndex != -1 )
4837 : {
4838 0 : templateName = templateNameWithExt.copy( 0, nIndex );
4839 0 : xPrjNameCache->insertByName( templateName, uno::makeAny( sVBAProjName ) );
4840 134 : }
4841 : }
4842 0 : catch( const uno::Exception& )
4843 : {
4844 134 : }
4845 : }
4846 182 : }
4847 :
4848 : class WW8Customizations
4849 : {
4850 : SvStream* mpTableStream;
4851 : WW8Fib mWw8Fib;
4852 : public:
4853 : WW8Customizations( SvStream*, WW8Fib& );
4854 : bool Import( SwDocShell* pShell );
4855 : };
4856 :
4857 182 : WW8Customizations::WW8Customizations( SvStream* pTableStream, WW8Fib& rFib ) : mpTableStream(pTableStream), mWw8Fib( rFib )
4858 : {
4859 182 : }
4860 :
4861 182 : bool WW8Customizations::Import( SwDocShell* pShell )
4862 : {
4863 182 : if ( mWw8Fib.lcbCmds == 0 || !IsEightPlus(mWw8Fib.GetFIBVersion()) )
4864 40 : return false;
4865 : try
4866 : {
4867 142 : Tcg aTCG;
4868 142 : long nCur = mpTableStream->Tell();
4869 142 : mpTableStream->Seek( mWw8Fib.fcCmds ); // point at tgc record
4870 142 : bool bReadResult = aTCG.Read( *mpTableStream );
4871 142 : mpTableStream->Seek( nCur ); // return to previous position, is that necessary?
4872 142 : if ( !bReadResult )
4873 : {
4874 : SAL_WARN("sw.ww8", "** Read of Customization data failed!!!! ");
4875 6 : return false;
4876 : }
4877 : #if OSL_DEBUG_LEVEL > 1
4878 : aTCG.Print( stderr );
4879 : #endif
4880 136 : return aTCG.ImportCustomToolBar( *pShell );
4881 : }
4882 0 : catch(...)
4883 : {
4884 : SAL_WARN("sw.ww8", "** Read of Customization data failed!!!! epically");
4885 0 : return false;
4886 : }
4887 : }
4888 :
4889 182 : bool SwWW8ImplReader::ReadGlobalTemplateSettings( const OUString& sCreatedFrom, const uno::Reference< container::XNameContainer >& xPrjNameCache )
4890 : {
4891 182 : SvtPathOptions aPathOpt;
4892 364 : OUString aAddinPath = aPathOpt.GetAddinPath();
4893 364 : uno::Sequence< OUString > sGlobalTemplates;
4894 :
4895 : // first get the autoload addins in the directory STARTUP
4896 364 : uno::Reference<ucb::XSimpleFileAccess3> xSFA(ucb::SimpleFileAccess::create(::comphelper::getProcessComponentContext()));
4897 :
4898 182 : if( xSFA->isFolder( aAddinPath ) )
4899 0 : sGlobalTemplates = xSFA->getFolderContents( aAddinPath, sal_False );
4900 :
4901 182 : sal_Int32 nEntries = sGlobalTemplates.getLength();
4902 182 : bool bRes = true;
4903 182 : for ( sal_Int32 i=0; i<nEntries; ++i )
4904 : {
4905 0 : INetURLObject aObj;
4906 0 : aObj.SetURL( sGlobalTemplates[ i ] );
4907 0 : bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
4908 0 : OUString aURL;
4909 0 : if ( bIsURL )
4910 0 : aURL = sGlobalTemplates[ i ];
4911 : else
4912 0 : osl::FileBase::getFileURLFromSystemPath( sGlobalTemplates[ i ], aURL );
4913 0 : if ( !aURL.endsWithIgnoreAsciiCase( ".dot" ) || ( !sCreatedFrom.isEmpty() && sCreatedFrom.equals( aURL ) ) )
4914 0 : continue; // don't try and read the same document as ourselves
4915 :
4916 0 : SotStorageRef rRoot = new SotStorage( aURL, STREAM_STD_READWRITE, STORAGE_TRANSACTED );
4917 :
4918 0 : BasicProjImportHelper aBasicImporter( *mpDocShell );
4919 : // Import vba via oox filter
4920 0 : aBasicImporter.import( mpDocShell->GetMedium()->GetInputStream() );
4921 0 : lcl_createTemplateToProjectEntry( xPrjNameCache, aURL, aBasicImporter.getProjectName() );
4922 : // Read toolbars & menus
4923 0 : SvStorageStreamRef refMainStream = rRoot->OpenSotStream( OUString( "WordDocument" ));
4924 0 : refMainStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
4925 0 : WW8Fib aWwFib( *refMainStream, 8 );
4926 0 : SvStorageStreamRef xTableStream = rRoot->OpenSotStream(OUString::createFromAscii( aWwFib.fWhichTblStm ? SL::a1Table : SL::a0Table), STREAM_STD_READ);
4927 :
4928 0 : if (xTableStream.Is() && SVSTREAM_OK == xTableStream->GetError())
4929 : {
4930 0 : xTableStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
4931 0 : WW8Customizations aGblCustomisations( xTableStream, aWwFib );
4932 0 : aGblCustomisations.Import( mpDocShell );
4933 : }
4934 0 : }
4935 364 : return bRes;
4936 : }
4937 :
4938 186 : sal_uLong SwWW8ImplReader::CoreLoad(WW8Glossary *pGloss, const SwPosition &rPos)
4939 : {
4940 186 : sal_uLong nErrRet = 0;
4941 :
4942 186 : rDoc.SetDocumentType( SwDoc::DOCTYPE_MSWORD );
4943 186 : if (mbNewDoc && pStg && !pGloss)
4944 182 : ReadDocInfo();
4945 :
4946 186 : ::ww8::WW8FibData * pFibData = new ::ww8::WW8FibData();
4947 :
4948 186 : if (pWwFib->fReadOnlyRecommended)
4949 0 : pFibData->setReadOnlyRecommended(true);
4950 : else
4951 186 : pFibData->setReadOnlyRecommended(false);
4952 :
4953 186 : if (pWwFib->fWriteReservation)
4954 0 : pFibData->setWriteReservation(true);
4955 : else
4956 186 : pFibData->setWriteReservation(false);
4957 :
4958 186 : ::sw::tExternalDataPointer pExternalFibData(pFibData);
4959 :
4960 186 : rDoc.getIDocumentExternalData().setExternalData(::sw::FIB, pExternalFibData);
4961 :
4962 : ::sw::tExternalDataPointer pSttbfAsoc
4963 372 : (new ::ww8::WW8Sttb<ww8::WW8Struct>(*pTableStream, pWwFib->fcSttbfAssoc, pWwFib->lcbSttbfAssoc));
4964 :
4965 186 : rDoc.getIDocumentExternalData().setExternalData(::sw::STTBF_ASSOC, pSttbfAsoc);
4966 :
4967 186 : if (pWwFib->fWriteReservation || pWwFib->fReadOnlyRecommended)
4968 : {
4969 0 : SwDocShell * pDocShell = rDoc.GetDocShell();
4970 0 : if (pDocShell)
4971 0 : pDocShell->SetReadOnlyUI(true);
4972 : }
4973 :
4974 186 : pPaM = rDoc.CreateUnoCrsr(rPos);
4975 :
4976 186 : pCtrlStck = new SwWW8FltControlStack( &rDoc, nFieldFlags, *this );
4977 :
4978 186 : mpRedlineStack = new sw::util::RedlineStack(rDoc);
4979 :
4980 : /*
4981 : RefFldStck: Keeps track of bookmarks which may be inserted as
4982 : variables intstead.
4983 : */
4984 186 : pReffedStck = new SwWW8ReferencedFltEndStack(&rDoc, nFieldFlags);
4985 186 : pReffingStck = new SwWW8FltRefStack(&rDoc, nFieldFlags);
4986 :
4987 186 : pAnchorStck = new SwWW8FltAnchorStack(&rDoc, nFieldFlags);
4988 :
4989 186 : sal_uInt16 nPageDescOffset = rDoc.GetPageDescCnt();
4990 :
4991 372 : SwNodeIndex aSttNdIdx( rDoc.GetNodes() );
4992 372 : SwRelNumRuleSpaces aRelNumRule(rDoc, mbNewDoc);
4993 :
4994 186 : sal_uInt16 eMode = nsRedlineMode_t::REDLINE_SHOW_INSERT;
4995 :
4996 186 : mpSprmParser = new wwSprmParser(pWwFib->GetFIBVersion());
4997 :
4998 : // Set handy helper variables
4999 186 : bVer6 = (6 == pWwFib->nVersion);
5000 186 : bVer7 = (7 == pWwFib->nVersion);
5001 186 : bVer67 = bVer6 || bVer7;
5002 186 : bVer8 = (8 == pWwFib->nVersion);
5003 :
5004 186 : eTextCharSet = WW8Fib::GetFIBCharset(pWwFib->chse);
5005 186 : eStructCharSet = WW8Fib::GetFIBCharset(pWwFib->chseTables);
5006 :
5007 186 : bWWBugNormal = pWwFib->nProduct == 0xc03d;
5008 :
5009 186 : if (!mbNewDoc)
5010 0 : aSttNdIdx = pPaM->GetPoint()->nNode;
5011 :
5012 186 : ::StartProgress(STR_STATSTR_W4WREAD, 0, 100, mpDocShell);
5013 :
5014 : // read Font Table
5015 186 : pFonts = new WW8Fonts( *pTableStream, *pWwFib );
5016 :
5017 : // Document Properties
5018 : pWDop = new WW8Dop( *pTableStream, pWwFib->nFib, pWwFib->fcDop,
5019 186 : pWwFib->lcbDop );
5020 :
5021 186 : if (mbNewDoc)
5022 186 : ImportDop();
5023 :
5024 : /*
5025 : Import revisioning data: author names
5026 : */
5027 186 : if( pWwFib->lcbSttbfRMark )
5028 : {
5029 : ReadRevMarkAuthorStrTabl( *pTableStream,
5030 : pWwFib->fcSttbfRMark,
5031 120 : pWwFib->lcbSttbfRMark, rDoc );
5032 : }
5033 :
5034 : // Initialize our String/ID map for Linked Sections
5035 372 : std::vector<OUString> aLinkStrings;
5036 372 : std::vector<ww::bytes> aStringIds;
5037 :
5038 186 : WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcSttbFnm,
5039 : pWwFib->lcbSttbFnm, bVer67 ? 2 : 0, eStructCharSet,
5040 372 : aLinkStrings, &aStringIds);
5041 :
5042 186 : for (size_t i=0; i < aLinkStrings.size() && i < aStringIds.size(); ++i)
5043 : {
5044 0 : ww::bytes stringId = aStringIds[i];
5045 0 : WW8_STRINGID *stringIdStruct = (WW8_STRINGID*)(&stringId[0]);
5046 0 : aLinkStringMap[SVBT16ToShort(stringIdStruct->nStringId)] =
5047 0 : aLinkStrings[i];
5048 0 : }
5049 :
5050 186 : ReadDocVars(); // import document variables as meta information.
5051 :
5052 186 : ::SetProgressState(nProgress, mpDocShell); // Update
5053 :
5054 186 : pLstManager = new WW8ListManager( *pTableStream, *this );
5055 :
5056 : /*
5057 : zuerst(!) alle Styles importieren (siehe WW8PAR2.CXX)
5058 : VOR dem Import der Listen !!
5059 : */
5060 186 : ::SetProgressState(nProgress, mpDocShell); // Update
5061 186 : pStyles = new WW8RStyle( *pWwFib, this ); // Styles
5062 186 : pStyles->Import();
5063 :
5064 : /*
5065 : In the end: (also see WW8PAR3.CXX)
5066 :
5067 : Go through all Styles and attach respective List Format
5068 : AFTER we imported the Styles and AFTER we imported the Lists!
5069 : */
5070 186 : ::SetProgressState(nProgress, mpDocShell); // Update
5071 186 : pStyles->PostProcessStyles();
5072 :
5073 186 : if (!vColl.empty())
5074 186 : SetOutlineStyles();
5075 :
5076 186 : pSBase = new WW8ScannerBase(pStrm,pTableStream,pDataStream,pWwFib);
5077 :
5078 : static const SvxExtNumType eNumTA[16] =
5079 : {
5080 : SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,
5081 : SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N,
5082 : SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
5083 : SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
5084 : SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
5085 : SVX_NUM_ARABIC, SVX_NUM_ARABIC
5086 : };
5087 :
5088 186 : if (pSBase->AreThereFootnotes())
5089 : {
5090 : static const SwFtnNum eNumA[4] =
5091 : {
5092 : FTNNUM_DOC, FTNNUM_CHAPTER, FTNNUM_PAGE, FTNNUM_DOC
5093 : };
5094 :
5095 2 : SwFtnInfo aInfo;
5096 2 : aInfo = rDoc.GetFtnInfo(); // Copy-Ctor private
5097 :
5098 2 : aInfo.ePos = FTNPOS_PAGE;
5099 2 : aInfo.eNum = eNumA[pWDop->rncFtn];
5100 2 : aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcFtnRef]) );
5101 2 : if( pWDop->nFtn )
5102 2 : aInfo.nFtnOffset = pWDop->nFtn - 1;
5103 2 : rDoc.SetFtnInfo( aInfo );
5104 : }
5105 186 : if( pSBase->AreThereEndnotes() )
5106 : {
5107 0 : SwEndNoteInfo aInfo;
5108 0 : aInfo = rDoc.GetEndNoteInfo(); // Same as for Ftn
5109 :
5110 0 : aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcEdnRef]) );
5111 0 : if( pWDop->nEdn )
5112 0 : aInfo.nFtnOffset = pWDop->nEdn - 1;
5113 0 : rDoc.SetEndNoteInfo( aInfo );
5114 : }
5115 :
5116 186 : if( pWwFib->lcbPlcfhdd )
5117 78 : pHdFt = new WW8PLCF_HdFt( pTableStream, *pWwFib, *pWDop );
5118 :
5119 186 : if (!mbNewDoc)
5120 : {
5121 : // inserting into an existing document:
5122 : // As only complete paragraphs are inserted, the current one
5123 : // needs to be splitted - once or even twice.
5124 0 : const SwPosition* pPos = pPaM->GetPoint();
5125 :
5126 : // split current paragraph to get new paragraph for the insertion
5127 0 : rDoc.getIDocumentContentOperations().SplitNode( *pPos, false );
5128 :
5129 : // another split, if insertion position was not at the end of the current paragraph.
5130 0 : SwTxtNode const*const pTxtNd = pPos->nNode.GetNode().GetTxtNode();
5131 0 : if ( pTxtNd->GetTxt().getLength() )
5132 : {
5133 0 : rDoc.getIDocumentContentOperations().SplitNode( *pPos, false );
5134 : // move PaM back to the newly empty paragraph
5135 0 : pPaM->Move( fnMoveBackward );
5136 : }
5137 :
5138 : // suppress insertion of tables inside footnotes.
5139 0 : const sal_uLong nNd = pPos->nNode.GetIndex();
5140 0 : bReadNoTbl = ( nNd < rDoc.GetNodes().GetEndOfInserts().GetIndex() &&
5141 0 : rDoc.GetNodes().GetEndOfInserts().StartOfSectionIndex() < nNd );
5142 : }
5143 :
5144 186 : ::SetProgressState(nProgress, mpDocShell); // Update
5145 :
5146 : // loop for each glossary entry and add dummy section node
5147 186 : if (pGloss)
5148 : {
5149 0 : WW8PLCF aPlc(*pTableStream, pWwFib->fcPlcfglsy, pWwFib->lcbPlcfglsy, 0);
5150 :
5151 : WW8_CP nStart, nEnd;
5152 : void* pDummy;
5153 :
5154 0 : for (int i = 0; i < pGloss->GetNoStrings(); ++i, aPlc.advance())
5155 : {
5156 0 : SwNodeIndex aIdx( rDoc.GetNodes().GetEndOfContent());
5157 : SwTxtFmtColl* pColl =
5158 0 : rDoc.getIDocumentStylePoolAccess().GetTxtCollFromPool(RES_POOLCOLL_STANDARD,
5159 0 : false);
5160 : SwStartNode *pNode =
5161 0 : rDoc.GetNodes().MakeTextSection(aIdx,
5162 0 : SwNormalStartNode,pColl);
5163 0 : pPaM->GetPoint()->nNode = pNode->GetIndex()+1;
5164 0 : pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(),0);
5165 0 : aPlc.Get( nStart, nEnd, pDummy );
5166 0 : ReadText(nStart,nEnd-nStart-1,MAN_MAINTEXT);
5167 0 : }
5168 : }
5169 : else // ordinary case
5170 : {
5171 186 : if (mbNewDoc && pStg && !pGloss) /*meaningless for a glossary, cmc*/
5172 : {
5173 182 : mpDocShell->SetIsTemplate( pWwFib->fDot ); // point at tgc record
5174 : uno::Reference<document::XDocumentPropertiesSupplier> const
5175 182 : xDocPropSupp(mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
5176 364 : uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
5177 :
5178 364 : OUString sCreatedFrom = xDocProps->getTemplateURL();
5179 364 : uno::Reference< container::XNameContainer > xPrjNameCache;
5180 364 : uno::Reference< lang::XMultiServiceFactory> xSF(mpDocShell->GetModel(), uno::UNO_QUERY);
5181 182 : if ( xSF.is() )
5182 182 : xPrjNameCache.set( xSF->createInstance( "ooo.vba.VBAProjectNameProvider" ), uno::UNO_QUERY );
5183 :
5184 : // Read Global templates
5185 182 : ReadGlobalTemplateSettings( sCreatedFrom, xPrjNameCache );
5186 :
5187 : // Create and insert Word vba Globals
5188 364 : uno::Any aGlobs;
5189 364 : uno::Sequence< uno::Any > aArgs(1);
5190 182 : aArgs[ 0 ] <<= mpDocShell->GetModel();
5191 182 : aGlobs <<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( "ooo.vba.word.Globals", aArgs );
5192 :
5193 : #if HAVE_FEATURE_SCRIPTING
5194 182 : BasicManager *pBasicMan = mpDocShell->GetBasicManager();
5195 182 : if (pBasicMan)
5196 182 : pBasicMan->SetGlobalUNOConstant( "VBAGlobals", aGlobs );
5197 : #endif
5198 364 : BasicProjImportHelper aBasicImporter( *mpDocShell );
5199 : // Import vba via oox filter
5200 182 : bool bRet = aBasicImporter.import( mpDocShell->GetMedium()->GetInputStream() );
5201 :
5202 182 : lcl_createTemplateToProjectEntry( xPrjNameCache, sCreatedFrom, aBasicImporter.getProjectName() );
5203 182 : WW8Customizations aCustomisations( pTableStream, *pWwFib );
5204 182 : aCustomisations.Import( mpDocShell );
5205 :
5206 182 : if( bRet )
5207 2 : rDoc.SetContainsMSVBasic(true);
5208 :
5209 364 : StoreMacroCmds();
5210 : }
5211 186 : mbOnLoadingMain = true;
5212 186 : ReadText(0, pWwFib->ccpText, MAN_MAINTEXT);
5213 186 : mbOnLoadingMain = false;
5214 : }
5215 :
5216 186 : ::SetProgressState(nProgress, mpDocShell); // Update
5217 :
5218 186 : if (pDrawPg && pMSDffManager && pMSDffManager->GetShapeOrders())
5219 : {
5220 : // Helper array to chain the inserted frames (instead of SdrTxtObj)
5221 56 : SvxMSDffShapeTxBxSort aTxBxSort;
5222 :
5223 : // Ensure correct z-order of read Escher objects
5224 56 : sal_uInt16 nShapeCount = pMSDffManager->GetShapeOrders()->size();
5225 :
5226 716 : for (sal_uInt16 nShapeNum=0; nShapeNum < nShapeCount; nShapeNum++)
5227 : {
5228 : SvxMSDffShapeOrder *pOrder =
5229 660 : &(*pMSDffManager->GetShapeOrders())[nShapeNum];
5230 : // Insert Pointer into new Sort array
5231 660 : if (pOrder->nTxBxComp && pOrder->pFly)
5232 12 : aTxBxSort.insert(pOrder);
5233 : }
5234 : // Chain Frames
5235 56 : if( !aTxBxSort.empty() )
5236 : {
5237 12 : SwFmtChain aChain;
5238 24 : for( SvxMSDffShapeTxBxSort::iterator it = aTxBxSort.begin(); it != aTxBxSort.end(); ++it )
5239 : {
5240 12 : SvxMSDffShapeOrder *pOrder = *it;
5241 :
5242 : // Initialize FlyFrame Formats
5243 12 : SwFlyFrmFmt* pFlyFmt = pOrder->pFly;
5244 12 : SwFlyFrmFmt* pNextFlyFmt = 0;
5245 12 : SwFlyFrmFmt* pPrevFlyFmt = 0;
5246 :
5247 : // Determine successor, if we can
5248 12 : SvxMSDffShapeTxBxSort::iterator tmpIter1 = it;
5249 12 : ++tmpIter1;
5250 12 : if( tmpIter1 != aTxBxSort.end() )
5251 : {
5252 0 : SvxMSDffShapeOrder *pNextOrder = *tmpIter1;
5253 0 : if ((0xFFFF0000 & pOrder->nTxBxComp)
5254 0 : == (0xFFFF0000 & pNextOrder->nTxBxComp))
5255 0 : pNextFlyFmt = pNextOrder->pFly;
5256 : }
5257 : // Determine precessor, if we can
5258 12 : if( it != aTxBxSort.begin() )
5259 : {
5260 0 : SvxMSDffShapeTxBxSort::iterator tmpIter2 = it;
5261 0 : --tmpIter2;
5262 0 : SvxMSDffShapeOrder *pPrevOrder = *tmpIter2;
5263 0 : if ((0xFFFF0000 & pOrder->nTxBxComp)
5264 0 : == (0xFFFF0000 & pPrevOrder->nTxBxComp))
5265 0 : pPrevFlyFmt = pPrevOrder->pFly;
5266 : }
5267 : // If successor or predecessor present, insert the
5268 : // chain at the FlyFrame Format
5269 12 : if (pNextFlyFmt || pPrevFlyFmt)
5270 : {
5271 0 : aChain.SetNext( pNextFlyFmt );
5272 0 : aChain.SetPrev( pPrevFlyFmt );
5273 0 : pFlyFmt->SetFmtAttr( aChain );
5274 : }
5275 12 : }
5276 56 : }
5277 : }
5278 :
5279 186 : if (mbNewDoc)
5280 : {
5281 186 : if( pWDop->fRevMarking )
5282 0 : eMode |= nsRedlineMode_t::REDLINE_ON;
5283 186 : if( pWDop->fRMView )
5284 178 : eMode |= nsRedlineMode_t::REDLINE_SHOW_DELETE;
5285 : }
5286 :
5287 186 : maInsertedTables.DelAndMakeTblFrms();
5288 186 : maSectionManager.InsertSegments();
5289 :
5290 186 : vColl.clear();
5291 :
5292 186 : DELETEZ( pStyles );
5293 :
5294 186 : if( pFormImpl )
5295 106 : DeleteFormImpl();
5296 186 : GrafikDtor();
5297 186 : DELETEZ( pMSDffManager );
5298 186 : DELETEZ( pHdFt );
5299 186 : DELETEZ( pSBase );
5300 186 : delete pWDop;
5301 186 : DELETEZ( pFonts );
5302 186 : delete mpAtnNames;
5303 186 : delete mpSprmParser;
5304 186 : ::EndProgress(mpDocShell);
5305 :
5306 186 : pDataStream = 0;
5307 186 : pTableStream = 0;
5308 :
5309 186 : DeleteCtrlStk();
5310 186 : mpRedlineStack->closeall(*pPaM->GetPoint());
5311 186 : delete mpRedlineStack;
5312 186 : DeleteAnchorStk();
5313 186 : DeleteRefStks();
5314 :
5315 : // For i120928,achieve the graphics from the special bookmark with is for graphic bullet
5316 : {
5317 186 : std::vector<const SwGrfNode*> vecBulletGrf;
5318 372 : std::vector<SwFrmFmt*> vecFrmFmt;
5319 :
5320 186 : IDocumentMarkAccess* const pMarkAccess = rDoc.getIDocumentMarkAccess();
5321 186 : if ( pMarkAccess )
5322 : {
5323 186 : IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findBookmark( "_PictureBullets" );
5324 186 : if ( ppBkmk != pMarkAccess->getBookmarksEnd() &&
5325 0 : IDocumentMarkAccess::GetType( *(ppBkmk->get()) ) == IDocumentMarkAccess::BOOKMARK )
5326 : {
5327 0 : SwTxtNode* pTxtNode = ppBkmk->get()->GetMarkStart().nNode.GetNode().GetTxtNode();
5328 :
5329 0 : if ( pTxtNode )
5330 : {
5331 0 : const SwpHints* pHints = pTxtNode->GetpSwpHints();
5332 0 : for( size_t nHintPos = 0; pHints && nHintPos < pHints->Count(); ++nHintPos)
5333 : {
5334 0 : const SwTxtAttr *pHt = (*pHints)[nHintPos];
5335 0 : const sal_Int32 st = pHt->GetStart();
5336 0 : if( pHt
5337 0 : && pHt->Which() == RES_TXTATR_FLYCNT
5338 0 : && (st >= ppBkmk->get()->GetMarkStart().nContent.GetIndex()) )
5339 : {
5340 0 : SwFrmFmt* pFrmFmt = pHt->GetFlyCnt().GetFrmFmt();
5341 0 : vecFrmFmt.push_back(pFrmFmt);
5342 0 : const SwNodeIndex* pNdIdx = pFrmFmt->GetCntnt().GetCntntIdx();
5343 : const SwNodes* pNodesArray = (pNdIdx != NULL)
5344 : ? &(pNdIdx->GetNodes())
5345 0 : : NULL;
5346 : const SwGrfNode *pGrf = (pNodesArray != NULL)
5347 0 : ? dynamic_cast<const SwGrfNode*>((*pNodesArray)[pNdIdx->GetIndex() + 1])
5348 0 : : NULL;
5349 0 : vecBulletGrf.push_back(pGrf);
5350 : }
5351 : }
5352 : // update graphic bullet information
5353 0 : size_t nCount = pLstManager->GetWW8LSTInfoNum();
5354 0 : for (size_t i = 0; i < nCount; ++i)
5355 : {
5356 0 : SwNumRule* pRule = pLstManager->GetNumRule(i);
5357 0 : for (sal_uInt16 j = 0; j < MAXLEVEL; ++j)
5358 : {
5359 0 : SwNumFmt aNumFmt(pRule->Get(j));
5360 0 : const sal_Int16 nType = aNumFmt.GetNumberingType();
5361 0 : const sal_uInt16 nGrfBulletCP = aNumFmt.GetGrfBulletCP();
5362 0 : if ( nType == SVX_NUM_BITMAP
5363 0 : && vecBulletGrf.size() > nGrfBulletCP
5364 0 : && vecBulletGrf[nGrfBulletCP] != NULL )
5365 : {
5366 0 : Graphic aGraphic = vecBulletGrf[nGrfBulletCP]->GetGrf();
5367 0 : SvxBrushItem aBrush(aGraphic, GPOS_AREA, SID_ATTR_BRUSH);
5368 0 : vcl::Font aFont = numfunc::GetDefBulletFont();
5369 0 : int nHeight = aFont.GetHeight() * 12;
5370 0 : Size aPrefSize( aGraphic.GetPrefSize());
5371 0 : if (aPrefSize.Height() * aPrefSize.Width() != 0 )
5372 : {
5373 0 : int nWidth = (nHeight * aPrefSize.Width()) / aPrefSize.Height();
5374 0 : Size aSize(nWidth, nHeight);
5375 0 : aNumFmt.SetGraphicBrush(&aBrush, &aSize);
5376 : }
5377 : else
5378 : {
5379 0 : aNumFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
5380 0 : aNumFmt.SetBulletChar(0x2190);
5381 : }
5382 0 : pRule->Set( j, aNumFmt );
5383 : }
5384 0 : }
5385 : }
5386 : // Remove additional pictures
5387 0 : for (sal_uInt16 i = 0; i < vecFrmFmt.size(); ++i)
5388 : {
5389 0 : rDoc.getIDocumentLayoutAccess().DelLayoutFmt(vecFrmFmt[i]);
5390 : }
5391 : }
5392 : }
5393 : }
5394 372 : DELETEZ( pLstManager );
5395 : }
5396 :
5397 : // remove extra paragraphs after attribute ctrl
5398 : // stacks etc. are destroyed, and before fields
5399 : // are updated
5400 186 : m_aExtraneousParas.delete_all_from_doc();
5401 :
5402 186 : UpdateFields();
5403 :
5404 : // delete the pam before the call for hide all redlines (Bug 73683)
5405 186 : if (mbNewDoc)
5406 186 : rDoc.getIDocumentRedlineAccess().SetRedlineMode((RedlineMode_t)( eMode ));
5407 :
5408 : SAL_WARN_IF(mpTableEndPaM, "sw.ww8", "document ended without table ending");
5409 186 : mpTableEndPaM.reset(); //ensure this is deleted before pPaM
5410 186 : delete pPaM, pPaM = 0;
5411 186 : mpLastAnchorPos.reset();//ensure this is deleted before UpdatePageDescs
5412 :
5413 186 : UpdatePageDescs(rDoc, nPageDescOffset);
5414 :
5415 372 : return nErrRet;
5416 : }
5417 :
5418 186 : sal_uLong SwWW8ImplReader::SetSubStreams(SvStorageStreamRef &rTableStream,
5419 : SvStorageStreamRef &rDataStream)
5420 : {
5421 186 : sal_uLong nErrRet = 0;
5422 : // 6 stands for "6 OR 7", 7 stands for "ONLY 7"
5423 186 : switch (pWwFib->nVersion)
5424 : {
5425 : case 6:
5426 : case 7:
5427 4 : pTableStream = pStrm;
5428 4 : pDataStream = pStrm;
5429 4 : break;
5430 : case 8:
5431 182 : if(!pStg)
5432 : {
5433 : OSL_ENSURE( pStg, "Version 8 always needs to have a Storage!!" );
5434 0 : nErrRet = ERR_SWG_READ_ERROR;
5435 0 : break;
5436 : }
5437 :
5438 364 : rTableStream = pStg->OpenSotStream( OUString::createFromAscii(
5439 : pWwFib->fWhichTblStm ? SL::a1Table : SL::a0Table),
5440 182 : STREAM_STD_READ);
5441 :
5442 182 : pTableStream = &rTableStream;
5443 182 : pTableStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
5444 :
5445 364 : rDataStream = pStg->OpenSotStream(OUString(SL::aData),
5446 182 : STREAM_STD_READ | STREAM_NOCREATE );
5447 :
5448 182 : if (rDataStream.Is() && SVSTREAM_OK == rDataStream->GetError())
5449 : {
5450 70 : pDataStream = &rDataStream;
5451 70 : pDataStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
5452 : }
5453 : else
5454 112 : pDataStream = pStrm;
5455 182 : break;
5456 : default:
5457 : // Program error!
5458 : OSL_ENSURE( false, "We forgot to encode nVersion!" );
5459 0 : nErrRet = ERR_SWG_READ_ERROR;
5460 0 : break;
5461 : }
5462 186 : return nErrRet;
5463 : }
5464 :
5465 : namespace
5466 : {
5467 0 : utl::TempFile *MakeTemp(SvFileStream &rSt)
5468 : {
5469 0 : utl::TempFile *pT = new utl::TempFile;
5470 0 : pT->EnableKillingFile();
5471 0 : rSt.Open(pT->GetFileName(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE);
5472 0 : return pT;
5473 : }
5474 :
5475 : #define WW_BLOCKSIZE 0x200
5476 :
5477 0 : void DecryptRC4(msfilter::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
5478 : {
5479 0 : rIn.Seek(STREAM_SEEK_TO_END);
5480 0 : const sal_Size nLen = rIn.Tell();
5481 0 : rIn.Seek(0);
5482 :
5483 : sal_uInt8 in[WW_BLOCKSIZE];
5484 0 : for (sal_Size nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
5485 : {
5486 0 : sal_Size nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI;
5487 0 : nBS = rIn.Read(in, nBS);
5488 0 : rCtx.InitCipher(nBlock);
5489 0 : rCtx.Decode(in, nBS, in, nBS);
5490 0 : rOut.Write(in, nBS);
5491 : }
5492 0 : }
5493 :
5494 0 : void DecryptXOR(msfilter::MSCodec_XorWord95 &rCtx, SvStream &rIn, SvStream &rOut)
5495 : {
5496 0 : sal_Size nSt = rIn.Tell();
5497 0 : rIn.Seek(STREAM_SEEK_TO_END);
5498 0 : sal_Size nLen = rIn.Tell();
5499 0 : rIn.Seek(nSt);
5500 :
5501 0 : rCtx.InitCipher();
5502 0 : rCtx.Skip(nSt);
5503 :
5504 : sal_uInt8 in[0x4096];
5505 0 : for (sal_Size nI = nSt; nI < nLen; nI += 0x4096)
5506 : {
5507 0 : sal_Size nBS = (nLen - nI > 0x4096 ) ? 0x4096 : nLen - nI;
5508 0 : nBS = rIn.Read(in, nBS);
5509 0 : rCtx.Decode(in, nBS);
5510 0 : rOut.Write(in, nBS);
5511 : }
5512 0 : }
5513 :
5514 : // moan, copy and paste :-(
5515 0 : OUString QueryPasswordForMedium(SfxMedium& rMedium)
5516 : {
5517 0 : OUString aPassw;
5518 :
5519 : using namespace com::sun::star;
5520 :
5521 0 : const SfxItemSet* pSet = rMedium.GetItemSet();
5522 : const SfxPoolItem *pPasswordItem;
5523 :
5524 0 : if(pSet && SfxItemState::SET == pSet->GetItemState(SID_PASSWORD, true, &pPasswordItem))
5525 0 : aPassw = ((const SfxStringItem *)pPasswordItem)->GetValue();
5526 : else
5527 : {
5528 : try
5529 : {
5530 0 : uno::Reference< task::XInteractionHandler > xHandler( rMedium.GetInteractionHandler() );
5531 0 : if( xHandler.is() )
5532 : {
5533 : ::comphelper::DocPasswordRequest* pRequest = new ::comphelper::DocPasswordRequest(
5534 : ::comphelper::DocPasswordRequestType_MS, task::PasswordRequestMode_PASSWORD_ENTER,
5535 0 : INetURLObject( rMedium.GetOrigURL() ).GetName( INetURLObject::DECODE_WITH_CHARSET ) );
5536 0 : uno::Reference< task::XInteractionRequest > xRequest( pRequest );
5537 :
5538 0 : xHandler->handle( xRequest );
5539 :
5540 0 : if( pRequest->isPassword() )
5541 0 : aPassw = pRequest->getPassword();
5542 0 : }
5543 : }
5544 0 : catch( const uno::Exception& )
5545 : {
5546 : }
5547 : }
5548 :
5549 0 : return aPassw;
5550 : }
5551 :
5552 0 : uno::Sequence< beans::NamedValue > InitXorWord95Codec( ::msfilter::MSCodec_XorWord95& rCodec, SfxMedium& rMedium, WW8Fib* pWwFib )
5553 : {
5554 0 : uno::Sequence< beans::NamedValue > aEncryptionData;
5555 0 : SFX_ITEMSET_ARG( rMedium.GetItemSet(), pEncryptionData, SfxUnoAnyItem, SID_ENCRYPTIONDATA, false );
5556 0 : if ( pEncryptionData && ( pEncryptionData->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
5557 0 : aEncryptionData.realloc( 0 );
5558 :
5559 0 : if ( !aEncryptionData.getLength() )
5560 : {
5561 0 : OUString sUniPassword = QueryPasswordForMedium( rMedium );
5562 :
5563 : OString sPassword(OUStringToOString(sUniPassword,
5564 0 : WW8Fib::GetFIBCharset(pWwFib->chseTables)));
5565 :
5566 0 : sal_Int32 nLen = sPassword.getLength();
5567 0 : if( nLen <= 15 )
5568 : {
5569 : sal_uInt8 pPassword[16];
5570 0 : memcpy(pPassword, sPassword.getStr(), nLen);
5571 0 : memset(pPassword+nLen, 0, sizeof(pPassword)-nLen);
5572 :
5573 0 : rCodec.InitKey( pPassword );
5574 0 : aEncryptionData = rCodec.GetEncryptionData();
5575 :
5576 : // the export supports RC4 algorithm only, so we have to
5577 : // generate the related EncryptionData as well, so that Save
5578 : // can export the document without asking for a password;
5579 : // as result there will be EncryptionData for both algorithms
5580 : // in the MediaDescriptor
5581 0 : ::msfilter::MSCodec_Std97 aCodec97;
5582 :
5583 : // Generate random number with a seed of time as salt.
5584 : TimeValue aTime;
5585 0 : osl_getSystemTime( &aTime );
5586 0 : rtlRandomPool aRandomPool = rtl_random_createPool();
5587 0 : rtl_random_addBytes ( aRandomPool, &aTime, 8 );
5588 :
5589 : sal_uInt8 pDocId[ 16 ];
5590 0 : rtl_random_getBytes( aRandomPool, pDocId, 16 );
5591 :
5592 0 : rtl_random_destroyPool( aRandomPool );
5593 :
5594 : sal_uInt16 pStd97Pass[16];
5595 0 : memset( pStd97Pass, 0, sizeof( pStd97Pass ) );
5596 0 : for( sal_Int32 nChar = 0; nChar < nLen; ++nChar )
5597 0 : pStd97Pass[nChar] = sUniPassword[nChar];
5598 :
5599 0 : aCodec97.InitKey( pStd97Pass, pDocId );
5600 :
5601 : // merge the EncryptionData, there should be no conflicts
5602 0 : ::comphelper::SequenceAsHashMap aEncryptionHash( aEncryptionData );
5603 0 : aEncryptionHash.update( ::comphelper::SequenceAsHashMap( aCodec97.GetEncryptionData() ) );
5604 0 : aEncryptionHash >> aEncryptionData;
5605 0 : }
5606 : }
5607 :
5608 0 : return aEncryptionData;
5609 : }
5610 :
5611 0 : uno::Sequence< beans::NamedValue > InitStd97Codec( ::msfilter::MSCodec_Std97& rCodec, sal_uInt8 pDocId[16], SfxMedium& rMedium )
5612 : {
5613 0 : uno::Sequence< beans::NamedValue > aEncryptionData;
5614 0 : SFX_ITEMSET_ARG( rMedium.GetItemSet(), pEncryptionData, SfxUnoAnyItem, SID_ENCRYPTIONDATA, false );
5615 0 : if ( pEncryptionData && ( pEncryptionData->GetValue() >>= aEncryptionData ) && !rCodec.InitCodec( aEncryptionData ) )
5616 0 : aEncryptionData.realloc( 0 );
5617 :
5618 0 : if ( !aEncryptionData.getLength() )
5619 : {
5620 0 : OUString sUniPassword = QueryPasswordForMedium( rMedium );
5621 :
5622 0 : sal_Int32 nLen = sUniPassword.getLength();
5623 0 : if ( nLen <= 15 )
5624 : {
5625 : sal_Unicode pPassword[16];
5626 0 : memset( pPassword, 0, sizeof( pPassword ) );
5627 0 : for( sal_Int32 nChar = 0; nChar < nLen; ++nChar )
5628 0 : pPassword[nChar] = sUniPassword[nChar];
5629 :
5630 0 : rCodec.InitKey( pPassword, pDocId );
5631 0 : aEncryptionData = rCodec.GetEncryptionData();
5632 0 : }
5633 : }
5634 :
5635 0 : return aEncryptionData;
5636 : }
5637 : }
5638 :
5639 186 : sal_uLong SwWW8ImplReader::LoadThroughDecryption(SwPaM& rPaM ,WW8Glossary *pGloss)
5640 : {
5641 186 : sal_uLong nErrRet = 0;
5642 186 : if (pGloss)
5643 0 : pWwFib = pGloss->GetFib();
5644 : else
5645 186 : pWwFib = new WW8Fib(*pStrm, nWantedVersion);
5646 :
5647 186 : if (pWwFib->nFibError)
5648 0 : nErrRet = ERR_SWG_READ_ERROR;
5649 :
5650 372 : SvStorageStreamRef xTableStream, xDataStream;
5651 :
5652 186 : if (!nErrRet)
5653 186 : nErrRet = SetSubStreams(xTableStream, xDataStream);
5654 :
5655 186 : utl::TempFile *pTempMain = 0;
5656 186 : utl::TempFile *pTempTable = 0;
5657 186 : utl::TempFile *pTempData = 0;
5658 372 : SvFileStream aDecryptMain;
5659 372 : SvFileStream aDecryptTable;
5660 372 : SvFileStream aDecryptData;
5661 :
5662 186 : bool bDecrypt = false;
5663 186 : enum {RC4, XOR, Other} eAlgo = Other;
5664 186 : if (pWwFib->fEncrypted && !nErrRet)
5665 : {
5666 0 : if (!pGloss)
5667 : {
5668 0 : bDecrypt = true;
5669 0 : if (8 != pWwFib->nVersion)
5670 0 : eAlgo = XOR;
5671 : else
5672 : {
5673 0 : if (pWwFib->nKey != 0)
5674 0 : eAlgo = XOR;
5675 : else
5676 : {
5677 0 : pTableStream->Seek(0);
5678 : sal_uInt32 nEncType;
5679 0 : pTableStream->ReadUInt32( nEncType );
5680 0 : if (nEncType == 0x10001)
5681 0 : eAlgo = RC4;
5682 : }
5683 : }
5684 : }
5685 : }
5686 :
5687 186 : if (bDecrypt)
5688 : {
5689 0 : nErrRet = ERRCODE_SVX_WRONGPASS;
5690 0 : SfxMedium* pMedium = mpDocShell->GetMedium();
5691 :
5692 0 : if ( pMedium )
5693 : {
5694 0 : switch (eAlgo)
5695 : {
5696 : default:
5697 0 : nErrRet = ERRCODE_SVX_READ_FILTER_CRYPT;
5698 0 : break;
5699 : case XOR:
5700 : {
5701 0 : msfilter::MSCodec_XorWord95 aCtx;
5702 0 : uno::Sequence< beans::NamedValue > aEncryptionData = InitXorWord95Codec( aCtx, *pMedium, pWwFib );
5703 :
5704 : // if initialization has failed the EncryptionData should be empty
5705 0 : if ( aEncryptionData.getLength() && aCtx.VerifyKey( pWwFib->nKey, pWwFib->nHash ) )
5706 : {
5707 0 : nErrRet = 0;
5708 0 : pTempMain = MakeTemp(aDecryptMain);
5709 :
5710 0 : pStrm->Seek(0);
5711 : size_t nUnencryptedHdr =
5712 0 : (8 == pWwFib->nVersion) ? 0x44 : 0x34;
5713 0 : sal_uInt8 *pIn = new sal_uInt8[nUnencryptedHdr];
5714 0 : nUnencryptedHdr = pStrm->Read(pIn, nUnencryptedHdr);
5715 0 : aDecryptMain.Write(pIn, nUnencryptedHdr);
5716 0 : delete [] pIn;
5717 :
5718 0 : DecryptXOR(aCtx, *pStrm, aDecryptMain);
5719 :
5720 0 : if (!pTableStream || pTableStream == pStrm)
5721 0 : pTableStream = &aDecryptMain;
5722 : else
5723 : {
5724 0 : pTempTable = MakeTemp(aDecryptTable);
5725 0 : DecryptXOR(aCtx, *pTableStream, aDecryptTable);
5726 0 : pTableStream = &aDecryptTable;
5727 : }
5728 :
5729 0 : if (!pDataStream || pDataStream == pStrm)
5730 0 : pDataStream = &aDecryptMain;
5731 : else
5732 : {
5733 0 : pTempData = MakeTemp(aDecryptData);
5734 0 : DecryptXOR(aCtx, *pDataStream, aDecryptData);
5735 0 : pDataStream = &aDecryptData;
5736 : }
5737 :
5738 0 : pMedium->GetItemSet()->ClearItem( SID_PASSWORD );
5739 0 : pMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
5740 0 : }
5741 : }
5742 0 : break;
5743 : case RC4:
5744 : {
5745 : sal_uInt8 aDocId[ 16 ];
5746 : sal_uInt8 aSaltData[ 16 ];
5747 : sal_uInt8 aSaltHash[ 16 ];
5748 :
5749 : bool bCouldReadHeaders =
5750 0 : checkRead(*pTableStream, aDocId, 16) &&
5751 0 : checkRead(*pTableStream, aSaltData, 16) &&
5752 0 : checkRead(*pTableStream, aSaltHash, 16);
5753 :
5754 0 : msfilter::MSCodec_Std97 aCtx;
5755 : // if initialization has failed the EncryptionData should be empty
5756 0 : uno::Sequence< beans::NamedValue > aEncryptionData;
5757 0 : if (bCouldReadHeaders)
5758 0 : aEncryptionData = InitStd97Codec( aCtx, aDocId, *pMedium );
5759 0 : if ( aEncryptionData.getLength() && aCtx.VerifyKey( aSaltData, aSaltHash ) )
5760 : {
5761 0 : nErrRet = 0;
5762 :
5763 0 : pTempMain = MakeTemp(aDecryptMain);
5764 :
5765 0 : pStrm->Seek(0);
5766 0 : sal_Size nUnencryptedHdr = 0x44;
5767 0 : sal_uInt8 *pIn = new sal_uInt8[nUnencryptedHdr];
5768 0 : nUnencryptedHdr = pStrm->Read(pIn, nUnencryptedHdr);
5769 :
5770 0 : DecryptRC4(aCtx, *pStrm, aDecryptMain);
5771 :
5772 0 : aDecryptMain.Seek(0);
5773 0 : aDecryptMain.Write(pIn, nUnencryptedHdr);
5774 0 : delete [] pIn;
5775 :
5776 0 : pTempTable = MakeTemp(aDecryptTable);
5777 0 : DecryptRC4(aCtx, *pTableStream, aDecryptTable);
5778 0 : pTableStream = &aDecryptTable;
5779 :
5780 0 : if (!pDataStream || pDataStream == pStrm)
5781 0 : pDataStream = &aDecryptMain;
5782 : else
5783 : {
5784 0 : pTempData = MakeTemp(aDecryptData);
5785 0 : DecryptRC4(aCtx, *pDataStream, aDecryptData);
5786 0 : pDataStream = &aDecryptData;
5787 : }
5788 :
5789 0 : pMedium->GetItemSet()->ClearItem( SID_PASSWORD );
5790 0 : pMedium->GetItemSet()->Put( SfxUnoAnyItem( SID_ENCRYPTIONDATA, uno::makeAny( aEncryptionData ) ) );
5791 0 : }
5792 : }
5793 0 : break;
5794 : }
5795 : }
5796 :
5797 0 : if (nErrRet == 0)
5798 : {
5799 0 : pStrm = &aDecryptMain;
5800 :
5801 0 : delete pWwFib;
5802 0 : pWwFib = new WW8Fib(*pStrm, nWantedVersion);
5803 0 : if (pWwFib->nFibError)
5804 0 : nErrRet = ERR_SWG_READ_ERROR;
5805 : }
5806 : }
5807 :
5808 186 : if (!nErrRet)
5809 186 : nErrRet = CoreLoad(pGloss, *rPaM.GetPoint());
5810 :
5811 186 : delete pTempMain;
5812 186 : delete pTempTable;
5813 186 : delete pTempData;
5814 :
5815 186 : if (!pGloss)
5816 186 : delete pWwFib;
5817 372 : return nErrRet;
5818 : }
5819 :
5820 186 : void SwWW8ImplReader::SetOutlineStyles()
5821 : {
5822 : // If we are inserted into a document then don't clobber existing outline
5823 : // levels.
5824 186 : sal_uInt16 nOutlineStyleListLevelWithAssignment = 0;
5825 186 : if (!mbNewDoc)
5826 : {
5827 0 : sw::ParaStyles aOutLined(sw::util::GetParaStyles(rDoc));
5828 0 : sw::util::SortByAssignedOutlineStyleListLevel(aOutLined);
5829 0 : sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend();
5830 0 : for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter)
5831 : {
5832 0 : if ((*aIter)->IsAssignedToListLevelOfOutlineStyle())
5833 0 : nOutlineStyleListLevelWithAssignment |= 1 << (*aIter)->GetAssignedOutlineStyleLevel();
5834 : else
5835 0 : break;
5836 0 : }
5837 : }
5838 :
5839 : // Check applied WW8 list styles at WW8 Built-In Heading Styles
5840 : // - Choose the list style which occurs most often as the one which provides
5841 : // the list level properties for the Outline Style.
5842 : // - Populate temporary list of WW8 Built-In Heading Styles for further
5843 : // iteration
5844 186 : std::vector<SwWW8StyInf*> aWW8BuiltInHeadingStyles;
5845 186 : const SwNumRule* pChosenWW8ListStyle = NULL;
5846 : {
5847 186 : std::map<const SwNumRule*, int> aWW8ListStyleCounts;
5848 6096 : for (sal_uInt16 nI = 0; nI < vColl.size(); ++nI)
5849 : {
5850 5910 : SwWW8StyInf& rSI = vColl[nI];
5851 :
5852 5910 : if (!rSI.IsWW8BuiltInHeadingStyle() || !rSI.HasWW8OutlineLevel())
5853 : {
5854 5702 : continue;
5855 : }
5856 :
5857 208 : aWW8BuiltInHeadingStyles.push_back(&rSI);
5858 :
5859 208 : const SwNumRule* pWW8ListStyle = rSI.GetOutlineNumrule();
5860 208 : if (pWW8ListStyle != NULL)
5861 : {
5862 : std::map<const SwNumRule*, int>::iterator aCountIter
5863 60 : = aWW8ListStyleCounts.find(pWW8ListStyle);
5864 60 : if (aCountIter == aWW8ListStyleCounts.end())
5865 : {
5866 22 : aWW8ListStyleCounts[pWW8ListStyle] = 1;
5867 : }
5868 : else
5869 : {
5870 38 : ++(aCountIter->second);
5871 : }
5872 : }
5873 : }
5874 :
5875 186 : int nCurrentMaxCount = 0;
5876 : std::map<const SwNumRule*, int>::iterator aCountIterEnd
5877 186 : = aWW8ListStyleCounts.end();
5878 208 : for (std::map<const SwNumRule*, int>::iterator aIter
5879 186 : = aWW8ListStyleCounts.begin();
5880 : aIter != aCountIterEnd; ++aIter)
5881 : {
5882 22 : if (aIter->second > nCurrentMaxCount)
5883 : {
5884 22 : nCurrentMaxCount = aIter->second;
5885 22 : pChosenWW8ListStyle = aIter->first;
5886 : }
5887 186 : }
5888 : }
5889 :
5890 : // - set list level properties of Outline Style - ODF's list style applied
5891 : // by default to headings
5892 : // - assign corresponding Heading Paragraph Styles to the Outline Style
5893 : // - If a heading Paragraph Styles is not applying the WW8 list style which
5894 : // had been chosen as
5895 : // the one which provides the list level properties for the Outline Style,
5896 : // its assignment to
5897 : // the Outline Style is removed. A potential applied WW8 list style is
5898 : // assigned directly and
5899 : // its default outline level is applied.
5900 372 : SwNumRule aOutlineRule(*rDoc.GetOutlineNumRule());
5901 186 : bool bAppliedChangedOutlineStyle = false;
5902 : std::vector<SwWW8StyInf*>::iterator aStylesIterEnd
5903 186 : = aWW8BuiltInHeadingStyles.end();
5904 394 : for (std::vector<SwWW8StyInf*>::iterator aStyleIter
5905 186 : = aWW8BuiltInHeadingStyles.begin();
5906 : aStyleIter != aStylesIterEnd; ++aStyleIter)
5907 : {
5908 208 : SwWW8StyInf* pStyleInf = (*aStyleIter);
5909 :
5910 208 : if (!pStyleInf->bColl) //Character Style
5911 0 : continue;
5912 :
5913 : const sal_uInt16 nOutlineStyleListLevelOfWW8BuiltInHeadingStyle
5914 208 : = 1 << pStyleInf->mnWW8OutlineLevel;
5915 208 : if (nOutlineStyleListLevelOfWW8BuiltInHeadingStyle
5916 : & nOutlineStyleListLevelWithAssignment)
5917 : {
5918 0 : continue;
5919 : }
5920 :
5921 276 : if (pChosenWW8ListStyle != NULL && pStyleInf->mnWW8OutlineLevel
5922 68 : == pStyleInf->nListLevel)
5923 : {
5924 : const SwNumFmt& rRule
5925 52 : = pChosenWW8ListStyle->Get(pStyleInf->mnWW8OutlineLevel);
5926 52 : aOutlineRule.Set(pStyleInf->mnWW8OutlineLevel, rRule);
5927 52 : bAppliedChangedOutlineStyle = true;
5928 : }
5929 :
5930 : // in case that there are more styles on this level ignore them
5931 : nOutlineStyleListLevelWithAssignment
5932 208 : |= nOutlineStyleListLevelOfWW8BuiltInHeadingStyle;
5933 :
5934 208 : SwTxtFmtColl* pTxtFmtColl = static_cast<SwTxtFmtColl*>(pStyleInf->pFmt);
5935 416 : if (pStyleInf->GetOutlineNumrule() != pChosenWW8ListStyle
5936 224 : || (pStyleInf->nListLevel < WW8ListManager::nMaxLevel
5937 60 : && pStyleInf->mnWW8OutlineLevel != pStyleInf->nListLevel))
5938 : {
5939 : // WW8 Built-In Heading Style does not apply the chosen one.
5940 : // --> delete assignment to OutlineStyle, but keep its current
5941 : // outline level
5942 16 : pTxtFmtColl->DeleteAssignmentToListLevelOfOutlineStyle(false);
5943 : // Apply existing WW8 list style a normal list style at the
5944 : // Paragraph Style
5945 16 : if (pStyleInf->GetOutlineNumrule() != NULL)
5946 : {
5947 : pTxtFmtColl->SetFmtAttr(
5948 8 : SwNumRuleItem(pStyleInf->GetOutlineNumrule()->GetName()));
5949 : }
5950 : // apply default outline level of WW8 Built-in Heading Style
5951 : const sal_uInt8 nOutlineLevel
5952 : = SwWW8StyInf::WW8OutlineLevelToOutlinelevel(
5953 16 : pStyleInf->mnWW8OutlineLevel);
5954 : pTxtFmtColl->SetFmtAttr(
5955 16 : SfxUInt16Item(RES_PARATR_OUTLINELEVEL, nOutlineLevel));
5956 : }
5957 : else
5958 : {
5959 : pTxtFmtColl->AssignToListLevelOfOutlineStyle(
5960 192 : pStyleInf->mnWW8OutlineLevel);
5961 : }
5962 : }
5963 :
5964 186 : if (bAppliedChangedOutlineStyle)
5965 : {
5966 22 : rDoc.SetOutlineNumRule(aOutlineRule);
5967 186 : }
5968 186 : }
5969 :
5970 30 : const OUString* SwWW8ImplReader::GetAnnotationAuthor(sal_uInt16 nIdx)
5971 : {
5972 30 : if (!mpAtnNames && pWwFib->lcbGrpStAtnOwners)
5973 : {
5974 : // Determine authors: can be found in the TableStream
5975 12 : mpAtnNames = new ::std::vector<OUString>;
5976 12 : SvStream& rStrm = *pTableStream;
5977 :
5978 12 : long nOldPos = rStrm.Tell();
5979 12 : rStrm.Seek( pWwFib->fcGrpStAtnOwners );
5980 :
5981 12 : long nRead = 0, nCount = pWwFib->lcbGrpStAtnOwners;
5982 48 : while (nRead < nCount)
5983 : {
5984 24 : if( bVer67 )
5985 : {
5986 : mpAtnNames->push_back(read_uInt8_PascalString(rStrm,
5987 0 : RTL_TEXTENCODING_MS_1252));
5988 0 : nRead += mpAtnNames->rbegin()->getLength() + 1; // Length + sal_uInt8 count
5989 : }
5990 : else
5991 : {
5992 24 : mpAtnNames->push_back(read_uInt16_PascalString(rStrm));
5993 : // Unicode: double the length + sal_uInt16 count
5994 24 : nRead += (mpAtnNames->rbegin()->getLength() + 1)*2;
5995 : }
5996 : }
5997 12 : rStrm.Seek( nOldPos );
5998 : }
5999 :
6000 30 : const OUString *pRet = 0;
6001 30 : if (mpAtnNames && nIdx < mpAtnNames->size())
6002 30 : pRet = &((*mpAtnNames)[nIdx]);
6003 30 : return pRet;
6004 : }
6005 :
6006 24 : int SwWW8ImplReader::GetAnnotationIndex(sal_uInt32 nTag)
6007 : {
6008 24 : if (!mpAtnIndexes.get() && pWwFib->lcbSttbfAtnbkmk)
6009 : {
6010 12 : mpAtnIndexes.reset(new std::map<sal_uInt32, int>());
6011 12 : std::vector<OUString> aStrings;
6012 24 : std::vector<ww::bytes> aEntries;
6013 12 : WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcSttbfAtnbkmk, pWwFib->lcbSttbfAtnbkmk, sizeof(struct WW8_ATNBE), eStructCharSet, aStrings, &aEntries);
6014 36 : for (size_t i = 0; i < aStrings.size() && i < aEntries.size(); ++i)
6015 : {
6016 24 : ww::bytes aEntry = aEntries[i];
6017 24 : WW8_ATNBE* pAtnbeStruct = (WW8_ATNBE*)(&aEntry[0]);
6018 24 : mpAtnIndexes->insert(std::pair<sal_uInt32, int>(SVBT32ToUInt32(pAtnbeStruct->nTag), i));
6019 36 : }
6020 : }
6021 24 : if (mpAtnIndexes.get())
6022 : {
6023 24 : std::map<sal_uInt32, int>::iterator it = mpAtnIndexes->find(nTag);
6024 24 : if (it != mpAtnIndexes->end())
6025 24 : return it->second;
6026 : }
6027 0 : return -1;
6028 : }
6029 :
6030 24 : sal_uInt16 SwWW8ImplReader::GetAnnotationEndIndex(sal_uInt16 nStart)
6031 : {
6032 : WW8_CP nStartAkt;
6033 : void* p;
6034 24 : if (mpAtnStarts->GetData(nStart, nStartAkt, p) && p)
6035 : {
6036 : // p is an FBKF, and its first 2 bytes is the ibkl member, which is the end index.
6037 24 : return SVBT16ToShort(*((SVBT16*)p));
6038 : }
6039 0 : return nStart;
6040 : }
6041 :
6042 24 : WW8_CP SwWW8ImplReader::GetAnnotationStart(int nIndex)
6043 : {
6044 24 : if (!mpAtnStarts.get() && pWwFib->lcbPlcfAtnbkf)
6045 : // A PLCFBKF is a PLC whose data elements are FBKF structures (4 bytes each).
6046 12 : mpAtnStarts.reset(new WW8PLCFspecial(pTableStream, pWwFib->fcPlcfAtnbkf, pWwFib->lcbPlcfAtnbkf, 4));
6047 :
6048 24 : if (mpAtnStarts.get())
6049 24 : return mpAtnStarts->GetPos(nIndex);
6050 : else
6051 0 : return SAL_MAX_INT32;
6052 : }
6053 :
6054 24 : WW8_CP SwWW8ImplReader::GetAnnotationEnd(int nIndex)
6055 : {
6056 24 : if (!mpAtnEnds.get() && pWwFib->lcbPlcfAtnbkl)
6057 : // The Plcfbkl structure is a PLC that contains only CPs and no additional data.
6058 12 : mpAtnEnds.reset(new WW8PLCFspecial(pTableStream, pWwFib->fcPlcfAtnbkl, pWwFib->lcbPlcfAtnbkl, 0));
6059 :
6060 24 : if (mpAtnEnds.get())
6061 24 : return mpAtnEnds->GetPos(nIndex);
6062 : else
6063 0 : return SAL_MAX_INT32;
6064 : }
6065 :
6066 190 : sal_uLong SwWW8ImplReader::LoadDoc( SwPaM& rPaM,WW8Glossary *pGloss)
6067 : {
6068 190 : sal_uLong nErrRet = 0;
6069 :
6070 : {
6071 : static const sal_Char* aNames[ 13 ] = {
6072 : "WinWord/WW", "WinWord/WW8", "WinWord/WWFT",
6073 : "WinWord/WWFLX", "WinWord/WWFLY",
6074 : "WinWord/WWF",
6075 : "WinWord/WWFA0", "WinWord/WWFA1", "WinWord/WWFA2",
6076 : "WinWord/WWFB0", "WinWord/WWFB1", "WinWord/WWFB2",
6077 : "WinWord/RegardHindiDigits"
6078 : };
6079 : sal_uInt32 aVal[ 13 ];
6080 :
6081 190 : SwFilterOptions aOpt( 13, aNames, aVal );
6082 :
6083 190 : nIniFlags = aVal[ 0 ];
6084 190 : nIniFlags1= aVal[ 1 ];
6085 : // Moves Flys by x twips to the right or left
6086 190 : nIniFlyDx = aVal[ 3 ];
6087 190 : nIniFlyDy = aVal[ 4 ];
6088 :
6089 190 : nFieldFlags = aVal[ 5 ];
6090 190 : nFieldTagAlways[0] = aVal[ 6 ];
6091 190 : nFieldTagAlways[1] = aVal[ 7 ];
6092 190 : nFieldTagAlways[2] = aVal[ 8 ];
6093 190 : nFieldTagBad[0] = aVal[ 9 ];
6094 190 : nFieldTagBad[1] = aVal[ 10 ];
6095 190 : nFieldTagBad[2] = aVal[ 11 ];
6096 190 : m_bRegardHindiDigits = aVal[ 12 ] > 0;
6097 : }
6098 :
6099 190 : sal_uInt16 nMagic(0);
6100 190 : pStrm->ReadUInt16( nMagic );
6101 :
6102 : // Remember: 6 means "6 OR 7", 7 means "JUST 7"
6103 190 : switch (nWantedVersion)
6104 : {
6105 : case 6:
6106 : case 7:
6107 4 : if (
6108 8 : 0xa59b != nMagic && 0xa59c != nMagic &&
6109 4 : 0xa5dc != nMagic && 0xa5db != nMagic &&
6110 0 : (nMagic < 0xa697 || nMagic > 0xa699)
6111 : )
6112 : {
6113 : // Test for own 97 fake!
6114 0 : if (pStg && 0xa5ec == nMagic)
6115 : {
6116 0 : sal_uLong nCurPos = pStrm->Tell();
6117 0 : if (pStrm->Seek(nCurPos + 22))
6118 : {
6119 : sal_uInt32 nfcMin;
6120 0 : pStrm->ReadUInt32( nfcMin );
6121 0 : if (0x300 != nfcMin)
6122 0 : nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
6123 : }
6124 0 : pStrm->Seek( nCurPos );
6125 : }
6126 : else
6127 0 : nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
6128 : }
6129 4 : break;
6130 : case 8:
6131 186 : if (0xa5ec != nMagic)
6132 4 : nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
6133 186 : break;
6134 : default:
6135 0 : nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
6136 : OSL_ENSURE( false, "We forgot to encode nVersion!" );
6137 0 : break;
6138 : }
6139 :
6140 190 : if (!nErrRet)
6141 186 : nErrRet = LoadThroughDecryption(rPaM ,pGloss);
6142 :
6143 190 : rDoc.PropagateOutlineRule();
6144 :
6145 190 : return nErrRet;
6146 : }
6147 :
6148 16 : extern "C" SAL_DLLPUBLIC_EXPORT Reader* SAL_CALL ImportDOC()
6149 : {
6150 16 : return new WW8Reader();
6151 : }
6152 :
6153 186 : sal_uLong WW8Reader::OpenMainStream( SvStorageStreamRef& rRef, sal_uInt16& rBuffSize )
6154 : {
6155 186 : sal_uLong nRet = ERR_SWG_READ_ERROR;
6156 : OSL_ENSURE( pStg, "Where is my Storage?" );
6157 186 : rRef = pStg->OpenSotStream( OUString("WordDocument"), STREAM_READ | STREAM_SHARE_DENYALL);
6158 :
6159 186 : if( rRef.Is() )
6160 : {
6161 186 : if( SVSTREAM_OK == rRef->GetError() )
6162 : {
6163 186 : sal_uInt16 nOld = rRef->GetBufferSize();
6164 186 : rRef->SetBufferSize( rBuffSize );
6165 186 : rBuffSize = nOld;
6166 186 : nRet = 0;
6167 : }
6168 : else
6169 0 : nRet = rRef->GetError();
6170 : }
6171 186 : return nRet;
6172 : }
6173 :
6174 192 : sal_uLong WW8Reader::Read(SwDoc &rDoc, const OUString& rBaseURL, SwPaM &rPam, const OUString & /* FileName */)
6175 : {
6176 192 : sal_uInt16 nOldBuffSize = 32768;
6177 192 : bool bNew = !bInsertMode; // New Doc (no inserting)
6178 :
6179 192 : SvStorageStreamRef refStrm; // So that no one else can steal the Stream
6180 192 : SvStream* pIn = pStrm;
6181 :
6182 192 : sal_uLong nRet = 0;
6183 192 : sal_uInt8 nVersion = 8;
6184 :
6185 384 : const OUString sFltName = GetFltName();
6186 192 : if ( sFltName=="WW6" )
6187 : {
6188 4 : if (pStrm)
6189 4 : nVersion = 6;
6190 : else
6191 : {
6192 : OSL_ENSURE(false, "WinWord 95 Reader-Read without Stream");
6193 0 : nRet = ERR_SWG_READ_ERROR;
6194 : }
6195 : }
6196 : else
6197 : {
6198 188 : if ( sFltName=="CWW6" )
6199 0 : nVersion = 6;
6200 188 : else if ( sFltName=="CWW7" )
6201 0 : nVersion = 7;
6202 :
6203 188 : if( pStg )
6204 : {
6205 186 : nRet = OpenMainStream( refStrm, nOldBuffSize );
6206 186 : pIn = &refStrm;
6207 : }
6208 : else
6209 : {
6210 : OSL_ENSURE(false, "WinWord 95/97 Reader-Read without Storage");
6211 2 : nRet = ERR_SWG_READ_ERROR;
6212 : }
6213 : }
6214 :
6215 192 : if( !nRet )
6216 : {
6217 190 : if (bNew)
6218 : {
6219 : // Remove Frame and offsets from Frame Template
6220 190 : Reader::ResetFrmFmts( rDoc );
6221 : }
6222 : SwWW8ImplReader* pRdr = new SwWW8ImplReader(nVersion, pStg, pIn, rDoc,
6223 190 : rBaseURL, bNew);
6224 : try
6225 : {
6226 190 : nRet = pRdr->LoadDoc( rPam );
6227 : }
6228 0 : catch( const std::exception& )
6229 : {
6230 0 : nRet = ERR_WW8_NO_WW8_FILE_ERR;
6231 : }
6232 190 : delete pRdr;
6233 :
6234 190 : if( refStrm.Is() )
6235 : {
6236 186 : refStrm->SetBufferSize( nOldBuffSize );
6237 186 : refStrm.Clear();
6238 : }
6239 : else
6240 : {
6241 4 : pIn->ResetError();
6242 : }
6243 :
6244 : }
6245 384 : return nRet;
6246 : }
6247 :
6248 576 : int WW8Reader::GetReaderType()
6249 : {
6250 576 : return SW_STORAGE_READER | SW_STREAM_READER;
6251 : }
6252 :
6253 0 : bool WW8Reader::HasGlossaries() const
6254 : {
6255 0 : return true;
6256 : }
6257 :
6258 0 : bool WW8Reader::ReadGlossaries(SwTextBlocks& rBlocks, bool bSaveRelFiles) const
6259 : {
6260 0 : bool bRet=false;
6261 :
6262 0 : WW8Reader *pThis = const_cast<WW8Reader *>(this);
6263 :
6264 0 : sal_uInt16 nOldBuffSize = 32768;
6265 0 : SvStorageStreamRef refStrm;
6266 0 : if (!pThis->OpenMainStream(refStrm, nOldBuffSize))
6267 : {
6268 0 : WW8Glossary aGloss( refStrm, 8, pStg );
6269 0 : bRet = aGloss.Load( rBlocks, bSaveRelFiles );
6270 : }
6271 0 : return bRet;
6272 : }
6273 :
6274 24 : bool SwMSDffManager::GetOLEStorageName(long nOLEId, OUString& rStorageName,
6275 : SvStorageRef& rSrcStorage, uno::Reference < embed::XStorage >& rDestStorage) const
6276 : {
6277 24 : bool bRet = false;
6278 :
6279 24 : sal_Int32 nPictureId = 0;
6280 24 : if (rReader.pStg)
6281 : {
6282 : // Via the TextBox-PLCF we get the right char Start-End positions
6283 : // We should then find the EmbedField and the corresponding Sprms
6284 : // in that Area.
6285 : // We only need the Sprm for the Picture Id.
6286 24 : long nOldPos = rReader.pStrm->Tell();
6287 : {
6288 : // #i32596# - consider return value of method
6289 : // <rReader.GetTxbxTextSttEndCp(..)>. If it returns false, method
6290 : // wasn't successful. Thus, continue in this case.
6291 : // Note: Ask MM for initialization of <nStartCp> and <nEndCp>.
6292 : // Note: Ask MM about assertions in method <rReader.GetTxbxTextSttEndCp(..)>.
6293 : WW8_CP nStartCp, nEndCp;
6294 24 : if ( rReader.GetTxbxTextSttEndCp(nStartCp, nEndCp,
6295 24 : static_cast<sal_uInt16>((nOLEId >> 16) & 0xFFFF),
6296 48 : static_cast<sal_uInt16>(nOLEId & 0xFFFF)) )
6297 : {
6298 24 : WW8PLCFxSaveAll aSave;
6299 24 : memset( &aSave, 0, sizeof( aSave ) );
6300 24 : rReader.pPlcxMan->SaveAllPLCFx( aSave );
6301 :
6302 24 : nStartCp += rReader.nDrawCpO;
6303 24 : nEndCp += rReader.nDrawCpO;
6304 24 : WW8PLCFx_Cp_FKP* pChp = rReader.pPlcxMan->GetChpPLCF();
6305 24 : wwSprmParser aSprmParser(rReader.pWwFib->GetFIBVersion());
6306 120 : while (nStartCp <= nEndCp && !nPictureId)
6307 : {
6308 72 : if (!pChp->SeekPos( nStartCp))
6309 0 : break;
6310 72 : WW8PLCFxDesc aDesc;
6311 72 : pChp->GetSprms( &aDesc );
6312 :
6313 72 : if (aDesc.nSprmsLen && aDesc.pMemPos) // Attributes present
6314 : {
6315 48 : long nLen = aDesc.nSprmsLen;
6316 48 : const sal_uInt8* pSprm = aDesc.pMemPos;
6317 :
6318 168 : while (nLen >= 2 && !nPictureId)
6319 : {
6320 72 : sal_uInt16 nId = aSprmParser.GetSprmId(pSprm);
6321 72 : sal_uInt16 nSL = aSprmParser.GetSprmSize(nId, pSprm);
6322 :
6323 72 : if( nLen < nSL )
6324 0 : break; // Not enough Bytes left
6325 :
6326 72 : if( 0x6A03 == nId && 0 < nLen )
6327 : {
6328 : nPictureId = SVBT32ToUInt32(pSprm +
6329 44 : aSprmParser.DistanceToData(nId));
6330 44 : bRet = true;
6331 : }
6332 72 : pSprm += nSL;
6333 72 : nLen -= nSL;
6334 : }
6335 : }
6336 72 : nStartCp = aDesc.nEndPos;
6337 : }
6338 :
6339 24 : rReader.pPlcxMan->RestoreAllPLCFx( aSave );
6340 : }
6341 : }
6342 24 : rReader.pStrm->Seek( nOldPos );
6343 : }
6344 :
6345 24 : if( bRet )
6346 : {
6347 24 : rStorageName = OUString('_');
6348 24 : rStorageName += OUString::number(nPictureId);
6349 48 : rSrcStorage = rReader.pStg->OpenSotStorage(OUString(
6350 24 : SL::aObjectPool));
6351 24 : if (!rReader.mpDocShell)
6352 0 : bRet=false;
6353 : else
6354 24 : rDestStorage = rReader.mpDocShell->GetStorage();
6355 : }
6356 24 : return bRet;
6357 : }
6358 :
6359 : /**
6360 : * When reading a single Box (which possibly is part of a group), we do
6361 : * not yet have enough information to decide whether we need it as a TextField
6362 : * or not.
6363 : * So convert all of them as a precaution.
6364 : * FIXME: Actually implement this!
6365 : */
6366 96 : bool SwMSDffManager::ShapeHasText(sal_uLong, sal_uLong) const
6367 : {
6368 96 : return true;
6369 : }
6370 :
6371 5844 : bool SwWW8ImplReader::InEqualOrHigherApo(int nLvl) const
6372 : {
6373 5844 : if (nLvl)
6374 1060 : --nLvl;
6375 : // #i60827# - check size of <maApos> to assure that <maApos.begin() + nLvl> can be performed.
6376 5844 : if ( sal::static_int_cast< sal_Int32>(nLvl) >= sal::static_int_cast< sal_Int32>(maApos.size()) )
6377 : {
6378 6 : return false;
6379 : }
6380 5838 : mycApoIter aIter = std::find(maApos.begin() + nLvl, maApos.end(), true);
6381 5838 : if (aIter != maApos.end())
6382 94 : return true;
6383 : else
6384 5744 : return false;
6385 : }
6386 :
6387 628 : bool SwWW8ImplReader::InEqualApo(int nLvl) const
6388 : {
6389 : // If we are in a table, see if an apo was inserted at the level below the table.
6390 628 : if (nLvl)
6391 66 : --nLvl;
6392 628 : if (nLvl < 0 || static_cast<size_t>(nLvl) >= maApos.size())
6393 0 : return false;
6394 628 : return maApos[nLvl];
6395 : }
6396 :
6397 : namespace sw
6398 : {
6399 : namespace hack
6400 : {
6401 76 : Position::Position(const SwPosition &rPos)
6402 76 : : maPtNode(rPos.nNode), mnPtCntnt(rPos.nContent.GetIndex())
6403 : {
6404 76 : }
6405 :
6406 76 : Position::Position(const Position &rPos)
6407 76 : : maPtNode(rPos.maPtNode), mnPtCntnt(rPos.mnPtCntnt)
6408 : {
6409 76 : }
6410 :
6411 18 : Position::operator SwPosition() const
6412 : {
6413 18 : SwPosition aRet(maPtNode);
6414 18 : aRet.nContent.Assign(maPtNode.GetNode().GetCntntNode(), mnPtCntnt);
6415 18 : return aRet;
6416 : }
6417 : }
6418 : }
6419 :
6420 2 : SwMacroInfo::SwMacroInfo()
6421 : : SdrObjUserData( SW_DRAWLAYER, SW_UD_IMAPDATA, 0 )
6422 2 : , mnShapeId(-1)
6423 :
6424 : {
6425 2 : }
6426 :
6427 4 : SwMacroInfo::~SwMacroInfo()
6428 : {
6429 4 : }
6430 :
6431 0 : SdrObjUserData* SwMacroInfo::Clone( SdrObject* /*pObj*/ ) const
6432 : {
6433 0 : return new SwMacroInfo( *this );
6434 102 : }
6435 :
6436 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|