update dev300-m58
[ooovba.git] / sw / source / filter / ww8 / ww8par.cxx
blob89fb527d7f0d4b81c4b66d02afab28456349f7e2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ww8par.cxx,v $
10 * $Revision: 1.199.12.6 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
33 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
35 #include <hash_set>
36 #include <com/sun/star/embed/ElementModes.hpp>
37 #include <com/sun/star/embed/XStorage.hpp>
38 #include <unotools/ucbstreamhelper.hxx>
39 #include <tools/solar.h>
40 #include <rtl/tencinfo.h>
42 #include <sot/storage.hxx>
43 #include <sfx2/docinf.hxx>
44 #include <sfx2/docfile.hxx>
45 #include <tools/urlobj.hxx>
46 #include <unotools/tempfile.hxx>
47 #include <svtools/sfxecode.hxx>
49 #include <comphelper/docpasswordrequest.hxx>
50 #include <hintids.hxx>
52 #include <svx/tstpitem.hxx>
53 #include <svx/cscoitem.hxx>
54 #include <svx/svdobj.hxx>
55 #include <svx/svdpage.hxx>
56 #include <svx/paperinf.hxx>
57 #include <svx/lrspitem.hxx> // SvxLRSpaceItem
58 #include <svx/ulspitem.hxx>
59 #include <svx/langitem.hxx>
60 // --> OD 2005-02-28 #i43427#
61 #include <svx/opaqitem.hxx>
62 // <--
63 #include <svx/svxmsbas.hxx>
64 #include <svx/unoapi.hxx>
65 #include <svx/svdoole2.hxx>
66 #include <svx/msdffimp.hxx>
67 #include <svx/svdoashp.hxx>
68 #include <svx/svxerr.hxx>
69 #include <svx/mscodec.hxx>
70 #include <svx/svdmodel.hxx>
71 #include <svx/svdogrp.hxx>
72 #include <svx/xflclit.hxx>
74 #include <svtools/fltrcfg.hxx>
75 #include <fmtfld.hxx>
76 #include <fmturl.hxx>
77 #include <fmtinfmt.hxx>
78 #include <IMark.hxx>
79 #include <reffld.hxx>
80 #include <fmthdft.hxx>
81 #include <fmtcntnt.hxx>
82 #include <fmtcnct.hxx>
83 #include <fmtpdsc.hxx>
84 #include <fmthbsh.hxx>
85 #include <ftninfo.hxx>
86 #include <fmtftn.hxx>
87 #include <txtftn.hxx>
88 #include <pam.hxx> // fuer SwPam
89 #include <doc.hxx>
90 #include <ndtxt.hxx> // class SwTxtNode
91 #include <pagedesc.hxx> // class SwPageDesc
92 #include <paratr.hxx>
93 #include <fmtclds.hxx>
94 #include <fmtclbl.hxx>
95 #include <section.hxx>
96 #include <docsh.hxx>
97 #include <docufld.hxx>
98 #include <swfltopt.hxx>
99 #include <viewsh.hxx>
100 #include <shellres.hxx>
101 #include <mdiexp.hxx> // Progress
102 #include <statstr.hrc> // ResId fuer Statusleiste
103 #include <swerror.h> // ERR_WW8_...
104 #include <swunodef.hxx>
105 #include <unodraw.hxx>
106 #include <swtable.hxx> // class SwTableLines, ...
107 // #i18732#
108 #include <fmtfollowtextflow.hxx>
109 #include <fchrfmt.hxx>
110 #include <charfmt.hxx>
113 #include <com/sun/star/i18n/ForbiddenCharacters.hpp>
114 #include <comphelper/extract.hxx>
115 #include <fltini.hxx>
117 #include <algorithm>
118 #include <functional>
119 #include "writerhelper.hxx"
120 #include "writerwordglue.hxx"
123 #include "ww8par2.hxx" // class WW8RStyle, class WW8AnchorPara
125 #include <frmatr.hxx>
127 #include <math.h>
128 #include <com/sun/star/beans/XPropertyContainer.hpp>
130 #include <com/sun/star/beans/PropertyAttribute.hpp>
131 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
132 #include <com/sun/star/document/XDocumentProperties.hpp>
133 #include <svtools/itemiter.hxx> //SfxItemIter
135 #include <stdio.h>
136 #include <comphelper/processfactory.hxx>
137 #include <basic/basmgr.hxx>
139 #include "ww8toolbar.hxx"
140 #include <osl/file.hxx>
141 #include <com/sun/star/document/XDocumentInfoSupplier.hpp>
143 #ifdef DEBUG
144 #include <iostream>
145 #include <dbgoutsw.hxx>
146 #endif
147 #include <unotools/localfilehelper.hxx>
148 #include <comphelper/configurationhelper.hxx>
150 #define MM_250 1417 // WW-Default fuer Hor. Seitenraender: 2.5 cm
151 #define MM_200 1134 // WW-Default fuer u.Seitenrand: 2.0 cm
153 using namespace ::com::sun::star;
154 using namespace sw::util;
155 using namespace sw::types;
156 using namespace nsHdFtFlags;
158 #include <com/sun/star/document/XEventsSupplier.hpp>
159 #include <com/sun/star/container/XNameReplace.hpp>
160 #include <com/sun/star/frame/XModel.hpp>
161 #include <svx/msvbahelper.hxx>
162 #include <svtools/pathoptions.hxx>
163 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
165 const static String sThisDocument( RTL_CONSTASCII_USTRINGPARAM("ThisDocument"));
167 struct DocEventNameTable
169 const sal_Char* sEventName;
170 const sal_Char* sMacroName;
173 const DocEventNameTable aEventNameTable[] =
175 {"OnNew", "Document_New"},
176 {"OnLoad", "Document_Open"},
177 {"OnPrepareUnload", "Document_Close"},
178 {NULL, NULL}
181 bool registerDocEvent( SfxObjectShell* pShell )
183 bool result = false;
184 const static rtl::OUString sEvtType( RTL_CONSTASCII_USTRINGPARAM("EventType") );
185 const static rtl::OUString sScript( RTL_CONSTASCII_USTRINGPARAM("Script") );
186 uno::Reference< document::XEventsSupplier > xEvtSupplier( pShell->GetModel(), uno::UNO_QUERY );
187 if( !xEvtSupplier.is() )
188 return result;
189 uno::Reference< container::XNameReplace > xEvts( xEvtSupplier->getEvents(), uno::UNO_QUERY );
190 if ( xEvts.is() )
192 for( const DocEventNameTable* pTable = aEventNameTable; pTable->sEventName != NULL; pTable++ )
194 rtl::OUString sEvt = rtl::OUString::createFromAscii( pTable->sEventName );
195 String sMacroName = String::CreateFromAscii( pTable->sMacroName ).Insert( '.', 0 ).Insert( sThisDocument, 0);
196 // fail to search the macro if the module is not specified.
197 ooo::vba::VBAMacroResolvedInfo aMacroInfo = ooo::vba::resolveVBAMacro( pShell, sMacroName );
198 if( !aMacroInfo.IsResolved() )
199 continue;
201 uno::Sequence< beans::PropertyValue > aEvents;
202 xEvts->getByName( sEvt ) >>= aEvents;
203 uno::Sequence< beans::PropertyValue > aOpenEvt( 2 );
204 aOpenEvt[ 0 ].Name = sEvtType;
205 aOpenEvt[ 0 ].Value = uno::makeAny(sScript);
206 aOpenEvt[ 1 ].Name = sScript;
207 rtl::OUString sUrl = ooo::vba::makeMacroURL( aMacroInfo.ResolvedMacro() );
208 aOpenEvt[ 1 ].Value = uno::makeAny(sUrl);
209 sal_Int32 nPos = aEvents.getLength();
211 sal_Int32 nNewSize = aEvents.getLength() + aOpenEvt.getLength();
212 if ( nNewSize > aEvents.getLength() )
213 aEvents.realloc( nNewSize );
215 for ( sal_Int32 nIndex = nPos, nCpyIndex = 0; nIndex<nNewSize; nIndex++, nCpyIndex++ )
216 aEvents[ nIndex ] = aOpenEvt[ nCpyIndex ];
218 uno::Any aParam = uno::makeAny( aEvents );
220 xEvts->replaceByName( sEvt, aParam );
221 result = true;
224 return result;
227 class Sttb : TBBase
229 struct SBBItem
231 sal_uInt16 cchData;
232 rtl::OUString data;
233 SBBItem() : cchData(0){}
235 sal_uInt16 fExtend;
236 sal_uInt16 cData;
237 sal_uInt16 cbExtra;
239 std::vector< SBBItem > dataItems;
241 Sttb(const Sttb&);
242 Sttb& operator = ( const Sttb&);
243 public:
244 Sttb();
245 ~Sttb();
246 bool Read(SvStream *pS);
247 void Print( FILE* fp );
248 rtl::OUString getStringAtIndex( sal_uInt32 );
251 Sttb::Sttb() : fExtend( 0 )
252 ,cData( 0 )
253 ,cbExtra( 0 )
257 Sttb::~Sttb()
261 bool Sttb::Read( SvStream* pS )
263 OSL_TRACE("Sttb::Read() stream pos 0x%x", pS->Tell() );
264 nOffSet = pS->Tell();
265 *pS >> fExtend >> cData >> cbExtra;
266 if ( cData )
268 for ( sal_Int32 index = 0; index < cData; ++index )
270 SBBItem aItem;
271 *pS >> aItem.cchData;
272 aItem.data = readUnicodeString( pS, aItem.cchData );
273 dataItems.push_back( aItem );
276 return true;
279 void Sttb::Print( FILE* fp )
281 fprintf( fp, "[ 0x%x ] Sttb - dump\n", nOffSet);
282 fprintf( fp, " fExtend 0x%x [expected 0xFFFF ]\n", fExtend );
283 fprintf( fp, " cData no. or string data items %d (0x%x)\n", cData, cData );
285 if ( cData )
287 for ( sal_Int32 index = 0; index < cData; ++index )
288 fprintf(fp," string dataItem[ %d(0x%x) ] has name %s\n", static_cast< int >( index ), static_cast< unsigned int >( index ), rtl::OUStringToOString( dataItems[ index ].data, RTL_TEXTENCODING_UTF8 ).getStr() );
293 rtl::OUString
294 Sttb::getStringAtIndex( sal_uInt32 index )
296 rtl::OUString aRet;
297 if ( index < dataItems.size() )
298 aRet = dataItems[ index ].data;
299 return aRet;
302 SwMSDffManager::SwMSDffManager( SwWW8ImplReader& rRdr )
303 : SvxMSDffManager(*rRdr.pTableStream, rRdr.GetBaseURL(), rRdr.pWwFib->fcDggInfo,
304 rRdr.pDataStream, 0, 0, COL_WHITE, 12, rRdr.pStrm,
305 rRdr.maTracer.GetTrace()),
306 rReader(rRdr), pFallbackStream(0), pOldEscherBlipCache(0)
308 SetSvxMSDffSettings( GetSvxMSDffSettings() );
309 nSvxMSDffOLEConvFlags = SwMSDffManager::GetFilterFlags();
312 UINT32 SwMSDffManager::GetFilterFlags()
314 UINT32 nFlags(0);
315 if (const SvtFilterOptions* pOpt = SvtFilterOptions::Get())
317 if (pOpt->IsMathType2Math())
318 nFlags |= OLE_MATHTYPE_2_STARMATH;
319 if (pOpt->IsExcel2Calc())
320 nFlags |= OLE_EXCEL_2_STARCALC;
321 if (pOpt->IsPowerPoint2Impress())
322 nFlags |= OLE_POWERPOINT_2_STARIMPRESS;
323 if (pOpt->IsWinWord2Writer())
324 nFlags |= OLE_WINWORD_2_STARWRITER;
326 return nFlags;
330 * I would like to override the default OLE importing to add a test
331 * and conversion of OCX controls from their native OLE type into our
332 * native nonOLE Form Control Objects.
334 * cmc
336 // --> OD 2004-12-14 #i32596# - consider new parameter <_nCalledByGroup>
337 SdrObject* SwMSDffManager::ImportOLE( long nOLEId,
338 const Graphic& rGrf,
339 const Rectangle& rBoundRect,
340 const Rectangle& rVisArea,
341 const int _nCalledByGroup,
342 sal_Int64 nAspect ) const
344 // --> OD 2004-12-14 #i32596# - no import of OLE object, if it's inside a group.
345 // NOTE: This can be undone, if grouping of Writer fly frames is possible or
346 // if drawing OLE objects are allowed in Writer.
347 if ( _nCalledByGroup > 0 )
349 return 0L;
351 // <--
353 SdrObject* pRet = 0;
354 String sStorageName;
355 SotStorageRef xSrcStg;
356 uno::Reference < embed::XStorage > xDstStg;
357 if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg ))
359 SvStorageRef xSrc = xSrcStg->OpenSotStorage( sStorageName,
360 STREAM_READWRITE| STREAM_SHARE_DENYALL );
361 ASSERT(rReader.pFormImpl, "No Form Implementation!");
362 STAR_REFERENCE( drawing::XShape ) xShape;
363 if ( (!(rReader.bIsHeader || rReader.bIsFooter)) &&
364 rReader.pFormImpl->ReadOCXStream(xSrc,&xShape,true))
366 pRet = GetSdrObjectFromXShape(xShape);
368 else
370 ErrCode nError = ERRCODE_NONE;
371 pRet = CreateSdrOLEFromStorage( sStorageName, xSrcStg, xDstStg,
372 rGrf, rBoundRect, rVisArea, pStData, nError, nSvxMSDffOLEConvFlags, nAspect );
375 return pRet;
378 void SwMSDffManager::DisableFallbackStream()
380 ASSERT(!pFallbackStream || !pOldEscherBlipCache,
381 "if you're recursive, you're broken");
382 pFallbackStream = pStData2;
383 pOldEscherBlipCache = pEscherBlipCache;
384 pEscherBlipCache = 0;
385 pStData2 = 0;
388 void SwMSDffManager::EnableFallbackStream()
390 pStData2 = pFallbackStream;
391 pEscherBlipCache = pOldEscherBlipCache;
392 pOldEscherBlipCache = 0;
393 pFallbackStream = 0;
396 USHORT SwWW8ImplReader::GetToggleAttrFlags() const
398 return pCtrlStck ? pCtrlStck->GetToggleAttrFlags() : 0;
401 USHORT SwWW8ImplReader::GetToggleBiDiAttrFlags() const
403 return pCtrlStck ? pCtrlStck->GetToggleBiDiAttrFlags() : 0;
406 void SwWW8ImplReader::SetToggleAttrFlags(USHORT nFlags)
408 if (pCtrlStck)
409 pCtrlStck->SetToggleAttrFlags(nFlags);
412 void SwWW8ImplReader::SetToggleBiDiAttrFlags(USHORT nFlags)
414 if (pCtrlStck)
415 pCtrlStck->SetToggleBiDiAttrFlags(nFlags);
419 SdrObject* SwMSDffManager::ProcessObj(SvStream& rSt,
420 DffObjData& rObjData,
421 void* pData,
422 Rectangle& rTextRect,
423 SdrObject* pObj
426 if( !rTextRect.IsEmpty() )
428 SvxMSDffImportData& rImportData = *(SvxMSDffImportData*)pData;
429 SvxMSDffImportRec* pImpRec = new SvxMSDffImportRec;
431 // fill Import Record with data
432 pImpRec->nShapeId = rObjData.nShapeId;
433 pImpRec->eShapeType = rObjData.eShapeType;
435 rObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt,
436 DFF_msofbtClientAnchor,
437 SEEK_FROM_CURRENT_AND_RESTART );
438 if( rObjData.bClientAnchor )
439 ProcessClientAnchor( rSt,
440 maShapeRecords.Current()->nRecLen,
441 pImpRec->pClientAnchorBuffer, pImpRec->nClientAnchorLen );
443 rObjData.bClientData = maShapeRecords.SeekToContent( rSt,
444 DFF_msofbtClientData,
445 SEEK_FROM_CURRENT_AND_RESTART );
446 if( rObjData.bClientData )
447 ProcessClientData( rSt,
448 maShapeRecords.Current()->nRecLen,
449 pImpRec->pClientDataBuffer, pImpRec->nClientDataLen );
452 // process user (== Winword) defined parameters in 0xF122 record
453 // --> OD 2008-04-10 #i84783#
454 // set special value to determine, if property is provided or not.
455 pImpRec->nLayoutInTableCell = 0xFFFFFFFF;
456 // <--
457 if( maShapeRecords.SeekToContent( rSt,
458 DFF_msofbtUDefProp,
459 SEEK_FROM_CURRENT_AND_RESTART )
460 && maShapeRecords.Current()->nRecLen )
462 UINT32 nBytesLeft = maShapeRecords.Current()->nRecLen;
463 UINT32 nUDData;
464 UINT16 nPID;
465 while( 5 < nBytesLeft )
467 rSt >> nPID;
468 if ( rSt.GetError() != 0 )
469 break;
470 rSt >> nUDData;
471 switch( nPID )
473 case 0x038F: pImpRec->nXAlign = nUDData; break;
474 case 0x0390: pImpRec->nXRelTo = nUDData; break;
475 case 0x0391: pImpRec->nYAlign = nUDData; break;
476 case 0x0392: pImpRec->nYRelTo = nUDData; break;
477 case 0x03BF: pImpRec->nLayoutInTableCell = nUDData; break;
479 if ( rSt.GetError() != 0 )
480 break;
481 pImpRec->bHasUDefProp = TRUE;
482 nBytesLeft -= 6;
486 // Textrahmen, auch Title oder Outline
487 UINT32 nTextId = GetPropertyValue( DFF_Prop_lTxid, 0 );
488 if( nTextId )
490 SfxItemSet aSet( pSdrModel->GetItemPool() );
492 //Originally anything that as a mso_sptTextBox was created as a
493 //textbox, this was changed for #88277# to be created as a simple
494 //rect to keep impress happy. For the rest of us we'd like to turn
495 //it back into a textbox again.
496 BOOL bIsSimpleDrawingTextBox = (pImpRec->eShapeType == mso_sptTextBox);
497 if (!bIsSimpleDrawingTextBox)
499 //Either
500 //a) its a simple text object or
501 //b) its a rectangle with text and square wrapping.
502 bIsSimpleDrawingTextBox =
504 (pImpRec->eShapeType == mso_sptTextSimple) ||
506 (pImpRec->eShapeType == mso_sptRectangle)
507 // && (eWrapMode == mso_wrapSquare)
508 && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() )
513 // Distance of Textbox to it's surrounding Autoshape
514 INT32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 91440L);
515 INT32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 91440L );
516 INT32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 45720L );
517 INT32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 45720L );
519 ScaleEmu( nTextLeft );
520 ScaleEmu( nTextRight );
521 ScaleEmu( nTextTop );
522 ScaleEmu( nTextBottom );
524 INT32 nTextRotationAngle=0;
525 bool bVerticalText = false;
526 if ( IsProperty( DFF_Prop_txflTextFlow ) )
528 MSO_TextFlow eTextFlow = (MSO_TextFlow)(GetPropertyValue(
529 DFF_Prop_txflTextFlow) & 0xFFFF);
530 switch( eTextFlow )
532 case mso_txflBtoT:
533 nTextRotationAngle = 9000;
534 break;
535 case mso_txflVertN:
536 case mso_txflTtoBN:
537 nTextRotationAngle = 27000;
538 break;
539 case mso_txflTtoBA:
540 bVerticalText = true;
541 break;
542 case mso_txflHorzA:
543 bVerticalText = true;
544 nTextRotationAngle = 9000;
545 case mso_txflHorzN:
546 default :
547 break;
551 if (nTextRotationAngle)
553 while (nTextRotationAngle > 360000)
554 nTextRotationAngle-=9000;
555 switch (nTextRotationAngle)
557 case 9000:
559 long nWidth = rTextRect.GetWidth();
560 rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight();
561 rTextRect.Bottom() = rTextRect.Top() + nWidth;
563 INT32 nOldTextLeft = nTextLeft;
564 INT32 nOldTextRight = nTextRight;
565 INT32 nOldTextTop = nTextTop;
566 INT32 nOldTextBottom = nTextBottom;
568 nTextLeft = nOldTextBottom;
569 nTextRight = nOldTextTop;
570 nTextTop = nOldTextLeft;
571 nTextBottom = nOldTextRight;
573 break;
574 case 27000:
576 long nWidth = rTextRect.GetWidth();
577 rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight();
578 rTextRect.Bottom() = rTextRect.Top() + nWidth;
580 INT32 nOldTextLeft = nTextLeft;
581 INT32 nOldTextRight = nTextRight;
582 INT32 nOldTextTop = nTextTop;
583 INT32 nOldTextBottom = nTextBottom;
585 nTextLeft = nOldTextTop;
586 nTextRight = nOldTextBottom;
587 nTextTop = nOldTextRight;
588 nTextBottom = nOldTextLeft;
590 break;
591 default:
592 break;
596 if (bIsSimpleDrawingTextBox)
598 SdrObject::Free( pObj );
599 pObj = new SdrRectObj(OBJ_TEXT, rTextRect);
602 // Die vertikalen Absatzeinrueckungen sind im BoundRect mit drin,
603 // hier rausrechnen
604 Rectangle aNewRect(rTextRect);
605 aNewRect.Bottom() -= nTextTop + nTextBottom;
606 aNewRect.Right() -= nTextLeft + nTextRight;
608 // Nur falls es eine einfache Textbox ist, darf der Writer
609 // das Objekt durch einen Rahmen ersetzen, ansonsten
610 if( bIsSimpleDrawingTextBox )
612 SvxMSDffShapeInfo aTmpRec( 0, pImpRec->nShapeId );
613 aTmpRec.bSortByShapeId = TRUE;
615 USHORT nFound;
616 if( GetShapeInfos()->Seek_Entry( &aTmpRec, &nFound ) )
618 SvxMSDffShapeInfo& rInfo = *GetShapeInfos()->GetObject(nFound);
619 pImpRec->bReplaceByFly = rInfo.bReplaceByFly;
620 pImpRec->bLastBoxInChain = rInfo.bLastBoxInChain;
624 if( bIsSimpleDrawingTextBox )
625 ApplyAttributes( rSt, aSet, rObjData );
627 bool bFitText = false;
628 if (GetPropertyValue(DFF_Prop_FitTextToShape) & 2)
630 aSet.Put( SdrTextAutoGrowHeightItem( TRUE ) );
631 aSet.Put( SdrTextMinFrameHeightItem(
632 aNewRect.Bottom() - aNewRect.Top() ) );
633 aSet.Put( SdrTextMinFrameWidthItem(
634 aNewRect.Right() - aNewRect.Left() ) );
635 bFitText = true;
637 else
639 aSet.Put( SdrTextAutoGrowHeightItem( FALSE ) );
640 aSet.Put( SdrTextAutoGrowWidthItem( FALSE ) );
643 switch ( (MSO_WrapMode)
644 GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) )
646 case mso_wrapNone :
647 aSet.Put( SdrTextAutoGrowWidthItem( TRUE ) );
648 pImpRec->bAutoWidth = true;
649 break;
650 case mso_wrapByPoints :
651 aSet.Put( SdrTextContourFrameItem( TRUE ) );
652 break;
653 default:
657 // Abstaende an den Raendern der Textbox setzen
658 aSet.Put( SdrTextLeftDistItem( nTextLeft ) );
659 aSet.Put( SdrTextRightDistItem( nTextRight ) );
660 aSet.Put( SdrTextUpperDistItem( nTextTop ) );
661 aSet.Put( SdrTextLowerDistItem( nTextBottom ) );
662 pImpRec->nDxTextLeft = nTextLeft;
663 pImpRec->nDyTextTop = nTextTop;
664 pImpRec->nDxTextRight = nTextRight;
665 pImpRec->nDyTextBottom = nTextBottom;
667 // --> SJ 2009-03-06 : taking the correct default (which is mso_anchorTop)
668 MSO_Anchor eTextAnchor =
669 (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop );
671 SdrTextVertAdjust eTVA = bVerticalText
672 ? SDRTEXTVERTADJUST_BLOCK
673 : SDRTEXTVERTADJUST_CENTER;
674 SdrTextHorzAdjust eTHA = bVerticalText
675 ? SDRTEXTHORZADJUST_CENTER
676 : SDRTEXTHORZADJUST_BLOCK;
678 switch( eTextAnchor )
680 case mso_anchorTop:
682 if ( bVerticalText )
683 eTHA = SDRTEXTHORZADJUST_RIGHT;
684 else
685 eTVA = SDRTEXTVERTADJUST_TOP;
687 break;
688 case mso_anchorTopCentered:
690 if ( bVerticalText )
691 eTHA = SDRTEXTHORZADJUST_RIGHT;
692 else
693 eTVA = SDRTEXTVERTADJUST_TOP;
695 break;
696 case mso_anchorMiddle:
697 break;
698 case mso_anchorMiddleCentered:
699 break;
700 case mso_anchorBottom:
702 if ( bVerticalText )
703 eTHA = SDRTEXTHORZADJUST_LEFT;
704 else
705 eTVA = SDRTEXTVERTADJUST_BOTTOM;
707 break;
708 case mso_anchorBottomCentered:
710 if ( bVerticalText )
711 eTHA = SDRTEXTHORZADJUST_LEFT;
712 else
713 eTVA = SDRTEXTVERTADJUST_BOTTOM;
715 break;
717 case mso_anchorTopBaseline:
718 case mso_anchorBottomBaseline:
719 case mso_anchorTopCenteredBaseline:
720 case mso_anchorBottomCenteredBaseline:
721 break;
723 default:
727 aSet.Put( SdrTextVertAdjustItem( eTVA ) );
728 aSet.Put( SdrTextHorzAdjustItem( eTHA ) );
730 pObj->SetMergedItemSet(aSet);
731 pObj->SetModel(pSdrModel);
733 if (bVerticalText && dynamic_cast< SdrTextObj* >( pObj ) )
734 dynamic_cast< SdrTextObj* >( pObj )->SetVerticalWriting(sal_True);
736 if ( bIsSimpleDrawingTextBox )
738 if ( nTextRotationAngle )
740 long nMinWH = rTextRect.GetWidth() < rTextRect.GetHeight() ?
741 rTextRect.GetWidth() : rTextRect.GetHeight();
742 nMinWH /= 2;
743 Point aPivot(rTextRect.TopLeft());
744 aPivot.X() += nMinWH;
745 aPivot.Y() += nMinWH;
746 double a = nTextRotationAngle * nPi180;
747 pObj->NbcRotate(aPivot, nTextRotationAngle, sin(a), cos(a));
751 if ( ( ( rObjData.nSpFlags & SP_FFLIPV ) || mnFix16Angle || nTextRotationAngle ) && dynamic_cast< SdrObjCustomShape* >( pObj ) )
753 SdrObjCustomShape* pCustomShape = dynamic_cast< SdrObjCustomShape* >( pObj );
755 double fExtraTextRotation = 0.0;
756 if ( mnFix16Angle && !( GetPropertyValue( DFF_Prop_FitTextToShape ) & 4 ) )
757 { // text is already rotated, we have to take back the object rotation if DFF_Prop_RotateText is false
758 fExtraTextRotation = -mnFix16Angle;
760 if ( rObjData.nSpFlags & SP_FFLIPV ) // sj: in ppt the text is flipped, whereas in word the text
761 { // remains unchanged, so we have to take back the flipping here
762 fExtraTextRotation += 18000.0; // because our core will flip text if the shape is flipped.
764 fExtraTextRotation += nTextRotationAngle;
765 if ( !::basegfx::fTools::equalZero( fExtraTextRotation ) )
767 fExtraTextRotation /= 100.0;
768 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
769 const rtl::OUString sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) );
770 com::sun::star::beans::PropertyValue aPropVal;
771 aPropVal.Name = sTextRotateAngle;
772 aPropVal.Value <<= fExtraTextRotation;
773 aGeometryItem.SetPropertyValue( aPropVal );
774 pCustomShape->SetMergedItem( aGeometryItem );
777 else if ( mnFix16Angle )
779 // rotate text with shape ?
780 double a = mnFix16Angle * nPi180;
781 pObj->NbcRotate( rObjData.aBoundRect.Center(), mnFix16Angle,
782 sin( a ), cos( a ) );
785 else if( !pObj )
787 // simple rectangular objects are ignored by ImportObj() :-(
788 // this is OK for Draw but not for Calc and Writer
789 // cause here these objects have a default border
790 pObj = new SdrRectObj(rTextRect);
791 pObj->SetModel( pSdrModel );
792 SfxItemSet aSet( pSdrModel->GetItemPool() );
793 ApplyAttributes( rSt, aSet, rObjData );
795 const SfxPoolItem* pPoolItem=NULL;
796 SfxItemState eState = aSet.GetItemState( XATTR_FILLCOLOR,
797 FALSE, &pPoolItem );
798 if( SFX_ITEM_DEFAULT == eState )
799 aSet.Put( XFillColorItem( String(),
800 Color( mnDefaultColor ) ) );
801 pObj->SetMergedItemSet(aSet);
804 //Means that fBehindDocument is set
805 if (GetPropertyValue(DFF_Prop_fPrint) & 0x20)
806 pImpRec->bDrawHell = TRUE;
807 else
808 pImpRec->bDrawHell = FALSE;
809 if (GetPropertyValue(DFF_Prop_fPrint) & 0x02)
810 pImpRec->bHidden = TRUE;
811 pImpRec->nNextShapeId = GetPropertyValue( DFF_Prop_hspNext, 0 );
813 if ( nTextId )
815 pImpRec->aTextId.nTxBxS = (UINT16)( nTextId >> 16 );
816 pImpRec->aTextId.nSequence = (UINT16)nTextId;
819 pImpRec->nDxWrapDistLeft = GetPropertyValue(
820 DFF_Prop_dxWrapDistLeft, 114935L ) / 635L;
821 pImpRec->nDyWrapDistTop = GetPropertyValue(
822 DFF_Prop_dyWrapDistTop, 0 ) / 635L;
823 pImpRec->nDxWrapDistRight = GetPropertyValue(
824 DFF_Prop_dxWrapDistRight, 114935L ) / 635L;
825 pImpRec->nDyWrapDistBottom = GetPropertyValue(
826 DFF_Prop_dyWrapDistBottom, 0 ) / 635L;
827 // 16.16 fraction times total image width or height, as appropriate.
829 if (SeekToContent(DFF_Prop_pWrapPolygonVertices, rSt))
831 delete pImpRec->pWrapPolygon;
832 sal_uInt16 nNumElemVert, nNumElemMemVert, nElemSizeVert;
833 rSt >> nNumElemVert >> nNumElemMemVert >> nElemSizeVert;
834 if (nNumElemVert && ((nElemSizeVert == 8) || (nElemSizeVert == 4)))
836 pImpRec->pWrapPolygon = new Polygon(nNumElemVert);
837 for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
839 sal_Int32 nX, nY;
840 if (nElemSizeVert == 8)
841 rSt >> nX >> nY;
842 else
844 sal_Int16 nSmallX, nSmallY;
845 rSt >> nSmallX >> nSmallY;
846 nX = nSmallX;
847 nY = nSmallY;
849 (*(pImpRec->pWrapPolygon))[i].X() = nX;
850 (*(pImpRec->pWrapPolygon))[i].Y() = nY;
855 pImpRec->nCropFromTop = GetPropertyValue(
856 DFF_Prop_cropFromTop, 0 );
857 pImpRec->nCropFromBottom = GetPropertyValue(
858 DFF_Prop_cropFromBottom, 0 );
859 pImpRec->nCropFromLeft = GetPropertyValue(
860 DFF_Prop_cropFromLeft, 0 );
861 pImpRec->nCropFromRight = GetPropertyValue(
862 DFF_Prop_cropFromRight, 0 );
864 UINT32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash );
865 // --> OD 2008-06-16 #156765#
866 if ( !IsHardAttribute( DFF_Prop_fLine ) &&
867 pImpRec->eShapeType == mso_sptPictureFrame )
869 nLineFlags &= ~0x08;
871 // <--
872 pImpRec->eLineStyle = (nLineFlags & 8)
873 ? (MSO_LineStyle)GetPropertyValue(
874 DFF_Prop_lineStyle,
875 mso_lineSimple )
876 : (MSO_LineStyle)USHRT_MAX;
878 pImpRec->nFlags = rObjData.nSpFlags;
880 if( pImpRec->nShapeId )
882 // Import-Record-Liste ergaenzen
883 pImpRec->pObj = pObj;
884 rImportData.aRecords.Insert( pImpRec );
886 // Eintrag in Z-Order-Liste um Zeiger auf dieses Objekt ergaenzen
887 /*Only store objects which are not deep inside the tree*/
888 if( ( rObjData.nCalledByGroup == 0 )
890 ( (rObjData.nSpFlags & SP_FGROUP)
891 && (rObjData.nCalledByGroup < 2) )
893 StoreShapeOrder( pImpRec->nShapeId,
894 ( ( (ULONG)pImpRec->aTextId.nTxBxS ) << 16 )
895 + pImpRec->aTextId.nSequence, pObj );
897 else
898 delete pImpRec;
901 return pObj;
904 /***************************************************************************
905 # Spezial FastSave - Attribute
906 #**************************************************************************/
908 void SwWW8ImplReader::Read_StyleCode( USHORT, const BYTE* pData, short nLen )
910 if (nLen < 0)
912 bCpxStyle = false;
913 return;
915 USHORT nColl = 0;
916 if (pWwFib->GetFIBVersion() <= ww::eWW2)
917 nColl = *pData;
918 else
919 nColl = SVBT16ToShort(pData);
920 if (nColl < nColls)
922 SetTxtFmtCollAndListLevel( *pPaM, pCollA[nColl] );
923 bCpxStyle = true;
927 // Read_Majority ist fuer Majority ( 103 ) und Majority50 ( 108 )
928 void SwWW8ImplReader::Read_Majority( USHORT, const BYTE* , short )
932 //-----------------------------------------
933 // Stack
934 //-----------------------------------------
935 void SwWW8FltControlStack::NewAttr(const SwPosition& rPos,
936 const SfxPoolItem& rAttr)
938 ASSERT(RES_TXTATR_FIELD != rAttr.Which(), "probably don't want to put"
939 "fields into the control stack");
940 ASSERT(RES_FLTR_REDLINE != rAttr.Which(), "probably don't want to put"
941 "redlines into the control stack");
942 SwFltControlStack::NewAttr(rPos, rAttr);
945 void SwWW8FltControlStack::SetAttr(const SwPosition& rPos, USHORT nAttrId,
946 BOOL bTstEnde, long nHand, BOOL )
948 //Doing a textbox, and using the control stack only as a temporary
949 //collection point for properties which will are not to be set into
950 //the real document
951 if (rReader.pPlcxMan && rReader.pPlcxMan->GetDoingDrawTextBox())
953 USHORT nCnt = static_cast< USHORT >(Count());
954 for (USHORT i=0; i < nCnt; ++i)
956 SwFltStackEntry* pEntry = (*this)[i];
957 if (nAttrId == pEntry->pAttr->Which())
959 DeleteAndDestroy(i--);
960 --nCnt;
964 else //Normal case, set the attribute into the document
965 SwFltControlStack::SetAttr(rPos, nAttrId, bTstEnde, nHand);
968 long GetListFirstLineIndent(const SwNumFmt &rFmt)
970 ASSERT( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
971 "<GetListFirstLineIndent> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
973 SvxAdjust eAdj = rFmt.GetNumAdjust();
974 long nReverseListIndented;
975 if (eAdj == SVX_ADJUST_RIGHT)
976 nReverseListIndented = -rFmt.GetCharTextDistance();
977 else if (eAdj == SVX_ADJUST_CENTER)
978 nReverseListIndented = rFmt.GetFirstLineOffset()/2;
979 else
980 nReverseListIndented = rFmt.GetFirstLineOffset();
981 return nReverseListIndented;
984 long lcl_GetTrueMargin(const SvxLRSpaceItem &rLR, const SwNumFmt &rFmt,
985 long &rFirstLinePos)
987 ASSERT( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
988 "<lcl_GetTrueMargin> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
990 const long nBodyIndent = rLR.GetTxtLeft();
991 const long nFirstLineDiff = rLR.GetTxtFirstLineOfst();
992 rFirstLinePos = nBodyIndent + nFirstLineDiff;
994 const long nPseudoListBodyIndent = rFmt.GetAbsLSpace();
995 const long nReverseListIndented = GetListFirstLineIndent(rFmt);
996 long nExtraListIndent = nPseudoListBodyIndent + nReverseListIndented;
998 return nExtraListIndent > 0 ? nExtraListIndent : 0;
1001 void SyncIndentWithList(SvxLRSpaceItem &rLR, const SwNumFmt &rFmt)
1003 long nWantedFirstLinePos;
1004 long nExtraListIndent = lcl_GetTrueMargin(rLR, rFmt, nWantedFirstLinePos);
1005 rLR.SetTxtLeft(nWantedFirstLinePos - nExtraListIndent);
1006 rLR.SetTxtFirstLineOfst(0);
1009 const SwNumFmt* SwWW8FltControlStack::GetNumFmtFromStack(const SwPosition &rPos,
1010 const SwTxtNode &rTxtNode)
1012 const SwNumFmt *pRet = 0;
1013 const SfxPoolItem *pItem = GetStackAttr(rPos, RES_FLTR_NUMRULE);
1014 if (pItem && rTxtNode.GetNumRule())
1016 String sName(((SfxStringItem*)pItem)->GetValue());
1017 if (rTxtNode.IsCountedInList())
1019 const SwNumRule *pRule = pDoc->FindNumRulePtr(sName);
1020 BYTE nLvl = static_cast< BYTE >(rTxtNode.GetActualListLevel());
1021 pRet = &(pRule->Get(nLvl));
1024 return pRet;
1027 void SwWW8FltControlStack::SetAttrInDoc(const SwPosition& rTmpPos,
1028 SwFltStackEntry* pEntry)
1030 switch( pEntry->pAttr->Which() )
1032 case RES_LR_SPACE:
1035 Loop over the affect nodes and
1036 a) convert the word style absolute indent to indent relative
1037 to any numbering indent active on the nodes
1038 b) adjust the writer style tabstops relative to the old
1039 paragraph indent to be relative to the new paragraph indent
1041 using namespace sw::util;
1042 SwPaM aRegion(rTmpPos);
1043 if (pEntry->MakeRegion(pDoc, aRegion, false))
1045 SvxLRSpaceItem aNewLR( *(SvxLRSpaceItem*)pEntry->pAttr );
1046 ULONG nStart = aRegion.Start()->nNode.GetIndex();
1047 ULONG nEnd = aRegion.End()->nNode.GetIndex();
1048 for(; nStart <= nEnd; ++nStart)
1050 SwNode* pNode = pDoc->GetNodes()[ nStart ];
1051 if (!pNode || !pNode->IsTxtNode())
1052 continue;
1054 SwCntntNode* pNd = (SwCntntNode*)pNode;
1055 SvxLRSpaceItem aOldLR = (const SvxLRSpaceItem&)
1056 pNd->GetAttr(RES_LR_SPACE);
1058 SwTxtNode *pTxtNode = (SwTxtNode*)pNode;
1060 const SwNumFmt *pNum = 0;
1061 pNum = GetNumFmtFromStack(*aRegion.GetPoint(),
1062 *pTxtNode);
1063 if (!pNum)
1064 pNum = GetNumFmtFromTxtNode(*pTxtNode);
1066 // --> OD 2008-06-03 #i86652#
1067 // if (pNum)
1068 if ( pNum &&
1069 pNum->GetPositionAndSpaceMode() ==
1070 SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1071 // <--
1073 SyncIndentWithList(aNewLR, *pNum);
1076 if (aNewLR == aOldLR)
1077 continue;
1079 pNd->SetAttr(aNewLR);
1084 break;
1085 case RES_TXTATR_FIELD:
1086 ASSERT(!this, "What is a field doing in the control stack,"
1087 "probably should have been in the endstack");
1088 break;
1089 case RES_TXTATR_INETFMT:
1091 SwPaM aRegion(rTmpPos);
1092 if (pEntry->MakeRegion(pDoc, aRegion, false))
1094 SwFrmFmt *pFrm;
1095 //If we have just one single inline graphic then
1096 //don't insert a field for the single frame, set
1097 //the frames hyperlink field attribute directly.
1098 if (0 != (pFrm = rReader.ContainsSingleInlineGraphic(aRegion)))
1100 const SwFmtINetFmt *pAttr = (const SwFmtINetFmt *)
1101 pEntry->pAttr;
1102 SwFmtURL aURL;
1103 aURL.SetURL(pAttr->GetValue(), false);
1104 aURL.SetTargetFrameName(pAttr->GetTargetFrame());
1105 pFrm->SetFmtAttr(aURL);
1107 else
1108 pDoc->Insert(aRegion, *pEntry->pAttr, 0);
1111 break;
1112 default:
1113 SwFltControlStack::SetAttrInDoc(rTmpPos, pEntry);
1114 break;
1118 const SfxPoolItem* SwWW8FltControlStack::GetFmtAttr(const SwPosition& rPos,
1119 USHORT nWhich)
1121 const SfxPoolItem *pItem = GetStackAttr(rPos, nWhich);
1122 if (!pItem)
1124 const SwCntntNode *pNd = pDoc->GetNodes()[ rPos.nNode ]->GetCntntNode();
1125 if (!pNd)
1126 pItem = &pDoc->GetAttrPool().GetDefaultItem(nWhich);
1127 else
1130 If we're hunting for the indent on a paragraph and need to use the
1131 parent style indent, then return the indent in msword format, and
1132 not writer format, because that's the style that the filter works
1133 in (naturally)
1135 if (nWhich == RES_LR_SPACE)
1137 SfxItemState eState = SFX_ITEM_DEFAULT;
1138 if (const SfxItemSet *pSet = pNd->GetpSwAttrSet())
1139 eState = pSet->GetItemState(RES_LR_SPACE, false);
1140 if (eState != SFX_ITEM_SET)
1141 pItem = &(rReader.pCollA[rReader.nAktColl].maWordLR);
1144 if (!pItem)
1145 pItem = &pNd->GetAttr(nWhich);
1148 return pItem;
1151 const SfxPoolItem* SwWW8FltControlStack::GetStackAttr(const SwPosition& rPos,
1152 USHORT nWhich)
1154 SwNodeIndex aNode( rPos.nNode, -1 );
1155 USHORT nIdx = rPos.nContent.GetIndex();
1157 USHORT nSize = static_cast< USHORT >(Count());
1158 while (nSize)
1160 const SwFltStackEntry* pEntry = (*this)[ --nSize ];
1161 if (pEntry->pAttr->Which() == nWhich)
1163 if ( (pEntry->bLocked) || (
1164 (pEntry->nMkNode <= aNode) && (pEntry->nPtNode >= aNode) &&
1165 (pEntry->nMkCntnt <= nIdx) && (pEntry->nPtCntnt >= nIdx) ) )
1167 return (const SfxPoolItem*)pEntry->pAttr;
1171 return 0;
1174 bool SwWW8FltRefStack::IsFtnEdnBkmField(const SwFmtFld& rFmtFld, USHORT& rBkmNo)
1176 const SwField* pFld = rFmtFld.GetFld();
1177 USHORT nSubType;
1178 if(pFld && (RES_GETREFFLD == pFld->Which())
1179 && ((REF_FOOTNOTE == (nSubType = pFld->GetSubType())) || (REF_ENDNOTE == nSubType))
1180 && ((SwGetRefField*)pFld)->GetSetRefName().Len())
1182 const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1183 IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark(
1184 ((SwGetRefField*)pFld)->GetSetRefName());
1185 if(ppBkmk != pMarkAccess->getMarksEnd())
1187 // find Sequence No of corresponding Foot-/Endnote
1188 rBkmNo = ppBkmk - pMarkAccess->getMarksBegin();
1189 return true;
1192 return false;
1195 void SwWW8FltRefStack::SetAttrInDoc(const SwPosition& rTmpPos,
1196 SwFltStackEntry* pEntry)
1198 switch( pEntry->pAttr->Which() )
1201 Look up these in our lists of bookmarks that were changed to
1202 variables, and replace the ref field with a var field, otherwise
1203 do normal (?) strange stuff
1205 case RES_TXTATR_FIELD:
1207 SwNodeIndex aIdx(pEntry->nMkNode, 1);
1208 SwPaM aPaM(aIdx, pEntry->nMkCntnt);
1210 SwFmtFld& rFmtFld = *(SwFmtFld*)pEntry->pAttr;
1211 SwField* pFld = rFmtFld.GetFld();
1213 // OD 2004-03-19 - <NOT> got lost from revision 1.128 to 1.129
1214 if (!RefToVar(pFld,pEntry))
1216 USHORT nBkmNo;
1217 if( IsFtnEdnBkmField(rFmtFld, nBkmNo) )
1219 ::sw::mark::IMark const * const pMark = (pDoc->getIDocumentMarkAccess()->getMarksBegin() + nBkmNo)->get();
1221 const SwPosition& rBkMrkPos = pMark->GetMarkPos();
1223 SwTxtNode* pTxt = rBkMrkPos.nNode.GetNode().GetTxtNode();
1224 if( pTxt && rBkMrkPos.nContent.GetIndex() )
1226 SwTxtAttr* pFtn = pTxt->GetTxtAttr(
1227 rBkMrkPos.nContent.GetIndex()-1, RES_TXTATR_FTN );
1228 if( pFtn )
1230 USHORT nRefNo = ((SwTxtFtn*)pFtn)->GetSeqRefNo();
1232 ((SwGetRefField*)pFld)->SetSeqNo( nRefNo );
1234 if( pFtn->GetFtn().IsEndNote() )
1235 ((SwGetRefField*)pFld)->SetSubType(REF_ENDNOTE);
1241 pDoc->Insert(aPaM, *pEntry->pAttr, 0);
1242 MoveAttrs(*aPaM.GetPoint());
1244 break;
1245 case RES_FLTR_TOX:
1246 SwFltEndStack::SetAttrInDoc(rTmpPos, pEntry);
1247 break;
1248 default:
1249 case RES_FLTR_BOOKMARK:
1250 ASSERT(!this, "EndStck used with non field, not what we want");
1251 SwFltEndStack::SetAttrInDoc(rTmpPos, pEntry);
1252 break;
1257 For styles we will do our tabstop arithmetic in word style and adjust them to
1258 writer style after all the styles have been finished and the dust settles as
1259 to what affects what.
1261 For explicit attributes we turn the adjusted writer tabstops back into 0 based
1262 word indexes and we'll turn them back into writer indexes when setting them
1263 into the document. If explicit left indent exist which affects them, then this
1264 is handled when the explict left indent is set into the document
1266 void SwWW8ImplReader::Read_Tab(USHORT , const BYTE* pData, short nLen)
1268 if (nLen < 0)
1270 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_TABSTOP);
1271 return;
1274 short i;
1275 const BYTE* pDel = pData + 1; // Del - Array
1276 BYTE nDel = pData[0];
1277 const BYTE* pIns = pData + 2*nDel + 2; // Ins - Array
1278 BYTE nIns = pData[nDel*2+1];
1279 WW8_TBD* pTyp = (WW8_TBD*)(pData + 2*nDel + 2*nIns + 2);// Typ - Array
1281 SvxTabStopItem aAttr(0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP);
1283 const SwTxtFmtColl* pSty = 0;
1284 USHORT nTabBase;
1285 if (pAktColl) // StyleDef
1287 nTabBase = pCollA[nAktColl].nBase;
1288 if (nTabBase < nColls) // Based On
1289 pSty = (const SwTxtFmtColl*)pCollA[nTabBase].pFmt;
1291 else
1292 { // Text
1293 nTabBase = nAktColl;
1294 pSty = (const SwTxtFmtColl*)pCollA[nAktColl].pFmt;
1297 bool bFound = false;
1298 ::std::hash_set<size_t> aLoopWatch;
1299 while (pSty && !bFound)
1301 const SfxPoolItem* pTabs;
1302 bFound = pSty->GetAttrSet().GetItemState(RES_PARATR_TABSTOP, false,
1303 &pTabs) == SFX_ITEM_SET;
1304 if( bFound )
1305 aAttr = *((const SvxTabStopItem*)pTabs);
1306 else
1309 USHORT nOldTabBase = nTabBase;
1310 // If based on another
1311 if (nTabBase < nColls)
1312 nTabBase = pCollA[nTabBase].nBase;
1314 if (
1315 nTabBase < nColls &&
1316 nOldTabBase != nTabBase &&
1317 nTabBase != ww::stiNil
1320 // #i61789: Stop searching when next style is the same as the
1321 // current one (prevent loop)
1322 aLoopWatch.insert(reinterpret_cast<size_t>(pSty));
1323 pSty = (const SwTxtFmtColl*)pCollA[nTabBase].pFmt;
1325 if (aLoopWatch.find(reinterpret_cast<size_t>(pSty)) !=
1326 aLoopWatch.end())
1327 pSty = 0;
1329 else
1330 pSty = 0; // gib die Suche auf
1334 SvxTabStop aTabStop;
1335 for (i=0; i < nDel; ++i)
1337 USHORT nPos = aAttr.GetPos(SVBT16ToShort(pDel + i*2));
1338 if( nPos != SVX_TAB_NOTFOUND )
1339 aAttr.Remove( nPos, 1 );
1342 for (i=0; i < nIns; ++i)
1344 short nPos = SVBT16ToShort(pIns + i*2);
1345 aTabStop.GetTabPos() = nPos;
1346 switch( SVBT8ToByte( pTyp[i].aBits1 ) & 0x7 ) // pTyp[i].jc
1348 case 0:
1349 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_LEFT;
1350 break;
1351 case 1:
1352 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_CENTER;
1353 break;
1354 case 2:
1355 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_RIGHT;
1356 break;
1357 case 3:
1358 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_DECIMAL;
1359 break;
1360 case 4:
1361 continue; // ignoriere Bar
1364 switch( SVBT8ToByte( pTyp[i].aBits1 ) >> 3 & 0x7 )
1366 case 0:
1367 aTabStop.GetFill() = ' ';
1368 break;
1369 case 1:
1370 aTabStop.GetFill() = '.';
1371 break;
1372 case 2:
1373 aTabStop.GetFill() = '-';
1374 break;
1375 case 3:
1376 case 4:
1377 aTabStop.GetFill() = '_';
1378 break;
1381 USHORT nPos2 = aAttr.GetPos( nPos );
1382 if (nPos2 != SVX_TAB_NOTFOUND)
1383 aAttr.Remove(nPos2, 1); // sonst weigert sich das Insert()
1384 aAttr.Insert(aTabStop);
1387 if (nIns || nDel)
1388 NewAttr(aAttr);
1389 else
1391 //Here we have a tab definition which inserts no extra tabs, or deletes
1392 //no existing tabs. An older version of writer is probably the creater
1393 //of the document :-( . So if we are importing a style we can just
1394 //ignore it. But if we are importing into text we cannot as during
1395 //text SwWW8ImplReader::Read_Tab is called at the begin and end of
1396 //the range the attrib affects, and ignoring it would upset the
1397 //balance
1398 if (!pAktColl) //not importing into a style
1400 using namespace sw::util;
1401 SvxTabStopItem aOrig = pSty ?
1402 ItemGet<SvxTabStopItem>(*pSty, RES_PARATR_TABSTOP) :
1403 DefaultItemGet<SvxTabStopItem>(rDoc, RES_PARATR_TABSTOP);
1404 NewAttr(aOrig);
1409 //-----------------------------------------
1410 // DOP
1411 //-----------------------------------------
1413 void SwWW8ImplReader::ImportDop()
1415 maTracer.EnterEnvironment(sw::log::eDocumentProperties);
1416 // correct the LastPrinted date in DocumentInfo
1417 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1418 mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
1419 uno::Reference<document::XDocumentProperties> xDocuProps(
1420 xDPS->getDocumentProperties());
1421 DBG_ASSERT(xDocuProps.is(), "DocumentProperties is null");
1422 if (xDocuProps.is())
1424 DateTime aLastPrinted(
1425 sw::ms::DTTM2DateTime(pWDop->dttmLastPrint));
1426 ::util::DateTime uDT(aLastPrinted.Get100Sec(),
1427 aLastPrinted.GetSec(), aLastPrinted.GetMin(),
1428 aLastPrinted.GetHour(), aLastPrinted.GetDay(),
1429 aLastPrinted.GetMonth(), aLastPrinted.GetYear());
1430 xDocuProps->setPrintDate(uDT);
1434 // COMPATIBILITY FLAGS START
1437 // i#78951, remember the unknown compatability options
1438 // so as to export them out
1439 rDoc.Setn32DummyCompatabilityOptions1( pWDop->GetCompatabilityOptions());
1440 rDoc.Setn32DummyCompatabilityOptions2( pWDop->GetCompatabilityOptions2());
1442 // Abstand zwischen zwei Absaetzen ist die SUMME von unterem
1443 // Abst. des ersten und oberem Abst. des zweiten
1444 rDoc.set(IDocumentSettingAccess::PARA_SPACE_MAX, pWDop->fDontUseHTMLAutoSpacing);
1445 rDoc.set(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES, true );
1446 maTracer.Log(sw::log::eDontUseHTMLAutoSpacing);
1447 // move tabs on alignment
1448 rDoc.set(IDocumentSettingAccess::TAB_COMPAT, true);
1449 // #i24363# tab stops relative to indent
1450 rDoc.set(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT, false);
1451 maTracer.Log(sw::log::eTabStopDistance);
1452 // OD 14.10.2003 #i18732# - adjust default of option 'FollowTextFlow'
1453 rDoc.SetDefault( SwFmtFollowTextFlow( FALSE ) );
1455 // Import Default-Tabs
1456 long nDefTabSiz = pWDop->dxaTab;
1457 if( nDefTabSiz < 56 )
1458 nDefTabSiz = 709;
1460 // wir wollen genau einen DefaultTab
1461 SvxTabStopItem aNewTab( 1, USHORT(nDefTabSiz), SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
1462 ((SvxTabStop&)aNewTab[0]).GetAdjustment() = SVX_TAB_ADJUST_DEFAULT;
1464 rDoc.GetAttrPool().SetPoolDefaultItem( aNewTab );
1466 if (!pWDop->fUsePrinterMetrics)
1467 maTracer.Log(sw::log::ePrinterMetrics);
1469 if (!pWDop->fNoLeading)
1470 maTracer.Log(sw::log::eExtraLeading);
1472 rDoc.set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, !pWDop->fUsePrinterMetrics);
1473 rDoc.set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, true);
1474 rDoc.set(IDocumentSettingAccess::ADD_FLY_OFFSETS, true );
1475 rDoc.set(IDocumentSettingAccess::ADD_EXT_LEADING, !pWDop->fNoLeading);
1477 // -> #111955#
1478 rDoc.set(IDocumentSettingAccess::OLD_NUMBERING, false);
1479 // <- #111955#
1481 // --> FME 2005-05-27 #i47448#
1482 rDoc.set(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, false);
1483 // <--
1485 // --> FME 2005-06-08 #i49277#
1486 rDoc.set(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, !pWDop->fExpShRtn); // #i56856#
1487 // --> FME 2005-08-11 #i53199#
1488 rDoc.set(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, false);
1490 rDoc.set(IDocumentSettingAccess::OLD_LINE_SPACING, false);
1492 // OD, MMAHER 2004-03-01 #i25901#- set new compatibility option
1493 // 'Add paragraph and table spacing at bottom of table cells'
1494 rDoc.set(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS, true);
1496 // OD 2004-03-17 #i11860# - set new compatibility option
1497 // 'Use former object positioning' to <FALSE>
1498 rDoc.set(IDocumentSettingAccess::USE_FORMER_OBJECT_POS, false);
1500 // OD 2004-05-10 #i27767# - set new compatibility option
1501 // 'Conder Wrapping mode when positioning object' to <TRUE>
1502 rDoc.set(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION, true);
1504 // --> FME 2004-04-22 # #108724#, #i13832#, #i24135#
1505 rDoc.set(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING, false);
1506 // <--
1508 // --> FME 2006-02-10 #131283#
1509 rDoc.set(IDocumentSettingAccess::TABLE_ROW_KEEP, true); //SetTableRowKeep( true );
1510 // <--
1512 // --> FME 2006-03-01 #i3952#
1513 rDoc.set(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, true);
1514 // <--
1516 rDoc.set(IDocumentSettingAccess::INVERT_BORDER_SPACING, true);
1517 rDoc.set(IDocumentSettingAccess::COLLAPSE_EMPTY_CELL_PARA, true);
1520 // COMPATIBILITY FLAGS END
1523 if (!pWDop->fNoLeading)
1524 maTracer.Log(sw::log::eExtraLeading);
1526 //import magic doptypography information, if its there
1527 if (pWwFib->nFib > 105)
1528 ImportDopTypography(pWDop->doptypography);
1530 // #110055# disable form design mode to be able to use imported controls directly
1531 // #i31239# always disable form design mode, not only in protected docs
1532 // if (pWDop->fProtEnabled)
1534 using namespace com::sun::star;
1536 uno::Reference<lang::XComponent> xModelComp(mpDocShell->GetModel(),
1537 uno::UNO_QUERY);
1538 uno::Reference<beans::XPropertySet> xDocProps(xModelComp,
1539 uno::UNO_QUERY);
1540 if (xDocProps.is())
1542 uno::Reference<beans::XPropertySetInfo> xInfo =
1543 xDocProps->getPropertySetInfo();
1544 sal_Bool bValue = false;
1545 if (xInfo.is() &&
1546 xInfo->hasPropertyByName(C2U("ApplyFormDesignMode")))
1548 xDocProps->setPropertyValue(C2U("ApplyFormDesignMode"),
1549 cppu::bool2any(bValue));
1553 const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
1554 sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
1555 if (bUseEnhFields) {
1556 rDoc.set(IDocumentSettingAccess::PROTECT_FORM, pWDop->fProtEnabled );
1559 maTracer.LeaveEnvironment(sw::log::eDocumentProperties);
1562 void SwWW8ImplReader::ImportDopTypography(const WW8DopTypography &rTypo)
1564 using namespace com::sun::star;
1565 switch (rTypo.iLevelOfKinsoku)
1567 case 2: //custom
1569 i18n::ForbiddenCharacters aForbidden(rTypo.rgxchFPunct,
1570 rTypo.rgxchLPunct);
1571 rDoc.setForbiddenCharacters(rTypo.GetConvertedLang(),
1572 aForbidden);
1573 //Obviously cannot set the standard level 1 for japanese, so
1574 //bail out now while we can.
1575 if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESE)
1576 return;
1578 break;
1579 default:
1580 break;
1584 This MS hack means that level 2 of japanese is not in operation, so we put
1585 in what we know are the MS defaults, there is a complementary reverse
1586 hack in the writer. Its our default as well, but we can set it anyway
1587 as a flag for later.
1589 if (!rTypo.reserved2)
1591 i18n::ForbiddenCharacters aForbidden(rTypo.GetJapanNotBeginLevel1(),
1592 rTypo.GetJapanNotEndLevel1());
1593 rDoc.setForbiddenCharacters(LANGUAGE_JAPANESE,aForbidden);
1596 rDoc.set(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION, rTypo.fKerningPunct);
1597 rDoc.setCharacterCompressionType(static_cast<SwCharCompressType>(rTypo.iJustification));
1600 //-----------------------------------------
1601 // Fuss- und Endnoten
1603 //-----------------------------------------
1605 WW8ReaderSave::WW8ReaderSave(SwWW8ImplReader* pRdr ,WW8_CP nStartCp) :
1606 maTmpPos(*pRdr->pPaM->GetPoint()),
1607 mpOldStck(pRdr->pCtrlStck),
1608 mpOldAnchorStck(pRdr->pAnchorStck),
1609 mpOldRedlines(pRdr->mpRedlineStack),
1610 mpOldPlcxMan(pRdr->pPlcxMan),
1611 mpWFlyPara(pRdr->pWFlyPara),
1612 mpSFlyPara(pRdr->pSFlyPara),
1613 mpPreviousNumPaM(pRdr->pPreviousNumPaM),
1614 mpPrevNumRule(pRdr->pPrevNumRule),
1615 mpTableDesc(pRdr->pTableDesc),
1616 mnInTable(pRdr->nInTable),
1617 mnAktColl(pRdr->nAktColl),
1618 mcSymbol(pRdr->cSymbol),
1619 mbIgnoreText(pRdr->bIgnoreText),
1620 mbSymbol(pRdr->bSymbol),
1621 mbHdFtFtnEdn(pRdr->bHdFtFtnEdn),
1622 mbTxbxFlySection(pRdr->bTxbxFlySection),
1623 mbAnl(pRdr->bAnl),
1624 mbInHyperlink(pRdr->bInHyperlink),
1625 mbPgSecBreak(pRdr->bPgSecBreak),
1626 mbWasParaEnd(pRdr->bWasParaEnd),
1627 mbHasBorder(pRdr->bHasBorder),
1628 mbFirstPara(pRdr->bFirstPara)
1630 pRdr->bSymbol = false;
1631 pRdr->bHdFtFtnEdn = true;
1632 pRdr->bTxbxFlySection = pRdr->bAnl = pRdr->bPgSecBreak = pRdr->bWasParaEnd
1633 = pRdr->bHasBorder = false;
1634 pRdr->bFirstPara = true;
1635 pRdr->nInTable = 0;
1636 pRdr->pWFlyPara = 0;
1637 pRdr->pSFlyPara = 0;
1638 pRdr->pPreviousNumPaM = 0;
1639 pRdr->pPrevNumRule = 0;
1640 pRdr->pTableDesc = 0;
1641 pRdr->nAktColl = 0;
1644 pRdr->pCtrlStck = new SwWW8FltControlStack(&pRdr->rDoc, pRdr->nFieldFlags,
1645 *pRdr);
1647 pRdr->mpRedlineStack = new sw::util::RedlineStack(pRdr->rDoc);
1649 pRdr->pAnchorStck = new SwWW8FltAnchorStack(&pRdr->rDoc, pRdr->nFieldFlags);
1651 // rette die Attributverwaltung: dies ist noetig, da der neu anzulegende
1652 // PLCFx Manager natuerlich auf die gleichen FKPs zugreift, wie der alte
1653 // und deren Start-End-Positionen veraendert...
1654 if (pRdr->pPlcxMan)
1655 pRdr->pPlcxMan->SaveAllPLCFx(maPLCFxSave);
1657 if (nStartCp != -1)
1659 pRdr->pPlcxMan = new WW8PLCFMan(pRdr->pSBase,
1660 mpOldPlcxMan->GetManType(), nStartCp);
1663 maOldApos.push_back(false);
1664 maOldApos.swap(pRdr->maApos);
1665 maOldFieldStack.swap(pRdr->maFieldStack);
1668 void WW8ReaderSave::Restore( SwWW8ImplReader* pRdr )
1670 pRdr->pWFlyPara = mpWFlyPara;
1671 pRdr->pSFlyPara = mpSFlyPara;
1672 pRdr->pPreviousNumPaM = mpPreviousNumPaM;
1673 pRdr->pPrevNumRule = mpPrevNumRule;
1674 pRdr->pTableDesc = mpTableDesc;
1675 pRdr->cSymbol = mcSymbol;
1676 pRdr->bSymbol = mbSymbol;
1677 pRdr->bIgnoreText = mbIgnoreText;
1678 pRdr->bHdFtFtnEdn = mbHdFtFtnEdn;
1679 pRdr->bTxbxFlySection = mbTxbxFlySection;
1680 pRdr->nInTable = mnInTable;
1681 pRdr->bAnl = mbAnl;
1682 pRdr->bInHyperlink = mbInHyperlink;
1683 pRdr->bWasParaEnd = mbWasParaEnd;
1684 pRdr->bPgSecBreak = mbPgSecBreak;
1685 pRdr->nAktColl = mnAktColl;
1686 pRdr->bHasBorder = mbHasBorder;
1687 pRdr->bFirstPara = mbFirstPara;
1689 // schliesse alle Attribute, da sonst Attribute
1690 // entstehen koennen, die aus dem Fly rausragen
1691 pRdr->DeleteCtrlStk();
1692 pRdr->pCtrlStck = mpOldStck;
1694 pRdr->mpRedlineStack->closeall(*pRdr->pPaM->GetPoint());
1695 delete pRdr->mpRedlineStack;
1696 pRdr->mpRedlineStack = mpOldRedlines;
1698 pRdr->DeleteAnchorStk();
1699 pRdr->pAnchorStck = mpOldAnchorStck;
1701 *pRdr->pPaM->GetPoint() = maTmpPos;
1703 if (mpOldPlcxMan != pRdr->pPlcxMan)
1705 delete pRdr->pPlcxMan;
1706 pRdr->pPlcxMan = mpOldPlcxMan;
1708 if (pRdr->pPlcxMan)
1709 pRdr->pPlcxMan->RestoreAllPLCFx(maPLCFxSave);
1710 pRdr->maApos.swap(maOldApos);
1711 pRdr->maFieldStack.swap(maOldFieldStack);
1714 void SwWW8ImplReader::Read_HdFtFtnText( const SwNodeIndex* pSttIdx,
1715 long nStartCp, long nLen, ManTypes nType )
1717 // rettet Flags u.ae. u. setzt sie zurueck
1718 WW8ReaderSave aSave( this );
1720 pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1; //
1721 pPaM->GetPoint()->nContent.Assign( pPaM->GetCntntNode(), 0 );
1723 // dann Text fuer Header, Footer o. Footnote einlesen
1725 ReadText( nStartCp, nLen, nType ); // Sepx dabei ignorieren
1726 aSave.Restore( this );
1729 //Use authornames, if not available fall back to initials.
1730 long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes)
1732 WW8PLCFx_SubDoc* pSD = pPlcxMan->GetAtn();
1733 if( !pSD )
1734 return 0;
1736 String sAuthor;
1737 if( bVer67 )
1739 const WW67_ATRD* pDescri = (const WW67_ATRD*)pSD->GetData();
1740 const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst));
1741 if (pA)
1742 sAuthor = *pA;
1743 else
1744 sAuthor = String(pDescri->xstUsrInitl + 1, pDescri->xstUsrInitl[0],
1745 RTL_TEXTENCODING_MS_1252);
1747 else
1749 const WW8_ATRD* pDescri = (const WW8_ATRD*)pSD->GetData();
1751 if (const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst)))
1752 sAuthor = *pA;
1753 else
1755 sal_uInt16 nLen = SVBT16ToShort(pDescri->xstUsrInitl[0]);
1756 for(sal_uInt16 nIdx = 1; nIdx <= nLen; ++nIdx)
1757 sAuthor += SVBT16ToShort(pDescri->xstUsrInitl[nIdx]);
1761 sal_uInt32 nDateTime = 0;
1763 if (BYTE * pExtended = pPlcxMan->GetExtendedAtrds()) // Word < 2002 has no date data for comments
1765 ULONG nIndex = pSD->GetIdx() & 0xFFFF; //Index is (stupidly) multiplexed for WW8PLCFx_SubDocs
1766 if (pWwFib->lcbAtrdExtra/18 > nIndex)
1767 nDateTime = SVBT32ToUInt32(*(SVBT32*)(pExtended+(nIndex*18)));
1770 DateTime aDate = sw::ms::DTTM2DateTime(nDateTime);
1772 String sTxt;
1773 OutlinerParaObject *pOutliner = ImportAsOutliner( sTxt, pRes->nCp2OrIdx,
1774 pRes->nCp2OrIdx + pRes->nMemLen, MAN_AND );
1776 this->pFmtOfJustInsertedApo = 0;
1777 SwPostItField aPostIt(
1778 (SwPostItFieldType*)rDoc.GetSysFldType(RES_POSTITFLD), sAuthor,
1779 sTxt, aDate );
1780 aPostIt.SetTextObject(pOutliner);
1782 rDoc.Insert(*pPaM, SwFmtFld(aPostIt), 0);
1784 return 0;
1787 void SwWW8ImplReader::Read_HdFtTextAsHackedFrame(long nStart, long nLen,
1788 SwFrmFmt &rHdFtFmt, sal_uInt16 nPageWidth)
1790 const SwNodeIndex* pSttIdx = rHdFtFmt.GetCntnt().GetCntntIdx();
1791 ASSERT(pSttIdx, "impossible");
1792 if (!pSttIdx)
1793 return;
1795 SwPosition aTmpPos(*pPaM->GetPoint());
1797 pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1;
1798 pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(), 0);
1800 SwFlyFrmFmt *pFrame = rDoc.MakeFlySection(FLY_AT_CNTNT, pPaM->GetPoint());
1802 pFrame->SetFmtAttr(SwFmtFrmSize(ATT_MIN_SIZE, nPageWidth, MINLAY));
1803 pFrame->SetFmtAttr(SwFmtSurround(SURROUND_THROUGHT));
1804 pFrame->SetFmtAttr(SwFmtHoriOrient(0, text::HoriOrientation::RIGHT)); //iFOO
1805 // --> OD 2005-02-28 #i43427# - send frame for header/footer into background.
1806 pFrame->SetFmtAttr( SvxOpaqueItem( RES_OPAQUE, false ) );
1807 SdrObject* pFrmObj = CreateContactObject( pFrame );
1808 ASSERT( pFrmObj,
1809 "<SwWW8ImplReader::Read_HdFtTextAsHackedFrame(..)> - missing SdrObject instance" );
1810 if ( pFrmObj )
1812 pFrmObj->SetOrdNum( 0L );
1814 // <--
1815 MoveInsideFly(pFrame);
1817 const SwNodeIndex* pHackIdx = pFrame->GetCntnt().GetCntntIdx();
1819 Read_HdFtFtnText(pHackIdx, nStart, nLen - 1, MAN_HDFT);
1821 MoveOutsideFly(pFrame, aTmpPos);
1824 void SwWW8ImplReader::Read_HdFtText(long nStart, long nLen, SwFrmFmt* pHdFtFmt)
1826 const SwNodeIndex* pSttIdx = pHdFtFmt->GetCntnt().GetCntntIdx();
1827 if (!pSttIdx)
1828 return;
1830 SwPosition aTmpPos( *pPaM->GetPoint() ); // merke alte Cursorposition
1832 Read_HdFtFtnText(pSttIdx, nStart, nLen - 1, MAN_HDFT);
1834 *pPaM->GetPoint() = aTmpPos;
1837 bool SwWW8ImplReader::HasOwnHeaderFooter(BYTE nWhichItems, BYTE grpfIhdt,
1838 int nSect)
1840 if (pHdFt)
1842 WW8_CP start;
1843 long nLen;
1844 BYTE nNumber = 5;
1846 for( BYTE nI = 0x20; nI; nI >>= 1, nNumber-- )
1848 if (nI & nWhichItems)
1850 bool bOk = true;
1851 if( bVer67 )
1852 bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 );
1853 else
1855 pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen);
1856 bOk = ( 2 <= nLen );
1859 if (bOk)
1860 return true;
1864 return false;
1867 void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect,
1868 const SwPageDesc *pPrev, const wwSection &rSection)
1870 BYTE nWhichItems = 0;
1871 SwPageDesc *pPD = 0;
1872 if (!bIsTitle)
1874 nWhichItems =
1875 rSection.maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST);
1876 pPD = rSection.mpPage;
1878 else
1880 // --> OD 2008-08-06 #150965#
1881 // Always read title page header/footer data - it could be used by following sections
1882 // nWhichItems =
1883 // rSection.maSep.grpfIhdt & (WW8_HEADER_FIRST | WW8_FOOTER_FIRST),
1884 nWhichItems = ( WW8_HEADER_FIRST | WW8_FOOTER_FIRST );
1885 // <--
1886 pPD = rSection.mpTitlePage;
1889 BYTE grpfIhdt = rSection.maSep.grpfIhdt;
1892 if( pHdFt )
1894 WW8_CP start;
1895 long nLen;
1896 BYTE nNumber = 5;
1898 for( BYTE nI = 0x20; nI; nI >>= 1, nNumber-- )
1900 if (nI & nWhichItems)
1902 bool bOk = true;
1903 if( bVer67 )
1904 bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 );
1905 else
1907 pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen);
1908 bOk = ( 2 <= nLen );
1911 bool bUseLeft
1912 = (nI & ( WW8_HEADER_EVEN | WW8_FOOTER_EVEN )) ? true: false;
1913 bool bFooter
1914 = (nI & ( WW8_FOOTER_EVEN | WW8_FOOTER_ODD | WW8_FOOTER_FIRST )) ? true: false;
1916 SwFrmFmt* pFmt = bUseLeft ? &pPD->GetLeft() : &pPD->GetMaster();
1918 SwFrmFmt* pHdFtFmt;
1919 if (bFooter)
1921 bIsFooter = true;
1922 //#i17196# Cannot have left without right
1923 if (!pPD->GetMaster().GetFooter().GetFooterFmt())
1924 pPD->GetMaster().SetFmtAttr(SwFmtFooter(true));
1925 if (bUseLeft)
1926 pPD->GetLeft().SetFmtAttr(SwFmtFooter(true));
1927 pHdFtFmt = (SwFrmFmt*)pFmt->GetFooter().GetFooterFmt();
1929 else
1931 bIsHeader = true;
1932 //#i17196# Cannot have left without right
1933 if (!pPD->GetMaster().GetHeader().GetHeaderFmt())
1934 pPD->GetMaster().SetFmtAttr(SwFmtHeader(true));
1935 if (bUseLeft)
1936 pPD->GetLeft().SetFmtAttr(SwFmtHeader(true));
1937 pHdFtFmt = (SwFrmFmt*)pFmt->GetHeader().GetHeaderFmt();
1940 if (bOk)
1942 bool bHackRequired = false;
1943 if (bIsHeader && rSection.IsFixedHeightHeader())
1944 bHackRequired = true;
1945 else if (bIsFooter && rSection.IsFixedHeightFooter())
1946 bHackRequired = true;
1948 if (bHackRequired)
1950 Read_HdFtTextAsHackedFrame(start, nLen, *pHdFtFmt,
1951 static_cast< sal_uInt16 >(rSection.GetTextAreaWidth()) );
1953 else
1954 Read_HdFtText(start, nLen, pHdFtFmt);
1956 else if (!bOk && pPrev)
1957 CopyPageDescHdFt(pPrev, pPD, nI);
1959 bIsHeader = bIsFooter = false;
1963 maTracer.LeaveEnvironment(sw::log::eDocumentProperties);
1966 bool wwSectionManager::SectionIsProtected(const wwSection &rSection) const
1968 return (mrReader.pWDop->fProtEnabled && !rSection.IsNotProtected());
1971 void wwSectionManager::SetHdFt(wwSection &rSection, int nSect,
1972 const wwSection *pPrevious)
1974 // Header / Footer nicht da
1975 if (!rSection.maSep.grpfIhdt)
1976 return;
1978 ASSERT(rSection.mpPage, "makes no sense to call with a main page");
1979 if (rSection.mpPage)
1981 mrReader.Read_HdFt(false, nSect, pPrevious ? pPrevious->mpPage : 0,
1982 rSection);
1985 if (rSection.mpTitlePage)
1987 // 2 Pagedescs noetig: 1.Seite und folgende
1988 // 1. Seite einlesen
1989 mrReader.Read_HdFt(true, nSect, pPrevious ? pPrevious->mpTitlePage : 0,
1990 rSection);
1993 // Kopf / Fuss - Index Updaten
1994 // Damit der Index auch spaeter noch stimmt
1995 if (mrReader.pHdFt)
1996 mrReader.pHdFt->UpdateIndex(rSection.maSep.grpfIhdt);
2000 class AttribHere : public std::unary_function<const xub_StrLen*, bool>
2002 private:
2003 xub_StrLen nPosition;
2004 public:
2005 AttribHere(xub_StrLen nPos) : nPosition(nPos) {}
2006 bool operator()(const xub_StrLen *pPosition) const
2008 return (*pPosition >= nPosition);
2012 void SwWW8ImplReader::AppendTxtNode(SwPosition& rPos)
2014 SwTxtNode* pTxt = pPaM->GetNode()->GetTxtNode();
2016 const SwNumRule* pRule = NULL;
2018 if (pTxt != NULL)
2019 pRule = sw::util::GetNumRuleFromTxtNode(*pTxt);
2021 if (
2022 pRule && !pWDop->fDontUseHTMLAutoSpacing &&
2023 (bParaAutoBefore || bParaAutoAfter)
2026 // If after spacing is set to auto, set the after space to 0
2027 if (bParaAutoAfter)
2028 SetLowerSpacing(*pPaM, 0);
2030 // If the previous textnode had numbering and
2031 // and before spacing is set to auto, set before space to 0
2032 if(pPrevNumRule && bParaAutoBefore)
2033 SetUpperSpacing(*pPaM, 0);
2035 // If the previous numbering rule was different we need
2036 // to insert a space after the previous paragraph
2037 if((pRule != pPrevNumRule) && pPreviousNumPaM)
2038 SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
2040 // cache current paragraph
2041 if(pPreviousNumPaM)
2042 delete pPreviousNumPaM, pPreviousNumPaM = 0;
2044 pPreviousNumPaM = new SwPaM(*pPaM);
2045 pPrevNumRule = pRule;
2047 else if(!pRule && pPreviousNumPaM)
2049 // If the previous paragraph has numbering but the current one does not
2050 // we need to add a space after the previous paragraph
2051 SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
2052 delete pPreviousNumPaM, pPreviousNumPaM = 0;
2053 pPrevNumRule = 0;
2055 else
2057 // clear paragraph cache
2058 if(pPreviousNumPaM)
2059 delete pPreviousNumPaM, pPreviousNumPaM = 0;
2060 pPrevNumRule = pRule;
2063 // If this is the first paragraph in the document and
2064 // Auto-spacing before paragraph is set,
2065 // set the upper spacing value to 0
2066 if(bParaAutoBefore && bFirstPara && !pWDop->fDontUseHTMLAutoSpacing)
2067 SetUpperSpacing(*pPaM, 0);
2069 bFirstPara = false;
2071 rDoc.AppendTxtNode(rPos);
2073 //We can flush all anchored graphics at the end of a paragraph.
2074 pAnchorStck->Flush();
2077 bool SwWW8ImplReader::SetSpacing(SwPaM &rMyPam, int nSpace, bool bIsUpper )
2079 bool bRet = false;
2080 const SwPosition* pSpacingPos = rMyPam.GetPoint();
2082 const SvxULSpaceItem* pULSpaceItem = (const SvxULSpaceItem*)pCtrlStck->GetFmtAttr(*pSpacingPos, RES_UL_SPACE);
2084 if(pULSpaceItem != 0)
2086 SvxULSpaceItem aUL(*pULSpaceItem);
2088 if(bIsUpper)
2089 aUL.SetUpper( static_cast< USHORT >(nSpace) );
2090 else
2091 aUL.SetLower( static_cast< USHORT >(nSpace) );
2093 xub_StrLen nEnd = pSpacingPos->nContent.GetIndex();
2094 rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), 0);
2095 pCtrlStck->NewAttr(*pSpacingPos, aUL);
2096 rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), nEnd);
2097 pCtrlStck->SetAttr(*pSpacingPos, RES_UL_SPACE);
2098 bRet = true;
2100 return bRet;
2103 bool SwWW8ImplReader::SetLowerSpacing(SwPaM &rMyPam, int nSpace)
2105 return SetSpacing(rMyPam, nSpace, false);
2108 bool SwWW8ImplReader::SetUpperSpacing(SwPaM &rMyPam, int nSpace)
2110 return SetSpacing(rMyPam, nSpace, true);
2113 USHORT SwWW8ImplReader::TabRowSprm(int nLevel) const
2115 if (bVer67)
2116 return 25;
2117 return nLevel ? 0x244C : 0x2417;
2120 void SwWW8ImplReader::EndSpecial()
2122 // Frame / Table / Anl
2123 if (bAnl)
2124 StopAllAnl(); // -> bAnl = false
2126 while(maApos.size() > 1)
2128 StopTable();
2129 maApos.pop_back();
2130 --nInTable;
2131 if (maApos[nInTable] == true)
2132 StopApo();
2135 if (maApos[0] == true)
2136 StopApo();
2138 ASSERT(!nInTable, "unclosed table!");
2141 bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync, WW8_CP nStartCp)
2143 // Frame / Table / Anl
2144 if (bInHyperlink)
2145 return false;
2147 rbReSync = false;
2149 ASSERT(nInTable >= 0,"nInTable < 0!");
2151 // TabRowEnd
2152 bool bTableRowEnd = (pPlcxMan->HasParaSprm(bVer67 ? 25 : 0x2417) != 0 );
2154 // es muss leider fuer jeden Absatz zuerst nachgesehen werden,
2155 // ob sich unter den sprms
2156 // das sprm 29 (bzw. 0x261B) befindet, das ein APO einleitet.
2157 // Alle weiteren sprms beziehen sich dann naemlich auf das APO und nicht
2158 // auf den normalen Text drumrum.
2159 // Dasselbe gilt fuer eine Tabelle ( sprm 24 (bzw. 0x2416) )
2160 // und Anls ( sprm 13 ).
2161 // WW: Tabelle in APO geht ( Beide Anfaende treten gleichzeitig auf )
2162 // WW: APO in Tabelle geht nicht
2163 // d.h. Wenn eine Tabelle Inhalt eines Apo ist, dann muss der
2164 // Apo-Anfang zuerst bearbeitet werden, damit die Tabelle im Apo steht
2165 // und nicht umgekehrt. Am Ende muss dagegen zuerst das Tabellenende
2166 // bearbeitet werden, da die Apo erst nach der Tabelle abgeschlossen
2167 // werden darf ( sonst wird das Apo-Ende nie gefunden ).
2168 // Dasselbe gilt fuer Fly / Anl, Tab / Anl, Fly / Tab / Anl.
2170 // Wenn die Tabelle in einem Apo steht, fehlen im TabRowEnd-Bereich
2171 // die Apo-Angaben. Damit hier die Apo nicht beendet wird, wird
2172 // ProcessApo dann nicht aufgerufen.
2174 // KHZ: When there is a table inside the Apo the Apo-flags are also
2175 // missing for the 2nd, 3rd... paragraphs of each cell.
2178 // 1st look for in-table flag, for 2000+ there is a subtable flag to
2179 // be considered, the sprm 6649 gives the level of the table
2180 BYTE nCellLevel = 0;
2182 if (bVer67)
2183 nCellLevel = 0 != pPlcxMan->HasParaSprm(24);
2184 else
2186 nCellLevel = 0 != pPlcxMan->HasParaSprm(0x2416);
2187 if (!nCellLevel)
2188 nCellLevel = 0 != pPlcxMan->HasParaSprm(0x244B);
2191 mark:
2193 WW8_TablePos *pTabPos=0;
2194 WW8_TablePos aTabPos;
2195 if (nCellLevel && !bVer67)
2197 WW8PLCFxSave1 aSave;
2198 pPlcxMan->GetPap()->Save( aSave );
2199 rbReSync = true;
2200 WW8PLCFx_Cp_FKP* pPap = pPlcxMan->GetPapPLCF();
2201 WW8_CP nMyStartCp=nStartCp;
2203 if (const BYTE *pLevel = pPlcxMan->HasParaSprm(0x6649))
2204 nCellLevel = *pLevel;
2206 bool bHasRowEnd = SearchRowEnd(pPap, nMyStartCp, (nInTable<nCellLevel?nInTable:nCellLevel-1));
2208 //Bad Table, remain unchanged in level, e.g. #i19667#
2209 if (!bHasRowEnd)
2210 nCellLevel = static_cast< BYTE >(nInTable);
2212 if (bHasRowEnd && ParseTabPos(&aTabPos,pPap))
2213 pTabPos = &aTabPos;
2215 pPlcxMan->GetPap()->Restore( aSave );
2218 // then look if we are in an Apo
2220 ApoTestResults aApo = TestApo(nCellLevel, bTableRowEnd, pTabPos);
2222 //look to see if we are in a Table, but Table in foot/end note not allowed
2223 bool bStartTab = (nInTable < nCellLevel) && !bFtnEdn;
2225 bool bStopTab = bWasTabRowEnd && (nInTable > nCellLevel) && !bFtnEdn;
2227 bWasTabRowEnd = false; // must be deactivated right here to prevent next
2228 // WW8TabDesc::TableCellEnd() from making nonsense
2230 if (nInTable && !bTableRowEnd && !bStopTab && (nInTable == nCellLevel && aApo.HasStartStop()))
2231 bStopTab = bStartTab = true; // Required to stop and start table
2233 // Dann auf Anl (Nummerierung) testen
2234 // und dann alle Ereignisse in der richtigen Reihenfolge bearbeiten
2236 if( bAnl && !bTableRowEnd )
2238 const BYTE* pSprm13 = pPlcxMan->HasParaSprm( 13 );
2239 if( pSprm13 )
2240 { // Noch Anl ?
2241 BYTE nT = static_cast< BYTE >(GetNumType( *pSprm13 ));
2242 if( ( nT != WW8_Pause && nT != nWwNumType ) // Anl-Wechsel
2243 || aApo.HasStartStop() // erzwungenes Anl-Ende
2244 || bStopTab || bStartTab )
2246 StopAnlToRestart(nT); // Anl-Restart ( = Wechsel ) ueber sprms
2248 else
2250 NextAnlLine( pSprm13 ); // naechste Anl-Zeile
2253 else
2254 { // Anl normal zuende
2255 StopAllAnl(); // Wirkliches Ende
2258 if (bStopTab)
2260 StopTable();
2261 maApos.pop_back();
2262 --nInTable;
2264 if (aApo.mbStopApo)
2266 StopApo();
2267 maApos[nInTable] = false;
2270 if (aApo.mbStartApo)
2272 maApos[nInTable] = StartApo(aApo, pTabPos);
2273 // nach StartApo ist ein ReSync noetig ( eigentlich nur, falls die Apo
2274 // ueber eine FKP-Grenze geht
2275 rbReSync = true;
2277 if (bStartTab)
2279 WW8PLCFxSave1 aSave;
2280 pPlcxMan->GetPap()->Save( aSave );
2282 if (bAnl) // Nummerierung ueber Zellengrenzen
2283 StopAllAnl(); // fuehrt zu Absturz -> keine Anls
2284 // in Tabellen
2285 while (nInTable < nCellLevel)
2287 if (StartTable(nStartCp)) {
2288 ++nInTable;
2290 else
2291 break;
2293 maApos.push_back(false);
2294 if (nInTable<nCellLevel)
2295 goto mark;
2298 // nach StartTable ist ein ReSync noetig ( eigentlich nur, falls die
2299 // Tabelle ueber eine FKP-Grenze geht
2300 rbReSync = true;
2301 pPlcxMan->GetPap()->Restore( aSave );
2303 return bTableRowEnd;
2306 CharSet SwWW8ImplReader::GetCurrentCharSet()
2309 #i2015
2310 If the hard charset is set use it, if not see if there is an open
2311 character run that has set the charset, if not then fallback to the
2312 current underlying paragraph style.
2314 CharSet eSrcCharSet = eHardCharSet;
2315 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2317 if (!maFontSrcCharSets.empty())
2318 eSrcCharSet = maFontSrcCharSets.top();
2319 if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && (nCharFmt != -1))
2320 eSrcCharSet = pCollA[nCharFmt].GetCharSet();
2321 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2322 eSrcCharSet = pCollA[nAktColl].GetCharSet();
2323 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2324 { // patch from cmc for #i52786#
2326 #i22206#/#i52786#
2327 The (default) character set used for a run of text is the default
2328 character set for the version of Word that last saved the document.
2330 This is a bit tentative, more might be required if the concept is correct.
2331 When later version of word write older 6/95 documents the charset is
2332 correctly set in the character runs involved, so its hard to reproduce
2333 documents that require this to be sure of the process involved.
2335 const SvxLanguageItem *pLang =
2336 (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
2337 if (pLang)
2339 switch (pLang->GetLanguage())
2341 case LANGUAGE_CZECH:
2342 eSrcCharSet = RTL_TEXTENCODING_MS_1250;
2343 break;
2344 default:
2345 eSrcCharSet = RTL_TEXTENCODING_MS_1252;
2346 break;
2351 return eSrcCharSet;
2354 void SwWW8ImplReader::PostProcessAttrs()
2356 if (mpPostProcessAttrsInfo != NULL)
2358 SfxItemIter aIter(mpPostProcessAttrsInfo->mItemSet);
2360 const SfxPoolItem * pItem = aIter.GetCurItem();
2361 if (pItem != NULL)
2365 pCtrlStck->NewAttr(*mpPostProcessAttrsInfo->mPaM.GetPoint(),
2366 *pItem);
2367 pCtrlStck->SetAttr(*mpPostProcessAttrsInfo->mPaM.GetMark(),
2368 pItem->Which(), true);
2370 while (!aIter.IsAtEnd() && 0 != (pItem = aIter.NextItem()));
2373 delete mpPostProcessAttrsInfo;
2374 mpPostProcessAttrsInfo = NULL;
2379 #i9241#
2380 It appears that some documents that are in a baltic 8 bit encoding which has
2381 some undefined characters can have use made of those characters, in which
2382 case they default to CP1252. If not then its perhaps that the font encoding
2383 is only in use for 6/7 and for 8+ if we are in 8bit mode then the encoding
2384 is always 1252.
2386 So a encoding converter that on an undefined character attempts to
2387 convert from 1252 on the undefined character
2389 sal_Size Custom8BitToUnicode(rtl_TextToUnicodeConverter hConverter,
2390 sal_Char *pIn, sal_Size nInLen, sal_Unicode *pOut, sal_Size nOutLen)
2392 const sal_uInt32 nFlags =
2393 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
2394 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
2395 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE |
2396 RTL_TEXTTOUNICODE_FLAGS_FLUSH;
2398 const sal_uInt32 nFlags2 =
2399 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE |
2400 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_IGNORE |
2401 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE |
2402 RTL_TEXTTOUNICODE_FLAGS_FLUSH;
2404 sal_Size nDestChars=0;
2405 sal_Size nConverted=0;
2409 sal_uInt32 nInfo = 0;
2410 sal_Size nThisConverted=0;
2412 nDestChars += rtl_convertTextToUnicode(hConverter, 0,
2413 pIn+nConverted, nInLen-nConverted,
2414 pOut+nDestChars, nOutLen-nDestChars,
2415 nFlags, &nInfo, &nThisConverted);
2417 ASSERT(nInfo == 0, "A character conversion failed!");
2419 nConverted += nThisConverted;
2421 if (
2422 nInfo & RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR ||
2423 nInfo & RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
2426 sal_Size nOtherConverted;
2427 rtl_TextToUnicodeConverter hCP1252Converter =
2428 rtl_createTextToUnicodeConverter(RTL_TEXTENCODING_MS_1252);
2429 nDestChars += rtl_convertTextToUnicode(hCP1252Converter, 0,
2430 pIn+nConverted, 1,
2431 pOut+nDestChars, nOutLen-nDestChars,
2432 nFlags2, &nInfo, &nOtherConverted);
2433 rtl_destroyTextToUnicodeConverter(hCP1252Converter);
2434 nConverted+=1;
2436 } while (nConverted < nInLen);
2438 return nDestChars;
2441 bool SwWW8ImplReader::LangUsesHindiNumbers(USHORT nLang)
2443 bool bResult = false;
2445 switch (nLang)
2447 case 0x1401: // Arabic(Algeria)
2448 case 0x3c01: // Arabic(Bahrain)
2449 case 0xc01: // Arabic(Egypt)
2450 case 0x801: // Arabic(Iraq)
2451 case 0x2c01: // Arabic (Jordan)
2452 case 0x3401: // Arabic(Kuwait)
2453 case 0x3001: // Arabic(Lebanon)
2454 case 0x1001: // Arabic(Libya)
2455 case 0x1801: // Arabic(Morocco)
2456 case 0x2001: // Arabic(Oman)
2457 case 0x4001: // Arabic(Qatar)
2458 case 0x401: // Arabic(Saudi Arabia)
2459 case 0x2801: // Arabic(Syria)
2460 case 0x1c01: // Arabic(Tunisia)
2461 case 0x3801: // Arabic(U.A.E)
2462 case 0x2401: // Arabic(Yemen)
2463 bResult = true;
2464 break;
2465 default:
2466 break;
2469 return bResult;
2472 sal_Unicode SwWW8ImplReader::TranslateToHindiNumbers(sal_Unicode nChar)
2474 if (nChar >= 0x0030 && nChar <= 0x0039)
2475 return nChar + 0x0630;
2477 return nChar;
2480 // Returnwert: true for no Sonderzeichen
2481 bool SwWW8ImplReader::ReadPlainChars(WW8_CP& rPos, long nEnd, long nCpOfs)
2483 // Unicode-Flag neu setzen und notfalls File-Pos korrigieren
2484 // merke: Seek kostet nicht viel, da inline geprueft wird,
2485 // ob die korrekte FilePos nicht schon erreicht ist.
2486 WW8_FC nStreamPos = pSBase->WW8Cp2Fc(nCpOfs+rPos, &bIsUnicode);
2487 pStrm->Seek( nStreamPos );
2489 xub_StrLen nLen;
2490 if (nEnd - rPos <= (STRING_MAXLEN-1))
2491 nLen = writer_cast<xub_StrLen>(nEnd - rPos);
2492 else
2493 nLen = STRING_MAXLEN-1;
2494 ASSERT(nLen, "String is 0");
2495 if (!nLen)
2496 return true;
2498 const CharSet eSrcCharSet = bVer67 ? GetCurrentCharSet() :
2499 RTL_TEXTENCODING_MS_1252;
2501 // (re)alloc UniString data
2502 String sPlainCharsBuf;
2504 sal_Unicode* pBuffer = sPlainCharsBuf.AllocBuffer( nLen );
2505 sal_Unicode* pWork = pBuffer;
2507 sal_Char* p8Bits = NULL;
2509 rtl_TextToUnicodeConverter hConverter = 0;
2510 if (!bIsUnicode || bVer67)
2511 hConverter = rtl_createTextToUnicodeConverter(eSrcCharSet);
2513 if (!bIsUnicode)
2514 p8Bits = new sal_Char[nLen];
2516 // read the stream data
2517 BYTE nBCode = 0;
2518 UINT16 nUCode;
2519 xub_StrLen nL2;
2521 USHORT nCTLLang = 0;
2522 const SfxPoolItem * pItem = GetFmtAttr(RES_CHRATR_CTL_LANGUAGE);
2523 if (pItem != NULL)
2524 nCTLLang = dynamic_cast<const SvxLanguageItem *>(pItem)->GetLanguage();
2526 for( nL2 = 0; nL2 < nLen; ++nL2, ++pWork )
2528 if (bIsUnicode)
2529 *pStrm >> nUCode; // unicode --> read 2 bytes
2530 else
2532 *pStrm >> nBCode; // old code --> read 1 byte
2533 nUCode = nBCode;
2536 if (pStrm->GetError())
2538 rPos = WW8_CP_MAX-10; // -> eof or other error
2539 sPlainCharsBuf.ReleaseBufferAccess( 0 );
2540 return true;
2543 if ((32 > nUCode) || (0xa0 == nUCode))
2545 pStrm->SeekRel( bIsUnicode ? -2 : -1 );
2546 break; // Sonderzeichen < 32, == 0xa0 gefunden
2549 if (bIsUnicode)
2551 if (!bVer67)
2552 *pWork = nUCode;
2553 else
2555 if (nUCode >= 0x3000) //0x8000 ?
2557 sal_Char aTest[2];
2558 aTest[0] = static_cast< sal_Char >((nUCode & 0xFF00) >> 8);
2559 aTest[1] = static_cast< sal_Char >(nUCode & 0x00FF);
2560 String aTemp(aTest, 2, eSrcCharSet);
2561 ASSERT(aTemp.Len() == 1, "so much for that theory");
2562 *pWork = aTemp.GetChar(0);
2564 else
2566 sal_Char cTest = static_cast< sal_Char >(nUCode & 0x00FF);
2567 Custom8BitToUnicode(hConverter, &cTest, 1, pWork, 1);
2571 else
2572 p8Bits[nL2] = nBCode;
2575 if (nL2)
2577 xub_StrLen nEndUsed = nL2;
2579 if (!bIsUnicode)
2580 nEndUsed = Custom8BitToUnicode(hConverter, p8Bits, nL2, pBuffer, nLen);
2582 for( xub_StrLen nI = 0; nI < nLen; ++nI, ++pBuffer )
2583 if (m_bRegardHindiDigits && bBidi && LangUsesHindiNumbers(nCTLLang))
2584 *pBuffer = TranslateToHindiNumbers(*pBuffer);
2586 sPlainCharsBuf.ReleaseBufferAccess( nEndUsed );
2588 AddTextToParagraph(sPlainCharsBuf);
2589 rPos += nL2;
2590 if (!maApos.back()) //a para end in apo doesn't count
2591 bWasParaEnd = false; //kein CR
2594 if (hConverter)
2595 rtl_destroyTextToUnicodeConverter(hConverter);
2596 delete [] p8Bits;
2597 return nL2 >= nLen;
2600 bool SwWW8ImplReader::AddTextToParagraph(const String& rAddString)
2602 const SwTxtNode* pNd = pPaM->GetCntntNode()->GetTxtNode();
2603 if (rAddString.Len())
2606 #ifdef DEBUG
2607 //!! does not compile with debug=t -> unresolved external (dbg_out),
2608 //!! sommeone who knows what he wants to get should fix this
2609 // ::std::clog << "<addTextToParagraph>" << dbg_out(rAddString)
2610 // << "</addTextToParagraph>" << ::std::endl;
2611 #endif
2613 if ((pNd->GetTxt().Len() + rAddString.Len()) < STRING_MAXLEN -1)
2615 rDoc.Insert (*pPaM, rAddString, true);
2617 else
2620 if (pNd->GetTxt().Len()< STRING_MAXLEN -1)
2622 String sTempStr (rAddString,0,
2623 STRING_MAXLEN - pNd->GetTxt().Len() -1);
2624 rDoc.Insert (*pPaM, sTempStr, true);
2625 sTempStr = rAddString.Copy(sTempStr.Len(),
2626 rAddString.Len() - sTempStr.Len());
2627 AppendTxtNode(*pPaM->GetPoint());
2628 rDoc.Insert (*pPaM,sTempStr, true );
2630 else
2632 AppendTxtNode(*pPaM->GetPoint());
2633 rDoc.Insert (*pPaM, rAddString, true);
2637 bReadTable = false;
2640 return true;
2643 // Returnwert: true for para end
2644 bool SwWW8ImplReader::ReadChars(WW8_CP& rPos, WW8_CP nNextAttr, long nTextEnd,
2645 long nCpOfs)
2647 long nEnd = ( nNextAttr < nTextEnd ) ? nNextAttr : nTextEnd;
2649 if (bSymbol || bIgnoreText)
2651 if( bSymbol ) // Spezialzeichen einfuegen
2653 for(USHORT nCh = 0; nCh < nEnd - rPos; ++nCh)
2654 rDoc.Insert( *pPaM, cSymbol );
2655 pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_FONT );
2657 pStrm->SeekRel( nEnd- rPos );
2658 rPos = nEnd; // ignoriere bis Attributende
2659 return false;
2662 while (true)
2664 if (ReadPlainChars(rPos, nEnd, nCpOfs))
2665 return false; // Fertig
2667 bool bStartLine = ReadChar(rPos, nCpOfs);
2668 rPos++;
2669 if (bPgSecBreak || bStartLine || rPos == nEnd) // CR oder Fertig
2671 return bStartLine;
2676 bool SwWW8ImplReader::HandlePageBreakChar()
2678 bool bParaEndAdded = false;
2679 //#i1909# section/page breaks should not occur in tables, word
2680 //itself ignores them in this case.
2681 if (!nInTable)
2683 bPgSecBreak = true;
2684 pCtrlStck->KillUnlockedAttrs(*pPaM->GetPoint());
2686 #74468#
2687 If its a 0x0c without a paragraph end before it, act like a
2688 paragraph end, but nevertheless, numbering (and perhaps other
2689 similiar constructs) do not exist on the para.
2691 if (!bWasParaEnd)
2693 bParaEndAdded = true;
2694 if (0 >= pPaM->GetPoint()->nContent.GetIndex())
2696 if (SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode())
2698 pTxtNode->SetAttr(
2699 *GetDfltAttr(RES_PARATR_NUMRULE));
2704 return bParaEndAdded;
2707 bool SwWW8ImplReader::ReadChar(long nPosCp, long nCpOfs)
2709 bool bNewParaEnd = false;
2710 // Unicode-Flag neu setzen und notfalls File-Pos korrigieren
2711 // merke: Seek kostet nicht viel, da inline geprueft wird,
2712 // ob die korrekte FilePos nicht schon erreicht ist.
2713 pStrm->Seek( pSBase->WW8Cp2Fc(nCpOfs+nPosCp, &bIsUnicode) );
2715 BYTE nBCode;
2716 UINT16 nWCharVal;
2717 if( bIsUnicode )
2718 *pStrm >> nWCharVal; // unicode --> read 2 bytes
2719 else
2721 *pStrm >> nBCode; // old code --> read 1 byte
2722 nWCharVal = nBCode;
2725 sal_Char cInsert = '\x0';
2726 bool bRet = false;
2727 switch (nWCharVal)
2729 case 0:
2731 // Seitennummer
2732 SwPageNumberField aFld(
2733 (SwPageNumberFieldType*)rDoc.GetSysFldType(
2734 RES_PAGENUMBERFLD ), PG_RANDOM, SVX_NUM_ARABIC);
2735 rDoc.Insert(*pPaM, SwFmtFld(aFld), 0);
2737 break;
2738 case 0xe:
2739 //#108817# if there is only one column word treats a column
2740 //break like a pagebreak.
2741 if (maSectionManager.CurrentSectionColCount() < 2)
2742 bRet = HandlePageBreakChar();
2743 else if (!nInTable)
2745 // Always insert a txtnode for a column break, e.g. ##
2746 SwCntntNode *pCntNd=pPaM->GetCntntNode();
2747 if (pCntNd!=NULL && pCntNd->Len()>0) // if par is empty not break is needed
2748 AppendTxtNode(*pPaM->GetPoint());
2749 rDoc.Insert(*pPaM, SvxFmtBreakItem(SVX_BREAK_COLUMN_BEFORE, RES_BREAK), 0);
2751 break;
2752 case 0x7:
2753 bNewParaEnd = true;
2754 TabCellEnd(); // table cell end (Flags abfragen!)
2755 break;
2756 case 0xf:
2757 if( !bSpec ) // "Satellit"
2758 cInsert = '\xa4';
2759 break;
2760 case 0x14:
2761 if( !bSpec ) // "Para-Ende"-Zeichen
2762 cInsert = '\xb5';
2763 break;
2764 case 0x15:
2765 if( !bSpec ) // Juristenparagraph
2766 cInsert = '\xa7';
2767 break;
2768 case 0x9:
2769 cInsert = '\x9'; // Tab
2770 break;
2771 case 0xb:
2772 cInsert = '\xa'; // Hard NewLine
2773 break;
2774 case 0xc:
2775 bRet = HandlePageBreakChar();
2776 break;
2777 case 0x1e:
2778 rDoc.Insert( *pPaM, CHAR_HARDHYPHEN); // Non-breaking hyphen
2779 break;
2780 case 0x1f:
2781 rDoc.Insert( *pPaM, CHAR_SOFTHYPHEN); // Non-required hyphens
2782 break;
2783 case 0xa0:
2784 rDoc.Insert( *pPaM, CHAR_HARDBLANK); // Non-breaking spaces
2785 break;
2786 case 0x1:
2788 Current thinking is that if bObj is set then we have a
2789 straightforward "traditional" ole object, otherwise we have a
2790 graphic preview of an associated ole2 object (or a simple
2791 graphic of course)
2793 if (!IsInlineEscherHack())
2795 SwFrmFmt *pResult = 0;
2796 if (bObj)
2797 pResult = ImportOle();
2798 else if (bSpec)
2799 pResult = ImportGraf();
2801 //#102160# If we have a bad 0x1 insert a space instead.
2802 if (!pResult)
2804 cInsert = ' ';
2805 ASSERT(!bObj && !bEmbeddObj && !nObjLocFc,
2806 "WW8: Please report this document, it may have a "
2807 "missing graphic");
2809 else
2811 // reset the flags.
2812 bObj = bEmbeddObj = false;
2813 nObjLocFc = 0;
2816 break;
2817 case 0x8:
2818 if( !bObj )
2819 Read_GrafLayer( nPosCp );
2820 break;
2821 case 0xd:
2822 bNewParaEnd = bRet = true;
2823 if (nInTable > 1)
2826 #i9666#/#i23161#
2827 Yes complex, if there is an entry in the undocumented PLCF
2828 which I believe to be a record of cell and row boundaries
2829 see if the magic bit which I believe to mean cell end is
2830 set. I also think btw that the third byte of the 4 byte
2831 value is the level of the cell
2833 WW8PLCFspecial* pTest = pPlcxMan->GetMagicTables();
2834 if (pTest && pTest->SeekPosExact(nPosCp+1+nCpOfs) &&
2835 pTest->Where() == nPosCp+1+nCpOfs)
2837 WW8_FC nPos;
2838 void *pData;
2839 pTest->Get(nPos, pData);
2840 sal_uInt32 nData = SVBT32ToUInt32(*(SVBT32*)pData);
2841 if (nData & 0x2) //Might be how it works
2843 TabCellEnd();
2844 bRet = false;
2847 else if (bWasTabCellEnd)
2849 TabCellEnd();
2850 bRet = false;
2854 bWasTabCellEnd = false;
2856 break; // line end
2857 case 0x5: // Annotation reference
2858 case 0x13:
2859 break;
2860 case 0x2:
2861 if (!maFtnStack.empty())
2862 cInsert = 0x2;
2863 break; // Auto-Fussnoten-Nummer
2864 #if OSL_DEBUG_LEVEL > 1
2865 default:
2866 ::std::clog << "<unknownValue val=\"" << nWCharVal << "\">" << ::std::endl;
2867 break;
2868 #endif
2871 if( '\x0' != cInsert )
2873 String sInsert = ByteString::ConvertToUnicode(cInsert,
2874 RTL_TEXTENCODING_MS_1252 );
2875 AddTextToParagraph(sInsert);
2877 if (!maApos.back()) //a para end in apo doesn't count
2878 bWasParaEnd = bNewParaEnd;
2879 return bRet;
2882 void SwWW8ImplReader::ProcessAktCollChange(WW8PLCFManResult& rRes,
2883 bool* pStartAttr, bool bCallProcessSpecial)
2885 USHORT nOldColl = nAktColl;
2886 nAktColl = pPlcxMan->GetColl();
2888 // Invalid Style-Id
2889 if (nAktColl >= nColls || !pCollA[nAktColl].pFmt || !pCollA[nAktColl].bColl)
2891 nAktColl = 0;
2892 bParaAutoBefore = false;
2893 bParaAutoAfter = false;
2895 else
2897 bParaAutoBefore = pCollA[nAktColl].bParaAutoBefore;
2898 bParaAutoAfter = pCollA[nAktColl].bParaAutoAfter;
2901 bool bTabRowEnd = false;
2902 if( pStartAttr && bCallProcessSpecial && !bInHyperlink )
2904 bool bReSync;
2905 // Frame / Table / Autonumbering List Level
2906 bTabRowEnd = ProcessSpecial(bReSync, rRes.nAktCp+pPlcxMan->GetCpOfs());
2907 if( bReSync )
2908 *pStartAttr = pPlcxMan->Get( &rRes ); // hole Attribut-Pos neu
2911 if (!bTabRowEnd && StyleExists(nAktColl))
2913 SetTxtFmtCollAndListLevel( *pPaM, pCollA[ nAktColl ]);
2914 ChkToggleAttr(pCollA[ nOldColl ].n81Flags, pCollA[ nAktColl ].n81Flags);
2915 ChkToggleBiDiAttr(pCollA[nOldColl].n81BiDiFlags,
2916 pCollA[nAktColl].n81BiDiFlags);
2920 long SwWW8ImplReader::ReadTextAttr(WW8_CP& rTxtPos, bool& rbStartLine)
2922 long nSkipChars = 0;
2923 WW8PLCFManResult aRes;
2925 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
2926 bool bStartAttr = pPlcxMan->Get(&aRes); // hole Attribut-Pos
2927 aRes.nAktCp = rTxtPos; // Akt. Cp-Pos
2929 bool bNewSection = (aRes.nFlags & MAN_MASK_NEW_SEP) && !bIgnoreText;
2930 if ( bNewSection ) // neue Section
2932 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
2933 // PageDesc erzeugen und fuellen
2934 maSectionManager.CreateSep(rTxtPos, bPgSecBreak);
2935 // -> 0xc war ein Sectionbreak, aber
2936 // kein Pagebreak;
2937 bPgSecBreak = false; // PageDesc erzeugen und fuellen
2938 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
2941 // neuer Absatz ueber Plcx.Fkp.papx
2942 if ( (aRes.nFlags & MAN_MASK_NEW_PAP)|| rbStartLine )
2944 ProcessAktCollChange( aRes, &bStartAttr,
2945 MAN_MASK_NEW_PAP == (aRes.nFlags & MAN_MASK_NEW_PAP) &&
2946 !bIgnoreText );
2947 rbStartLine = false;
2950 // position of last CP that's to be ignored
2951 long nSkipPos = -1;
2953 if( 0 < aRes.nSprmId ) // leere Attrs ignorieren
2955 if( ( eFTN > aRes.nSprmId ) || ( 0x0800 <= aRes.nSprmId ) )
2957 if( bStartAttr ) // WW-Attribute
2959 if( aRes.nMemLen >= 0 )
2960 ImportSprm(aRes.pMemPos, aRes.nSprmId);
2962 else
2963 EndSprm( aRes.nSprmId ); // Attr ausschalten
2965 else if( aRes.nSprmId < 0x800 ) // eigene Hilfs-Attribute
2967 if (bStartAttr)
2969 nSkipChars = ImportExtSprm(&aRes);
2970 if (
2971 (aRes.nSprmId == eFTN) || (aRes.nSprmId == eEDN) ||
2972 (aRes.nSprmId == eFLD) || (aRes.nSprmId == eAND)
2975 // Felder/Ftn-/End-Note hier ueberlesen
2976 rTxtPos += nSkipChars;
2977 nSkipPos = rTxtPos-1;
2980 else
2981 EndExtSprm( aRes.nSprmId );
2985 pStrm->Seek(pSBase->WW8Cp2Fc( pPlcxMan->GetCpOfs() + rTxtPos, &bIsUnicode));
2987 // Find next Attr position (and Skip attributes of field contents if needed)
2988 if (nSkipChars && !bIgnoreText)
2989 pCtrlStck->MarkAllAttrsOld();
2990 bool bOldIgnoreText = bIgnoreText;
2991 bIgnoreText = true;
2992 USHORT nOldColl = nAktColl;
2993 bool bDoPlcxManPlusPLus = true;
2994 long nNext;
2997 if( bDoPlcxManPlusPLus )
2998 (*pPlcxMan)++;
2999 nNext = pPlcxMan->Where();
3001 if (mpPostProcessAttrsInfo &&
3002 mpPostProcessAttrsInfo->mnCpStart == nNext)
3004 mpPostProcessAttrsInfo->mbCopy = true;
3007 if( (0 <= nNext) && (nSkipPos >= nNext) )
3009 nNext = ReadTextAttr( rTxtPos, rbStartLine );
3010 bDoPlcxManPlusPLus = false;
3011 bIgnoreText = true;
3014 if (mpPostProcessAttrsInfo &&
3015 nNext > mpPostProcessAttrsInfo->mnCpEnd)
3017 mpPostProcessAttrsInfo->mbCopy = false;
3020 while( nSkipPos >= nNext );
3021 bIgnoreText = bOldIgnoreText;
3022 if( nSkipChars )
3024 pCtrlStck->KillUnlockedAttrs( *pPaM->GetPoint() );
3025 if( nOldColl != pPlcxMan->GetColl() )
3026 ProcessAktCollChange(aRes, 0, false);
3029 return nNext;
3032 void SwWW8ImplReader::ReadAttrs(WW8_CP& rNext, WW8_CP& rTxtPos, bool& rbStartLine)
3034 if( rTxtPos >= rNext )
3035 { // Stehen Attribute an ?
3039 rNext = ReadTextAttr( rTxtPos, rbStartLine );
3041 while( rTxtPos >= rNext );
3044 else if ( rbStartLine )
3046 // keine Attribute, aber trotzdem neue Zeile
3047 // wenn eine Zeile mit einem Seitenumbruch aufhoert und sich keine
3048 // Absatzattribute / Absatzvorlagen aendern, ist das Zeilenende
3049 // nicht im Plcx.Fkp.papx eingetragen, d.h. ( nFlags & MAN_MASK_NEW_PAP )
3050 // ist false. Deshalb muss als Sonderbehandlung hier die Vorlage gesetzt
3051 // werden.
3052 if (!bCpxStyle && nAktColl < nColls)
3053 SetTxtFmtCollAndListLevel(*pPaM, pCollA[nAktColl]);
3054 rbStartLine = false;
3058 // CloseAttrEnds zum Lesen nur der Attributenden am Ende eines Textes oder
3059 // Textbereiches ( Kopfzeile, Fussnote, ...). Attributanfaenge, Felder
3060 // werden ignoriert.
3061 void SwWW8ImplReader::CloseAttrEnds()
3063 //If there are any unclosed sprms then copy them to
3064 //another stack and close the ones that must be closed
3065 std::stack<USHORT> aStack;
3066 pPlcxMan->TransferOpenSprms(aStack);
3068 while (!aStack.empty())
3070 USHORT nSprmId = aStack.top();
3071 if ((0 < nSprmId) && (( eFTN > nSprmId) || (0x0800 <= nSprmId)))
3072 EndSprm(nSprmId);
3073 aStack.pop();
3076 EndSpecial();
3079 bool SwWW8ImplReader::ReadText(long nStartCp, long nTextLen, ManTypes nType)
3081 sw::log::Environment eContext = sw::log::eMainText;
3082 if (nType == MAN_MAINTEXT)
3083 eContext = sw::log::eMainText;
3084 else
3085 eContext = sw::log::eSubDoc;
3086 maTracer.EnterEnvironment(eContext);
3088 bool bJoined=false;
3090 bool bStartLine = true;
3091 short nCrCount = 0;
3092 short nDistance = 0;
3094 bWasParaEnd = false;
3095 nAktColl = 0;
3096 pAktItemSet = 0;
3097 nCharFmt = -1;
3098 bSpec = false;
3099 bPgSecBreak = false;
3101 pPlcxMan = new WW8PLCFMan( pSBase, nType, nStartCp );
3102 long nCpOfs = pPlcxMan->GetCpOfs(); // Offset fuer Header/Footer, Footnote
3104 WW8_CP nNext = pPlcxMan->Where();
3105 SwTxtNode* pPreviousNode = 0;
3106 BYTE nDropLines = 0;
3107 SwCharFmt* pNewSwCharFmt = 0;
3108 const SwCharFmt* pFmt = 0;
3109 pStrm->Seek( pSBase->WW8Cp2Fc( nStartCp + nCpOfs, &bIsUnicode ) );
3111 WW8_CP l = nStartCp;
3112 while ( l<nStartCp+nTextLen )
3114 ReadAttrs( nNext, l, bStartLine );// behandelt auch Section-Breaks
3115 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
3117 if (mpPostProcessAttrsInfo != NULL)
3118 PostProcessAttrs();
3120 if( l>= nStartCp + nTextLen )
3121 break;
3123 bStartLine = ReadChars(l, nNext, nStartCp+nTextLen, nCpOfs);
3125 // If the previous paragraph was a dropcap then do not
3126 // create a new txtnode and join the two paragraphs together
3128 if (bStartLine && !pPreviousNode) // Zeilenende
3129 AppendTxtNode(*pPaM->GetPoint());
3131 if (pPreviousNode && bStartLine)
3133 SwTxtNode* pEndNd = pPaM->GetNode()->GetTxtNode();
3134 const xub_StrLen nDropCapLen = pPreviousNode->GetTxt().Len();
3136 // Need to reset the font size and text position for the dropcap
3138 SwPaM aTmp(*pEndNd, 0, *pEndNd, nDropCapLen+1);
3139 pCtrlStck->Delete(aTmp);
3142 // Get the default document dropcap which we can use as our template
3143 const SwFmtDrop* defaultDrop =
3144 (const SwFmtDrop*) GetFmtAttr(RES_PARATR_DROP);
3145 SwFmtDrop aDrop(*defaultDrop);
3147 aDrop.GetLines() = nDropLines;
3148 aDrop.GetDistance() = nDistance;
3149 aDrop.GetChars() = writer_cast<BYTE>(nDropCapLen);
3150 // Word has no concept of a "whole word dropcap"
3151 aDrop.GetWholeWord() = false;
3153 if (pFmt)
3154 aDrop.SetCharFmt(const_cast<SwCharFmt*>(pFmt));
3155 else if(pNewSwCharFmt)
3156 aDrop.SetCharFmt(const_cast<SwCharFmt*>(pNewSwCharFmt));
3158 SwPosition aStart(*pEndNd);
3159 pCtrlStck->NewAttr(aStart, aDrop);
3160 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_DROP);
3161 pPreviousNode = 0;
3163 else if (bDropCap)
3165 // If we have found a dropcap store the textnode
3166 pPreviousNode = pPaM->GetNode()->GetTxtNode();
3168 const BYTE *pDCS;
3170 if (bVer67)
3171 pDCS = pPlcxMan->GetPapPLCF()->HasSprm(46);
3172 else
3173 pDCS = pPlcxMan->GetPapPLCF()->HasSprm(0x442C);
3175 if (pDCS)
3176 nDropLines = (*pDCS) >> 3;
3177 else // There is no Drop Cap Specifier hence no dropcap
3178 pPreviousNode = 0;
3180 if (const BYTE *pDistance = pPlcxMan->GetPapPLCF()->HasSprm(0x842F))
3181 nDistance = SVBT16ToShort( pDistance );
3182 else
3183 nDistance = 0;
3185 const SwFmtCharFmt *pSwFmtCharFmt = 0;
3187 if(pAktItemSet)
3188 pSwFmtCharFmt = &(ItemGet<SwFmtCharFmt>(*pAktItemSet, RES_TXTATR_CHARFMT));
3190 if(pSwFmtCharFmt)
3191 pFmt = pSwFmtCharFmt->GetCharFmt();
3193 if(pAktItemSet && !pFmt)
3195 String sPrefix(CREATE_CONST_ASC( "WW8Dropcap"));
3196 sPrefix += String::CreateFromInt32( nDropCap++ );
3197 pNewSwCharFmt = rDoc.MakeCharFmt(sPrefix, (SwCharFmt*)rDoc.GetDfltCharFmt());
3198 pAktItemSet->ClearItem(RES_CHRATR_ESCAPEMENT);
3199 pNewSwCharFmt->SetFmtAttr( *pAktItemSet );
3202 delete pAktItemSet;
3203 pAktItemSet = 0;
3204 bDropCap=false;
3207 if (bStartLine || bWasTabRowEnd)
3209 // alle 64 CRs aufrufen not for Header u. ae.
3210 if ((nCrCount++ & 0x40) == 0 && nType == MAN_MAINTEXT)
3212 nProgress = (USHORT)( l * 100 / nTextLen );
3213 ::SetProgressState(nProgress, mpDocShell); // Update
3217 // If we have encountered a 0x0c which indicates either section of
3218 // pagebreak then look it up to see if it is a section break, and
3219 // if it is not then insert a page break. If it is a section break
3220 // it will be handled as such in the ReadAttrs of the next loop
3221 if (bPgSecBreak)
3223 // We need only to see if a section is ending at this cp,
3224 // the plcf will already be sitting on the correct location
3225 // if it is there.
3226 WW8PLCFxDesc aTemp;
3227 aTemp.nStartPos = aTemp.nEndPos = WW8_CP_MAX;
3228 if (pPlcxMan->GetSepPLCF())
3229 pPlcxMan->GetSepPLCF()->GetSprms(&aTemp);
3230 if ((aTemp.nStartPos != l) && (aTemp.nEndPos != l))
3232 // --> OD 2005-01-07 #i39251# - insert text node for page break,
3233 // if no one inserted.
3234 // --> OD 2005-02-28 #i43118# - refine condition: the anchor
3235 // control stack has to have entries, otherwise it's not needed
3236 // to insert a text node.
3237 if ( !bStartLine && pAnchorStck->Count() > 0 )
3239 AppendTxtNode(*pPaM->GetPoint());
3241 // <--
3242 rDoc.Insert(*pPaM, SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK), 0);
3243 bPgSecBreak = false;
3248 if (pPaM->GetPoint()->nContent.GetIndex())
3249 AppendTxtNode(*pPaM->GetPoint());
3251 if (!bInHyperlink)
3252 bJoined = JoinNode(*pPaM);
3254 CloseAttrEnds();
3256 delete pPlcxMan, pPlcxMan = 0;
3257 maTracer.LeaveEnvironment(eContext);
3258 return bJoined;
3261 /***************************************************************************
3262 # class SwWW8ImplReader
3263 #**************************************************************************/
3265 SwWW8ImplReader::SwWW8ImplReader(BYTE nVersionPara, SvStorage* pStorage,
3266 SvStream* pSt, SwDoc& rD, const String& rBaseURL, bool bNewDoc) :
3267 mpDocShell(rD.GetDocShell()),
3268 maTracer(*(mpDocShell->GetMedium())),
3269 pStg(pStorage),
3270 pStrm(pSt),
3271 pTableStream(0),
3272 pDataStream(0),
3273 rDoc(rD),
3274 maSectionManager(*this),
3275 maInsertedTables(rD),
3276 maSectionNameGenerator(rD,CREATE_CONST_ASC("WW")),
3277 maGrfNameGenerator(bNewDoc,String('G')),
3278 maParaStyleMapper(rD),
3279 maCharStyleMapper(rD),
3280 pMSDffManager(0),
3281 mpAtnNames(0),
3282 pAuthorInfos(0),
3283 sBaseURL(rBaseURL),
3284 m_bRegardHindiDigits( false ),
3285 mbNewDoc(bNewDoc),
3286 nDropCap(0),
3287 nIdctHint(0),
3288 bBidi(false),
3289 bReadTable(false)
3291 pStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
3292 nWantedVersion = nVersionPara;
3293 pCtrlStck = 0;
3294 mpRedlineStack = 0;
3295 pReffedStck = 0;
3296 pReffingStck = 0;
3297 pAnchorStck = 0;
3298 pFonts = 0;
3299 pSBase = 0;
3300 pPlcxMan = 0;
3301 pStyles = 0;
3302 pAktColl = 0;
3303 pLstManager = 0;
3304 pAktItemSet = 0;
3305 pCollA = 0;
3306 pDfltTxtFmtColl = 0;
3307 pStandardFmtColl = 0;
3308 pHdFt = 0;
3309 pWFlyPara = 0;
3310 pSFlyPara = 0;
3311 pFlyFmtOfJustInsertedGraphic = 0;
3312 pFmtOfJustInsertedApo = 0;
3313 pPreviousNumPaM = 0;
3314 pPrevNumRule = 0;
3315 nColls = nAktColl = 0;
3316 nObjLocFc = nPicLocFc = 0;
3317 nInTable=0;
3318 bReadNoTbl = bPgSecBreak = bSpec = bObj = bTxbxFlySection
3319 = bHasBorder = bSymbol = bIgnoreText
3320 = bWasTabRowEnd = bWasTabCellEnd = false;
3321 bShdTxtCol = bCharShdTxtCol = bAnl = bHdFtFtnEdn = bFtnEdn
3322 = bIsHeader = bIsFooter = bIsUnicode = bCpxStyle = bStyNormal =
3323 bWWBugNormal = false;
3325 mpPostProcessAttrsInfo = 0;
3327 bNoAttrImport = bPgChpLevel = bEmbeddObj = false;
3328 bAktAND_fNumberAcross = false;
3329 bNoLnNumYet = true;
3330 bInHyperlink = false;
3331 bWasParaEnd = false;
3332 bDropCap = false;
3333 bFirstPara = true;
3334 bParaAutoBefore = false;
3335 bParaAutoAfter = false;
3336 nProgress = 0;
3337 nSwNumLevel = nWwNumType = 0xff;
3338 pTableDesc = 0;
3339 pNumOlst = 0;
3340 pNode_FLY_AT_CNTNT = 0;
3341 pDrawModel = 0;
3342 pDrawPg = 0;
3343 mpDrawEditEngine = 0;
3344 pWWZOrder = 0;
3345 pFormImpl = 0;
3346 mpChosenOutlineNumRule = 0;
3347 pNumFldType = 0;
3348 nFldNum = 0;
3350 nLFOPosition = USHRT_MAX;
3351 nListLevel = WW8ListManager::nMaxLevel;
3352 eHardCharSet = RTL_TEXTENCODING_DONTKNOW;
3354 nPgChpDelim = nPgChpLevel = 0;
3356 maApos.push_back(false);
3359 void SwWW8ImplReader::DeleteStk(SwFltControlStack* pStck)
3361 if( pStck )
3363 pStck->SetAttr( *pPaM->GetPoint(), 0, false);
3364 pStck->SetAttr( *pPaM->GetPoint(), 0, false);
3365 delete pStck;
3367 else
3369 ASSERT( !this, "WW-Stack bereits geloescht" );
3373 void wwSectionManager::SetSegmentToPageDesc(const wwSection &rSection,
3374 bool bTitlePage, bool bIgnoreCols)
3376 SwPageDesc &rPage = bTitlePage ? *rSection.mpTitlePage : *rSection.mpPage;
3378 SetNumberingType(rSection, rPage);
3380 SwFrmFmt &rFmt = rPage.GetMaster();
3382 if (mrReader.pWDop->fUseBackGroundInAllmodes && mrReader.pMSDffManager)
3384 Rectangle aRect(0, 0, 100, 100); //A dummy, we don't care about the size
3385 SvxMSDffImportData aData(aRect);
3386 SdrObject* pObject = 0;
3387 if (mrReader.pMSDffManager->GetShape(0x401, pObject, aData))
3389 SvxMSDffImportRec * pRec = aData.GetRecord(0);
3391 // Only handle shape if it is a background shape
3392 if ((pRec->nFlags & 0x400) != 0)
3394 SfxItemSet aSet(rFmt.GetAttrSet());
3395 mrReader.MatchSdrItemsIntoFlySet(pObject, aSet, mso_lineSimple,
3396 mso_sptRectangle, aRect);
3397 rFmt.SetFmtAttr(aSet.Get(RES_BACKGROUND));
3401 wwULSpaceData aULData;
3402 GetPageULData(rSection, bTitlePage, aULData);
3403 SetPageULSpaceItems(rFmt, aULData, rSection);
3405 SetPage(rPage, rFmt, rSection, bIgnoreCols);
3407 bool bSetBorder = false;
3408 switch (rSection.maSep.pgbApplyTo)
3410 case 0:
3411 case 3:
3412 bSetBorder = true;
3413 break;
3414 case 1:
3415 bSetBorder = bTitlePage;
3416 break;
3417 case 2:
3418 bSetBorder = !bTitlePage;
3419 break;
3421 if (bSetBorder)
3422 mrReader.SetPageBorder(rFmt, rSection);
3424 mrReader.SetDocumentGrid(rFmt, rSection);
3427 void wwSectionManager::SetUseOn(wwSection &rSection)
3429 bool bEven = (rSection.maSep.grpfIhdt & (WW8_HEADER_EVEN|WW8_FOOTER_EVEN)) ?
3430 true : false;
3432 bool bMirror = mrReader.pWDop->fMirrorMargins ||
3433 mrReader.pWDop->doptypography.f2on1;
3435 UseOnPage eUseBase = bMirror ? nsUseOnPage::PD_MIRROR : nsUseOnPage::PD_ALL;
3436 UseOnPage eUse = eUseBase;
3437 if (!bEven)
3438 eUse = (UseOnPage)(eUse | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE);
3440 ASSERT(rSection.mpPage, "Makes no sense to call me with no pages to set");
3441 if (rSection.mpPage)
3442 rSection.mpPage->WriteUseOn(eUse);
3443 if (rSection.mpTitlePage)
3445 rSection.mpTitlePage->WriteUseOn(
3446 (UseOnPage) (eUseBase | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE));
3450 //Set the page descriptor on this node, handle the different cases for a text
3451 //node or a table
3452 void GiveNodePageDesc(SwNodeIndex &rIdx, const SwFmtPageDesc &rPgDesc,
3453 SwDoc &rDoc)
3456 If its a table here, apply the pagebreak to the table
3457 properties, otherwise we add it to the para at this
3458 position
3460 if (rIdx.GetNode().IsTableNode())
3462 SwTable& rTable =
3463 rIdx.GetNode().GetTableNode()->GetTable();
3464 SwFrmFmt* pApply = rTable.GetFrmFmt();
3465 ASSERT(pApply, "impossible");
3466 if (pApply)
3467 pApply->SetFmtAttr(rPgDesc);
3469 else
3471 SwPosition aPamStart(rIdx);
3472 aPamStart.nContent.Assign(
3473 rIdx.GetNode().GetCntntNode(), 0);
3474 SwPaM aPage(aPamStart);
3476 rDoc.Insert(aPage, rPgDesc, 0);
3480 //Map a word section with to either one or two writer page descriptors
3481 //depending on if the word section has a title page
3482 SwFmtPageDesc wwSectionManager::SetSwFmtPageDesc(mySegIter &rIter,
3483 mySegIter &rStart, bool bIgnoreCols)
3485 SwFmtPageDesc aEmpty;
3486 // --> OD 2008-08-06 #150965#
3487 // Always read title page header/footer data - it could be used by following sections
3488 // if (rIter->HasTitlePage())
3489 // <--
3491 if (IsNewDoc() && rIter == rStart)
3493 rIter->mpTitlePage =
3494 mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_FIRST);
3496 else
3498 USHORT nPos = mrReader.rDoc.MakePageDesc(
3499 ViewShell::GetShellRes()->GetPageDescName(mnDesc)
3500 , 0, false);
3501 rIter->mpTitlePage = &mrReader.rDoc._GetPageDesc(nPos);
3503 ASSERT(rIter->mpTitlePage, "no page!");
3504 if (!rIter->mpTitlePage)
3505 return aEmpty;
3507 SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
3510 if (IsNewDoc() && rIter == rStart)
3512 rIter->mpPage =
3513 mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_STANDARD);
3515 else
3517 USHORT nPos = mrReader.rDoc.MakePageDesc(
3518 ViewShell::GetShellRes()->GetPageDescName(mnDesc,
3519 false, rIter->HasTitlePage()),
3520 rIter->mpTitlePage, false);
3521 rIter->mpPage = &mrReader.rDoc._GetPageDesc(nPos);
3523 ASSERT(rIter->mpPage, "no page!");
3524 if (!rIter->mpPage)
3525 return aEmpty;
3527 //Set page before hd/ft
3528 const wwSection *pPrevious = 0;
3529 if (rIter != rStart)
3530 pPrevious = &(*(rIter-1));
3531 SetHdFt(*rIter, std::distance(rStart, rIter), pPrevious);
3532 SetUseOn(*rIter);
3534 //Set hd/ft after set page
3535 if (rIter->mpTitlePage)
3536 SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
3537 SetSegmentToPageDesc(*rIter, false, bIgnoreCols);
3539 SwFmtPageDesc aRet(rIter->HasTitlePage() ?
3540 rIter->mpTitlePage : rIter->mpPage);
3542 rIter->mpPage->SetFollow(rIter->mpPage);
3544 if (rIter->mpTitlePage)
3545 rIter->mpTitlePage->SetFollow(rIter->mpPage);
3547 if (rIter->PageRestartNo())
3548 aRet.SetNumOffset(rIter->PageStartAt());
3550 ++mnDesc;
3551 return aRet;
3554 bool wwSectionManager::IsNewDoc() const
3556 return mrReader.mbNewDoc;
3559 void wwSectionManager::InsertSegments()
3561 const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
3562 sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
3563 mySegIter aEnd = maSegments.end();
3564 mySegIter aStart = maSegments.begin();
3565 for (mySegIter aIter = aStart; aIter != aEnd; ++aIter)
3567 mySegIter aNext = aIter+1;
3568 mySegIter aPrev = (aIter == aStart) ? aIter : aIter-1;
3570 // If two following sections are different in following properties, Word will interprete a continuous
3571 // section break between them as if it was a section break next page.
3572 bool bThisAndPreviousAreCompatible = ((aIter->GetPageWidth() == aPrev->GetPageWidth()) &&
3573 (aIter->GetPageHeight() == aPrev->GetPageHeight()) && (aIter->IsLandScape() == aPrev->IsLandScape()));
3575 bool bInsertSection = (aIter != aStart) ? (aIter->IsContinous() && bThisAndPreviousAreCompatible): false;
3576 bool bInsertPageDesc = !bInsertSection;
3577 bool bProtected = SectionIsProtected(*aIter); // do we really need this ?? I guess I have a different logic in editshell which disales this...
3578 if (bUseEnhFields && mrReader.pWDop->fProtEnabled && aIter->IsNotProtected()) {
3579 // here we have the special case that the whole document is protected, with the execption of this section.
3580 // I want to address this when I do the section rework, so for the moment we disable the overall protection then...
3581 mrReader.rDoc.set(IDocumentSettingAccess::PROTECT_FORM, false );
3585 if (bInsertPageDesc)
3588 If a cont section follows this section then we won't be
3589 creating a page desc with 2+ cols as we cannot host a one
3590 col section in a 2+ col pagedesc and make it look like
3591 word. But if the current section actually has columns then
3592 we are forced to insert a section here as well as a page
3593 descriptor.
3596 bool bIgnoreCols = false;
3597 bool bThisAndNextAreCompatible = (aNext != aEnd) ? ((aIter->GetPageWidth() == aNext->GetPageWidth()) &&
3598 (aIter->GetPageHeight() == aNext->GetPageHeight()) && (aIter->IsLandScape() == aNext->IsLandScape())) : true;
3600 if ((aNext != aEnd && aNext->IsContinous() && bThisAndNextAreCompatible) || bProtected)
3602 bIgnoreCols = true;
3603 if ((aIter->NoCols() > 1) || bProtected)
3604 bInsertSection = true;
3607 SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, bIgnoreCols));
3608 if (!aDesc.GetPageDesc())
3609 continue;
3610 GiveNodePageDesc(aIter->maStart, aDesc, mrReader.rDoc);
3613 SwTxtNode* pTxtNd = 0;
3614 if (bInsertSection)
3616 //Start getting the bounds of this section
3617 SwPaM aSectPaM(*mrReader.pPaM);
3618 SwNodeIndex aAnchor(aSectPaM.GetPoint()->nNode);
3619 if (aNext != aEnd)
3621 aAnchor = aNext->maStart;
3622 aSectPaM.GetPoint()->nNode = aAnchor;
3623 aSectPaM.GetPoint()->nContent.Assign(
3624 aNext->maStart.GetNode().GetCntntNode(), 0);
3625 aSectPaM.Move(fnMoveBackward);
3628 const SwPosition* pPos = aSectPaM.GetPoint();
3629 const SwTxtNode* pSttNd =
3630 mrReader.rDoc.GetNodes()[ pPos->nNode ]->GetTxtNode();
3631 const SwTableNode* pTableNd = pSttNd ? pSttNd->FindTableNode() : 0;
3632 if (pTableNd)
3634 pTxtNd =
3635 mrReader.rDoc.GetNodes().MakeTxtNode(aAnchor,
3636 mrReader.rDoc.GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
3638 aSectPaM.GetPoint()->nNode = SwNodeIndex(*pTxtNd);
3639 aSectPaM.GetPoint()->nContent.Assign(
3640 aSectPaM.GetCntntNode(), 0);
3643 aSectPaM.SetMark();
3645 aSectPaM.GetPoint()->nNode = aIter->maStart;
3646 aSectPaM.GetPoint()->nContent.Assign(
3647 aSectPaM.GetCntntNode(), 0);
3648 //End getting the bounds of this section, quite a job eh ?
3650 SwSectionFmt *pRet = InsertSection(aSectPaM, *aIter);
3651 //The last section if continous is always unbalanced
3652 if (pRet)
3654 //Set the columns to be UnBalanced if that compatability option
3655 //is set
3656 if (mrReader.pWDop->fNoColumnBalance)
3657 pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
3658 else
3660 //Otherwise set to unbalanced if the following section is
3661 //not continuous, (which also means that the last section
3662 //is unbalanced)
3663 if (aNext == aEnd || !aNext->IsContinous())
3664 pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
3668 bool bHasOwnHdFt = false;
3670 #112027# #110379#
3671 In this nightmare scenario the continuous section has its own
3672 headers and footers so we will try and find a hard page break
3673 between here and the end of the section and put the headers and
3674 footers there.
3676 if (!bInsertPageDesc)
3678 bHasOwnHdFt =
3679 mrReader.HasOwnHeaderFooter(
3680 aIter->maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST),
3681 aIter->maSep.grpfIhdt, std::distance(aStart, aIter)
3684 if (bHasOwnHdFt)
3686 // #i40766# Need to cache the page descriptor in case there is
3687 // no page break in the section
3688 SwPageDesc *pOrig = aIter->mpPage;
3689 SwPageDesc *pOrigTitle = aIter->mpTitlePage;
3690 bool bFailed = true;
3691 SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, true));
3692 if (aDesc.GetPageDesc())
3694 ULONG nStart = aSectPaM.Start()->nNode.GetIndex();
3695 ULONG nEnd = aSectPaM.End()->nNode.GetIndex();
3696 for(; nStart <= nEnd; ++nStart)
3698 SwNode* pNode = mrReader.rDoc.GetNodes()[nStart];
3699 if (!pNode)
3700 continue;
3701 if (sw::util::HasPageBreak(*pNode))
3703 SwNodeIndex aIdx(*pNode);
3704 GiveNodePageDesc(aIdx, aDesc, mrReader.rDoc);
3705 bFailed = false;
3706 break;
3710 if(bFailed)
3712 aIter->mpPage = pOrig;
3713 aIter->mpTitlePage = pOrigTitle;
3718 if (pTxtNd)
3720 SwNodeIndex aIdx(*pTxtNd);
3721 SwPosition aPos(aIdx);
3722 SwPaM aTest(aPos);
3723 mrReader.rDoc.DelFullPara(aTest);
3724 pTxtNd = 0;
3729 void SwWW8ImplReader::StoreMacroCmds()
3731 if (pWwFib->lcbCmds)
3733 maTracer.Log(sw::log::eContainsWordBasic);
3735 pTableStream->Seek(pWwFib->fcCmds);
3737 uno::Reference < embed::XStorage > xRoot(mpDocShell->GetStorage());
3740 uno::Reference < io::XStream > xStream =
3741 xRoot->openStreamElement( CREATE_CONST_ASC(SL::aMSMacroCmds), embed::ElementModes::READWRITE );
3742 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xStream );
3744 sal_uInt8 *pBuffer = new sal_uInt8[pWwFib->lcbCmds];
3745 pTableStream->Read(pBuffer, pWwFib->lcbCmds);
3746 pStream->Write(pBuffer, pWwFib->lcbCmds);
3747 delete[] pBuffer;
3748 delete pStream;
3750 catch ( uno::Exception& )
3756 void SwWW8ImplReader::ReadDocVars()
3758 std::vector<String> aDocVarStrings;
3759 std::vector<ww::bytes> aDocVarStringIds;
3760 std::vector<String> aDocValueStrings;
3761 WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcStwUser,
3762 pWwFib->lcbStwUser, bVer67 ? 2 : 0, eStructCharSet,
3763 aDocVarStrings, &aDocVarStringIds, &aDocValueStrings);
3764 if (!bVer67) {
3765 using namespace ::com::sun::star;
3767 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
3768 mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
3769 uno::Reference<document::XDocumentProperties> xDocProps(
3770 xDPS->getDocumentProperties());
3771 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
3772 uno::Reference<beans::XPropertyContainer> xUserDefinedProps =
3773 xDocProps->getUserDefinedProperties();
3774 DBG_ASSERT(xUserDefinedProps.is(), "UserDefinedProperties is null");
3776 for(size_t i=0; i<aDocVarStrings.size(); i++)
3778 uno::Any aDefaultValue;
3779 ::rtl::OUString name(aDocVarStrings[i]);
3780 uno::Any aValue;
3781 aValue <<= ::rtl::OUString(aDocValueStrings[i]);
3782 try {
3783 xUserDefinedProps->addProperty( name,
3784 beans::PropertyAttribute::REMOVEABLE,
3785 aValue );
3786 } catch (uno::Exception &) {
3787 // ignore
3793 //-----------------------------------------
3794 // Document Info
3795 //-----------------------------------------
3797 void SwWW8ImplReader::ReadDocInfo()
3799 if( pStg )
3801 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
3802 mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
3803 uno::Reference<document::XDocumentProperties> xDocProps(
3804 xDPS->getDocumentProperties());
3805 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
3807 if (xDocProps.is()) {
3808 if ( pWwFib->fDot )
3810 rtl::OUString sTemplateURL;
3811 SfxMedium* pMedium = mpDocShell->GetMedium();
3812 if ( pMedium )
3814 rtl::OUString aName = pMedium->GetName();
3815 INetURLObject aURL( aName );
3816 sTemplateURL = aURL.GetMainURL(INetURLObject::DECODE_TO_IURI);
3817 if ( sTemplateURL.getLength() > 0 )
3818 xDocProps->setTemplateURL( sTemplateURL );
3821 else // not a template
3823 long nCur = pTableStream->Tell();
3824 Sttb aSttb;
3825 pTableStream->Seek( pWwFib->fcSttbfAssoc ); // point at tgc record
3826 if (!aSttb.Read( pTableStream ) )
3827 OSL_TRACE("** Read of SttbAssoc data failed!!!! ");
3828 pTableStream->Seek( nCur ); // return to previous position, is that necessary?
3829 #if DEBUG
3830 aSttb.Print( stderr );
3831 #endif
3832 String sPath = aSttb.getStringAtIndex( 0x1 );
3833 String aURL;
3834 // attempt to convert to url ( won't work for obvious reasons on linux
3835 if ( sPath.Len() )
3836 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sPath, aURL );
3837 if ( aURL.Len() )
3838 xDocProps->setTemplateURL( aURL );
3839 else
3840 xDocProps->setTemplateURL( sPath );
3843 sfx2::LoadOlePropertySet(xDocProps, pStg);
3848 void lcl_createTemplateToProjectEntry( const uno::Reference< container::XNameContainer >& xPrjNameCache, const rtl::OUString& sTemplatePathOrURL, const rtl::OUString& sVBAProjName )
3850 if ( xPrjNameCache.is() )
3852 INetURLObject aObj;
3853 aObj.SetURL( sTemplatePathOrURL );
3854 bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
3855 rtl::OUString aURL;
3856 if ( bIsURL )
3857 aURL = sTemplatePathOrURL;
3858 else
3860 osl::FileBase::getFileURLFromSystemPath( sTemplatePathOrURL, aURL );
3861 aObj.SetURL( aURL );
3865 rtl::OUString templateNameWithExt = aObj.GetLastName();
3866 rtl::OUString templateName;
3867 sal_Int32 nIndex = templateNameWithExt.lastIndexOf( '.' );
3868 //xPrjNameCache->insertByName( templateNameWithExt, uno::makeAny( sVBAProjName ) );
3869 if ( nIndex != -1 )
3871 templateName = templateNameWithExt.copy( 0, nIndex );
3872 xPrjNameCache->insertByName( templateName, uno::makeAny( sVBAProjName ) );
3875 catch( uno::Exception& )
3881 class WW8Customizations
3883 SvStream* mpTableStream;
3884 WW8Fib mWw8Fib;
3885 public:
3886 WW8Customizations( SvStream*, WW8Fib& );
3887 bool Import( SwDocShell* pShell );
3890 WW8Customizations::WW8Customizations( SvStream* pTableStream, WW8Fib& rFib ) : mpTableStream(pTableStream), mWw8Fib( rFib )
3894 bool WW8Customizations::Import( SwDocShell* pShell )
3896 if ( mWw8Fib.lcbCmds == 0 )
3897 return false;
3898 Tcg aTCG;
3899 long nCur = mpTableStream->Tell();
3900 mpTableStream->Seek( mWw8Fib.fcCmds ); // point at tgc record
3901 if (!aTCG.Read( mpTableStream ) )
3902 OSL_TRACE("** Read of Customization data failed!!!! ");
3903 mpTableStream->Seek( nCur ); // return to previous position, is that necessary?
3904 #if DEBUG
3905 aTCG.Print( stderr );
3906 #endif
3907 return aTCG.ImportCustomToolBar( *pShell );
3910 bool SwWW8ImplReader::ReadGlobalTemplateSettings( const rtl::OUString& sCreatedFrom, const uno::Reference< container::XNameContainer >& xPrjNameCache )
3912 SvtPathOptions aPathOpt;
3913 String aAddinPath = aPathOpt.GetAddinPath();
3914 uno::Sequence< rtl::OUString > sGlobalTemplates;
3916 // first get the autoload addins in the directory STARTUP
3917 uno::Reference< ucb::XSimpleFileAccess > xSFA( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), uno::UNO_QUERY_THROW );
3919 if( xSFA->isFolder( aAddinPath ) )
3920 sGlobalTemplates = xSFA->getFolderContents( aAddinPath, sal_False );
3922 sal_Int32 nEntries = sGlobalTemplates.getLength();
3923 bool bRes = true;
3924 const SvtFilterOptions* pVBAFlags = SvtFilterOptions::Get();
3925 for ( sal_Int32 i=0; i<nEntries; ++i )
3927 INetURLObject aObj;
3928 aObj.SetURL( sGlobalTemplates[ i ] );
3929 bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
3930 rtl::OUString aURL;
3931 if ( bIsURL )
3932 aURL = sGlobalTemplates[ i ];
3933 else
3934 osl::FileBase::getFileURLFromSystemPath( sGlobalTemplates[ i ], aURL );
3935 if ( !aURL.endsWithIgnoreAsciiCaseAsciiL( ".dot", 4 ) || ( sCreatedFrom.getLength() && sCreatedFrom.equals( aURL ) ) )
3936 continue; // don't try and read the same document as ourselves
3938 SotStorageRef rRoot = new SotStorage( aURL, STREAM_STD_READWRITE, STORAGE_TRANSACTED );
3940 // Read Macro Projects
3941 SvxImportMSVBasic aVBasic(*mpDocShell, *rRoot,
3942 pVBAFlags->IsLoadWordBasicCode(),
3943 pVBAFlags->IsLoadWordBasicStorage() );
3946 String s1(CREATE_CONST_ASC("Macros"));
3947 String s2(CREATE_CONST_ASC("VBA"));
3948 int nRet = aVBasic.Import( s1, s2, ! pVBAFlags->IsLoadWordBasicCode() );
3949 lcl_createTemplateToProjectEntry( xPrjNameCache, aURL, aVBasic.GetVBAProjectName() );
3950 // Read toolbars & menus
3951 SvStorageStreamRef refMainStream = rRoot->OpenSotStream( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("WordDocument") ) );
3952 refMainStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
3953 WW8Fib aWwFib( *refMainStream, 8 );
3954 SvStorageStreamRef xTableStream = rRoot->OpenSotStream(String::CreateFromAscii( aWwFib.fWhichTblStm ? SL::a1Table : SL::a0Table), STREAM_STD_READ);
3956 if (xTableStream.Is() && SVSTREAM_OK == xTableStream->GetError())
3958 xTableStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
3959 WW8Customizations aGblCustomisations( xTableStream, aWwFib );
3960 aGblCustomisations.Import( mpDocShell );
3963 return bRes;
3966 ULONG SwWW8ImplReader::CoreLoad(WW8Glossary *pGloss, const SwPosition &rPos)
3968 ULONG nErrRet = 0;
3970 if (mbNewDoc && pStg && !pGloss)
3971 ReadDocInfo();
3973 pPaM = new SwPaM(rPos);
3975 pCtrlStck = new SwWW8FltControlStack( &rDoc, nFieldFlags, *this );
3977 mpRedlineStack = new sw::util::RedlineStack(rDoc);
3980 RefFldStck: Keeps track of bookmarks which may be inserted as
3981 variables intstead.
3983 pReffedStck = new SwFltEndStack(&rDoc, nFieldFlags);
3984 pReffingStck = new SwWW8FltRefStack(&rDoc, nFieldFlags);
3986 pAnchorStck = new SwWW8FltAnchorStack(&rDoc, nFieldFlags);
3988 sal_uInt16 nPageDescOffset = rDoc.GetPageDescCnt();
3990 SwNodeIndex aSttNdIdx( rDoc.GetNodes() );
3991 SwRelNumRuleSpaces aRelNumRule(rDoc, mbNewDoc);
3993 USHORT eMode = nsRedlineMode_t::REDLINE_SHOW_INSERT;
3995 mpSprmParser = new wwSprmParser(pWwFib->GetFIBVersion());
3997 // praktische Hilfsvariablen besetzen:
3998 bVer6 = (6 == pWwFib->nVersion);
3999 bVer7 = (7 == pWwFib->nVersion);
4000 bVer67 = bVer6 || bVer7;
4001 bVer8 = (8 == pWwFib->nVersion);
4003 eTextCharSet = WW8Fib::GetFIBCharset(pWwFib->chse);
4004 eStructCharSet = WW8Fib::GetFIBCharset(pWwFib->chseTables);
4006 bWWBugNormal = pWwFib->nProduct == 0xc03d;
4008 if (!mbNewDoc)
4009 aSttNdIdx = pPaM->GetPoint()->nNode;
4011 ::StartProgress(STR_STATSTR_W4WREAD, 0, 100, mpDocShell);
4013 #ifdef DEBUGDUMP
4014 //experimental embedded ttf dumper
4015 if (pWwFib->lcbSttbttmbd && (7 < pWwFib->nVersion))
4017 pTableStream->Seek(pWwFib->fcSttbttmbd);
4018 sal_uInt16 nZeros;
4019 *pTableStream >> nZeros;
4020 sal_uInt16 nNoEntries;
4021 *pTableStream >> nNoEntries;
4022 sal_uInt32 nUnknown1;
4023 *pTableStream >> nUnknown1;
4024 sal_uInt16 nUnknown2;
4025 *pTableStream >> nUnknown2;
4026 std::vector<sal_uInt32> aOffsets;
4027 for (sal_uInt16 nI = 0; nI < nNoEntries; ++nI)
4029 sal_uInt32 nOffset;
4030 *pTableStream >> nOffset;
4031 aOffsets.push_back(nOffset);
4032 sal_uInt32 nUnknown3;
4033 *pTableStream >> nUnknown3;
4034 sal_uInt32 nUnknown4;
4035 *pTableStream >> nUnknown4;
4037 typedef std::vector<sal_uInt32>::iterator myIter;
4038 myIter aEnd = aOffsets.end();
4039 myIter aIter = aOffsets.begin();
4040 while (aIter != aEnd)
4042 sal_uInt32 nOffset = *aIter;
4043 sal_uInt32 nLen = STREAM_SEEK_TO_END;
4044 ++aIter;
4045 pStrm->Seek(nOffset);
4046 if (aIter != aEnd)
4047 nLen = *aIter - nOffset;
4048 SvStream *pDbg = sw::hack::CreateDebuggingStream(CREATE_CONST_ASC(".ttf.dump"));
4049 sw::hack::DumpStream(*pStrm, *pDbg, nLen);
4050 delete pDbg;
4053 #endif
4055 // read Font Table
4056 pFonts = new WW8Fonts( *pTableStream, *pWwFib );
4058 // Document Properties
4059 pWDop = new WW8Dop( *pTableStream, pWwFib->nFib, pWwFib->fcDop,
4060 pWwFib->lcbDop );
4062 if (mbNewDoc)
4063 ImportDop();
4066 Import revisioning data: author names
4068 if( pWwFib->lcbSttbfRMark )
4070 ReadRevMarkAuthorStrTabl( *pTableStream,
4071 pWwFib->fcSttbfRMark,
4072 pWwFib->lcbSttbfRMark, rDoc );
4075 // M.M. Initialize our String/ID map for Linked Sections
4076 std::vector<String> aLinkStrings;
4077 std::vector<ww::bytes> aStringIds;
4079 WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcSttbFnm,
4080 pWwFib->lcbSttbFnm, bVer67 ? 2 : 0, eStructCharSet,
4081 aLinkStrings, &aStringIds);
4083 for (size_t i=0; i < aLinkStrings.size(); ++i)
4085 ww::bytes stringId = aStringIds[i];
4086 WW8_STRINGID *stringIdStruct = (WW8_STRINGID*)(&stringId[0]);
4087 aLinkStringMap[SVBT16ToShort(stringIdStruct->nStringId)] =
4088 aLinkStrings[i];
4091 ReadDocVars(); // #129053# import document variables as meta information.
4093 ::SetProgressState(nProgress, mpDocShell); // Update
4095 pLstManager = new WW8ListManager( *pTableStream, *this );
4098 zuerst(!) alle Styles importieren (siehe WW8PAR2.CXX)
4099 VOR dem Import der Listen !!
4101 ::SetProgressState(nProgress, mpDocShell); // Update
4102 pStyles = new WW8RStyle( *pWwFib, this ); // Styles
4103 pStyles->Import();
4106 zu guter Letzt: (siehe ebenfalls WW8PAR3.CXX)
4107 ===============
4108 alle Styles durchgehen und ggfs. zugehoeriges Listen-Format
4109 anhaengen NACH dem Import der Styles und NACH dem Import der
4110 Listen !!
4112 ::SetProgressState(nProgress, mpDocShell); // Update
4113 pStyles->PostProcessStyles();
4115 if (pCollA)
4116 SetOutLineStyles();
4118 pSBase = new WW8ScannerBase(pStrm,pTableStream,pDataStream,pWwFib);
4120 static const SvxExtNumType eNumTA[16] =
4122 SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,
4123 SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N,
4124 SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
4125 SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
4126 SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
4127 SVX_NUM_ARABIC, SVX_NUM_ARABIC
4130 if (pSBase->AreThereFootnotes())
4132 static const SwFtnNum eNumA[4] =
4134 FTNNUM_DOC, FTNNUM_CHAPTER, FTNNUM_PAGE, FTNNUM_DOC
4137 SwFtnInfo aInfo;
4138 aInfo = rDoc.GetFtnInfo(); // Copy-Ctor privat
4140 aInfo.ePos = FTNPOS_PAGE;
4141 aInfo.eNum = eNumA[pWDop->rncFtn];
4142 aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcFtnRef]) );
4143 if( pWDop->nFtn )
4144 aInfo.nFtnOffset = pWDop->nFtn - 1;
4145 rDoc.SetFtnInfo( aInfo );
4147 if( pSBase->AreThereEndnotes() )
4149 SwEndNoteInfo aInfo;
4150 aInfo = rDoc.GetEndNoteInfo(); // parallel zu Ftn
4152 // Ich kann nicht setzen, wann neu nummerieren...
4153 // aInfo.eNum = eNumA[pWDop->pDop->rncEdn];
4154 aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcEdnRef]) );
4155 if( pWDop->nEdn )
4156 aInfo.nFtnOffset = pWDop->nEdn - 1;
4157 rDoc.SetEndNoteInfo( aInfo );
4160 if( pWwFib->lcbPlcfhdd )
4161 pHdFt = new WW8PLCF_HdFt( pTableStream, *pWwFib, *pWDop );
4163 if (!mbNewDoc)
4165 // in ein Dokument einfuegen ?
4166 // Da immer ganze Zeile eingelesen werden, muessen
4167 // evtl. Zeilen eingefuegt / aufgebrochen werden
4169 const SwPosition* pPos = pPaM->GetPoint();
4170 const SwTxtNode* pSttNd =
4171 rDoc.GetNodes()[ pPos->nNode ]->GetTxtNode();
4173 USHORT nCntPos = pPos->nContent.GetIndex();
4175 // EinfuegePos nicht in leerer Zeile
4176 if( nCntPos && pSttNd->GetTxt().Len() )
4177 rDoc.SplitNode( *pPos, false ); // neue Zeile erzeugen
4179 if( pSttNd->GetTxt().Len() )
4180 { // EinfuegePos nicht am Ende der Zeile
4181 rDoc.SplitNode( *pPos, false ); // neue Zeile
4182 pPaM->Move( fnMoveBackward ); // gehe in leere Zeile
4185 // verhinder das Einlesen von Tabellen in Fussnoten / Tabellen
4186 ULONG nNd = pPos->nNode.GetIndex();
4187 bReadNoTbl = 0 != pSttNd->FindTableNode() ||
4188 ( nNd < rDoc.GetNodes().GetEndOfInserts().GetIndex() &&
4189 rDoc.GetNodes().GetEndOfInserts().StartOfSectionIndex()
4190 < nNd );
4194 ::SetProgressState(nProgress, mpDocShell); // Update
4196 // loop for each glossary entry and add dummy section node
4197 if (pGloss)
4199 WW8PLCF aPlc(pTableStream, pWwFib->fcPlcfglsy, pWwFib->lcbPlcfglsy, 0);
4201 WW8_CP nStart, nEnd;
4202 void* pDummy;
4204 for (int i=0;i<pGloss->GetNoStrings();i++,aPlc++)
4206 SwNodeIndex aIdx( rDoc.GetNodes().GetEndOfContent());
4207 SwTxtFmtColl* pColl =
4208 rDoc.GetTxtCollFromPool(RES_POOLCOLL_STANDARD,
4209 false);
4210 SwStartNode *pNode =
4211 rDoc.GetNodes().MakeTextSection(aIdx,
4212 SwNormalStartNode,pColl);
4213 pPaM->GetPoint()->nNode = pNode->GetIndex()+1;
4214 pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(),0);
4215 aPlc.Get( nStart, nEnd, pDummy );
4216 ReadText(nStart,nEnd-nStart-1,MAN_MAINTEXT);
4219 else //ordinary case
4221 if (mbNewDoc && pStg && !pGloss) /*meaningless for a glossary, cmc*/
4223 mpDocShell->SetIsTemplate( pWwFib->fDot ); // point at tgc record
4224 const SvtFilterOptions* pVBAFlags = SvtFilterOptions::Get();
4225 maTracer.EnterEnvironment(sw::log::eMacros);
4226 // dissable below for 3.1 at the moment, 'cause it's kinda immature
4227 // similarly the project reference in svx/source/msvba
4228 #if 1
4229 uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( mpDocShell->GetModel(), uno::UNO_QUERY_THROW );
4230 uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW );
4231 uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
4233 rtl::OUString sCreatedFrom = xDocProps->getTemplateURL();
4234 uno::Reference< container::XNameContainer > xPrjNameCache;
4235 uno::Reference< lang::XMultiServiceFactory> xSF(mpDocShell->GetModel(), uno::UNO_QUERY);
4236 if ( xSF.is() )
4237 xPrjNameCache.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAProjectNameProvider" ) ) ), uno::UNO_QUERY );
4239 // Read Global templates
4240 ReadGlobalTemplateSettings( sCreatedFrom, xPrjNameCache );
4241 #endif
4242 // Create and insert Word vba Globals
4243 uno::Any aGlobs;
4244 uno::Sequence< uno::Any > aArgs(1);
4245 aArgs[ 0 ] <<= mpDocShell->GetModel();
4246 aGlobs <<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( ::rtl::OUString::createFromAscii( "ooo.vba.word.Globals"), aArgs );
4247 mpDocShell->GetBasicManager()->SetGlobalUNOConstant( "VBAGlobals", aGlobs );
4249 SvxImportMSVBasic aVBasic(*mpDocShell, *pStg,
4250 pVBAFlags->IsLoadWordBasicCode(),
4251 pVBAFlags->IsLoadWordBasicStorage() );
4252 String s1(CREATE_CONST_ASC("Macros"));
4253 String s2(CREATE_CONST_ASC("VBA"));
4254 int nRet = aVBasic.Import( s1, s2, ! pVBAFlags->IsLoadWordBasicCode() );
4255 // dissable below for 3.1 at the moment, 'cause it's kinda immature
4256 // similarly the project reference in svx/source/msvba
4257 #if 1
4258 lcl_createTemplateToProjectEntry( xPrjNameCache, sCreatedFrom, aVBasic.GetVBAProjectName() );
4259 WW8Customizations aCustomisations( pTableStream, *pWwFib );
4260 aCustomisations.Import( mpDocShell );
4261 #endif
4262 if( 2 & nRet )
4264 maTracer.Log(sw::log::eContainsVisualBasic);
4265 rDoc.SetContainsMSVBasic(true);
4268 StoreMacroCmds();
4270 // Hackly to register the document event.
4271 // should be find a better solution to share the codes with Excel Workbook event.
4272 registerDocEvent( mpDocShell );
4274 maTracer.LeaveEnvironment(sw::log::eMacros);
4276 ReadText(0, pWwFib->ccpText, MAN_MAINTEXT);
4280 ::SetProgressState(nProgress, mpDocShell); // Update
4282 if (pDrawPg && pMSDffManager && pMSDffManager->GetShapeOrders())
4284 // Hilfsarray zum Verketten der (statt SdrTxtObj) eingefuegten
4285 // Rahmen
4286 SvxMSDffShapeTxBxSort aTxBxSort;
4288 // korrekte Z-Order der eingelesen Escher-Objekte sicherstellen
4289 USHORT nShapeCount = pMSDffManager->GetShapeOrders()->Count();
4291 for (USHORT nShapeNum=0; nShapeNum < nShapeCount; nShapeNum++)
4293 SvxMSDffShapeOrder *pOrder =
4294 pMSDffManager->GetShapeOrders()->GetObject(nShapeNum);
4295 // Pointer in neues Sort-Array einfuegen
4296 if (pOrder->nTxBxComp && pOrder->pFly)
4297 aTxBxSort.Insert(pOrder);
4299 // zu verkettende Rahmen jetzt verketten
4300 USHORT nTxBxCount = aTxBxSort.Count();
4301 if( nTxBxCount )
4303 SwFmtChain aChain;
4304 for (USHORT nTxBxNum=0; nTxBxNum < nTxBxCount; nTxBxNum++)
4306 SvxMSDffShapeOrder *pOrder =
4307 aTxBxSort.GetObject(nTxBxNum);
4309 // Fly-Frame-Formate initialisieren
4310 SwFlyFrmFmt* pFlyFmt = pOrder->pFly;
4311 SwFlyFrmFmt* pNextFlyFmt = 0;
4312 SwFlyFrmFmt* pPrevFlyFmt = 0;
4313 // ggfs. Nachfolger ermitteln
4314 if( 1+nTxBxNum < nTxBxCount )
4316 SvxMSDffShapeOrder *pNextOrder =
4317 aTxBxSort.GetObject(nTxBxNum+1);
4318 if ((0xFFFF0000 & pOrder->nTxBxComp)
4319 == (0xFFFF0000 & pNextOrder->nTxBxComp))
4320 pNextFlyFmt = pNextOrder->pFly;
4322 // ggfs. Vorgaenger ermitteln
4323 if( nTxBxNum )
4325 SvxMSDffShapeOrder *pPrevOrder =
4326 aTxBxSort.GetObject(nTxBxNum-1);
4327 if ((0xFFFF0000 & pOrder->nTxBxComp)
4328 == (0xFFFF0000 & pPrevOrder->nTxBxComp))
4329 pPrevFlyFmt = pPrevOrder->pFly;
4331 // Falls Nachfolger oder Vorgaenger vorhanden,
4332 // die Verkettung am Fly-Frame-Format eintragen
4333 if (pNextFlyFmt || pPrevFlyFmt)
4335 aChain.SetNext( pNextFlyFmt );
4336 aChain.SetPrev( pPrevFlyFmt );
4337 pFlyFmt->SetFmtAttr( aChain );
4345 if (mbNewDoc)
4347 if( pWDop->fRevMarking )
4348 eMode |= nsRedlineMode_t::REDLINE_ON;
4349 if( pWDop->fRMView )
4350 eMode |= nsRedlineMode_t::REDLINE_SHOW_DELETE;
4353 maInsertedTables.DelAndMakeTblFrms();
4354 maSectionManager.InsertSegments();
4356 if (pCollA)
4357 delete[] pCollA;
4359 DELETEZ( pStyles );
4361 if( pFormImpl )
4362 DeleteFormImpl();
4363 GrafikDtor();
4364 DELETEZ( pMSDffManager );
4365 DELETEZ( pHdFt );
4366 DELETEZ( pLstManager );
4367 DELETEZ( pSBase );
4368 delete pWDop;
4369 DELETEZ( pFonts );
4370 delete mpAtnNames;
4371 DELETEZ( pAuthorInfos );
4372 delete mpSprmParser;
4373 ::EndProgress(mpDocShell);
4375 pDataStream = 0;
4376 pTableStream = 0;
4378 DeleteCtrlStk();
4379 mpRedlineStack->closeall(*pPaM->GetPoint());
4380 delete mpRedlineStack;
4381 DeleteAnchorStk();
4382 DeleteRefStks();
4384 UpdateFields();
4386 // delete the pam before the call for hide all redlines (Bug 73683)
4387 if (mbNewDoc)
4388 rDoc.SetRedlineMode((RedlineMode_t)( eMode ));
4390 UpdatePageDescs(rDoc, nPageDescOffset);
4392 delete pPaM, pPaM = 0;
4393 return nErrRet;
4396 ULONG SwWW8ImplReader::SetSubStreams(SvStorageStreamRef &rTableStream,
4397 SvStorageStreamRef &rDataStream)
4399 ULONG nErrRet = 0;
4400 // 6 stands for "6 OR 7", 7 stand for "ONLY 7"
4401 switch (pWwFib->nVersion)
4403 case 6:
4404 case 7:
4405 pTableStream = pStrm;
4406 pDataStream = pStrm;
4407 break;
4408 case 8:
4409 if(!pStg)
4411 ASSERT( pStg, "Version 8 muss immer einen Storage haben!" );
4412 nErrRet = ERR_SWG_READ_ERROR;
4413 break;
4416 rTableStream = pStg->OpenSotStream( String::CreateFromAscii(
4417 pWwFib->fWhichTblStm ? SL::a1Table : SL::a0Table),
4418 STREAM_STD_READ);
4420 pTableStream = &rTableStream;
4421 pTableStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
4423 rDataStream = pStg->OpenSotStream(CREATE_CONST_ASC(SL::aData),
4424 STREAM_STD_READ | STREAM_NOCREATE );
4426 if (rDataStream.Is() && SVSTREAM_OK == rDataStream->GetError())
4428 pDataStream = &rDataStream;
4429 pDataStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
4431 else
4432 pDataStream = pStrm;
4433 break;
4434 default:
4435 // Programm-Fehler!
4436 ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
4437 nErrRet = ERR_SWG_READ_ERROR;
4438 break;
4440 return nErrRet;
4443 namespace
4445 utl::TempFile *MakeTemp(SvFileStream &rSt)
4447 utl::TempFile *pT = new utl::TempFile;
4448 pT->EnableKillingFile();
4449 rSt.Open(pT->GetFileName(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE);
4450 return pT;
4453 #define WW_BLOCKSIZE 0x200
4455 void DecryptRC4(svx::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
4457 rIn.Seek(STREAM_SEEK_TO_END);
4458 ULONG nLen = rIn.Tell();
4459 rIn.Seek(0);
4461 sal_uInt8 in[WW_BLOCKSIZE];
4462 for (ULONG nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
4464 ULONG nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI;
4465 rIn.Read(in, nBS);
4466 rCtx.InitCipher(nBlock);
4467 rCtx.Decode(in, nBS, in, nBS);
4468 rOut.Write(in, nBS);
4472 void DecryptXOR(svx::MSCodec_XorWord95 &rCtx, SvStream &rIn, SvStream &rOut)
4474 ULONG nSt = rIn.Tell();
4475 rIn.Seek(STREAM_SEEK_TO_END);
4476 ULONG nLen = rIn.Tell();
4477 rIn.Seek(nSt);
4479 rCtx.InitCipher();
4480 rCtx.Skip(nSt);
4482 sal_uInt8 in[0x4096];
4483 for (ULONG nI = nSt; nI < nLen; nI += 0x4096)
4485 ULONG nBS = (nLen - nI > 0x4096 ) ? 0x4096 : nLen - nI;
4486 rIn.Read(in, nBS);
4487 rCtx.Decode(in, nBS);
4488 rOut.Write(in, nBS);
4492 //moan, copy and paste :-(
4493 String QueryPasswordForMedium(SfxMedium& rMedium)
4495 String aPassw;
4497 using namespace com::sun::star;
4499 const SfxItemSet* pSet = rMedium.GetItemSet();
4500 const SfxPoolItem *pPasswordItem;
4502 if(pSet && SFX_ITEM_SET == pSet->GetItemState(SID_PASSWORD, TRUE, &pPasswordItem))
4503 aPassw = ((const SfxStringItem *)pPasswordItem)->GetValue();
4504 else
4508 uno::Reference< task::XInteractionHandler > xHandler( rMedium.GetInteractionHandler() );
4509 if( xHandler.is() )
4511 ::comphelper::DocPasswordRequest* pRequest = new ::comphelper::DocPasswordRequest(
4512 ::comphelper::DocPasswordRequestType_MS, task::PasswordRequestMode_PASSWORD_ENTER,
4513 INetURLObject( rMedium.GetOrigURL() ).GetName( INetURLObject::DECODE_WITH_CHARSET ) );
4514 uno::Reference< task::XInteractionRequest > xRequest( pRequest );
4516 xHandler->handle( xRequest );
4518 if( pRequest->isPassword() )
4519 aPassw = pRequest->getPassword();
4522 catch( uno::Exception& )
4527 return aPassw;
4532 ULONG SwWW8ImplReader::LoadThroughDecryption(SwPaM& rPaM ,WW8Glossary *pGloss)
4534 ULONG nErrRet = 0;
4535 if (pGloss)
4536 pWwFib = pGloss->GetFib();
4537 else
4538 pWwFib = new WW8Fib(*pStrm, nWantedVersion);
4540 if (pWwFib->nFibError)
4541 nErrRet = ERR_SWG_READ_ERROR;
4543 SvStorageStreamRef xTableStream, xDataStream;
4545 if (!nErrRet)
4546 nErrRet = SetSubStreams(xTableStream, xDataStream);
4548 utl::TempFile *pTempMain = 0;
4549 utl::TempFile *pTempTable = 0;
4550 utl::TempFile *pTempData = 0;
4551 SvFileStream aDecryptMain;
4552 SvFileStream aDecryptTable;
4553 SvFileStream aDecryptData;
4555 bool bDecrypt = false;
4556 enum {RC4, XOR, Other} eAlgo = Other;
4557 if (pWwFib->fEncrypted && !nErrRet)
4559 if (!pGloss)
4561 bDecrypt = true;
4562 if (8 != pWwFib->nVersion)
4563 eAlgo = XOR;
4564 else
4566 if (pWwFib->nKey != 0)
4567 eAlgo = XOR;
4568 else
4570 pTableStream->Seek(0);
4571 sal_uInt32 nEncType;
4572 *pTableStream >> nEncType;
4573 if (nEncType == 0x10001)
4574 eAlgo = RC4;
4580 if (bDecrypt)
4582 nErrRet = ERRCODE_SVX_WRONGPASS;
4583 switch (eAlgo)
4585 default:
4586 nErrRet = ERRCODE_SVX_READ_FILTER_CRYPT;
4587 break;
4588 case XOR:
4590 String sUniPassword =
4591 QueryPasswordForMedium(*(mpDocShell->GetMedium()));
4593 ByteString sPassword(sUniPassword,
4594 WW8Fib::GetFIBCharset(pWwFib->chseTables));
4596 xub_StrLen nLen = sPassword.Len();
4597 // DR: do not cut a wrong (too long) password
4598 if( nLen <= 15 )
4600 sal_uInt8 aPassword[16] = {0};
4602 for (xub_StrLen nChar = 0; nChar < sPassword.Len(); ++nChar )
4603 aPassword[nChar] = sPassword.GetChar(nChar);
4605 svx::MSCodec_XorWord95 aCtx;
4606 aCtx.InitKey(aPassword);
4607 if (aCtx.VerifyKey(pWwFib->nKey, pWwFib->nHash))
4609 nErrRet = 0;
4610 pTempMain = MakeTemp(aDecryptMain);
4612 pStrm->Seek(0);
4613 size_t nUnencryptedHdr =
4614 (8 == pWwFib->nVersion) ? 0x44 : 0x34;
4615 sal_uInt8 *pIn = new sal_uInt8[nUnencryptedHdr];
4616 pStrm->Read(pIn, nUnencryptedHdr);
4617 aDecryptMain.Write(pIn, nUnencryptedHdr);
4618 delete pIn;
4620 DecryptXOR(aCtx, *pStrm, aDecryptMain);
4622 if (!pTableStream || pTableStream == pStrm)
4623 pTableStream = &aDecryptMain;
4624 else
4626 pTempTable = MakeTemp(aDecryptTable);
4627 DecryptXOR(aCtx, *pTableStream, aDecryptTable);
4628 pTableStream = &aDecryptTable;
4631 if (!pDataStream || pDataStream == pStrm)
4632 pDataStream = &aDecryptMain;
4633 else
4635 pTempData = MakeTemp(aDecryptData);
4636 DecryptXOR(aCtx, *pDataStream, aDecryptData);
4637 pDataStream = &aDecryptData;
4642 break;
4643 case RC4:
4645 String sUniPassword =
4646 QueryPasswordForMedium(*(mpDocShell->GetMedium()));
4648 xub_StrLen nLen = sUniPassword.Len();
4649 // DR: do not cut a wrong (too long) password
4650 if (nLen <= 15)
4652 sal_Unicode aPassword[16] = {0};
4653 for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
4654 aPassword[nChar] = sUniPassword.GetChar(nChar);
4656 sal_uInt8 aDocId[ 16 ];
4657 pTableStream->Read(aDocId, 16);
4658 sal_uInt8 aSaltData[ 16 ];
4659 pTableStream->Read(aSaltData, 16);
4660 sal_uInt8 aSaltHash[ 16 ];
4661 pTableStream->Read(aSaltHash, 16);
4663 svx::MSCodec_Std97 aCtx;
4664 aCtx.InitKey(aPassword, aDocId);
4665 if (aCtx.VerifyKey(aSaltData, aSaltHash))
4667 nErrRet = 0;
4669 pTempTable = MakeTemp(aDecryptTable);
4670 DecryptRC4(aCtx, *pTableStream, aDecryptTable);
4671 pTableStream = &aDecryptTable;
4673 pTempMain = MakeTemp(aDecryptMain);
4674 DecryptRC4(aCtx, *pStrm, aDecryptMain);
4676 if (!pDataStream || pDataStream == pStrm)
4677 pDataStream = &aDecryptMain;
4678 else
4680 pTempData = MakeTemp(aDecryptData);
4681 DecryptRC4(aCtx, *pDataStream, aDecryptData);
4682 pDataStream = &aDecryptData;
4684 SfxMedium* pMedium = mpDocShell->GetMedium();
4685 if ( pMedium )
4687 SfxItemSet* pSet = pMedium->GetItemSet();
4688 if ( pSet )
4689 pSet->Put( SfxStringItem(SID_PASSWORD, sUniPassword) );
4694 break;
4697 if (nErrRet == 0)
4699 pStrm = &aDecryptMain;
4701 delete pWwFib;
4702 pWwFib = new WW8Fib(*pStrm, nWantedVersion);
4703 if (pWwFib->nFibError)
4704 nErrRet = ERR_SWG_READ_ERROR;
4708 if (!nErrRet)
4709 nErrRet = CoreLoad(pGloss, *rPaM.GetPoint());
4711 delete pTempMain;
4712 delete pTempTable;
4713 delete pTempData;
4715 if (!pGloss)
4716 delete pWwFib;
4717 return nErrRet;
4720 class outlineeq : public std::unary_function<const SwTxtFmtColl*, bool>
4722 private:
4723 BYTE mnNum;
4724 public:
4725 outlineeq(BYTE nNum) : mnNum(nNum) {}
4726 bool operator()(const SwTxtFmtColl *pTest) const
4728 //return pTest->GetOutlineLevel() == mnNum; //#outline level,zhaojianwei
4729 return pTest->IsAssignedToListLevelOfOutlineStyle() && pTest->GetAssignedOutlineStyleLevel() == mnNum; //<-end,zhaojianwei
4733 void SwWW8ImplReader::SetOutLineStyles()
4736 #i3674# & #101291# Load new document and insert document cases.
4738 SwNumRule aOutlineRule(*rDoc.GetOutlineNumRule());
4739 // --> OD 2005-10-14 #i53044,i53213#
4740 // <mpChosenOutlineNumRule> has to be set to point to local variable
4741 // <aOutlineRule>, because its used below to be compared this <&aOutlineRule>.
4742 // But at the end of the method <mpChosenOutlineNumRule> has to be set to
4743 // <rDoc.GetOutlineNumRule()>, because <aOutlineRule> will be destroyed.
4744 // mpChosenOutlineNumRule = rDoc.GetOutlineNumRule();
4745 mpChosenOutlineNumRule = &aOutlineRule;
4746 // <--
4748 sw::ParaStyles aOutLined(sw::util::GetParaStyles(rDoc));
4749 // --> OD 2009-02-04 #i98791# - sorting algorithm adjusted
4750 sw::util::SortByAssignedOutlineStyleListLevel(aOutLined);
4751 // <--
4753 typedef sw::ParaStyleIter myParaStyleIter;
4755 If we are inserted into a document then don't clobber existing existing
4756 levels.
4758 USHORT nFlagsStyleOutlLevel = 0;
4759 if (!mbNewDoc)
4761 // --> OD 2008-12-16 #i70748#
4762 // backward iteration needed due to the outline level attribute
4763 sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend();
4764 for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter)
4765 // <--
4767 //if ((*aIter)->GetOutlineLevel() < MAXLEVEL) //#outline level,zhaojianwei,
4768 //nFlagsStyleOutlLevel |= 1 << (*aIter)->GetOutlineLevel();
4769 if ((*aIter)->IsAssignedToListLevelOfOutlineStyle())
4770 nFlagsStyleOutlLevel |= 1 << (*aIter)->GetAssignedOutlineStyleLevel();//<-end,zhaojianwei
4771 else
4772 break;
4775 else
4778 #111955#
4779 Only import *one* of the possible multiple outline numbering rules, so
4780 pick the one that affects most styles. If we're not importing a new
4781 document, we got to stick with what is already there.
4783 // --> OD 2005-11-07 #127520# - use index in text format collection
4784 // array <pCollA> as key of the outline numbering map <aRuleMap>
4785 // instead of the memory pointer of the outline numbering rule
4786 // to assure that, if two outline numbering rule affect the same
4787 // count of text formats, always the same outline numbering rule is chosen.
4788 std::map<USHORT, int>aRuleMap;
4789 typedef std::map<USHORT, int>::iterator myIter;
4790 for (USHORT nI = 0; nI < nColls; ++nI)
4792 SwWW8StyInf& rSI = pCollA[ nI ];
4793 if (
4794 (MAXLEVEL > rSI.nOutlineLevel) && rSI.pOutlineNumrule &&
4795 rSI.pFmt
4798 // --> OD 2005-11-07 #127520#
4799 myIter aIter = aRuleMap.find(nI);
4800 // <--
4801 if (aIter == aRuleMap.end())
4803 // --> OD 2005-11-07 #127520#
4804 aRuleMap[nI] = 1;
4805 // <--
4807 else
4808 ++(aIter->second);
4812 int nMax = 0;
4813 myIter aEnd2 = aRuleMap.end();
4814 for (myIter aIter = aRuleMap.begin(); aIter != aEnd2; ++aIter++)
4816 if (aIter->second > nMax)
4818 nMax = aIter->second;
4819 // --> OD 2005-11-07 #127520#
4820 mpChosenOutlineNumRule = pCollA[ aIter->first ].pOutlineNumrule;
4821 // <--
4824 // <--
4826 ASSERT(mpChosenOutlineNumRule, "Impossible");
4827 if (mpChosenOutlineNumRule)
4828 aOutlineRule = *mpChosenOutlineNumRule;
4830 if (mpChosenOutlineNumRule != &aOutlineRule)
4832 // --> OD 2008-12-16 #i70748#
4833 // backward iteration needed due to the outline level attribute
4834 sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend();
4835 for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter)
4836 // <--
4838 //if ((*aIter)->GetOutlineLevel() < MAXLEVEL)//#outline level,zhaojianwei
4839 // (*aIter)->SetOutlineLevel(NO_NUMBERING);
4840 if((*aIter)->IsAssignedToListLevelOfOutlineStyle())
4841 (*aIter)->DeleteAssignmentToListLevelOfOutlineStyle(); //<-end
4843 else
4844 break;
4849 USHORT nOldFlags = nFlagsStyleOutlLevel;
4851 for (USHORT nI = 0; nI < nColls; ++nI)
4853 SwWW8StyInf& rSI = pCollA[nI];
4855 if (rSI.IsOutlineNumbered())
4857 USHORT nAktFlags = 1 << rSI.nOutlineLevel;
4858 if (
4859 (nAktFlags & nFlagsStyleOutlLevel) ||
4860 (rSI.pOutlineNumrule != mpChosenOutlineNumRule)
4864 If our spot is already taken by something we can't replace
4865 then don't insert and remove our outline level.
4867 rSI.pFmt->SetFmtAttr(
4868 SwNumRuleItem( rSI.pOutlineNumrule->GetName() ) );
4869 //((SwTxtFmtColl*)rSI.pFmt)->SetOutlineLevel(NO_NUMBERING);
4870 ((SwTxtFmtColl*)rSI.pFmt)->DeleteAssignmentToListLevelOfOutlineStyle();//#outline level,zhaojianwei
4872 else
4875 If there is a style already set for this outline
4876 numbering level and its not a style set by us already
4877 then we can remove it outline numbering.
4878 (its one of the default headings in a new document
4879 so we can clobber it)
4880 Of course if we are being inserted into a document that
4881 already has some set we can't do this, thats covered by
4882 the list of level in nFlagsStyleOutlLevel to ignore.
4884 outlineeq aCmp(rSI.nOutlineLevel);
4885 myParaStyleIter aResult = std::find_if(aOutLined.begin(),
4886 aOutLined.end(), aCmp);
4888 myParaStyleIter aEnd = aOutLined.end();
4889 while (aResult != aEnd && aCmp(*aResult))
4891 //(*aResult)->SetOutlineLevel(NO_NUMBERING);//#outline level,zhaojianwei
4892 (*aResult)->DeleteAssignmentToListLevelOfOutlineStyle();
4893 ++aResult;
4897 #i1886#
4898 I believe that when a list is registered onto a winword
4899 style which is an outline numbering style (i.e.
4900 nOutlineLevel is set) that the style of numbering is for
4901 the level is indexed by the *list* level that was
4902 registered on that style, and not the outlinenumbering
4903 level, which is probably a logical sequencing, and not a
4904 physical mapping into the list style reged on that outline
4905 style.
4907 BYTE nFromLevel = rSI.nListLevel;
4908 BYTE nToLevel = rSI.nOutlineLevel;
4909 const SwNumFmt& rRule=rSI.pOutlineNumrule->Get(nFromLevel);
4910 aOutlineRule.Set(nToLevel, rRule);
4911 // Set my outline level
4912 //((SwTxtFmtColl*)rSI.pFmt)->SetOutlineLevel(nToLevel);//#outline level,zhaojianwei
4913 ((SwTxtFmtColl*)rSI.pFmt)->AssignToListLevelOfOutlineStyle(nToLevel); //<-end,zhaojianwei
4914 // If there are more styles on this level ignore them
4915 nFlagsStyleOutlLevel |= nAktFlags;
4919 if (nOldFlags != nFlagsStyleOutlLevel)
4920 rDoc.SetOutlineNumRule(aOutlineRule);
4921 // --> OD 2005-10-14 #i53044,i53213#
4922 if ( mpChosenOutlineNumRule == &aOutlineRule )
4924 mpChosenOutlineNumRule = rDoc.GetOutlineNumRule();
4926 // <--
4929 const String* SwWW8ImplReader::GetAnnotationAuthor(sal_uInt16 nIdx)
4931 if (!mpAtnNames && pWwFib->lcbGrpStAtnOwners)
4933 // Authoren bestimmen: steht im TableStream
4934 mpAtnNames = new ::std::vector<String>;
4935 SvStream& rStrm = *pTableStream;
4937 long nOldPos = rStrm.Tell();
4938 rStrm.Seek( pWwFib->fcGrpStAtnOwners );
4940 long nRead = 0, nCount = pWwFib->lcbGrpStAtnOwners;
4941 while (nRead < nCount)
4943 if( bVer67 )
4945 mpAtnNames->push_back(WW8ReadPString(rStrm, false));
4946 nRead += mpAtnNames->rbegin()->Len() + 1; // Laenge + BYTE Count
4948 else
4950 mpAtnNames->push_back(WW8Read_xstz(rStrm, 0, false));
4951 // UNICode: doppelte Laenge + USHORT Count
4952 nRead += mpAtnNames->rbegin()->Len() * 2 + 2;
4955 rStrm.Seek( nOldPos );
4958 const String *pRet = 0;
4959 if (mpAtnNames && nIdx < mpAtnNames->size())
4960 pRet = &((*mpAtnNames)[nIdx]);
4961 return pRet;
4964 ULONG SwWW8ImplReader::LoadDoc( SwPaM& rPaM,WW8Glossary *pGloss)
4966 ULONG nErrRet = 0;
4969 static const sal_Char* aNames[ 13 ] = {
4970 "WinWord/WW", "WinWord/WW8", "WinWord/WWFT",
4971 "WinWord/WWFLX", "WinWord/WWFLY",
4972 "WinWord/WWF",
4973 "WinWord/WWFA0", "WinWord/WWFA1", "WinWord/WWFA2",
4974 "WinWord/WWFB0", "WinWord/WWFB1", "WinWord/WWFB2",
4975 "WinWord/RegardHindiDigits"
4977 sal_uInt32 aVal[ 13 ];
4979 SwFilterOptions aOpt( 13, aNames, aVal );
4981 nIniFlags = aVal[ 0 ];
4982 nIniFlags1= aVal[ 1 ];
4983 // schiebt Flys um x twips nach rechts o. links
4984 nIniFlyDx = aVal[ 3 ];
4985 nIniFlyDy = aVal[ 4 ];
4987 nFieldFlags = aVal[ 5 ];
4988 nFieldTagAlways[0] = aVal[ 6 ];
4989 nFieldTagAlways[1] = aVal[ 7 ];
4990 nFieldTagAlways[2] = aVal[ 8 ];
4991 nFieldTagBad[0] = aVal[ 9 ];
4992 nFieldTagBad[1] = aVal[ 10 ];
4993 nFieldTagBad[2] = aVal[ 11 ];
4994 m_bRegardHindiDigits = aVal[ 12 ] > 0;
4997 UINT16 nMagic;
4998 *pStrm >> nMagic;
5000 // beachte: 6 steht fuer "6 ODER 7", 7 steht fuer "NUR 7"
5001 switch (nWantedVersion)
5003 case 6:
5004 case 7:
5005 if (
5006 (0xa5dc != nMagic && 0xa5db != nMagic) &&
5007 (nMagic < 0xa697 || nMagic > 0xa699)
5010 //JP 06.05.99: teste auf eigenen 97-Fake!
5011 if (pStg && 0xa5ec == nMagic)
5013 ULONG nCurPos = pStrm->Tell();
5014 if (pStrm->Seek(nCurPos + 22))
5016 UINT32 nfcMin;
5017 *pStrm >> nfcMin;
5018 if (0x300 != nfcMin)
5019 nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
5021 pStrm->Seek( nCurPos );
5023 else
5024 nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
5026 break;
5027 case 8:
5028 if (0xa5ec != nMagic)
5029 nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
5030 break;
5031 default:
5032 nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
5033 ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
5034 break;
5037 if (!nErrRet)
5038 nErrRet = LoadThroughDecryption(rPaM ,pGloss);
5040 rDoc.PropagateOutlineRule();
5042 return nErrRet;
5045 extern "C" SAL_DLLPUBLIC_EXPORT Reader* SAL_CALL ImportDOC()
5047 return new WW8Reader();
5050 ULONG WW8Reader::Read(SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & /* FileName */)
5052 USHORT nOldBuffSize = 32768;
5053 bool bNew = !bInsertMode; // Neues Doc ( kein Einfuegen )
5056 SvStorageStreamRef refStrm; // damit uns keiner den Stream klaut
5057 SvStream* pIn = pStrm;
5059 ULONG nRet = 0;
5060 BYTE nVersion = 8;
5062 String sFltName = GetFltName();
5063 if( sFltName.EqualsAscii( "WW6" ) )
5065 if (pStrm)
5066 nVersion = 6;
5067 else
5069 ASSERT(!this, "WinWord 95 Reader-Read ohne Stream");
5070 nRet = ERR_SWG_READ_ERROR;
5073 else
5075 if( sFltName.EqualsAscii( "CWW6" ) )
5076 nVersion = 6;
5077 else if( sFltName.EqualsAscii( "CWW7" ) )
5078 nVersion = 7;
5080 if( pStg )
5082 nRet = OpenMainStream( refStrm, nOldBuffSize );
5083 pIn = &refStrm;
5085 else
5087 ASSERT(!this, "WinWord 95/97 Reader-Read ohne Storage");
5088 nRet = ERR_SWG_READ_ERROR;
5092 if( !nRet )
5094 //JP 18.01.96: Alle Ueberschriften sind normalerweise ohne
5095 // Kapitelnummer. Darum hier explizit abschalten
5096 // weil das Default jetzt wieder auf AN ist.
5097 if (bNew)
5099 Reader::SetNoOutlineNum( rDoc );
5100 // MIB 27.09.96: Umrandung uns Abstaende aus Frm-Vorlagen entf.
5101 Reader::ResetFrmFmts( rDoc );
5103 SwWW8ImplReader* pRdr = new SwWW8ImplReader(nVersion, pStg, pIn, rDoc,
5104 rBaseURL, bNew);
5105 nRet = pRdr->LoadDoc( rPam );
5106 delete pRdr;
5108 if( refStrm.Is() )
5110 refStrm->SetBufferSize( nOldBuffSize );
5111 refStrm.Clear();
5113 else if (pIn)
5114 pIn->ResetError();
5117 return nRet;
5120 int WW8Reader::GetReaderType()
5122 return SW_STORAGE_READER | SW_STREAM_READER;
5125 BOOL WW8Reader::HasGlossaries() const
5127 return true;
5130 BOOL WW8Reader::ReadGlossaries(SwTextBlocks& rBlocks, BOOL bSaveRelFiles) const
5132 bool bRet=false;
5134 WW8Reader *pThis = const_cast<WW8Reader *>(this);
5136 USHORT nOldBuffSize = 32768;
5137 SvStorageStreamRef refStrm;
5138 if (!pThis->OpenMainStream(refStrm, nOldBuffSize))
5140 WW8Glossary aGloss( refStrm, 8, pStg );
5141 bRet = aGloss.Load( rBlocks, bSaveRelFiles ? true : false);
5143 return bRet ? true : false;
5146 BOOL SwMSDffManager::GetOLEStorageName(long nOLEId, String& rStorageName,
5147 SvStorageRef& rSrcStorage, uno::Reference < embed::XStorage >& rDestStorage) const
5149 bool bRet = false;
5151 long nPictureId = 0;
5152 if (rReader.pStg)
5154 // dann holen wir uns mal ueber den TextBox-PLCF die richtigen
5155 // Char Start-/End-Positionen. In dem Bereich sollte dann
5156 // das EinbettenFeld und die entsprechenden Sprms zu finden
5157 // sein. Wir brauchen hier aber nur das Sprm fuer die Picture Id
5158 long nOldPos = rReader.pStrm->Tell();
5160 // --> OD 2004-12-08 #i32596# - consider return value of method
5161 // <rReader.GetTxbxTextSttEndCp(..)>. If it returns false, method
5162 // wasn't successful. Thus, continue in this case.
5163 // Note: Ask MM for initialization of <nStartCp> and <nEndCp>.
5164 // Note: Ask MM about assertions in method <rReader.GetTxbxTextSttEndCp(..)>.
5165 WW8_CP nStartCp, nEndCp;
5166 if ( rReader.GetTxbxTextSttEndCp(nStartCp, nEndCp,
5167 static_cast<sal_uInt16>((nOLEId >> 16) & 0xFFFF),
5168 static_cast<sal_uInt16>(nOLEId & 0xFFFF)) )
5170 WW8PLCFxSaveAll aSave;
5171 memset( &aSave, 0, sizeof( aSave ) );
5172 rReader.pPlcxMan->SaveAllPLCFx( aSave );
5174 nStartCp += rReader.nDrawCpO;
5175 nEndCp += rReader.nDrawCpO;
5176 WW8PLCFx_Cp_FKP* pChp = rReader.pPlcxMan->GetChpPLCF();
5177 wwSprmParser aSprmParser(rReader.pWwFib->GetFIBVersion());
5178 while (nStartCp <= nEndCp && !nPictureId)
5180 WW8PLCFxDesc aDesc;
5181 pChp->SeekPos( nStartCp );
5182 pChp->GetSprms( &aDesc );
5184 if (aDesc.nSprmsLen && aDesc.pMemPos) // Attribut(e) vorhanden
5186 long nLen = aDesc.nSprmsLen;
5187 const BYTE* pSprm = aDesc.pMemPos;
5189 while (nLen >= 2 && !nPictureId)
5191 USHORT nId = aSprmParser.GetSprmId(pSprm);
5192 USHORT nSL = aSprmParser.GetSprmSize(nId, pSprm);
5194 if( nLen < nSL )
5195 break; // nicht mehr genug Bytes uebrig
5197 if( 0x6A03 == nId && 0 < nLen )
5199 nPictureId = SVBT32ToUInt32(pSprm +
5200 aSprmParser.DistanceToData(nId));
5201 bRet = true;
5203 pSprm += nSL;
5204 nLen -= nSL;
5207 nStartCp = aDesc.nEndPos;
5210 rReader.pPlcxMan->RestoreAllPLCFx( aSave );
5212 // <--
5214 rReader.pStrm->Seek( nOldPos );
5217 if( bRet )
5219 rStorageName = '_';
5220 rStorageName += String::CreateFromInt32(nPictureId);
5221 rSrcStorage = rReader.pStg->OpenSotStorage(CREATE_CONST_ASC(
5222 SL::aObjectPool));
5223 if (!rReader.mpDocShell)
5224 bRet=false;
5225 else
5226 rDestStorage = rReader.mpDocShell->GetStorage();
5228 return bRet;
5231 BOOL SwMSDffManager::ShapeHasText(ULONG, ULONG) const
5233 // Zur Zeit des Einlesens einer einzelnen Box, die womoeglich Teil einer
5234 // Gruppe ist, liegen noch nicht genuegend Informationen vor, um
5235 // entscheiden zu koennen, ob wir sie nicht doch als Textfeld benoetigen.
5236 // Also vorsichtshalber mal alle umwandeln:
5237 return true;
5240 bool SwWW8ImplReader::InEqualOrHigherApo(int nLvl) const
5242 if (nLvl)
5243 --nLvl;
5244 // --> OD 2006-01-19 #i60827#
5245 // check size of <maApos> to assure that <maApos.begin() + nLvl> can be performed.
5246 if ( sal::static_int_cast< sal_Int32>(nLvl) >= sal::static_int_cast< sal_Int32>(maApos.size()) )
5248 return false;
5250 // <--
5251 mycApoIter aIter = std::find(maApos.begin() + nLvl, maApos.end(), true);
5252 if (aIter != maApos.end())
5253 return true;
5254 else
5255 return false;
5258 bool SwWW8ImplReader::InEqualApo(int nLvl) const
5260 //If we are in a table, see if an apo was inserted at the level below
5261 //the table.
5262 if (nLvl)
5263 --nLvl;
5264 return maApos[nLvl];
5267 namespace sw
5269 namespace hack
5271 Position::Position(const SwPosition &rPos)
5272 : maPtNode(rPos.nNode), mnPtCntnt(rPos.nContent.GetIndex())
5276 Position::Position(const Position &rPos)
5277 : maPtNode(rPos.maPtNode), mnPtCntnt(rPos.mnPtCntnt)
5281 Position::operator SwPosition() const
5283 SwPosition aRet(maPtNode);
5284 aRet.nContent.Assign(maPtNode.GetNode().GetCntntNode(), mnPtCntnt);
5285 return aRet;
5290 /* vi:set tabstop=4 shiftwidth=4 expandtab: */