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