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