merge the formfield patch from ooo-build
[ooovba.git] / sw / source / filter / ww8 / ww8par.cxx
blob43191258bb859f0a184a16b1c90feafbf10530c2
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 <ftninfo.hxx>
85 #include <fmtftn.hxx>
86 #include <txtftn.hxx>
87 #include <pam.hxx> // fuer SwPam
88 #include <doc.hxx>
89 #include <ndtxt.hxx> // class SwTxtNode
90 #include <pagedesc.hxx> // class SwPageDesc
91 #include <paratr.hxx>
92 #include <fmtclds.hxx>
93 #include <fmtclbl.hxx>
94 #include <section.hxx>
95 #include <docsh.hxx>
96 #include <docufld.hxx>
97 #include <swfltopt.hxx>
98 #include <viewsh.hxx>
99 #include <shellres.hxx>
100 #include <mdiexp.hxx> // Progress
101 #include <statstr.hrc> // ResId fuer Statusleiste
102 #include <swerror.h> // ERR_WW8_...
103 #include <swunodef.hxx>
104 #include <unodraw.hxx>
105 #include <swtable.hxx> // class SwTableLines, ...
106 // #i18732#
107 #include <fmtfollowtextflow.hxx>
108 #include <fchrfmt.hxx>
109 #include <charfmt.hxx>
112 #include <com/sun/star/i18n/ForbiddenCharacters.hpp>
113 #include <comphelper/extract.hxx>
114 #include <fltini.hxx>
116 #include <algorithm>
117 #include <functional>
118 #include "writerhelper.hxx"
119 #include "writerwordglue.hxx"
122 #include "ww8par2.hxx" // class WW8RStyle, class WW8AnchorPara
124 #include <frmatr.hxx>
126 #include <math.h>
127 #include <com/sun/star/beans/XPropertyContainer.hpp>
129 #include <com/sun/star/beans/PropertyAttribute.hpp>
130 #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp>
131 #include <com/sun/star/document/XDocumentProperties.hpp>
132 #include <svtools/itemiter.hxx> //SfxItemIter
134 #include <stdio.h>
135 #include <comphelper/processfactory.hxx>
136 #include <basic/basmgr.hxx>
138 #include "ww8toolbar.hxx"
139 #include <osl/file.hxx>
140 #include <com/sun/star/document/XDocumentInfoSupplier.hpp>
142 #ifdef DEBUG
143 #include <iostream>
144 #include <dbgoutsw.hxx>
145 #endif
146 #include <unotools/localfilehelper.hxx>
147 #include <comphelper/configurationhelper.hxx>
149 #define MM_250 1417 // WW-Default fuer Hor. Seitenraender: 2.5 cm
150 #define MM_200 1134 // WW-Default fuer u.Seitenrand: 2.0 cm
152 using namespace ::com::sun::star;
153 using namespace sw::util;
154 using namespace sw::types;
155 using namespace nsHdFtFlags;
157 #include <com/sun/star/document/XEventsSupplier.hpp>
158 #include <com/sun/star/container/XNameReplace.hpp>
159 #include <com/sun/star/frame/XModel.hpp>
160 #include <svx/msvbahelper.hxx>
161 #include <svtools/pathoptions.hxx>
162 #include <com/sun/star/ucb/XSimpleFileAccess.hpp>
164 const static String sThisDocument( RTL_CONSTASCII_USTRINGPARAM("ThisDocument"));
166 struct DocEventNameTable
168 const sal_Char* sEventName;
169 const sal_Char* sMacroName;
172 const DocEventNameTable aEventNameTable[] =
174 {"OnNew", "Document_New"},
175 {"OnLoad", "Document_Open"},
176 {"OnPrepareUnload", "Document_Close"},
177 {NULL, NULL}
180 bool registerDocEvent( SfxObjectShell* pShell )
182 bool result = false;
183 const static rtl::OUString sEvtType( RTL_CONSTASCII_USTRINGPARAM("EventType") );
184 const static rtl::OUString sScript( RTL_CONSTASCII_USTRINGPARAM("Script") );
185 uno::Reference< document::XEventsSupplier > xEvtSupplier( pShell->GetModel(), uno::UNO_QUERY );
186 if( !xEvtSupplier.is() )
187 return result;
188 uno::Reference< container::XNameReplace > xEvts( xEvtSupplier->getEvents(), uno::UNO_QUERY );
189 if ( xEvts.is() )
191 for( const DocEventNameTable* pTable = aEventNameTable; pTable->sEventName != NULL; pTable++ )
193 rtl::OUString sEvt = rtl::OUString::createFromAscii( pTable->sEventName );
194 String sMacroName = String::CreateFromAscii( pTable->sMacroName ).Insert( '.', 0 ).Insert( sThisDocument, 0);
195 // fail to search the macro if the module is not specified.
196 ooo::vba::VBAMacroResolvedInfo aMacroInfo = ooo::vba::resolveVBAMacro( pShell, sMacroName );
197 if( !aMacroInfo.IsResolved() )
198 continue;
200 uno::Sequence< beans::PropertyValue > aEvents;
201 xEvts->getByName( sEvt ) >>= aEvents;
202 uno::Sequence< beans::PropertyValue > aOpenEvt( 2 );
203 aOpenEvt[ 0 ].Name = sEvtType;
204 aOpenEvt[ 0 ].Value = uno::makeAny(sScript);
205 aOpenEvt[ 1 ].Name = sScript;
206 rtl::OUString sUrl = ooo::vba::makeMacroURL( aMacroInfo.ResolvedMacro() );
207 aOpenEvt[ 1 ].Value = uno::makeAny(sUrl);
208 sal_Int32 nPos = aEvents.getLength();
210 sal_Int32 nNewSize = aEvents.getLength() + aOpenEvt.getLength();
211 if ( nNewSize > aEvents.getLength() )
212 aEvents.realloc( nNewSize );
214 for ( sal_Int32 nIndex = nPos, nCpyIndex = 0; nIndex<nNewSize; nIndex++, nCpyIndex++ )
215 aEvents[ nIndex ] = aOpenEvt[ nCpyIndex ];
217 uno::Any aParam = uno::makeAny( aEvents );
219 xEvts->replaceByName( sEvt, aParam );
220 result = true;
223 return result;
226 class Sttb : TBBase
228 struct SBBItem
230 sal_uInt16 cchData;
231 rtl::OUString data;
232 SBBItem() : cchData(0){}
234 sal_uInt16 fExtend;
235 sal_uInt16 cData;
236 sal_uInt16 cbExtra;
238 std::vector< SBBItem > dataItems;
240 Sttb(const Sttb&);
241 Sttb& operator = ( const Sttb&);
242 public:
243 Sttb();
244 ~Sttb();
245 bool Read(SvStream *pS);
246 void Print( FILE* fp );
247 rtl::OUString getStringAtIndex( sal_uInt32 );
250 Sttb::Sttb() : fExtend( 0 )
251 ,cData( 0 )
252 ,cbExtra( 0 )
256 Sttb::~Sttb()
260 bool Sttb::Read( SvStream* pS )
262 OSL_TRACE("Sttb::Read() stream pos 0x%x", pS->Tell() );
263 nOffSet = pS->Tell();
264 *pS >> fExtend >> cData >> cbExtra;
265 if ( cData )
267 for ( sal_Int32 index = 0; index < cData; ++index )
269 SBBItem aItem;
270 *pS >> aItem.cchData;
271 aItem.data = readUnicodeString( pS, aItem.cchData );
272 dataItems.push_back( aItem );
275 return true;
278 void Sttb::Print( FILE* fp )
280 fprintf( fp, "[ 0x%x ] Sttb - dump\n", nOffSet);
281 fprintf( fp, " fExtend 0x%x [expected 0xFFFF ]\n", fExtend );
282 fprintf( fp, " cData no. or string data items %d (0x%x)\n", cData, cData );
284 if ( cData )
286 for ( sal_Int32 index = 0; index < cData; ++index )
287 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() );
292 rtl::OUString
293 Sttb::getStringAtIndex( sal_uInt32 index )
295 rtl::OUString aRet;
296 if ( index < dataItems.size() )
297 aRet = dataItems[ index ].data;
298 return aRet;
301 SwMSDffManager::SwMSDffManager( SwWW8ImplReader& rRdr )
302 : SvxMSDffManager(*rRdr.pTableStream, rRdr.GetBaseURL(), rRdr.pWwFib->fcDggInfo,
303 rRdr.pDataStream, 0, 0, COL_WHITE, 12, rRdr.pStrm,
304 rRdr.maTracer.GetTrace()),
305 rReader(rRdr), pFallbackStream(0), pOldEscherBlipCache(0)
307 SetSvxMSDffSettings( GetSvxMSDffSettings() );
308 nSvxMSDffOLEConvFlags = SwMSDffManager::GetFilterFlags();
311 UINT32 SwMSDffManager::GetFilterFlags()
313 UINT32 nFlags(0);
314 if (const SvtFilterOptions* pOpt = SvtFilterOptions::Get())
316 if (pOpt->IsMathType2Math())
317 nFlags |= OLE_MATHTYPE_2_STARMATH;
318 if (pOpt->IsExcel2Calc())
319 nFlags |= OLE_EXCEL_2_STARCALC;
320 if (pOpt->IsPowerPoint2Impress())
321 nFlags |= OLE_POWERPOINT_2_STARIMPRESS;
322 if (pOpt->IsWinWord2Writer())
323 nFlags |= OLE_WINWORD_2_STARWRITER;
325 return nFlags;
329 * I would like to override the default OLE importing to add a test
330 * and conversion of OCX controls from their native OLE type into our
331 * native nonOLE Form Control Objects.
333 * cmc
335 // --> OD 2004-12-14 #i32596# - consider new parameter <_nCalledByGroup>
336 SdrObject* SwMSDffManager::ImportOLE( long nOLEId,
337 const Graphic& rGrf,
338 const Rectangle& rBoundRect,
339 const Rectangle& rVisArea,
340 const int _nCalledByGroup,
341 sal_Int64 nAspect ) const
343 // --> OD 2004-12-14 #i32596# - no import of OLE object, if it's inside a group.
344 // NOTE: This can be undone, if grouping of Writer fly frames is possible or
345 // if drawing OLE objects are allowed in Writer.
346 if ( _nCalledByGroup > 0 )
348 return 0L;
350 // <--
352 SdrObject* pRet = 0;
353 String sStorageName;
354 SotStorageRef xSrcStg;
355 uno::Reference < embed::XStorage > xDstStg;
356 if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg ))
358 SvStorageRef xSrc = xSrcStg->OpenSotStorage( sStorageName,
359 STREAM_READWRITE| STREAM_SHARE_DENYALL );
360 ASSERT(rReader.pFormImpl, "No Form Implementation!");
361 STAR_REFERENCE( drawing::XShape ) xShape;
362 if ( (!(rReader.bIsHeader || rReader.bIsFooter)) &&
363 rReader.pFormImpl->ReadOCXStream(xSrc,&xShape,true))
365 pRet = GetSdrObjectFromXShape(xShape);
367 else
369 ErrCode nError = ERRCODE_NONE;
370 pRet = CreateSdrOLEFromStorage( sStorageName, xSrcStg, xDstStg,
371 rGrf, rBoundRect, rVisArea, pStData, nError, nSvxMSDffOLEConvFlags, nAspect );
374 return pRet;
377 void SwMSDffManager::DisableFallbackStream()
379 ASSERT(!pFallbackStream || !pOldEscherBlipCache,
380 "if you're recursive, you're broken");
381 pFallbackStream = pStData2;
382 pOldEscherBlipCache = pEscherBlipCache;
383 pEscherBlipCache = 0;
384 pStData2 = 0;
387 void SwMSDffManager::EnableFallbackStream()
389 pStData2 = pFallbackStream;
390 pEscherBlipCache = pOldEscherBlipCache;
391 pOldEscherBlipCache = 0;
392 pFallbackStream = 0;
395 USHORT SwWW8ImplReader::GetToggleAttrFlags() const
397 return pCtrlStck ? pCtrlStck->GetToggleAttrFlags() : 0;
400 USHORT SwWW8ImplReader::GetToggleBiDiAttrFlags() const
402 return pCtrlStck ? pCtrlStck->GetToggleBiDiAttrFlags() : 0;
405 void SwWW8ImplReader::SetToggleAttrFlags(USHORT nFlags)
407 if (pCtrlStck)
408 pCtrlStck->SetToggleAttrFlags(nFlags);
411 void SwWW8ImplReader::SetToggleBiDiAttrFlags(USHORT nFlags)
413 if (pCtrlStck)
414 pCtrlStck->SetToggleBiDiAttrFlags(nFlags);
418 SdrObject* SwMSDffManager::ProcessObj(SvStream& rSt,
419 DffObjData& rObjData,
420 void* pData,
421 Rectangle& rTextRect,
422 SdrObject* pObj
425 if( !rTextRect.IsEmpty() )
427 SvxMSDffImportData& rImportData = *(SvxMSDffImportData*)pData;
428 SvxMSDffImportRec* pImpRec = new SvxMSDffImportRec;
430 // fill Import Record with data
431 pImpRec->nShapeId = rObjData.nShapeId;
432 pImpRec->eShapeType = rObjData.eShapeType;
434 rObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt,
435 DFF_msofbtClientAnchor,
436 SEEK_FROM_CURRENT_AND_RESTART );
437 if( rObjData.bClientAnchor )
438 ProcessClientAnchor( rSt,
439 maShapeRecords.Current()->nRecLen,
440 pImpRec->pClientAnchorBuffer, pImpRec->nClientAnchorLen );
442 rObjData.bClientData = maShapeRecords.SeekToContent( rSt,
443 DFF_msofbtClientData,
444 SEEK_FROM_CURRENT_AND_RESTART );
445 if( rObjData.bClientData )
446 ProcessClientData( rSt,
447 maShapeRecords.Current()->nRecLen,
448 pImpRec->pClientDataBuffer, pImpRec->nClientDataLen );
451 // process user (== Winword) defined parameters in 0xF122 record
452 // --> OD 2008-04-10 #i84783#
453 // set special value to determine, if property is provided or not.
454 pImpRec->nLayoutInTableCell = 0xFFFFFFFF;
455 // <--
456 if( maShapeRecords.SeekToContent( rSt,
457 DFF_msofbtUDefProp,
458 SEEK_FROM_CURRENT_AND_RESTART )
459 && maShapeRecords.Current()->nRecLen )
461 UINT32 nBytesLeft = maShapeRecords.Current()->nRecLen;
462 UINT32 nUDData;
463 UINT16 nPID;
464 while( 5 < nBytesLeft )
466 rSt >> nPID;
467 if ( rSt.GetError() != 0 )
468 break;
469 rSt >> nUDData;
470 switch( nPID )
472 case 0x038F: pImpRec->nXAlign = nUDData; break;
473 case 0x0390: pImpRec->nXRelTo = nUDData; break;
474 case 0x0391: pImpRec->nYAlign = nUDData; break;
475 case 0x0392: pImpRec->nYRelTo = nUDData; break;
476 case 0x03BF: pImpRec->nLayoutInTableCell = nUDData; break;
478 if ( rSt.GetError() != 0 )
479 break;
480 pImpRec->bHasUDefProp = TRUE;
481 nBytesLeft -= 6;
485 // Textrahmen, auch Title oder Outline
486 UINT32 nTextId = GetPropertyValue( DFF_Prop_lTxid, 0 );
487 if( nTextId )
489 SfxItemSet aSet( pSdrModel->GetItemPool() );
491 //Originally anything that as a mso_sptTextBox was created as a
492 //textbox, this was changed for #88277# to be created as a simple
493 //rect to keep impress happy. For the rest of us we'd like to turn
494 //it back into a textbox again.
495 BOOL bIsSimpleDrawingTextBox = (pImpRec->eShapeType == mso_sptTextBox);
496 if (!bIsSimpleDrawingTextBox)
498 //Either
499 //a) its a simple text object or
500 //b) its a rectangle with text and square wrapping.
501 bIsSimpleDrawingTextBox =
503 (pImpRec->eShapeType == mso_sptTextSimple) ||
505 (pImpRec->eShapeType == mso_sptRectangle)
506 // && (eWrapMode == mso_wrapSquare)
507 && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() )
512 // Distance of Textbox to it's surrounding Autoshape
513 INT32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 91440L);
514 INT32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 91440L );
515 INT32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 45720L );
516 INT32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 45720L );
518 ScaleEmu( nTextLeft );
519 ScaleEmu( nTextRight );
520 ScaleEmu( nTextTop );
521 ScaleEmu( nTextBottom );
523 INT32 nTextRotationAngle=0;
524 bool bVerticalText = false;
525 if ( IsProperty( DFF_Prop_txflTextFlow ) )
527 MSO_TextFlow eTextFlow = (MSO_TextFlow)(GetPropertyValue(
528 DFF_Prop_txflTextFlow) & 0xFFFF);
529 switch( eTextFlow )
531 case mso_txflBtoT:
532 nTextRotationAngle = 9000;
533 break;
534 case mso_txflVertN:
535 case mso_txflTtoBN:
536 nTextRotationAngle = 27000;
537 break;
538 case mso_txflTtoBA:
539 bVerticalText = true;
540 break;
541 case mso_txflHorzA:
542 bVerticalText = true;
543 nTextRotationAngle = 9000;
544 case mso_txflHorzN:
545 default :
546 break;
550 if (nTextRotationAngle)
552 while (nTextRotationAngle > 360000)
553 nTextRotationAngle-=9000;
554 switch (nTextRotationAngle)
556 case 9000:
558 long nWidth = rTextRect.GetWidth();
559 rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight();
560 rTextRect.Bottom() = rTextRect.Top() + nWidth;
562 INT32 nOldTextLeft = nTextLeft;
563 INT32 nOldTextRight = nTextRight;
564 INT32 nOldTextTop = nTextTop;
565 INT32 nOldTextBottom = nTextBottom;
567 nTextLeft = nOldTextBottom;
568 nTextRight = nOldTextTop;
569 nTextTop = nOldTextLeft;
570 nTextBottom = nOldTextRight;
572 break;
573 case 27000:
575 long nWidth = rTextRect.GetWidth();
576 rTextRect.Right() = rTextRect.Left() + rTextRect.GetHeight();
577 rTextRect.Bottom() = rTextRect.Top() + nWidth;
579 INT32 nOldTextLeft = nTextLeft;
580 INT32 nOldTextRight = nTextRight;
581 INT32 nOldTextTop = nTextTop;
582 INT32 nOldTextBottom = nTextBottom;
584 nTextLeft = nOldTextTop;
585 nTextRight = nOldTextBottom;
586 nTextTop = nOldTextRight;
587 nTextBottom = nOldTextLeft;
589 break;
590 default:
591 break;
595 if (bIsSimpleDrawingTextBox)
597 SdrObject::Free( pObj );
598 pObj = new SdrRectObj(OBJ_TEXT, rTextRect);
601 // Die vertikalen Absatzeinrueckungen sind im BoundRect mit drin,
602 // hier rausrechnen
603 Rectangle aNewRect(rTextRect);
604 aNewRect.Bottom() -= nTextTop + nTextBottom;
605 aNewRect.Right() -= nTextLeft + nTextRight;
607 // Nur falls es eine einfache Textbox ist, darf der Writer
608 // das Objekt durch einen Rahmen ersetzen, ansonsten
609 if( bIsSimpleDrawingTextBox )
611 SvxMSDffShapeInfo aTmpRec( 0, pImpRec->nShapeId );
612 aTmpRec.bSortByShapeId = TRUE;
614 USHORT nFound;
615 if( GetShapeInfos()->Seek_Entry( &aTmpRec, &nFound ) )
617 SvxMSDffShapeInfo& rInfo = *GetShapeInfos()->GetObject(nFound);
618 pImpRec->bReplaceByFly = rInfo.bReplaceByFly;
619 pImpRec->bLastBoxInChain = rInfo.bLastBoxInChain;
623 if( bIsSimpleDrawingTextBox )
624 ApplyAttributes( rSt, aSet, rObjData );
626 bool bFitText = false;
627 if (GetPropertyValue(DFF_Prop_FitTextToShape) & 2)
629 aSet.Put( SdrTextAutoGrowHeightItem( TRUE ) );
630 aSet.Put( SdrTextMinFrameHeightItem(
631 aNewRect.Bottom() - aNewRect.Top() ) );
632 aSet.Put( SdrTextMinFrameWidthItem(
633 aNewRect.Right() - aNewRect.Left() ) );
634 bFitText = true;
636 else
638 aSet.Put( SdrTextAutoGrowHeightItem( FALSE ) );
639 aSet.Put( SdrTextAutoGrowWidthItem( FALSE ) );
642 switch ( (MSO_WrapMode)
643 GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare ) )
645 case mso_wrapNone :
646 aSet.Put( SdrTextAutoGrowWidthItem( TRUE ) );
647 pImpRec->bAutoWidth = true;
648 break;
649 case mso_wrapByPoints :
650 aSet.Put( SdrTextContourFrameItem( TRUE ) );
651 break;
652 default:
656 // Abstaende an den Raendern der Textbox setzen
657 aSet.Put( SdrTextLeftDistItem( nTextLeft ) );
658 aSet.Put( SdrTextRightDistItem( nTextRight ) );
659 aSet.Put( SdrTextUpperDistItem( nTextTop ) );
660 aSet.Put( SdrTextLowerDistItem( nTextBottom ) );
661 pImpRec->nDxTextLeft = nTextLeft;
662 pImpRec->nDyTextTop = nTextTop;
663 pImpRec->nDxTextRight = nTextRight;
664 pImpRec->nDyTextBottom = nTextBottom;
666 // --> SJ 2009-03-06 : taking the correct default (which is mso_anchorTop)
667 MSO_Anchor eTextAnchor =
668 (MSO_Anchor)GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop );
670 SdrTextVertAdjust eTVA = bVerticalText
671 ? SDRTEXTVERTADJUST_BLOCK
672 : SDRTEXTVERTADJUST_CENTER;
673 SdrTextHorzAdjust eTHA = bVerticalText
674 ? SDRTEXTHORZADJUST_CENTER
675 : SDRTEXTHORZADJUST_BLOCK;
677 switch( eTextAnchor )
679 case mso_anchorTop:
681 if ( bVerticalText )
682 eTHA = SDRTEXTHORZADJUST_RIGHT;
683 else
684 eTVA = SDRTEXTVERTADJUST_TOP;
686 break;
687 case mso_anchorTopCentered:
689 if ( bVerticalText )
690 eTHA = SDRTEXTHORZADJUST_RIGHT;
691 else
692 eTVA = SDRTEXTVERTADJUST_TOP;
694 break;
695 case mso_anchorMiddle:
696 break;
697 case mso_anchorMiddleCentered:
698 break;
699 case mso_anchorBottom:
701 if ( bVerticalText )
702 eTHA = SDRTEXTHORZADJUST_LEFT;
703 else
704 eTVA = SDRTEXTVERTADJUST_BOTTOM;
706 break;
707 case mso_anchorBottomCentered:
709 if ( bVerticalText )
710 eTHA = SDRTEXTHORZADJUST_LEFT;
711 else
712 eTVA = SDRTEXTVERTADJUST_BOTTOM;
714 break;
716 case mso_anchorTopBaseline:
717 case mso_anchorBottomBaseline:
718 case mso_anchorTopCenteredBaseline:
719 case mso_anchorBottomCenteredBaseline:
720 break;
722 default:
726 aSet.Put( SdrTextVertAdjustItem( eTVA ) );
727 aSet.Put( SdrTextHorzAdjustItem( eTHA ) );
729 pObj->SetMergedItemSet(aSet);
730 pObj->SetModel(pSdrModel);
732 if (bVerticalText && dynamic_cast< SdrTextObj* >( pObj ) )
733 dynamic_cast< SdrTextObj* >( pObj )->SetVerticalWriting(sal_True);
735 if ( bIsSimpleDrawingTextBox )
737 if ( nTextRotationAngle )
739 long nMinWH = rTextRect.GetWidth() < rTextRect.GetHeight() ?
740 rTextRect.GetWidth() : rTextRect.GetHeight();
741 nMinWH /= 2;
742 Point aPivot(rTextRect.TopLeft());
743 aPivot.X() += nMinWH;
744 aPivot.Y() += nMinWH;
745 double a = nTextRotationAngle * nPi180;
746 pObj->NbcRotate(aPivot, nTextRotationAngle, sin(a), cos(a));
750 if ( ( ( rObjData.nSpFlags & SP_FFLIPV ) || mnFix16Angle || nTextRotationAngle ) && dynamic_cast< SdrObjCustomShape* >( pObj ) )
752 SdrObjCustomShape* pCustomShape = dynamic_cast< SdrObjCustomShape* >( pObj );
754 double fExtraTextRotation = 0.0;
755 if ( mnFix16Angle && !( GetPropertyValue( DFF_Prop_FitTextToShape ) & 4 ) )
756 { // text is already rotated, we have to take back the object rotation if DFF_Prop_RotateText is false
757 fExtraTextRotation = -mnFix16Angle;
759 if ( rObjData.nSpFlags & SP_FFLIPV ) // sj: in ppt the text is flipped, whereas in word the text
760 { // remains unchanged, so we have to take back the flipping here
761 fExtraTextRotation += 18000.0; // because our core will flip text if the shape is flipped.
763 fExtraTextRotation += nTextRotationAngle;
764 if ( !::basegfx::fTools::equalZero( fExtraTextRotation ) )
766 fExtraTextRotation /= 100.0;
767 SdrCustomShapeGeometryItem aGeometryItem( (SdrCustomShapeGeometryItem&)pCustomShape->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
768 const rtl::OUString sTextRotateAngle( RTL_CONSTASCII_USTRINGPARAM ( "TextRotateAngle" ) );
769 com::sun::star::beans::PropertyValue aPropVal;
770 aPropVal.Name = sTextRotateAngle;
771 aPropVal.Value <<= fExtraTextRotation;
772 aGeometryItem.SetPropertyValue( aPropVal );
773 pCustomShape->SetMergedItem( aGeometryItem );
776 else if ( mnFix16Angle )
778 // rotate text with shape ?
779 double a = mnFix16Angle * nPi180;
780 pObj->NbcRotate( rObjData.aBoundRect.Center(), mnFix16Angle,
781 sin( a ), cos( a ) );
784 else if( !pObj )
786 // simple rectangular objects are ignored by ImportObj() :-(
787 // this is OK for Draw but not for Calc and Writer
788 // cause here these objects have a default border
789 pObj = new SdrRectObj(rTextRect);
790 pObj->SetModel( pSdrModel );
791 SfxItemSet aSet( pSdrModel->GetItemPool() );
792 ApplyAttributes( rSt, aSet, rObjData );
794 const SfxPoolItem* pPoolItem=NULL;
795 SfxItemState eState = aSet.GetItemState( XATTR_FILLCOLOR,
796 FALSE, &pPoolItem );
797 if( SFX_ITEM_DEFAULT == eState )
798 aSet.Put( XFillColorItem( String(),
799 Color( mnDefaultColor ) ) );
800 pObj->SetMergedItemSet(aSet);
803 //Means that fBehindDocument is set
804 if (GetPropertyValue(DFF_Prop_fPrint) & 0x20)
805 pImpRec->bDrawHell = TRUE;
806 else
807 pImpRec->bDrawHell = FALSE;
808 if (GetPropertyValue(DFF_Prop_fPrint) & 0x02)
809 pImpRec->bHidden = TRUE;
810 pImpRec->nNextShapeId = GetPropertyValue( DFF_Prop_hspNext, 0 );
812 if ( nTextId )
814 pImpRec->aTextId.nTxBxS = (UINT16)( nTextId >> 16 );
815 pImpRec->aTextId.nSequence = (UINT16)nTextId;
818 pImpRec->nDxWrapDistLeft = GetPropertyValue(
819 DFF_Prop_dxWrapDistLeft, 114935L ) / 635L;
820 pImpRec->nDyWrapDistTop = GetPropertyValue(
821 DFF_Prop_dyWrapDistTop, 0 ) / 635L;
822 pImpRec->nDxWrapDistRight = GetPropertyValue(
823 DFF_Prop_dxWrapDistRight, 114935L ) / 635L;
824 pImpRec->nDyWrapDistBottom = GetPropertyValue(
825 DFF_Prop_dyWrapDistBottom, 0 ) / 635L;
826 // 16.16 fraction times total image width or height, as appropriate.
828 if (SeekToContent(DFF_Prop_pWrapPolygonVertices, rSt))
830 delete pImpRec->pWrapPolygon;
831 sal_uInt16 nNumElemVert, nNumElemMemVert, nElemSizeVert;
832 rSt >> nNumElemVert >> nNumElemMemVert >> nElemSizeVert;
833 if (nNumElemVert && ((nElemSizeVert == 8) || (nElemSizeVert == 4)))
835 pImpRec->pWrapPolygon = new Polygon(nNumElemVert);
836 for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
838 sal_Int32 nX, nY;
839 if (nElemSizeVert == 8)
840 rSt >> nX >> nY;
841 else
843 sal_Int16 nSmallX, nSmallY;
844 rSt >> nSmallX >> nSmallY;
845 nX = nSmallX;
846 nY = nSmallY;
848 (*(pImpRec->pWrapPolygon))[i].X() = nX;
849 (*(pImpRec->pWrapPolygon))[i].Y() = nY;
854 pImpRec->nCropFromTop = GetPropertyValue(
855 DFF_Prop_cropFromTop, 0 );
856 pImpRec->nCropFromBottom = GetPropertyValue(
857 DFF_Prop_cropFromBottom, 0 );
858 pImpRec->nCropFromLeft = GetPropertyValue(
859 DFF_Prop_cropFromLeft, 0 );
860 pImpRec->nCropFromRight = GetPropertyValue(
861 DFF_Prop_cropFromRight, 0 );
863 UINT32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash );
864 // --> OD 2008-06-16 #156765#
865 if ( !IsHardAttribute( DFF_Prop_fLine ) &&
866 pImpRec->eShapeType == mso_sptPictureFrame )
868 nLineFlags &= ~0x08;
870 // <--
871 pImpRec->eLineStyle = (nLineFlags & 8)
872 ? (MSO_LineStyle)GetPropertyValue(
873 DFF_Prop_lineStyle,
874 mso_lineSimple )
875 : (MSO_LineStyle)USHRT_MAX;
877 pImpRec->nFlags = rObjData.nSpFlags;
879 if( pImpRec->nShapeId )
881 // Import-Record-Liste ergaenzen
882 pImpRec->pObj = pObj;
883 rImportData.aRecords.Insert( pImpRec );
885 // Eintrag in Z-Order-Liste um Zeiger auf dieses Objekt ergaenzen
886 /*Only store objects which are not deep inside the tree*/
887 if( ( rObjData.nCalledByGroup == 0 )
889 ( (rObjData.nSpFlags & SP_FGROUP)
890 && (rObjData.nCalledByGroup < 2) )
892 StoreShapeOrder( pImpRec->nShapeId,
893 ( ( (ULONG)pImpRec->aTextId.nTxBxS ) << 16 )
894 + pImpRec->aTextId.nSequence, pObj );
896 else
897 delete pImpRec;
900 return pObj;
903 /***************************************************************************
904 # Spezial FastSave - Attribute
905 #**************************************************************************/
907 void SwWW8ImplReader::Read_StyleCode( USHORT, const BYTE* pData, short nLen )
909 if (nLen < 0)
911 bCpxStyle = false;
912 return;
914 USHORT nColl = 0;
915 if (pWwFib->GetFIBVersion() <= ww::eWW2)
916 nColl = *pData;
917 else
918 nColl = SVBT16ToShort(pData);
919 if (nColl < nColls)
921 SetTxtFmtCollAndListLevel( *pPaM, pCollA[nColl] );
922 bCpxStyle = true;
926 // Read_Majority ist fuer Majority ( 103 ) und Majority50 ( 108 )
927 void SwWW8ImplReader::Read_Majority( USHORT, const BYTE* , short )
931 //-----------------------------------------
932 // Stack
933 //-----------------------------------------
934 void SwWW8FltControlStack::NewAttr(const SwPosition& rPos,
935 const SfxPoolItem& rAttr)
937 ASSERT(RES_TXTATR_FIELD != rAttr.Which(), "probably don't want to put"
938 "fields into the control stack");
939 ASSERT(RES_FLTR_REDLINE != rAttr.Which(), "probably don't want to put"
940 "redlines into the control stack");
941 SwFltControlStack::NewAttr(rPos, rAttr);
944 void SwWW8FltControlStack::SetAttr(const SwPosition& rPos, USHORT nAttrId,
945 BOOL bTstEnde, long nHand, BOOL )
947 //Doing a textbox, and using the control stack only as a temporary
948 //collection point for properties which will are not to be set into
949 //the real document
950 if (rReader.pPlcxMan && rReader.pPlcxMan->GetDoingDrawTextBox())
952 USHORT nCnt = static_cast< USHORT >(Count());
953 for (USHORT i=0; i < nCnt; ++i)
955 SwFltStackEntry* pEntry = (*this)[i];
956 if (nAttrId == pEntry->pAttr->Which())
958 DeleteAndDestroy(i--);
959 --nCnt;
963 else //Normal case, set the attribute into the document
964 SwFltControlStack::SetAttr(rPos, nAttrId, bTstEnde, nHand);
967 long GetListFirstLineIndent(const SwNumFmt &rFmt)
969 ASSERT( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
970 "<GetListFirstLineIndent> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
972 SvxAdjust eAdj = rFmt.GetNumAdjust();
973 long nReverseListIndented;
974 if (eAdj == SVX_ADJUST_RIGHT)
975 nReverseListIndented = -rFmt.GetCharTextDistance();
976 else if (eAdj == SVX_ADJUST_CENTER)
977 nReverseListIndented = rFmt.GetFirstLineOffset()/2;
978 else
979 nReverseListIndented = rFmt.GetFirstLineOffset();
980 return nReverseListIndented;
983 long lcl_GetTrueMargin(const SvxLRSpaceItem &rLR, const SwNumFmt &rFmt,
984 long &rFirstLinePos)
986 ASSERT( rFmt.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_WIDTH_AND_POSITION,
987 "<lcl_GetTrueMargin> - misusage: position-and-space-mode does not equal LABEL_WIDTH_AND_POSITION" );
989 const long nBodyIndent = rLR.GetTxtLeft();
990 const long nFirstLineDiff = rLR.GetTxtFirstLineOfst();
991 rFirstLinePos = nBodyIndent + nFirstLineDiff;
993 const long nPseudoListBodyIndent = rFmt.GetAbsLSpace();
994 const long nReverseListIndented = GetListFirstLineIndent(rFmt);
995 long nExtraListIndent = nPseudoListBodyIndent + nReverseListIndented;
997 return nExtraListIndent > 0 ? nExtraListIndent : 0;
1000 void SyncIndentWithList(SvxLRSpaceItem &rLR, const SwNumFmt &rFmt)
1002 long nWantedFirstLinePos;
1003 long nExtraListIndent = lcl_GetTrueMargin(rLR, rFmt, nWantedFirstLinePos);
1004 rLR.SetTxtLeft(nWantedFirstLinePos - nExtraListIndent);
1005 rLR.SetTxtFirstLineOfst(0);
1008 const SwNumFmt* SwWW8FltControlStack::GetNumFmtFromStack(const SwPosition &rPos,
1009 const SwTxtNode &rTxtNode)
1011 const SwNumFmt *pRet = 0;
1012 const SfxPoolItem *pItem = GetStackAttr(rPos, RES_FLTR_NUMRULE);
1013 if (pItem && rTxtNode.GetNumRule())
1015 String sName(((SfxStringItem*)pItem)->GetValue());
1016 if (rTxtNode.IsCountedInList())
1018 const SwNumRule *pRule = pDoc->FindNumRulePtr(sName);
1019 BYTE nLvl = static_cast< BYTE >(rTxtNode.GetActualListLevel());
1020 pRet = &(pRule->Get(nLvl));
1023 return pRet;
1026 void SwWW8FltControlStack::SetAttrInDoc(const SwPosition& rTmpPos,
1027 SwFltStackEntry* pEntry)
1029 switch( pEntry->pAttr->Which() )
1031 case RES_LR_SPACE:
1034 Loop over the affect nodes and
1035 a) convert the word style absolute indent to indent relative
1036 to any numbering indent active on the nodes
1037 b) adjust the writer style tabstops relative to the old
1038 paragraph indent to be relative to the new paragraph indent
1040 using namespace sw::util;
1041 SwPaM aRegion(rTmpPos);
1042 if (pEntry->MakeRegion(pDoc, aRegion, false))
1044 SvxLRSpaceItem aNewLR( *(SvxLRSpaceItem*)pEntry->pAttr );
1045 ULONG nStart = aRegion.Start()->nNode.GetIndex();
1046 ULONG nEnd = aRegion.End()->nNode.GetIndex();
1047 for(; nStart <= nEnd; ++nStart)
1049 SwNode* pNode = pDoc->GetNodes()[ nStart ];
1050 if (!pNode || !pNode->IsTxtNode())
1051 continue;
1053 SwCntntNode* pNd = (SwCntntNode*)pNode;
1054 SvxLRSpaceItem aOldLR = (const SvxLRSpaceItem&)
1055 pNd->GetAttr(RES_LR_SPACE);
1057 SwTxtNode *pTxtNode = (SwTxtNode*)pNode;
1059 const SwNumFmt *pNum = 0;
1060 pNum = GetNumFmtFromStack(*aRegion.GetPoint(),
1061 *pTxtNode);
1062 if (!pNum)
1063 pNum = GetNumFmtFromTxtNode(*pTxtNode);
1065 // --> OD 2008-06-03 #i86652#
1066 // if (pNum)
1067 if ( pNum &&
1068 pNum->GetPositionAndSpaceMode() ==
1069 SvxNumberFormat::LABEL_WIDTH_AND_POSITION )
1070 // <--
1072 SyncIndentWithList(aNewLR, *pNum);
1075 if (aNewLR == aOldLR)
1076 continue;
1078 pNd->SetAttr(aNewLR);
1083 break;
1084 case RES_TXTATR_FIELD:
1085 ASSERT(!this, "What is a field doing in the control stack,"
1086 "probably should have been in the endstack");
1087 break;
1088 case RES_TXTATR_INETFMT:
1090 SwPaM aRegion(rTmpPos);
1091 if (pEntry->MakeRegion(pDoc, aRegion, false))
1093 SwFrmFmt *pFrm;
1094 //If we have just one single inline graphic then
1095 //don't insert a field for the single frame, set
1096 //the frames hyperlink field attribute directly.
1097 if (0 != (pFrm = rReader.ContainsSingleInlineGraphic(aRegion)))
1099 const SwFmtINetFmt *pAttr = (const SwFmtINetFmt *)
1100 pEntry->pAttr;
1101 SwFmtURL aURL;
1102 aURL.SetURL(pAttr->GetValue(), false);
1103 aURL.SetTargetFrameName(pAttr->GetTargetFrame());
1104 pFrm->SetFmtAttr(aURL);
1106 else
1108 pDoc->InsertPoolItem(aRegion, *pEntry->pAttr, 0);
1112 break;
1113 default:
1114 SwFltControlStack::SetAttrInDoc(rTmpPos, pEntry);
1115 break;
1119 const SfxPoolItem* SwWW8FltControlStack::GetFmtAttr(const SwPosition& rPos,
1120 USHORT nWhich)
1122 const SfxPoolItem *pItem = GetStackAttr(rPos, nWhich);
1123 if (!pItem)
1125 const SwCntntNode *pNd = pDoc->GetNodes()[ rPos.nNode ]->GetCntntNode();
1126 if (!pNd)
1127 pItem = &pDoc->GetAttrPool().GetDefaultItem(nWhich);
1128 else
1131 If we're hunting for the indent on a paragraph and need to use the
1132 parent style indent, then return the indent in msword format, and
1133 not writer format, because that's the style that the filter works
1134 in (naturally)
1136 if (nWhich == RES_LR_SPACE)
1138 SfxItemState eState = SFX_ITEM_DEFAULT;
1139 if (const SfxItemSet *pSet = pNd->GetpSwAttrSet())
1140 eState = pSet->GetItemState(RES_LR_SPACE, false);
1141 if (eState != SFX_ITEM_SET)
1142 pItem = &(rReader.pCollA[rReader.nAktColl].maWordLR);
1145 if (!pItem)
1146 pItem = &pNd->GetAttr(nWhich);
1149 return pItem;
1152 const SfxPoolItem* SwWW8FltControlStack::GetStackAttr(const SwPosition& rPos,
1153 USHORT nWhich)
1155 SwNodeIndex aNode( rPos.nNode, -1 );
1156 USHORT nIdx = rPos.nContent.GetIndex();
1158 USHORT nSize = static_cast< USHORT >(Count());
1159 while (nSize)
1161 const SwFltStackEntry* pEntry = (*this)[ --nSize ];
1162 if (pEntry->pAttr->Which() == nWhich)
1164 if ( (pEntry->bLocked) || (
1165 (pEntry->nMkNode <= aNode) && (pEntry->nPtNode >= aNode) &&
1166 (pEntry->nMkCntnt <= nIdx) && (pEntry->nPtCntnt >= nIdx) ) )
1168 return (const SfxPoolItem*)pEntry->pAttr;
1172 return 0;
1175 bool SwWW8FltRefStack::IsFtnEdnBkmField(const SwFmtFld& rFmtFld, USHORT& rBkmNo)
1177 const SwField* pFld = rFmtFld.GetFld();
1178 USHORT nSubType;
1179 if(pFld && (RES_GETREFFLD == pFld->Which())
1180 && ((REF_FOOTNOTE == (nSubType = pFld->GetSubType())) || (REF_ENDNOTE == nSubType))
1181 && ((SwGetRefField*)pFld)->GetSetRefName().Len())
1183 const IDocumentMarkAccess* const pMarkAccess = pDoc->getIDocumentMarkAccess();
1184 IDocumentMarkAccess::const_iterator_t ppBkmk = pMarkAccess->findMark(
1185 ((SwGetRefField*)pFld)->GetSetRefName());
1186 if(ppBkmk != pMarkAccess->getMarksEnd())
1188 // find Sequence No of corresponding Foot-/Endnote
1189 rBkmNo = ppBkmk - pMarkAccess->getMarksBegin();
1190 return true;
1193 return false;
1196 void SwWW8FltRefStack::SetAttrInDoc(const SwPosition& rTmpPos,
1197 SwFltStackEntry* pEntry)
1199 switch( pEntry->pAttr->Which() )
1202 Look up these in our lists of bookmarks that were changed to
1203 variables, and replace the ref field with a var field, otherwise
1204 do normal (?) strange stuff
1206 case RES_TXTATR_FIELD:
1208 SwNodeIndex aIdx(pEntry->nMkNode, 1);
1209 SwPaM aPaM(aIdx, pEntry->nMkCntnt);
1211 SwFmtFld& rFmtFld = *(SwFmtFld*)pEntry->pAttr;
1212 SwField* pFld = rFmtFld.GetFld();
1214 // OD 2004-03-19 - <NOT> got lost from revision 1.128 to 1.129
1215 if (!RefToVar(pFld,pEntry))
1217 USHORT nBkmNo;
1218 if( IsFtnEdnBkmField(rFmtFld, nBkmNo) )
1220 ::sw::mark::IMark const * const pMark = (pDoc->getIDocumentMarkAccess()->getMarksBegin() + nBkmNo)->get();
1222 const SwPosition& rBkMrkPos = pMark->GetMarkPos();
1224 SwTxtNode* pTxt = rBkMrkPos.nNode.GetNode().GetTxtNode();
1225 if( pTxt && rBkMrkPos.nContent.GetIndex() )
1227 SwTxtAttr* const pFtn = pTxt->GetTxtAttrForCharAt(
1228 rBkMrkPos.nContent.GetIndex()-1, RES_TXTATR_FTN );
1229 if( pFtn )
1231 USHORT nRefNo = ((SwTxtFtn*)pFtn)->GetSeqRefNo();
1233 ((SwGetRefField*)pFld)->SetSeqNo( nRefNo );
1235 if( pFtn->GetFtn().IsEndNote() )
1236 ((SwGetRefField*)pFld)->SetSubType(REF_ENDNOTE);
1242 pDoc->InsertPoolItem(aPaM, *pEntry->pAttr, 0);
1243 MoveAttrs(*aPaM.GetPoint());
1245 break;
1246 case RES_FLTR_TOX:
1247 SwFltEndStack::SetAttrInDoc(rTmpPos, pEntry);
1248 break;
1249 default:
1250 case RES_FLTR_BOOKMARK:
1251 ASSERT(!this, "EndStck used with non field, not what we want");
1252 SwFltEndStack::SetAttrInDoc(rTmpPos, pEntry);
1253 break;
1258 For styles we will do our tabstop arithmetic in word style and adjust them to
1259 writer style after all the styles have been finished and the dust settles as
1260 to what affects what.
1262 For explicit attributes we turn the adjusted writer tabstops back into 0 based
1263 word indexes and we'll turn them back into writer indexes when setting them
1264 into the document. If explicit left indent exist which affects them, then this
1265 is handled when the explict left indent is set into the document
1267 void SwWW8ImplReader::Read_Tab(USHORT , const BYTE* pData, short nLen)
1269 if (nLen < 0)
1271 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_TABSTOP);
1272 return;
1275 short i;
1276 const BYTE* pDel = pData + 1; // Del - Array
1277 BYTE nDel = pData[0];
1278 const BYTE* pIns = pData + 2*nDel + 2; // Ins - Array
1279 BYTE nIns = pData[nDel*2+1];
1280 WW8_TBD* pTyp = (WW8_TBD*)(pData + 2*nDel + 2*nIns + 2);// Typ - Array
1282 SvxTabStopItem aAttr(0, 0, SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP);
1284 const SwTxtFmtColl* pSty = 0;
1285 USHORT nTabBase;
1286 if (pAktColl) // StyleDef
1288 nTabBase = pCollA[nAktColl].nBase;
1289 if (nTabBase < nColls) // Based On
1290 pSty = (const SwTxtFmtColl*)pCollA[nTabBase].pFmt;
1292 else
1293 { // Text
1294 nTabBase = nAktColl;
1295 pSty = (const SwTxtFmtColl*)pCollA[nAktColl].pFmt;
1298 bool bFound = false;
1299 ::std::hash_set<size_t> aLoopWatch;
1300 while (pSty && !bFound)
1302 const SfxPoolItem* pTabs;
1303 bFound = pSty->GetAttrSet().GetItemState(RES_PARATR_TABSTOP, false,
1304 &pTabs) == SFX_ITEM_SET;
1305 if( bFound )
1306 aAttr = *((const SvxTabStopItem*)pTabs);
1307 else
1310 USHORT nOldTabBase = nTabBase;
1311 // If based on another
1312 if (nTabBase < nColls)
1313 nTabBase = pCollA[nTabBase].nBase;
1315 if (
1316 nTabBase < nColls &&
1317 nOldTabBase != nTabBase &&
1318 nTabBase != ww::stiNil
1321 // #i61789: Stop searching when next style is the same as the
1322 // current one (prevent loop)
1323 aLoopWatch.insert(reinterpret_cast<size_t>(pSty));
1324 pSty = (const SwTxtFmtColl*)pCollA[nTabBase].pFmt;
1326 if (aLoopWatch.find(reinterpret_cast<size_t>(pSty)) !=
1327 aLoopWatch.end())
1328 pSty = 0;
1330 else
1331 pSty = 0; // gib die Suche auf
1335 SvxTabStop aTabStop;
1336 for (i=0; i < nDel; ++i)
1338 USHORT nPos = aAttr.GetPos(SVBT16ToShort(pDel + i*2));
1339 if( nPos != SVX_TAB_NOTFOUND )
1340 aAttr.Remove( nPos, 1 );
1343 for (i=0; i < nIns; ++i)
1345 short nPos = SVBT16ToShort(pIns + i*2);
1346 aTabStop.GetTabPos() = nPos;
1347 switch( SVBT8ToByte( pTyp[i].aBits1 ) & 0x7 ) // pTyp[i].jc
1349 case 0:
1350 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_LEFT;
1351 break;
1352 case 1:
1353 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_CENTER;
1354 break;
1355 case 2:
1356 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_RIGHT;
1357 break;
1358 case 3:
1359 aTabStop.GetAdjustment() = SVX_TAB_ADJUST_DECIMAL;
1360 break;
1361 case 4:
1362 continue; // ignoriere Bar
1365 switch( SVBT8ToByte( pTyp[i].aBits1 ) >> 3 & 0x7 )
1367 case 0:
1368 aTabStop.GetFill() = ' ';
1369 break;
1370 case 1:
1371 aTabStop.GetFill() = '.';
1372 break;
1373 case 2:
1374 aTabStop.GetFill() = '-';
1375 break;
1376 case 3:
1377 case 4:
1378 aTabStop.GetFill() = '_';
1379 break;
1382 USHORT nPos2 = aAttr.GetPos( nPos );
1383 if (nPos2 != SVX_TAB_NOTFOUND)
1384 aAttr.Remove(nPos2, 1); // sonst weigert sich das Insert()
1385 aAttr.Insert(aTabStop);
1388 if (nIns || nDel)
1389 NewAttr(aAttr);
1390 else
1392 //Here we have a tab definition which inserts no extra tabs, or deletes
1393 //no existing tabs. An older version of writer is probably the creater
1394 //of the document :-( . So if we are importing a style we can just
1395 //ignore it. But if we are importing into text we cannot as during
1396 //text SwWW8ImplReader::Read_Tab is called at the begin and end of
1397 //the range the attrib affects, and ignoring it would upset the
1398 //balance
1399 if (!pAktColl) //not importing into a style
1401 using namespace sw::util;
1402 SvxTabStopItem aOrig = pSty ?
1403 ItemGet<SvxTabStopItem>(*pSty, RES_PARATR_TABSTOP) :
1404 DefaultItemGet<SvxTabStopItem>(rDoc, RES_PARATR_TABSTOP);
1405 NewAttr(aOrig);
1410 //-----------------------------------------
1411 // DOP
1412 //-----------------------------------------
1414 void SwWW8ImplReader::ImportDop()
1416 maTracer.EnterEnvironment(sw::log::eDocumentProperties);
1417 // correct the LastPrinted date in DocumentInfo
1418 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
1419 mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
1420 uno::Reference<document::XDocumentProperties> xDocuProps(
1421 xDPS->getDocumentProperties());
1422 DBG_ASSERT(xDocuProps.is(), "DocumentProperties is null");
1423 if (xDocuProps.is())
1425 DateTime aLastPrinted(
1426 sw::ms::DTTM2DateTime(pWDop->dttmLastPrint));
1427 ::util::DateTime uDT(aLastPrinted.Get100Sec(),
1428 aLastPrinted.GetSec(), aLastPrinted.GetMin(),
1429 aLastPrinted.GetHour(), aLastPrinted.GetDay(),
1430 aLastPrinted.GetMonth(), aLastPrinted.GetYear());
1431 xDocuProps->setPrintDate(uDT);
1435 // COMPATIBILITY FLAGS START
1438 // i#78951, remember the unknown compatability options
1439 // so as to export them out
1440 rDoc.Setn32DummyCompatabilityOptions1( pWDop->GetCompatabilityOptions());
1441 rDoc.Setn32DummyCompatabilityOptions2( pWDop->GetCompatabilityOptions2());
1443 // Abstand zwischen zwei Absaetzen ist die SUMME von unterem
1444 // Abst. des ersten und oberem Abst. des zweiten
1445 rDoc.set(IDocumentSettingAccess::PARA_SPACE_MAX, pWDop->fDontUseHTMLAutoSpacing);
1446 rDoc.set(IDocumentSettingAccess::PARA_SPACE_MAX_AT_PAGES, true );
1447 maTracer.Log(sw::log::eDontUseHTMLAutoSpacing);
1448 // move tabs on alignment
1449 rDoc.set(IDocumentSettingAccess::TAB_COMPAT, true);
1450 // #i24363# tab stops relative to indent
1451 rDoc.set(IDocumentSettingAccess::TABS_RELATIVE_TO_INDENT, false);
1452 maTracer.Log(sw::log::eTabStopDistance);
1453 // OD 14.10.2003 #i18732# - adjust default of option 'FollowTextFlow'
1454 rDoc.SetDefault( SwFmtFollowTextFlow( FALSE ) );
1456 // Import Default-Tabs
1457 long nDefTabSiz = pWDop->dxaTab;
1458 if( nDefTabSiz < 56 )
1459 nDefTabSiz = 709;
1461 // wir wollen genau einen DefaultTab
1462 SvxTabStopItem aNewTab( 1, USHORT(nDefTabSiz), SVX_TAB_ADJUST_DEFAULT, RES_PARATR_TABSTOP );
1463 ((SvxTabStop&)aNewTab[0]).GetAdjustment() = SVX_TAB_ADJUST_DEFAULT;
1465 rDoc.GetAttrPool().SetPoolDefaultItem( aNewTab );
1467 if (!pWDop->fUsePrinterMetrics)
1468 maTracer.Log(sw::log::ePrinterMetrics);
1470 if (!pWDop->fNoLeading)
1471 maTracer.Log(sw::log::eExtraLeading);
1473 rDoc.set(IDocumentSettingAccess::USE_VIRTUAL_DEVICE, !pWDop->fUsePrinterMetrics);
1474 rDoc.set(IDocumentSettingAccess::USE_HIRES_VIRTUAL_DEVICE, true);
1475 rDoc.set(IDocumentSettingAccess::ADD_FLY_OFFSETS, true );
1476 rDoc.set(IDocumentSettingAccess::ADD_EXT_LEADING, !pWDop->fNoLeading);
1478 // -> #111955#
1479 rDoc.set(IDocumentSettingAccess::OLD_NUMBERING, false);
1480 // <- #111955#
1482 // --> FME 2005-05-27 #i47448#
1483 rDoc.set(IDocumentSettingAccess::IGNORE_FIRST_LINE_INDENT_IN_NUMBERING, false);
1484 // <--
1486 // --> FME 2005-06-08 #i49277#
1487 rDoc.set(IDocumentSettingAccess::DO_NOT_JUSTIFY_LINES_WITH_MANUAL_BREAK, !pWDop->fExpShRtn); // #i56856#
1488 // --> FME 2005-08-11 #i53199#
1489 rDoc.set(IDocumentSettingAccess::DO_NOT_RESET_PARA_ATTRS_FOR_NUM_FONT, false);
1491 rDoc.set(IDocumentSettingAccess::OLD_LINE_SPACING, false);
1493 // OD, MMAHER 2004-03-01 #i25901#- set new compatibility option
1494 // 'Add paragraph and table spacing at bottom of table cells'
1495 rDoc.set(IDocumentSettingAccess::ADD_PARA_SPACING_TO_TABLE_CELLS, true);
1497 // OD 2004-03-17 #i11860# - set new compatibility option
1498 // 'Use former object positioning' to <FALSE>
1499 rDoc.set(IDocumentSettingAccess::USE_FORMER_OBJECT_POS, false);
1501 // OD 2004-05-10 #i27767# - set new compatibility option
1502 // 'Conder Wrapping mode when positioning object' to <TRUE>
1503 rDoc.set(IDocumentSettingAccess::CONSIDER_WRAP_ON_OBJECT_POSITION, true);
1505 // --> FME 2004-04-22 # #108724#, #i13832#, #i24135#
1506 rDoc.set(IDocumentSettingAccess::USE_FORMER_TEXT_WRAPPING, false);
1507 // <--
1509 // --> FME 2006-02-10 #131283#
1510 rDoc.set(IDocumentSettingAccess::TABLE_ROW_KEEP, true); //SetTableRowKeep( true );
1511 // <--
1513 // --> FME 2006-03-01 #i3952#
1514 rDoc.set(IDocumentSettingAccess::IGNORE_TABS_AND_BLANKS_FOR_LINE_CALCULATION, true);
1515 // <--
1517 rDoc.set(IDocumentSettingAccess::INVERT_BORDER_SPACING, true);
1518 rDoc.set(IDocumentSettingAccess::COLLAPSE_EMPTY_CELL_PARA, true);
1521 // COMPATIBILITY FLAGS END
1524 if (!pWDop->fNoLeading)
1525 maTracer.Log(sw::log::eExtraLeading);
1527 //import magic doptypography information, if its there
1528 if (pWwFib->nFib > 105)
1529 ImportDopTypography(pWDop->doptypography);
1531 // #110055# disable form design mode to be able to use imported controls directly
1532 // #i31239# always disable form design mode, not only in protected docs
1533 // if (pWDop->fProtEnabled)
1535 using namespace com::sun::star;
1537 uno::Reference<lang::XComponent> xModelComp(mpDocShell->GetModel(),
1538 uno::UNO_QUERY);
1539 uno::Reference<beans::XPropertySet> xDocProps(xModelComp,
1540 uno::UNO_QUERY);
1541 if (xDocProps.is())
1543 uno::Reference<beans::XPropertySetInfo> xInfo =
1544 xDocProps->getPropertySetInfo();
1545 sal_Bool bValue = false;
1546 if (xInfo.is() &&
1547 xInfo->hasPropertyByName(C2U("ApplyFormDesignMode")))
1549 xDocProps->setPropertyValue(C2U("ApplyFormDesignMode"),
1550 cppu::bool2any(bValue));
1554 const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
1555 sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
1556 if (bUseEnhFields) {
1557 rDoc.set(IDocumentSettingAccess::PROTECT_FORM, pWDop->fProtEnabled );
1560 maTracer.LeaveEnvironment(sw::log::eDocumentProperties);
1563 void SwWW8ImplReader::ImportDopTypography(const WW8DopTypography &rTypo)
1565 using namespace com::sun::star;
1566 switch (rTypo.iLevelOfKinsoku)
1568 case 2: //custom
1570 i18n::ForbiddenCharacters aForbidden(rTypo.rgxchFPunct,
1571 rTypo.rgxchLPunct);
1572 rDoc.setForbiddenCharacters(rTypo.GetConvertedLang(),
1573 aForbidden);
1574 //Obviously cannot set the standard level 1 for japanese, so
1575 //bail out now while we can.
1576 if (rTypo.GetConvertedLang() == LANGUAGE_JAPANESE)
1577 return;
1579 break;
1580 default:
1581 break;
1585 This MS hack means that level 2 of japanese is not in operation, so we put
1586 in what we know are the MS defaults, there is a complementary reverse
1587 hack in the writer. Its our default as well, but we can set it anyway
1588 as a flag for later.
1590 if (!rTypo.reserved2)
1592 i18n::ForbiddenCharacters aForbidden(rTypo.GetJapanNotBeginLevel1(),
1593 rTypo.GetJapanNotEndLevel1());
1594 rDoc.setForbiddenCharacters(LANGUAGE_JAPANESE,aForbidden);
1597 rDoc.set(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION, rTypo.fKerningPunct);
1598 rDoc.setCharacterCompressionType(static_cast<SwCharCompressType>(rTypo.iJustification));
1601 //-----------------------------------------
1602 // Fuss- und Endnoten
1604 //-----------------------------------------
1606 WW8ReaderSave::WW8ReaderSave(SwWW8ImplReader* pRdr ,WW8_CP nStartCp) :
1607 maTmpPos(*pRdr->pPaM->GetPoint()),
1608 mpOldStck(pRdr->pCtrlStck),
1609 mpOldAnchorStck(pRdr->pAnchorStck),
1610 mpOldRedlines(pRdr->mpRedlineStack),
1611 mpOldPlcxMan(pRdr->pPlcxMan),
1612 mpWFlyPara(pRdr->pWFlyPara),
1613 mpSFlyPara(pRdr->pSFlyPara),
1614 mpPreviousNumPaM(pRdr->pPreviousNumPaM),
1615 mpPrevNumRule(pRdr->pPrevNumRule),
1616 mpTableDesc(pRdr->pTableDesc),
1617 mnInTable(pRdr->nInTable),
1618 mnAktColl(pRdr->nAktColl),
1619 mcSymbol(pRdr->cSymbol),
1620 mbIgnoreText(pRdr->bIgnoreText),
1621 mbSymbol(pRdr->bSymbol),
1622 mbHdFtFtnEdn(pRdr->bHdFtFtnEdn),
1623 mbTxbxFlySection(pRdr->bTxbxFlySection),
1624 mbAnl(pRdr->bAnl),
1625 mbInHyperlink(pRdr->bInHyperlink),
1626 mbPgSecBreak(pRdr->bPgSecBreak),
1627 mbWasParaEnd(pRdr->bWasParaEnd),
1628 mbHasBorder(pRdr->bHasBorder),
1629 mbFirstPara(pRdr->bFirstPara)
1631 pRdr->bSymbol = false;
1632 pRdr->bHdFtFtnEdn = true;
1633 pRdr->bTxbxFlySection = pRdr->bAnl = pRdr->bPgSecBreak = pRdr->bWasParaEnd
1634 = pRdr->bHasBorder = false;
1635 pRdr->bFirstPara = true;
1636 pRdr->nInTable = 0;
1637 pRdr->pWFlyPara = 0;
1638 pRdr->pSFlyPara = 0;
1639 pRdr->pPreviousNumPaM = 0;
1640 pRdr->pPrevNumRule = 0;
1641 pRdr->pTableDesc = 0;
1642 pRdr->nAktColl = 0;
1645 pRdr->pCtrlStck = new SwWW8FltControlStack(&pRdr->rDoc, pRdr->nFieldFlags,
1646 *pRdr);
1648 pRdr->mpRedlineStack = new sw::util::RedlineStack(pRdr->rDoc);
1650 pRdr->pAnchorStck = new SwWW8FltAnchorStack(&pRdr->rDoc, pRdr->nFieldFlags);
1652 // rette die Attributverwaltung: dies ist noetig, da der neu anzulegende
1653 // PLCFx Manager natuerlich auf die gleichen FKPs zugreift, wie der alte
1654 // und deren Start-End-Positionen veraendert...
1655 if (pRdr->pPlcxMan)
1656 pRdr->pPlcxMan->SaveAllPLCFx(maPLCFxSave);
1658 if (nStartCp != -1)
1660 pRdr->pPlcxMan = new WW8PLCFMan(pRdr->pSBase,
1661 mpOldPlcxMan->GetManType(), nStartCp);
1664 maOldApos.push_back(false);
1665 maOldApos.swap(pRdr->maApos);
1666 maOldFieldStack.swap(pRdr->maFieldStack);
1669 void WW8ReaderSave::Restore( SwWW8ImplReader* pRdr )
1671 pRdr->pWFlyPara = mpWFlyPara;
1672 pRdr->pSFlyPara = mpSFlyPara;
1673 pRdr->pPreviousNumPaM = mpPreviousNumPaM;
1674 pRdr->pPrevNumRule = mpPrevNumRule;
1675 pRdr->pTableDesc = mpTableDesc;
1676 pRdr->cSymbol = mcSymbol;
1677 pRdr->bSymbol = mbSymbol;
1678 pRdr->bIgnoreText = mbIgnoreText;
1679 pRdr->bHdFtFtnEdn = mbHdFtFtnEdn;
1680 pRdr->bTxbxFlySection = mbTxbxFlySection;
1681 pRdr->nInTable = mnInTable;
1682 pRdr->bAnl = mbAnl;
1683 pRdr->bInHyperlink = mbInHyperlink;
1684 pRdr->bWasParaEnd = mbWasParaEnd;
1685 pRdr->bPgSecBreak = mbPgSecBreak;
1686 pRdr->nAktColl = mnAktColl;
1687 pRdr->bHasBorder = mbHasBorder;
1688 pRdr->bFirstPara = mbFirstPara;
1690 // schliesse alle Attribute, da sonst Attribute
1691 // entstehen koennen, die aus dem Fly rausragen
1692 pRdr->DeleteCtrlStk();
1693 pRdr->pCtrlStck = mpOldStck;
1695 pRdr->mpRedlineStack->closeall(*pRdr->pPaM->GetPoint());
1696 delete pRdr->mpRedlineStack;
1697 pRdr->mpRedlineStack = mpOldRedlines;
1699 pRdr->DeleteAnchorStk();
1700 pRdr->pAnchorStck = mpOldAnchorStck;
1702 *pRdr->pPaM->GetPoint() = maTmpPos;
1704 if (mpOldPlcxMan != pRdr->pPlcxMan)
1706 delete pRdr->pPlcxMan;
1707 pRdr->pPlcxMan = mpOldPlcxMan;
1709 if (pRdr->pPlcxMan)
1710 pRdr->pPlcxMan->RestoreAllPLCFx(maPLCFxSave);
1711 pRdr->maApos.swap(maOldApos);
1712 pRdr->maFieldStack.swap(maOldFieldStack);
1715 void SwWW8ImplReader::Read_HdFtFtnText( const SwNodeIndex* pSttIdx,
1716 long nStartCp, long nLen, ManTypes nType )
1718 // rettet Flags u.ae. u. setzt sie zurueck
1719 WW8ReaderSave aSave( this );
1721 pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1; //
1722 pPaM->GetPoint()->nContent.Assign( pPaM->GetCntntNode(), 0 );
1724 // dann Text fuer Header, Footer o. Footnote einlesen
1726 ReadText( nStartCp, nLen, nType ); // Sepx dabei ignorieren
1727 aSave.Restore( this );
1730 //Use authornames, if not available fall back to initials.
1731 long SwWW8ImplReader::Read_And(WW8PLCFManResult* pRes)
1733 WW8PLCFx_SubDoc* pSD = pPlcxMan->GetAtn();
1734 if( !pSD )
1735 return 0;
1737 String sAuthor;
1738 if( bVer67 )
1740 const WW67_ATRD* pDescri = (const WW67_ATRD*)pSD->GetData();
1741 const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst));
1742 if (pA)
1743 sAuthor = *pA;
1744 else
1745 sAuthor = String(pDescri->xstUsrInitl + 1, pDescri->xstUsrInitl[0],
1746 RTL_TEXTENCODING_MS_1252);
1748 else
1750 const WW8_ATRD* pDescri = (const WW8_ATRD*)pSD->GetData();
1752 if (const String* pA = GetAnnotationAuthor(SVBT16ToShort(pDescri->ibst)))
1753 sAuthor = *pA;
1754 else
1756 sal_uInt16 nLen = SVBT16ToShort(pDescri->xstUsrInitl[0]);
1757 for(sal_uInt16 nIdx = 1; nIdx <= nLen; ++nIdx)
1758 sAuthor += SVBT16ToShort(pDescri->xstUsrInitl[nIdx]);
1762 sal_uInt32 nDateTime = 0;
1764 if (BYTE * pExtended = pPlcxMan->GetExtendedAtrds()) // Word < 2002 has no date data for comments
1766 ULONG nIndex = pSD->GetIdx() & 0xFFFF; //Index is (stupidly) multiplexed for WW8PLCFx_SubDocs
1767 if (pWwFib->lcbAtrdExtra/18 > nIndex)
1768 nDateTime = SVBT32ToUInt32(*(SVBT32*)(pExtended+(nIndex*18)));
1771 DateTime aDate = sw::ms::DTTM2DateTime(nDateTime);
1773 String sTxt;
1774 OutlinerParaObject *pOutliner = ImportAsOutliner( sTxt, pRes->nCp2OrIdx,
1775 pRes->nCp2OrIdx + pRes->nMemLen, MAN_AND );
1777 this->pFmtOfJustInsertedApo = 0;
1778 SwPostItField aPostIt(
1779 (SwPostItFieldType*)rDoc.GetSysFldType(RES_POSTITFLD), sAuthor,
1780 sTxt, aDate );
1781 aPostIt.SetTextObject(pOutliner);
1783 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aPostIt), 0);
1785 return 0;
1788 void SwWW8ImplReader::Read_HdFtTextAsHackedFrame(long nStart, long nLen,
1789 SwFrmFmt &rHdFtFmt, sal_uInt16 nPageWidth)
1791 const SwNodeIndex* pSttIdx = rHdFtFmt.GetCntnt().GetCntntIdx();
1792 ASSERT(pSttIdx, "impossible");
1793 if (!pSttIdx)
1794 return;
1796 SwPosition aTmpPos(*pPaM->GetPoint());
1798 pPaM->GetPoint()->nNode = pSttIdx->GetIndex() + 1;
1799 pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(), 0);
1801 SwFlyFrmFmt *pFrame = rDoc.MakeFlySection(FLY_AT_CNTNT, pPaM->GetPoint());
1803 pFrame->SetFmtAttr(SwFmtFrmSize(ATT_MIN_SIZE, nPageWidth, MINLAY));
1804 pFrame->SetFmtAttr(SwFmtSurround(SURROUND_THROUGHT));
1805 pFrame->SetFmtAttr(SwFmtHoriOrient(0, text::HoriOrientation::RIGHT)); //iFOO
1806 // --> OD 2005-02-28 #i43427# - send frame for header/footer into background.
1807 pFrame->SetFmtAttr( SvxOpaqueItem( RES_OPAQUE, false ) );
1808 SdrObject* pFrmObj = CreateContactObject( pFrame );
1809 ASSERT( pFrmObj,
1810 "<SwWW8ImplReader::Read_HdFtTextAsHackedFrame(..)> - missing SdrObject instance" );
1811 if ( pFrmObj )
1813 pFrmObj->SetOrdNum( 0L );
1815 // <--
1816 MoveInsideFly(pFrame);
1818 const SwNodeIndex* pHackIdx = pFrame->GetCntnt().GetCntntIdx();
1820 Read_HdFtFtnText(pHackIdx, nStart, nLen - 1, MAN_HDFT);
1822 MoveOutsideFly(pFrame, aTmpPos);
1825 void SwWW8ImplReader::Read_HdFtText(long nStart, long nLen, SwFrmFmt* pHdFtFmt)
1827 const SwNodeIndex* pSttIdx = pHdFtFmt->GetCntnt().GetCntntIdx();
1828 if (!pSttIdx)
1829 return;
1831 SwPosition aTmpPos( *pPaM->GetPoint() ); // merke alte Cursorposition
1833 Read_HdFtFtnText(pSttIdx, nStart, nLen - 1, MAN_HDFT);
1835 *pPaM->GetPoint() = aTmpPos;
1838 bool SwWW8ImplReader::HasOwnHeaderFooter(BYTE nWhichItems, BYTE grpfIhdt,
1839 int nSect)
1841 if (pHdFt)
1843 WW8_CP start;
1844 long nLen;
1845 BYTE nNumber = 5;
1847 for( BYTE nI = 0x20; nI; nI >>= 1, nNumber-- )
1849 if (nI & nWhichItems)
1851 bool bOk = true;
1852 if( bVer67 )
1853 bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 );
1854 else
1856 pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen);
1857 bOk = ( 2 <= nLen );
1860 if (bOk)
1861 return true;
1865 return false;
1868 void SwWW8ImplReader::Read_HdFt(bool bIsTitle, int nSect,
1869 const SwPageDesc *pPrev, const wwSection &rSection)
1871 BYTE nWhichItems = 0;
1872 SwPageDesc *pPD = 0;
1873 if (!bIsTitle)
1875 nWhichItems =
1876 rSection.maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST);
1877 pPD = rSection.mpPage;
1879 else
1881 // --> OD 2008-08-06 #150965#
1882 // Always read title page header/footer data - it could be used by following sections
1883 // nWhichItems =
1884 // rSection.maSep.grpfIhdt & (WW8_HEADER_FIRST | WW8_FOOTER_FIRST),
1885 nWhichItems = ( WW8_HEADER_FIRST | WW8_FOOTER_FIRST );
1886 // <--
1887 pPD = rSection.mpTitlePage;
1890 BYTE grpfIhdt = rSection.maSep.grpfIhdt;
1893 if( pHdFt )
1895 WW8_CP start;
1896 long nLen;
1897 BYTE nNumber = 5;
1899 for( BYTE nI = 0x20; nI; nI >>= 1, nNumber-- )
1901 if (nI & nWhichItems)
1903 bool bOk = true;
1904 if( bVer67 )
1905 bOk = ( pHdFt->GetTextPos(grpfIhdt, nI, start, nLen ) && nLen >= 2 );
1906 else
1908 pHdFt->GetTextPosExact( static_cast< short >(nNumber + (nSect+1)*6), start, nLen);
1909 bOk = ( 2 <= nLen );
1912 bool bUseLeft
1913 = (nI & ( WW8_HEADER_EVEN | WW8_FOOTER_EVEN )) ? true: false;
1914 bool bFooter
1915 = (nI & ( WW8_FOOTER_EVEN | WW8_FOOTER_ODD | WW8_FOOTER_FIRST )) ? true: false;
1917 SwFrmFmt* pFmt = bUseLeft ? &pPD->GetLeft() : &pPD->GetMaster();
1919 SwFrmFmt* pHdFtFmt;
1920 if (bFooter)
1922 bIsFooter = true;
1923 //#i17196# Cannot have left without right
1924 if (!pPD->GetMaster().GetFooter().GetFooterFmt())
1925 pPD->GetMaster().SetFmtAttr(SwFmtFooter(true));
1926 if (bUseLeft)
1927 pPD->GetLeft().SetFmtAttr(SwFmtFooter(true));
1928 pHdFtFmt = (SwFrmFmt*)pFmt->GetFooter().GetFooterFmt();
1930 else
1932 bIsHeader = true;
1933 //#i17196# Cannot have left without right
1934 if (!pPD->GetMaster().GetHeader().GetHeaderFmt())
1935 pPD->GetMaster().SetFmtAttr(SwFmtHeader(true));
1936 if (bUseLeft)
1937 pPD->GetLeft().SetFmtAttr(SwFmtHeader(true));
1938 pHdFtFmt = (SwFrmFmt*)pFmt->GetHeader().GetHeaderFmt();
1941 if (bOk)
1943 bool bHackRequired = false;
1944 if (bIsHeader && rSection.IsFixedHeightHeader())
1945 bHackRequired = true;
1946 else if (bIsFooter && rSection.IsFixedHeightFooter())
1947 bHackRequired = true;
1949 if (bHackRequired)
1951 Read_HdFtTextAsHackedFrame(start, nLen, *pHdFtFmt,
1952 static_cast< sal_uInt16 >(rSection.GetTextAreaWidth()) );
1954 else
1955 Read_HdFtText(start, nLen, pHdFtFmt);
1957 else if (!bOk && pPrev)
1958 CopyPageDescHdFt(pPrev, pPD, nI);
1960 bIsHeader = bIsFooter = false;
1964 maTracer.LeaveEnvironment(sw::log::eDocumentProperties);
1967 bool wwSectionManager::SectionIsProtected(const wwSection &rSection) const
1969 return (mrReader.pWDop->fProtEnabled && !rSection.IsNotProtected());
1972 void wwSectionManager::SetHdFt(wwSection &rSection, int nSect,
1973 const wwSection *pPrevious)
1975 // Header / Footer nicht da
1976 if (!rSection.maSep.grpfIhdt)
1977 return;
1979 ASSERT(rSection.mpPage, "makes no sense to call with a main page");
1980 if (rSection.mpPage)
1982 mrReader.Read_HdFt(false, nSect, pPrevious ? pPrevious->mpPage : 0,
1983 rSection);
1986 if (rSection.mpTitlePage)
1988 // 2 Pagedescs noetig: 1.Seite und folgende
1989 // 1. Seite einlesen
1990 mrReader.Read_HdFt(true, nSect, pPrevious ? pPrevious->mpTitlePage : 0,
1991 rSection);
1994 // Kopf / Fuss - Index Updaten
1995 // Damit der Index auch spaeter noch stimmt
1996 if (mrReader.pHdFt)
1997 mrReader.pHdFt->UpdateIndex(rSection.maSep.grpfIhdt);
2001 class AttribHere : public std::unary_function<const xub_StrLen*, bool>
2003 private:
2004 xub_StrLen nPosition;
2005 public:
2006 AttribHere(xub_StrLen nPos) : nPosition(nPos) {}
2007 bool operator()(const xub_StrLen *pPosition) const
2009 return (*pPosition >= nPosition);
2013 void SwWW8ImplReader::AppendTxtNode(SwPosition& rPos)
2015 SwTxtNode* pTxt = pPaM->GetNode()->GetTxtNode();
2017 const SwNumRule* pRule = NULL;
2019 if (pTxt != NULL)
2020 pRule = sw::util::GetNumRuleFromTxtNode(*pTxt);
2022 if (
2023 pRule && !pWDop->fDontUseHTMLAutoSpacing &&
2024 (bParaAutoBefore || bParaAutoAfter)
2027 // If after spacing is set to auto, set the after space to 0
2028 if (bParaAutoAfter)
2029 SetLowerSpacing(*pPaM, 0);
2031 // If the previous textnode had numbering and
2032 // and before spacing is set to auto, set before space to 0
2033 if(pPrevNumRule && bParaAutoBefore)
2034 SetUpperSpacing(*pPaM, 0);
2036 // If the previous numbering rule was different we need
2037 // to insert a space after the previous paragraph
2038 if((pRule != pPrevNumRule) && pPreviousNumPaM)
2039 SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
2041 // cache current paragraph
2042 if(pPreviousNumPaM)
2043 delete pPreviousNumPaM, pPreviousNumPaM = 0;
2045 pPreviousNumPaM = new SwPaM(*pPaM);
2046 pPrevNumRule = pRule;
2048 else if(!pRule && pPreviousNumPaM)
2050 // If the previous paragraph has numbering but the current one does not
2051 // we need to add a space after the previous paragraph
2052 SetLowerSpacing(*pPreviousNumPaM, GetParagraphAutoSpace(pWDop->fDontUseHTMLAutoSpacing));
2053 delete pPreviousNumPaM, pPreviousNumPaM = 0;
2054 pPrevNumRule = 0;
2056 else
2058 // clear paragraph cache
2059 if(pPreviousNumPaM)
2060 delete pPreviousNumPaM, pPreviousNumPaM = 0;
2061 pPrevNumRule = pRule;
2064 // If this is the first paragraph in the document and
2065 // Auto-spacing before paragraph is set,
2066 // set the upper spacing value to 0
2067 if(bParaAutoBefore && bFirstPara && !pWDop->fDontUseHTMLAutoSpacing)
2068 SetUpperSpacing(*pPaM, 0);
2070 bFirstPara = false;
2072 rDoc.AppendTxtNode(rPos);
2074 //We can flush all anchored graphics at the end of a paragraph.
2075 pAnchorStck->Flush();
2078 bool SwWW8ImplReader::SetSpacing(SwPaM &rMyPam, int nSpace, bool bIsUpper )
2080 bool bRet = false;
2081 const SwPosition* pSpacingPos = rMyPam.GetPoint();
2083 const SvxULSpaceItem* pULSpaceItem = (const SvxULSpaceItem*)pCtrlStck->GetFmtAttr(*pSpacingPos, RES_UL_SPACE);
2085 if(pULSpaceItem != 0)
2087 SvxULSpaceItem aUL(*pULSpaceItem);
2089 if(bIsUpper)
2090 aUL.SetUpper( static_cast< USHORT >(nSpace) );
2091 else
2092 aUL.SetLower( static_cast< USHORT >(nSpace) );
2094 xub_StrLen nEnd = pSpacingPos->nContent.GetIndex();
2095 rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), 0);
2096 pCtrlStck->NewAttr(*pSpacingPos, aUL);
2097 rMyPam.GetPoint()->nContent.Assign(rMyPam.GetCntntNode(), nEnd);
2098 pCtrlStck->SetAttr(*pSpacingPos, RES_UL_SPACE);
2099 bRet = true;
2101 return bRet;
2104 bool SwWW8ImplReader::SetLowerSpacing(SwPaM &rMyPam, int nSpace)
2106 return SetSpacing(rMyPam, nSpace, false);
2109 bool SwWW8ImplReader::SetUpperSpacing(SwPaM &rMyPam, int nSpace)
2111 return SetSpacing(rMyPam, nSpace, true);
2114 USHORT SwWW8ImplReader::TabRowSprm(int nLevel) const
2116 if (bVer67)
2117 return 25;
2118 return nLevel ? 0x244C : 0x2417;
2121 void SwWW8ImplReader::EndSpecial()
2123 // Frame / Table / Anl
2124 if (bAnl)
2125 StopAllAnl(); // -> bAnl = false
2127 while(maApos.size() > 1)
2129 StopTable();
2130 maApos.pop_back();
2131 --nInTable;
2132 if (maApos[nInTable] == true)
2133 StopApo();
2136 if (maApos[0] == true)
2137 StopApo();
2139 ASSERT(!nInTable, "unclosed table!");
2142 bool SwWW8ImplReader::ProcessSpecial(bool &rbReSync, WW8_CP nStartCp)
2144 // Frame / Table / Anl
2145 if (bInHyperlink)
2146 return false;
2148 rbReSync = false;
2150 ASSERT(nInTable >= 0,"nInTable < 0!");
2152 // TabRowEnd
2153 bool bTableRowEnd = (pPlcxMan->HasParaSprm(bVer67 ? 25 : 0x2417) != 0 );
2155 // es muss leider fuer jeden Absatz zuerst nachgesehen werden,
2156 // ob sich unter den sprms
2157 // das sprm 29 (bzw. 0x261B) befindet, das ein APO einleitet.
2158 // Alle weiteren sprms beziehen sich dann naemlich auf das APO und nicht
2159 // auf den normalen Text drumrum.
2160 // Dasselbe gilt fuer eine Tabelle ( sprm 24 (bzw. 0x2416) )
2161 // und Anls ( sprm 13 ).
2162 // WW: Tabelle in APO geht ( Beide Anfaende treten gleichzeitig auf )
2163 // WW: APO in Tabelle geht nicht
2164 // d.h. Wenn eine Tabelle Inhalt eines Apo ist, dann muss der
2165 // Apo-Anfang zuerst bearbeitet werden, damit die Tabelle im Apo steht
2166 // und nicht umgekehrt. Am Ende muss dagegen zuerst das Tabellenende
2167 // bearbeitet werden, da die Apo erst nach der Tabelle abgeschlossen
2168 // werden darf ( sonst wird das Apo-Ende nie gefunden ).
2169 // Dasselbe gilt fuer Fly / Anl, Tab / Anl, Fly / Tab / Anl.
2171 // Wenn die Tabelle in einem Apo steht, fehlen im TabRowEnd-Bereich
2172 // die Apo-Angaben. Damit hier die Apo nicht beendet wird, wird
2173 // ProcessApo dann nicht aufgerufen.
2175 // KHZ: When there is a table inside the Apo the Apo-flags are also
2176 // missing for the 2nd, 3rd... paragraphs of each cell.
2179 // 1st look for in-table flag, for 2000+ there is a subtable flag to
2180 // be considered, the sprm 6649 gives the level of the table
2181 BYTE nCellLevel = 0;
2183 if (bVer67)
2184 nCellLevel = 0 != pPlcxMan->HasParaSprm(24);
2185 else
2187 nCellLevel = 0 != pPlcxMan->HasParaSprm(0x2416);
2188 if (!nCellLevel)
2189 nCellLevel = 0 != pPlcxMan->HasParaSprm(0x244B);
2192 mark:
2194 WW8_TablePos *pTabPos=0;
2195 WW8_TablePos aTabPos;
2196 if (nCellLevel && !bVer67)
2198 WW8PLCFxSave1 aSave;
2199 pPlcxMan->GetPap()->Save( aSave );
2200 rbReSync = true;
2201 WW8PLCFx_Cp_FKP* pPap = pPlcxMan->GetPapPLCF();
2202 WW8_CP nMyStartCp=nStartCp;
2204 if (const BYTE *pLevel = pPlcxMan->HasParaSprm(0x6649))
2205 nCellLevel = *pLevel;
2207 bool bHasRowEnd = SearchRowEnd(pPap, nMyStartCp, (nInTable<nCellLevel?nInTable:nCellLevel-1));
2209 //Bad Table, remain unchanged in level, e.g. #i19667#
2210 if (!bHasRowEnd)
2211 nCellLevel = static_cast< BYTE >(nInTable);
2213 if (bHasRowEnd && ParseTabPos(&aTabPos,pPap))
2214 pTabPos = &aTabPos;
2216 pPlcxMan->GetPap()->Restore( aSave );
2219 // then look if we are in an Apo
2221 ApoTestResults aApo = TestApo(nCellLevel, bTableRowEnd, pTabPos);
2223 //look to see if we are in a Table, but Table in foot/end note not allowed
2224 bool bStartTab = (nInTable < nCellLevel) && !bFtnEdn;
2226 bool bStopTab = bWasTabRowEnd && (nInTable > nCellLevel) && !bFtnEdn;
2228 bWasTabRowEnd = false; // must be deactivated right here to prevent next
2229 // WW8TabDesc::TableCellEnd() from making nonsense
2231 if (nInTable && !bTableRowEnd && !bStopTab && (nInTable == nCellLevel && aApo.HasStartStop()))
2232 bStopTab = bStartTab = true; // Required to stop and start table
2234 // Dann auf Anl (Nummerierung) testen
2235 // und dann alle Ereignisse in der richtigen Reihenfolge bearbeiten
2237 if( bAnl && !bTableRowEnd )
2239 const BYTE* pSprm13 = pPlcxMan->HasParaSprm( 13 );
2240 if( pSprm13 )
2241 { // Noch Anl ?
2242 BYTE nT = static_cast< BYTE >(GetNumType( *pSprm13 ));
2243 if( ( nT != WW8_Pause && nT != nWwNumType ) // Anl-Wechsel
2244 || aApo.HasStartStop() // erzwungenes Anl-Ende
2245 || bStopTab || bStartTab )
2247 StopAnlToRestart(nT); // Anl-Restart ( = Wechsel ) ueber sprms
2249 else
2251 NextAnlLine( pSprm13 ); // naechste Anl-Zeile
2254 else
2255 { // Anl normal zuende
2256 StopAllAnl(); // Wirkliches Ende
2259 if (bStopTab)
2261 StopTable();
2262 maApos.pop_back();
2263 --nInTable;
2265 if (aApo.mbStopApo)
2267 StopApo();
2268 maApos[nInTable] = false;
2271 if (aApo.mbStartApo)
2273 maApos[nInTable] = StartApo(aApo, pTabPos);
2274 // nach StartApo ist ein ReSync noetig ( eigentlich nur, falls die Apo
2275 // ueber eine FKP-Grenze geht
2276 rbReSync = true;
2278 if (bStartTab)
2280 WW8PLCFxSave1 aSave;
2281 pPlcxMan->GetPap()->Save( aSave );
2283 if (bAnl) // Nummerierung ueber Zellengrenzen
2284 StopAllAnl(); // fuehrt zu Absturz -> keine Anls
2285 // in Tabellen
2286 while (nInTable < nCellLevel)
2288 if (StartTable(nStartCp)) {
2289 ++nInTable;
2291 else
2292 break;
2294 maApos.push_back(false);
2295 if (nInTable<nCellLevel)
2296 goto mark;
2299 // nach StartTable ist ein ReSync noetig ( eigentlich nur, falls die
2300 // Tabelle ueber eine FKP-Grenze geht
2301 rbReSync = true;
2302 pPlcxMan->GetPap()->Restore( aSave );
2304 return bTableRowEnd;
2307 CharSet SwWW8ImplReader::GetCurrentCharSet()
2310 #i2015
2311 If the hard charset is set use it, if not see if there is an open
2312 character run that has set the charset, if not then fallback to the
2313 current underlying paragraph style.
2315 CharSet eSrcCharSet = eHardCharSet;
2316 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2318 if (!maFontSrcCharSets.empty())
2319 eSrcCharSet = maFontSrcCharSets.top();
2320 if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && (nCharFmt != -1))
2321 eSrcCharSet = pCollA[nCharFmt].GetCharSet();
2322 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2323 eSrcCharSet = pCollA[nAktColl].GetCharSet();
2324 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2325 { // patch from cmc for #i52786#
2327 #i22206#/#i52786#
2328 The (default) character set used for a run of text is the default
2329 character set for the version of Word that last saved the document.
2331 This is a bit tentative, more might be required if the concept is correct.
2332 When later version of word write older 6/95 documents the charset is
2333 correctly set in the character runs involved, so its hard to reproduce
2334 documents that require this to be sure of the process involved.
2336 const SvxLanguageItem *pLang =
2337 (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
2338 if (pLang)
2340 switch (pLang->GetLanguage())
2342 case LANGUAGE_CZECH:
2343 case LANGUAGE_HUNGARIAN:
2344 case LANGUAGE_POLISH:
2345 eSrcCharSet = RTL_TEXTENCODING_MS_1250;
2346 break;
2347 case LANGUAGE_RUSSIAN:
2348 eSrcCharSet = RTL_TEXTENCODING_MS_1251;
2349 break;
2350 case LANGUAGE_GREEK:
2351 eSrcCharSet = RTL_TEXTENCODING_MS_1253;
2352 break;
2353 case LANGUAGE_TURKISH:
2354 eSrcCharSet = RTL_TEXTENCODING_MS_1254;
2355 break;
2356 default:
2357 eSrcCharSet = RTL_TEXTENCODING_MS_1252;
2358 break;
2363 return eSrcCharSet;
2366 //Takashi Ono for CJK
2367 CharSet SwWW8ImplReader::GetCurrentCJKCharSet()
2370 #i2015
2371 If the hard charset is set use it, if not see if there is an open
2372 character run that has set the charset, if not then fallback to the
2373 current underlying paragraph style.
2375 CharSet eSrcCharSet = eHardCharSet;
2376 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2378 if (!maFontSrcCJKCharSets.empty())
2379 eSrcCharSet = maFontSrcCJKCharSets.top();
2380 if ((eSrcCharSet == RTL_TEXTENCODING_DONTKNOW) && (nCharFmt != -1))
2381 eSrcCharSet = pCollA[nCharFmt].GetCJKCharSet();
2382 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2383 eSrcCharSet = pCollA[nAktColl].GetCJKCharSet();
2384 if (eSrcCharSet == RTL_TEXTENCODING_DONTKNOW)
2385 { // patch from cmc for #i52786#
2387 #i22206#/#i52786#
2388 The (default) character set used for a run of text is the default
2389 character set for the version of Word that last saved the document.
2391 This is a bit tentative, more might be required if the concept is correct.
2392 When later version of word write older 6/95 documents the charset is
2393 correctly set in the character runs involved, so its hard to reproduce
2394 documents that require this to be sure of the process involved.
2396 const SvxLanguageItem *pLang =
2397 (const SvxLanguageItem*)GetFmtAttr(RES_CHRATR_LANGUAGE);
2398 if (pLang)
2400 switch (pLang->GetLanguage())
2402 case LANGUAGE_CZECH:
2403 eSrcCharSet = RTL_TEXTENCODING_MS_1250;
2404 break;
2405 default:
2406 eSrcCharSet = RTL_TEXTENCODING_MS_1252;
2407 break;
2412 return eSrcCharSet;
2415 void SwWW8ImplReader::PostProcessAttrs()
2417 if (mpPostProcessAttrsInfo != NULL)
2419 SfxItemIter aIter(mpPostProcessAttrsInfo->mItemSet);
2421 const SfxPoolItem * pItem = aIter.GetCurItem();
2422 if (pItem != NULL)
2426 pCtrlStck->NewAttr(*mpPostProcessAttrsInfo->mPaM.GetPoint(),
2427 *pItem);
2428 pCtrlStck->SetAttr(*mpPostProcessAttrsInfo->mPaM.GetMark(),
2429 pItem->Which(), true);
2431 while (!aIter.IsAtEnd() && 0 != (pItem = aIter.NextItem()));
2434 delete mpPostProcessAttrsInfo;
2435 mpPostProcessAttrsInfo = NULL;
2440 #i9241#
2441 It appears that some documents that are in a baltic 8 bit encoding which has
2442 some undefined characters can have use made of those characters, in which
2443 case they default to CP1252. If not then its perhaps that the font encoding
2444 is only in use for 6/7 and for 8+ if we are in 8bit mode then the encoding
2445 is always 1252.
2447 So a encoding converter that on an undefined character attempts to
2448 convert from 1252 on the undefined character
2450 sal_Size Custom8BitToUnicode(rtl_TextToUnicodeConverter hConverter,
2451 sal_Char *pIn, sal_Size nInLen, sal_Unicode *pOut, sal_Size nOutLen)
2453 const sal_uInt32 nFlags =
2454 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
2455 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
2456 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE |
2457 RTL_TEXTTOUNICODE_FLAGS_FLUSH;
2459 const sal_uInt32 nFlags2 =
2460 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_IGNORE |
2461 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_IGNORE |
2462 RTL_TEXTTOUNICODE_FLAGS_INVALID_IGNORE |
2463 RTL_TEXTTOUNICODE_FLAGS_FLUSH;
2465 sal_Size nDestChars=0;
2466 sal_Size nConverted=0;
2470 sal_uInt32 nInfo = 0;
2471 sal_Size nThisConverted=0;
2473 nDestChars += rtl_convertTextToUnicode(hConverter, 0,
2474 pIn+nConverted, nInLen-nConverted,
2475 pOut+nDestChars, nOutLen-nDestChars,
2476 nFlags, &nInfo, &nThisConverted);
2478 ASSERT(nInfo == 0, "A character conversion failed!");
2480 nConverted += nThisConverted;
2482 if (
2483 nInfo & RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR ||
2484 nInfo & RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR
2487 sal_Size nOtherConverted;
2488 rtl_TextToUnicodeConverter hCP1252Converter =
2489 rtl_createTextToUnicodeConverter(RTL_TEXTENCODING_MS_1252);
2490 nDestChars += rtl_convertTextToUnicode(hCP1252Converter, 0,
2491 pIn+nConverted, 1,
2492 pOut+nDestChars, nOutLen-nDestChars,
2493 nFlags2, &nInfo, &nOtherConverted);
2494 rtl_destroyTextToUnicodeConverter(hCP1252Converter);
2495 nConverted+=1;
2497 } while (nConverted < nInLen);
2499 return nDestChars;
2502 bool SwWW8ImplReader::LangUsesHindiNumbers(USHORT nLang)
2504 bool bResult = false;
2506 switch (nLang)
2508 case 0x1401: // Arabic(Algeria)
2509 case 0x3c01: // Arabic(Bahrain)
2510 case 0xc01: // Arabic(Egypt)
2511 case 0x801: // Arabic(Iraq)
2512 case 0x2c01: // Arabic (Jordan)
2513 case 0x3401: // Arabic(Kuwait)
2514 case 0x3001: // Arabic(Lebanon)
2515 case 0x1001: // Arabic(Libya)
2516 case 0x1801: // Arabic(Morocco)
2517 case 0x2001: // Arabic(Oman)
2518 case 0x4001: // Arabic(Qatar)
2519 case 0x401: // Arabic(Saudi Arabia)
2520 case 0x2801: // Arabic(Syria)
2521 case 0x1c01: // Arabic(Tunisia)
2522 case 0x3801: // Arabic(U.A.E)
2523 case 0x2401: // Arabic(Yemen)
2524 bResult = true;
2525 break;
2526 default:
2527 break;
2530 return bResult;
2533 sal_Unicode SwWW8ImplReader::TranslateToHindiNumbers(sal_Unicode nChar)
2535 if (nChar >= 0x0030 && nChar <= 0x0039)
2536 return nChar + 0x0630;
2538 return nChar;
2541 // Returnwert: true for no Sonderzeichen
2542 bool SwWW8ImplReader::ReadPlainChars(WW8_CP& rPos, long nEnd, long nCpOfs)
2544 // Unicode-Flag neu setzen und notfalls File-Pos korrigieren
2545 // merke: Seek kostet nicht viel, da inline geprueft wird,
2546 // ob die korrekte FilePos nicht schon erreicht ist.
2547 WW8_FC nStreamPos = pSBase->WW8Cp2Fc(nCpOfs+rPos, &bIsUnicode);
2548 pStrm->Seek( nStreamPos );
2550 xub_StrLen nLen;
2551 if (nEnd - rPos <= (STRING_MAXLEN-1))
2552 nLen = writer_cast<xub_StrLen>(nEnd - rPos);
2553 else
2554 nLen = STRING_MAXLEN-1;
2555 ASSERT(nLen, "String is 0");
2556 if (!nLen)
2557 return true;
2559 const CharSet eSrcCharSet = bVer67 ? GetCurrentCharSet() :
2560 RTL_TEXTENCODING_MS_1252;
2561 const CharSet eSrcCJKCharSet = bVer67 ? GetCurrentCJKCharSet() :
2562 RTL_TEXTENCODING_MS_1252;
2564 // (re)alloc UniString data
2565 String sPlainCharsBuf;
2567 sal_Unicode* pBuffer = sPlainCharsBuf.AllocBuffer( nLen );
2568 sal_Unicode* pWork = pBuffer;
2570 sal_Char* p8Bits = NULL;
2572 rtl_TextToUnicodeConverter hConverter = 0;
2573 if (!bIsUnicode || bVer67)
2574 hConverter = rtl_createTextToUnicodeConverter(eSrcCharSet);
2576 if (!bIsUnicode)
2577 p8Bits = new sal_Char[nLen];
2579 // read the stream data
2580 BYTE nBCode = 0;
2581 UINT16 nUCode;
2582 xub_StrLen nL2;
2584 USHORT nCTLLang = 0;
2585 const SfxPoolItem * pItem = GetFmtAttr(RES_CHRATR_CTL_LANGUAGE);
2586 if (pItem != NULL)
2587 nCTLLang = dynamic_cast<const SvxLanguageItem *>(pItem)->GetLanguage();
2589 for( nL2 = 0; nL2 < nLen; ++nL2, ++pWork )
2591 if (bIsUnicode)
2592 *pStrm >> nUCode; // unicode --> read 2 bytes
2593 else
2595 *pStrm >> nBCode; // old code --> read 1 byte
2596 nUCode = nBCode;
2599 if (pStrm->GetError())
2601 rPos = WW8_CP_MAX-10; // -> eof or other error
2602 sPlainCharsBuf.ReleaseBufferAccess( 0 );
2603 return true;
2606 if ((32 > nUCode) || (0xa0 == nUCode))
2608 pStrm->SeekRel( bIsUnicode ? -2 : -1 );
2609 break; // Sonderzeichen < 32, == 0xa0 gefunden
2612 if (bIsUnicode)
2614 if (!bVer67)
2615 *pWork = nUCode;
2616 else
2618 if (nUCode >= 0x3000) //0x8000 ?
2620 sal_Char aTest[2];
2621 aTest[0] = static_cast< sal_Char >((nUCode & 0xFF00) >> 8);
2622 aTest[1] = static_cast< sal_Char >(nUCode & 0x00FF);
2623 String aTemp(aTest, 2, eSrcCJKCharSet);
2624 ASSERT(aTemp.Len() == 1, "so much for that theory");
2625 *pWork = aTemp.GetChar(0);
2627 else
2629 sal_Char cTest = static_cast< sal_Char >(nUCode & 0x00FF);
2630 Custom8BitToUnicode(hConverter, &cTest, 1, pWork, 1);
2634 else
2635 p8Bits[nL2] = nBCode;
2638 if (nL2)
2640 xub_StrLen nEndUsed = nL2;
2642 if (!bIsUnicode)
2643 nEndUsed = Custom8BitToUnicode(hConverter, p8Bits, nL2, pBuffer, nLen);
2645 for( xub_StrLen nI = 0; nI < nLen; ++nI, ++pBuffer )
2646 if (m_bRegardHindiDigits && bBidi && LangUsesHindiNumbers(nCTLLang))
2647 *pBuffer = TranslateToHindiNumbers(*pBuffer);
2649 sPlainCharsBuf.ReleaseBufferAccess( nEndUsed );
2651 AddTextToParagraph(sPlainCharsBuf);
2652 rPos += nL2;
2653 if (!maApos.back()) //a para end in apo doesn't count
2654 bWasParaEnd = false; //kein CR
2657 if (hConverter)
2658 rtl_destroyTextToUnicodeConverter(hConverter);
2659 delete [] p8Bits;
2660 return nL2 >= nLen;
2663 bool SwWW8ImplReader::AddTextToParagraph(const String& rAddString)
2665 const SwTxtNode* pNd = pPaM->GetCntntNode()->GetTxtNode();
2666 if (rAddString.Len())
2669 #ifdef DEBUG
2670 //!! does not compile with debug=t -> unresolved external (dbg_out),
2671 //!! sommeone who knows what he wants to get should fix this
2672 // ::std::clog << "<addTextToParagraph>" << dbg_out(rAddString)
2673 // << "</addTextToParagraph>" << ::std::endl;
2674 #endif
2676 if ((pNd->GetTxt().Len() + rAddString.Len()) < STRING_MAXLEN -1)
2678 rDoc.InsertString(*pPaM, rAddString);
2680 else
2683 if (pNd->GetTxt().Len()< STRING_MAXLEN -1)
2685 String sTempStr (rAddString,0,
2686 STRING_MAXLEN - pNd->GetTxt().Len() -1);
2687 rDoc.InsertString(*pPaM, sTempStr);
2688 sTempStr = rAddString.Copy(sTempStr.Len(),
2689 rAddString.Len() - sTempStr.Len());
2690 AppendTxtNode(*pPaM->GetPoint());
2691 rDoc.InsertString(*pPaM, sTempStr);
2693 else
2695 AppendTxtNode(*pPaM->GetPoint());
2696 rDoc.InsertString(*pPaM, rAddString);
2700 bReadTable = false;
2703 return true;
2706 // Returnwert: true for para end
2707 bool SwWW8ImplReader::ReadChars(WW8_CP& rPos, WW8_CP nNextAttr, long nTextEnd,
2708 long nCpOfs)
2710 long nEnd = ( nNextAttr < nTextEnd ) ? nNextAttr : nTextEnd;
2712 if (bSymbol || bIgnoreText)
2714 if( bSymbol ) // Spezialzeichen einfuegen
2716 for(USHORT nCh = 0; nCh < nEnd - rPos; ++nCh)
2718 rDoc.InsertString( *pPaM, cSymbol );
2720 pCtrlStck->SetAttr( *pPaM->GetPoint(), RES_CHRATR_FONT );
2722 pStrm->SeekRel( nEnd- rPos );
2723 rPos = nEnd; // ignoriere bis Attributende
2724 return false;
2727 while (true)
2729 if (ReadPlainChars(rPos, nEnd, nCpOfs))
2730 return false; // Fertig
2732 bool bStartLine = ReadChar(rPos, nCpOfs);
2733 rPos++;
2734 if (bPgSecBreak || bStartLine || rPos == nEnd) // CR oder Fertig
2736 return bStartLine;
2741 bool SwWW8ImplReader::HandlePageBreakChar()
2743 bool bParaEndAdded = false;
2744 //#i1909# section/page breaks should not occur in tables, word
2745 //itself ignores them in this case.
2746 if (!nInTable)
2748 bPgSecBreak = true;
2749 pCtrlStck->KillUnlockedAttrs(*pPaM->GetPoint());
2751 #74468#
2752 If its a 0x0c without a paragraph end before it, act like a
2753 paragraph end, but nevertheless, numbering (and perhaps other
2754 similiar constructs) do not exist on the para.
2756 if (!bWasParaEnd)
2758 bParaEndAdded = true;
2759 if (0 >= pPaM->GetPoint()->nContent.GetIndex())
2761 if (SwTxtNode* pTxtNode = pPaM->GetNode()->GetTxtNode())
2763 pTxtNode->SetAttr(
2764 *GetDfltAttr(RES_PARATR_NUMRULE));
2769 return bParaEndAdded;
2772 bool SwWW8ImplReader::ReadChar(long nPosCp, long nCpOfs)
2774 bool bNewParaEnd = false;
2775 // Unicode-Flag neu setzen und notfalls File-Pos korrigieren
2776 // merke: Seek kostet nicht viel, da inline geprueft wird,
2777 // ob die korrekte FilePos nicht schon erreicht ist.
2778 pStrm->Seek( pSBase->WW8Cp2Fc(nCpOfs+nPosCp, &bIsUnicode) );
2780 BYTE nBCode;
2781 UINT16 nWCharVal;
2782 if( bIsUnicode )
2783 *pStrm >> nWCharVal; // unicode --> read 2 bytes
2784 else
2786 *pStrm >> nBCode; // old code --> read 1 byte
2787 nWCharVal = nBCode;
2790 sal_Char cInsert = '\x0';
2791 bool bRet = false;
2792 switch (nWCharVal)
2794 case 0:
2796 // Seitennummer
2797 SwPageNumberField aFld(
2798 (SwPageNumberFieldType*)rDoc.GetSysFldType(
2799 RES_PAGENUMBERFLD ), PG_RANDOM, SVX_NUM_ARABIC);
2800 rDoc.InsertPoolItem(*pPaM, SwFmtFld(aFld), 0);
2802 break;
2803 case 0xe:
2804 //#108817# if there is only one column word treats a column
2805 //break like a pagebreak.
2806 if (maSectionManager.CurrentSectionColCount() < 2)
2807 bRet = HandlePageBreakChar();
2808 else if (!nInTable)
2810 // Always insert a txtnode for a column break, e.g. ##
2811 SwCntntNode *pCntNd=pPaM->GetCntntNode();
2812 if (pCntNd!=NULL && pCntNd->Len()>0) // if par is empty not break is needed
2813 AppendTxtNode(*pPaM->GetPoint());
2814 rDoc.InsertPoolItem(*pPaM, SvxFmtBreakItem(SVX_BREAK_COLUMN_BEFORE, RES_BREAK), 0);
2816 break;
2817 case 0x7:
2818 bNewParaEnd = true;
2819 TabCellEnd(); // table cell end (Flags abfragen!)
2820 break;
2821 case 0xf:
2822 if( !bSpec ) // "Satellit"
2823 cInsert = '\xa4';
2824 break;
2825 case 0x14:
2826 if( !bSpec ) // "Para-Ende"-Zeichen
2827 cInsert = '\xb5';
2828 break;
2829 case 0x15:
2830 if( !bSpec ) // Juristenparagraph
2831 cInsert = '\xa7';
2832 break;
2833 case 0x9:
2834 cInsert = '\x9'; // Tab
2835 break;
2836 case 0xb:
2837 cInsert = '\xa'; // Hard NewLine
2838 break;
2839 case 0xc:
2840 bRet = HandlePageBreakChar();
2841 break;
2842 case 0x1e: // Non-breaking hyphen
2843 rDoc.InsertString( *pPaM, CHAR_HARDHYPHEN );
2844 break;
2845 case 0x1f: // Non-required hyphens
2846 rDoc.InsertString( *pPaM, CHAR_SOFTHYPHEN );
2847 break;
2848 case 0xa0: // Non-breaking spaces
2849 rDoc.InsertString( *pPaM, CHAR_HARDBLANK );
2850 break;
2851 case 0x1:
2853 Current thinking is that if bObj is set then we have a
2854 straightforward "traditional" ole object, otherwise we have a
2855 graphic preview of an associated ole2 object (or a simple
2856 graphic of course)
2858 if (!IsInlineEscherHack())
2860 SwFrmFmt *pResult = 0;
2861 if (bObj)
2862 pResult = ImportOle();
2863 else if (bSpec)
2864 pResult = ImportGraf();
2866 //#102160# If we have a bad 0x1 insert a space instead.
2867 if (!pResult)
2869 cInsert = ' ';
2870 ASSERT(!bObj && !bEmbeddObj && !nObjLocFc,
2871 "WW8: Please report this document, it may have a "
2872 "missing graphic");
2874 else
2876 // reset the flags.
2877 bObj = bEmbeddObj = false;
2878 nObjLocFc = 0;
2881 break;
2882 case 0x8:
2883 if( !bObj )
2884 Read_GrafLayer( nPosCp );
2885 break;
2886 case 0xd:
2887 bNewParaEnd = bRet = true;
2888 if (nInTable > 1)
2891 #i9666#/#i23161#
2892 Yes complex, if there is an entry in the undocumented PLCF
2893 which I believe to be a record of cell and row boundaries
2894 see if the magic bit which I believe to mean cell end is
2895 set. I also think btw that the third byte of the 4 byte
2896 value is the level of the cell
2898 WW8PLCFspecial* pTest = pPlcxMan->GetMagicTables();
2899 if (pTest && pTest->SeekPosExact(nPosCp+1+nCpOfs) &&
2900 pTest->Where() == nPosCp+1+nCpOfs)
2902 WW8_FC nPos;
2903 void *pData;
2904 pTest->Get(nPos, pData);
2905 sal_uInt32 nData = SVBT32ToUInt32(*(SVBT32*)pData);
2906 if (nData & 0x2) //Might be how it works
2908 TabCellEnd();
2909 bRet = false;
2912 else if (bWasTabCellEnd)
2914 TabCellEnd();
2915 bRet = false;
2919 bWasTabCellEnd = false;
2921 break; // line end
2922 case 0x5: // Annotation reference
2923 case 0x13:
2924 break;
2925 case 0x2:
2926 if (!maFtnStack.empty())
2927 cInsert = 0x2;
2928 break; // Auto-Fussnoten-Nummer
2929 #if OSL_DEBUG_LEVEL > 1
2930 default:
2931 ::std::clog << "<unknownValue val=\"" << nWCharVal << "\">" << ::std::endl;
2932 break;
2933 #endif
2936 if( '\x0' != cInsert )
2938 String sInsert = ByteString::ConvertToUnicode(cInsert,
2939 RTL_TEXTENCODING_MS_1252 );
2940 AddTextToParagraph(sInsert);
2942 if (!maApos.back()) //a para end in apo doesn't count
2943 bWasParaEnd = bNewParaEnd;
2944 return bRet;
2947 void SwWW8ImplReader::ProcessAktCollChange(WW8PLCFManResult& rRes,
2948 bool* pStartAttr, bool bCallProcessSpecial)
2950 USHORT nOldColl = nAktColl;
2951 nAktColl = pPlcxMan->GetColl();
2953 // Invalid Style-Id
2954 if (nAktColl >= nColls || !pCollA[nAktColl].pFmt || !pCollA[nAktColl].bColl)
2956 nAktColl = 0;
2957 bParaAutoBefore = false;
2958 bParaAutoAfter = false;
2960 else
2962 bParaAutoBefore = pCollA[nAktColl].bParaAutoBefore;
2963 bParaAutoAfter = pCollA[nAktColl].bParaAutoAfter;
2966 bool bTabRowEnd = false;
2967 if( pStartAttr && bCallProcessSpecial && !bInHyperlink )
2969 bool bReSync;
2970 // Frame / Table / Autonumbering List Level
2971 bTabRowEnd = ProcessSpecial(bReSync, rRes.nAktCp+pPlcxMan->GetCpOfs());
2972 if( bReSync )
2973 *pStartAttr = pPlcxMan->Get( &rRes ); // hole Attribut-Pos neu
2976 if (!bTabRowEnd && StyleExists(nAktColl))
2978 SetTxtFmtCollAndListLevel( *pPaM, pCollA[ nAktColl ]);
2979 ChkToggleAttr(pCollA[ nOldColl ].n81Flags, pCollA[ nAktColl ].n81Flags);
2980 ChkToggleBiDiAttr(pCollA[nOldColl].n81BiDiFlags,
2981 pCollA[nAktColl].n81BiDiFlags);
2985 long SwWW8ImplReader::ReadTextAttr(WW8_CP& rTxtPos, bool& rbStartLine)
2987 long nSkipChars = 0;
2988 WW8PLCFManResult aRes;
2990 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
2991 bool bStartAttr = pPlcxMan->Get(&aRes); // hole Attribut-Pos
2992 aRes.nAktCp = rTxtPos; // Akt. Cp-Pos
2994 bool bNewSection = (aRes.nFlags & MAN_MASK_NEW_SEP) && !bIgnoreText;
2995 if ( bNewSection ) // neue Section
2997 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
2998 // PageDesc erzeugen und fuellen
2999 maSectionManager.CreateSep(rTxtPos, bPgSecBreak);
3000 // -> 0xc war ein Sectionbreak, aber
3001 // kein Pagebreak;
3002 bPgSecBreak = false; // PageDesc erzeugen und fuellen
3003 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
3006 // neuer Absatz ueber Plcx.Fkp.papx
3007 if ( (aRes.nFlags & MAN_MASK_NEW_PAP)|| rbStartLine )
3009 ProcessAktCollChange( aRes, &bStartAttr,
3010 MAN_MASK_NEW_PAP == (aRes.nFlags & MAN_MASK_NEW_PAP) &&
3011 !bIgnoreText );
3012 rbStartLine = false;
3015 // position of last CP that's to be ignored
3016 long nSkipPos = -1;
3018 if( 0 < aRes.nSprmId ) // leere Attrs ignorieren
3020 if( ( eFTN > aRes.nSprmId ) || ( 0x0800 <= aRes.nSprmId ) )
3022 if( bStartAttr ) // WW-Attribute
3024 if( aRes.nMemLen >= 0 )
3025 ImportSprm(aRes.pMemPos, aRes.nSprmId);
3027 else
3028 EndSprm( aRes.nSprmId ); // Attr ausschalten
3030 else if( aRes.nSprmId < 0x800 ) // eigene Hilfs-Attribute
3032 if (bStartAttr)
3034 nSkipChars = ImportExtSprm(&aRes);
3035 if (
3036 (aRes.nSprmId == eFTN) || (aRes.nSprmId == eEDN) ||
3037 (aRes.nSprmId == eFLD) || (aRes.nSprmId == eAND)
3040 // Felder/Ftn-/End-Note hier ueberlesen
3041 rTxtPos += nSkipChars;
3042 nSkipPos = rTxtPos-1;
3045 else
3046 EndExtSprm( aRes.nSprmId );
3050 pStrm->Seek(pSBase->WW8Cp2Fc( pPlcxMan->GetCpOfs() + rTxtPos, &bIsUnicode));
3052 // Find next Attr position (and Skip attributes of field contents if needed)
3053 if (nSkipChars && !bIgnoreText)
3054 pCtrlStck->MarkAllAttrsOld();
3055 bool bOldIgnoreText = bIgnoreText;
3056 bIgnoreText = true;
3057 USHORT nOldColl = nAktColl;
3058 bool bDoPlcxManPlusPLus = true;
3059 long nNext;
3062 if( bDoPlcxManPlusPLus )
3063 (*pPlcxMan)++;
3064 nNext = pPlcxMan->Where();
3066 if (mpPostProcessAttrsInfo &&
3067 mpPostProcessAttrsInfo->mnCpStart == nNext)
3069 mpPostProcessAttrsInfo->mbCopy = true;
3072 if( (0 <= nNext) && (nSkipPos >= nNext) )
3074 nNext = ReadTextAttr( rTxtPos, rbStartLine );
3075 bDoPlcxManPlusPLus = false;
3076 bIgnoreText = true;
3079 if (mpPostProcessAttrsInfo &&
3080 nNext > mpPostProcessAttrsInfo->mnCpEnd)
3082 mpPostProcessAttrsInfo->mbCopy = false;
3085 while( nSkipPos >= nNext );
3086 bIgnoreText = bOldIgnoreText;
3087 if( nSkipChars )
3089 pCtrlStck->KillUnlockedAttrs( *pPaM->GetPoint() );
3090 if( nOldColl != pPlcxMan->GetColl() )
3091 ProcessAktCollChange(aRes, 0, false);
3094 return nNext;
3097 void SwWW8ImplReader::ReadAttrs(WW8_CP& rNext, WW8_CP& rTxtPos, bool& rbStartLine)
3099 if( rTxtPos >= rNext )
3100 { // Stehen Attribute an ?
3104 rNext = ReadTextAttr( rTxtPos, rbStartLine );
3106 while( rTxtPos >= rNext );
3109 else if ( rbStartLine )
3111 // keine Attribute, aber trotzdem neue Zeile
3112 // wenn eine Zeile mit einem Seitenumbruch aufhoert und sich keine
3113 // Absatzattribute / Absatzvorlagen aendern, ist das Zeilenende
3114 // nicht im Plcx.Fkp.papx eingetragen, d.h. ( nFlags & MAN_MASK_NEW_PAP )
3115 // ist false. Deshalb muss als Sonderbehandlung hier die Vorlage gesetzt
3116 // werden.
3117 if (!bCpxStyle && nAktColl < nColls)
3118 SetTxtFmtCollAndListLevel(*pPaM, pCollA[nAktColl]);
3119 rbStartLine = false;
3123 // CloseAttrEnds zum Lesen nur der Attributenden am Ende eines Textes oder
3124 // Textbereiches ( Kopfzeile, Fussnote, ...). Attributanfaenge, Felder
3125 // werden ignoriert.
3126 void SwWW8ImplReader::CloseAttrEnds()
3128 //If there are any unclosed sprms then copy them to
3129 //another stack and close the ones that must be closed
3130 std::stack<USHORT> aStack;
3131 pPlcxMan->TransferOpenSprms(aStack);
3133 while (!aStack.empty())
3135 USHORT nSprmId = aStack.top();
3136 if ((0 < nSprmId) && (( eFTN > nSprmId) || (0x0800 <= nSprmId)))
3137 EndSprm(nSprmId);
3138 aStack.pop();
3141 EndSpecial();
3144 bool SwWW8ImplReader::ReadText(long nStartCp, long nTextLen, ManTypes nType)
3146 sw::log::Environment eContext = sw::log::eMainText;
3147 if (nType == MAN_MAINTEXT)
3148 eContext = sw::log::eMainText;
3149 else
3150 eContext = sw::log::eSubDoc;
3151 maTracer.EnterEnvironment(eContext);
3153 bool bJoined=false;
3155 bool bStartLine = true;
3156 short nCrCount = 0;
3157 short nDistance = 0;
3159 bWasParaEnd = false;
3160 nAktColl = 0;
3161 pAktItemSet = 0;
3162 nCharFmt = -1;
3163 bSpec = false;
3164 bPgSecBreak = false;
3166 pPlcxMan = new WW8PLCFMan( pSBase, nType, nStartCp );
3167 long nCpOfs = pPlcxMan->GetCpOfs(); // Offset fuer Header/Footer, Footnote
3169 WW8_CP nNext = pPlcxMan->Where();
3170 SwTxtNode* pPreviousNode = 0;
3171 BYTE nDropLines = 0;
3172 SwCharFmt* pNewSwCharFmt = 0;
3173 const SwCharFmt* pFmt = 0;
3174 pStrm->Seek( pSBase->WW8Cp2Fc( nStartCp + nCpOfs, &bIsUnicode ) );
3176 WW8_CP l = nStartCp;
3177 while ( l<nStartCp+nTextLen )
3179 ReadAttrs( nNext, l, bStartLine );// behandelt auch Section-Breaks
3180 ASSERT(pPaM->GetNode()->GetTxtNode(), "Missing txtnode");
3182 if (mpPostProcessAttrsInfo != NULL)
3183 PostProcessAttrs();
3185 if( l>= nStartCp + nTextLen )
3186 break;
3188 bStartLine = ReadChars(l, nNext, nStartCp+nTextLen, nCpOfs);
3190 // If the previous paragraph was a dropcap then do not
3191 // create a new txtnode and join the two paragraphs together
3193 if (bStartLine && !pPreviousNode) // Zeilenende
3194 AppendTxtNode(*pPaM->GetPoint());
3196 if (pPreviousNode && bStartLine)
3198 SwTxtNode* pEndNd = pPaM->GetNode()->GetTxtNode();
3199 const xub_StrLen nDropCapLen = pPreviousNode->GetTxt().Len();
3201 // Need to reset the font size and text position for the dropcap
3203 SwPaM aTmp(*pEndNd, 0, *pEndNd, nDropCapLen+1);
3204 pCtrlStck->Delete(aTmp);
3207 // Get the default document dropcap which we can use as our template
3208 const SwFmtDrop* defaultDrop =
3209 (const SwFmtDrop*) GetFmtAttr(RES_PARATR_DROP);
3210 SwFmtDrop aDrop(*defaultDrop);
3212 aDrop.GetLines() = nDropLines;
3213 aDrop.GetDistance() = nDistance;
3214 aDrop.GetChars() = writer_cast<BYTE>(nDropCapLen);
3215 // Word has no concept of a "whole word dropcap"
3216 aDrop.GetWholeWord() = false;
3218 if (pFmt)
3219 aDrop.SetCharFmt(const_cast<SwCharFmt*>(pFmt));
3220 else if(pNewSwCharFmt)
3221 aDrop.SetCharFmt(const_cast<SwCharFmt*>(pNewSwCharFmt));
3223 SwPosition aStart(*pEndNd);
3224 pCtrlStck->NewAttr(aStart, aDrop);
3225 pCtrlStck->SetAttr(*pPaM->GetPoint(), RES_PARATR_DROP);
3226 pPreviousNode = 0;
3228 else if (bDropCap)
3230 // If we have found a dropcap store the textnode
3231 pPreviousNode = pPaM->GetNode()->GetTxtNode();
3233 const BYTE *pDCS;
3235 if (bVer67)
3236 pDCS = pPlcxMan->GetPapPLCF()->HasSprm(46);
3237 else
3238 pDCS = pPlcxMan->GetPapPLCF()->HasSprm(0x442C);
3240 if (pDCS)
3241 nDropLines = (*pDCS) >> 3;
3242 else // There is no Drop Cap Specifier hence no dropcap
3243 pPreviousNode = 0;
3245 if (const BYTE *pDistance = pPlcxMan->GetPapPLCF()->HasSprm(0x842F))
3246 nDistance = SVBT16ToShort( pDistance );
3247 else
3248 nDistance = 0;
3250 const SwFmtCharFmt *pSwFmtCharFmt = 0;
3252 if(pAktItemSet)
3253 pSwFmtCharFmt = &(ItemGet<SwFmtCharFmt>(*pAktItemSet, RES_TXTATR_CHARFMT));
3255 if(pSwFmtCharFmt)
3256 pFmt = pSwFmtCharFmt->GetCharFmt();
3258 if(pAktItemSet && !pFmt)
3260 String sPrefix(CREATE_CONST_ASC( "WW8Dropcap"));
3261 sPrefix += String::CreateFromInt32( nDropCap++ );
3262 pNewSwCharFmt = rDoc.MakeCharFmt(sPrefix, (SwCharFmt*)rDoc.GetDfltCharFmt());
3263 pAktItemSet->ClearItem(RES_CHRATR_ESCAPEMENT);
3264 pNewSwCharFmt->SetFmtAttr( *pAktItemSet );
3267 delete pAktItemSet;
3268 pAktItemSet = 0;
3269 bDropCap=false;
3272 if (bStartLine || bWasTabRowEnd)
3274 // alle 64 CRs aufrufen not for Header u. ae.
3275 if ((nCrCount++ & 0x40) == 0 && nType == MAN_MAINTEXT)
3277 nProgress = (USHORT)( l * 100 / nTextLen );
3278 ::SetProgressState(nProgress, mpDocShell); // Update
3282 // If we have encountered a 0x0c which indicates either section of
3283 // pagebreak then look it up to see if it is a section break, and
3284 // if it is not then insert a page break. If it is a section break
3285 // it will be handled as such in the ReadAttrs of the next loop
3286 if (bPgSecBreak)
3288 // We need only to see if a section is ending at this cp,
3289 // the plcf will already be sitting on the correct location
3290 // if it is there.
3291 WW8PLCFxDesc aTemp;
3292 aTemp.nStartPos = aTemp.nEndPos = WW8_CP_MAX;
3293 if (pPlcxMan->GetSepPLCF())
3294 pPlcxMan->GetSepPLCF()->GetSprms(&aTemp);
3295 if ((aTemp.nStartPos != l) && (aTemp.nEndPos != l))
3297 // --> OD 2005-01-07 #i39251# - insert text node for page break,
3298 // if no one inserted.
3299 // --> OD 2005-02-28 #i43118# - refine condition: the anchor
3300 // control stack has to have entries, otherwise it's not needed
3301 // to insert a text node.
3302 if ( !bStartLine && pAnchorStck->Count() > 0 )
3304 AppendTxtNode(*pPaM->GetPoint());
3306 // <--
3307 rDoc.InsertPoolItem(*pPaM,
3308 SvxFmtBreakItem(SVX_BREAK_PAGE_BEFORE, RES_BREAK), 0);
3309 bPgSecBreak = false;
3314 if (pPaM->GetPoint()->nContent.GetIndex())
3315 AppendTxtNode(*pPaM->GetPoint());
3317 if (!bInHyperlink)
3318 bJoined = JoinNode(*pPaM);
3320 CloseAttrEnds();
3322 delete pPlcxMan, pPlcxMan = 0;
3323 maTracer.LeaveEnvironment(eContext);
3324 return bJoined;
3327 /***************************************************************************
3328 # class SwWW8ImplReader
3329 #**************************************************************************/
3331 SwWW8ImplReader::SwWW8ImplReader(BYTE nVersionPara, SvStorage* pStorage,
3332 SvStream* pSt, SwDoc& rD, const String& rBaseURL, bool bNewDoc) :
3333 mpDocShell(rD.GetDocShell()),
3334 maTracer(*(mpDocShell->GetMedium())),
3335 pStg(pStorage),
3336 pStrm(pSt),
3337 pTableStream(0),
3338 pDataStream(0),
3339 rDoc(rD),
3340 maSectionManager(*this),
3341 maInsertedTables(rD),
3342 maSectionNameGenerator(rD,CREATE_CONST_ASC("WW")),
3343 maGrfNameGenerator(bNewDoc,String('G')),
3344 maParaStyleMapper(rD),
3345 maCharStyleMapper(rD),
3346 pMSDffManager(0),
3347 mpAtnNames(0),
3348 pAuthorInfos(0),
3349 sBaseURL(rBaseURL),
3350 m_bRegardHindiDigits( false ),
3351 mbNewDoc(bNewDoc),
3352 nDropCap(0),
3353 nIdctHint(0),
3354 bBidi(false),
3355 bReadTable(false)
3357 pStrm->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
3358 nWantedVersion = nVersionPara;
3359 pCtrlStck = 0;
3360 mpRedlineStack = 0;
3361 pReffedStck = 0;
3362 pReffingStck = 0;
3363 pAnchorStck = 0;
3364 pFonts = 0;
3365 pSBase = 0;
3366 pPlcxMan = 0;
3367 pStyles = 0;
3368 pAktColl = 0;
3369 pLstManager = 0;
3370 pAktItemSet = 0;
3371 pCollA = 0;
3372 pDfltTxtFmtColl = 0;
3373 pStandardFmtColl = 0;
3374 pHdFt = 0;
3375 pWFlyPara = 0;
3376 pSFlyPara = 0;
3377 pFlyFmtOfJustInsertedGraphic = 0;
3378 pFmtOfJustInsertedApo = 0;
3379 pPreviousNumPaM = 0;
3380 pPrevNumRule = 0;
3381 nColls = nAktColl = 0;
3382 nObjLocFc = nPicLocFc = 0;
3383 nInTable=0;
3384 bReadNoTbl = bPgSecBreak = bSpec = bObj = bTxbxFlySection
3385 = bHasBorder = bSymbol = bIgnoreText
3386 = bWasTabRowEnd = bWasTabCellEnd = false;
3387 bShdTxtCol = bCharShdTxtCol = bAnl = bHdFtFtnEdn = bFtnEdn
3388 = bIsHeader = bIsFooter = bIsUnicode = bCpxStyle = bStyNormal =
3389 bWWBugNormal = false;
3391 mpPostProcessAttrsInfo = 0;
3393 bNoAttrImport = bPgChpLevel = bEmbeddObj = false;
3394 bAktAND_fNumberAcross = false;
3395 bNoLnNumYet = true;
3396 bInHyperlink = false;
3397 bWasParaEnd = false;
3398 bDropCap = false;
3399 bFirstPara = true;
3400 bParaAutoBefore = false;
3401 bParaAutoAfter = false;
3402 nProgress = 0;
3403 nSwNumLevel = nWwNumType = 0xff;
3404 pTableDesc = 0;
3405 pNumOlst = 0;
3406 pNode_FLY_AT_CNTNT = 0;
3407 pDrawModel = 0;
3408 pDrawPg = 0;
3409 mpDrawEditEngine = 0;
3410 pWWZOrder = 0;
3411 pFormImpl = 0;
3412 mpChosenOutlineNumRule = 0;
3413 pNumFldType = 0;
3414 nFldNum = 0;
3416 nLFOPosition = USHRT_MAX;
3417 nListLevel = WW8ListManager::nMaxLevel;
3418 eHardCharSet = RTL_TEXTENCODING_DONTKNOW;
3420 nPgChpDelim = nPgChpLevel = 0;
3422 maApos.push_back(false);
3425 void SwWW8ImplReader::DeleteStk(SwFltControlStack* pStck)
3427 if( pStck )
3429 pStck->SetAttr( *pPaM->GetPoint(), 0, false);
3430 pStck->SetAttr( *pPaM->GetPoint(), 0, false);
3431 delete pStck;
3433 else
3435 ASSERT( !this, "WW-Stack bereits geloescht" );
3439 void wwSectionManager::SetSegmentToPageDesc(const wwSection &rSection,
3440 bool bTitlePage, bool bIgnoreCols)
3442 SwPageDesc &rPage = bTitlePage ? *rSection.mpTitlePage : *rSection.mpPage;
3444 SetNumberingType(rSection, rPage);
3446 SwFrmFmt &rFmt = rPage.GetMaster();
3448 if (mrReader.pWDop->fUseBackGroundInAllmodes && mrReader.pMSDffManager)
3450 Rectangle aRect(0, 0, 100, 100); //A dummy, we don't care about the size
3451 SvxMSDffImportData aData(aRect);
3452 SdrObject* pObject = 0;
3453 if (mrReader.pMSDffManager->GetShape(0x401, pObject, aData))
3455 SvxMSDffImportRec * pRec = aData.GetRecord(0);
3457 // Only handle shape if it is a background shape
3458 if ((pRec->nFlags & 0x400) != 0)
3460 SfxItemSet aSet(rFmt.GetAttrSet());
3461 mrReader.MatchSdrItemsIntoFlySet(pObject, aSet, mso_lineSimple,
3462 mso_sptRectangle, aRect);
3463 rFmt.SetFmtAttr(aSet.Get(RES_BACKGROUND));
3467 wwULSpaceData aULData;
3468 GetPageULData(rSection, bTitlePage, aULData);
3469 SetPageULSpaceItems(rFmt, aULData, rSection);
3471 SetPage(rPage, rFmt, rSection, bIgnoreCols);
3473 bool bSetBorder = false;
3474 switch (rSection.maSep.pgbApplyTo)
3476 case 0:
3477 case 3:
3478 bSetBorder = true;
3479 break;
3480 case 1:
3481 bSetBorder = bTitlePage;
3482 break;
3483 case 2:
3484 bSetBorder = !bTitlePage;
3485 break;
3487 if (bSetBorder)
3488 mrReader.SetPageBorder(rFmt, rSection);
3490 mrReader.SetDocumentGrid(rFmt, rSection);
3493 void wwSectionManager::SetUseOn(wwSection &rSection)
3495 bool bEven = (rSection.maSep.grpfIhdt & (WW8_HEADER_EVEN|WW8_FOOTER_EVEN)) ?
3496 true : false;
3498 bool bMirror = mrReader.pWDop->fMirrorMargins ||
3499 mrReader.pWDop->doptypography.f2on1;
3501 UseOnPage eUseBase = bMirror ? nsUseOnPage::PD_MIRROR : nsUseOnPage::PD_ALL;
3502 UseOnPage eUse = eUseBase;
3503 if (!bEven)
3504 eUse = (UseOnPage)(eUse | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE);
3506 ASSERT(rSection.mpPage, "Makes no sense to call me with no pages to set");
3507 if (rSection.mpPage)
3508 rSection.mpPage->WriteUseOn(eUse);
3509 if (rSection.mpTitlePage)
3511 rSection.mpTitlePage->WriteUseOn(
3512 (UseOnPage) (eUseBase | nsUseOnPage::PD_HEADERSHARE | nsUseOnPage::PD_FOOTERSHARE));
3516 //Set the page descriptor on this node, handle the different cases for a text
3517 //node or a table
3518 void GiveNodePageDesc(SwNodeIndex &rIdx, const SwFmtPageDesc &rPgDesc,
3519 SwDoc &rDoc)
3522 If its a table here, apply the pagebreak to the table
3523 properties, otherwise we add it to the para at this
3524 position
3526 if (rIdx.GetNode().IsTableNode())
3528 SwTable& rTable =
3529 rIdx.GetNode().GetTableNode()->GetTable();
3530 SwFrmFmt* pApply = rTable.GetFrmFmt();
3531 ASSERT(pApply, "impossible");
3532 if (pApply)
3533 pApply->SetFmtAttr(rPgDesc);
3535 else
3537 SwPosition aPamStart(rIdx);
3538 aPamStart.nContent.Assign(
3539 rIdx.GetNode().GetCntntNode(), 0);
3540 SwPaM aPage(aPamStart);
3542 rDoc.InsertPoolItem(aPage, rPgDesc, 0);
3546 //Map a word section with to either one or two writer page descriptors
3547 //depending on if the word section has a title page
3548 SwFmtPageDesc wwSectionManager::SetSwFmtPageDesc(mySegIter &rIter,
3549 mySegIter &rStart, bool bIgnoreCols)
3551 SwFmtPageDesc aEmpty;
3552 // --> OD 2008-08-06 #150965#
3553 // Always read title page header/footer data - it could be used by following sections
3554 // if (rIter->HasTitlePage())
3555 // <--
3557 if (IsNewDoc() && rIter == rStart)
3559 rIter->mpTitlePage =
3560 mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_FIRST);
3562 else
3564 USHORT nPos = mrReader.rDoc.MakePageDesc(
3565 ViewShell::GetShellRes()->GetPageDescName(mnDesc)
3566 , 0, false);
3567 rIter->mpTitlePage = &mrReader.rDoc._GetPageDesc(nPos);
3569 ASSERT(rIter->mpTitlePage, "no page!");
3570 if (!rIter->mpTitlePage)
3571 return aEmpty;
3573 SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
3576 if (IsNewDoc() && rIter == rStart)
3578 rIter->mpPage =
3579 mrReader.rDoc.GetPageDescFromPool(RES_POOLPAGE_STANDARD);
3581 else
3583 USHORT nPos = mrReader.rDoc.MakePageDesc(
3584 ViewShell::GetShellRes()->GetPageDescName(mnDesc,
3585 false, rIter->HasTitlePage()),
3586 rIter->mpTitlePage, false);
3587 rIter->mpPage = &mrReader.rDoc._GetPageDesc(nPos);
3589 ASSERT(rIter->mpPage, "no page!");
3590 if (!rIter->mpPage)
3591 return aEmpty;
3593 //Set page before hd/ft
3594 const wwSection *pPrevious = 0;
3595 if (rIter != rStart)
3596 pPrevious = &(*(rIter-1));
3597 SetHdFt(*rIter, std::distance(rStart, rIter), pPrevious);
3598 SetUseOn(*rIter);
3600 //Set hd/ft after set page
3601 if (rIter->mpTitlePage)
3602 SetSegmentToPageDesc(*rIter, true, bIgnoreCols);
3603 SetSegmentToPageDesc(*rIter, false, bIgnoreCols);
3605 SwFmtPageDesc aRet(rIter->HasTitlePage() ?
3606 rIter->mpTitlePage : rIter->mpPage);
3608 rIter->mpPage->SetFollow(rIter->mpPage);
3610 if (rIter->mpTitlePage)
3611 rIter->mpTitlePage->SetFollow(rIter->mpPage);
3613 if (rIter->PageRestartNo())
3614 aRet.SetNumOffset(rIter->PageStartAt());
3616 ++mnDesc;
3617 return aRet;
3620 bool wwSectionManager::IsNewDoc() const
3622 return mrReader.mbNewDoc;
3625 void wwSectionManager::InsertSegments()
3627 const SvtFilterOptions* pOpt = SvtFilterOptions::Get();
3628 sal_Bool bUseEnhFields=(pOpt && pOpt->IsUseEnhancedFields());
3629 mySegIter aEnd = maSegments.end();
3630 mySegIter aStart = maSegments.begin();
3631 for (mySegIter aIter = aStart; aIter != aEnd; ++aIter)
3633 mySegIter aNext = aIter+1;
3634 mySegIter aPrev = (aIter == aStart) ? aIter : aIter-1;
3636 // If two following sections are different in following properties, Word will interprete a continuous
3637 // section break between them as if it was a section break next page.
3638 bool bThisAndPreviousAreCompatible = ((aIter->GetPageWidth() == aPrev->GetPageWidth()) &&
3639 (aIter->GetPageHeight() == aPrev->GetPageHeight()) && (aIter->IsLandScape() == aPrev->IsLandScape()));
3641 bool bInsertSection = (aIter != aStart) ? (aIter->IsContinous() && bThisAndPreviousAreCompatible): false;
3642 bool bInsertPageDesc = !bInsertSection;
3643 bool bProtected = SectionIsProtected(*aIter); // do we really need this ?? I guess I have a different logic in editshell which disales this...
3644 if (bUseEnhFields && mrReader.pWDop->fProtEnabled && aIter->IsNotProtected()) {
3645 // here we have the special case that the whole document is protected, with the execption of this section.
3646 // I want to address this when I do the section rework, so for the moment we disable the overall protection then...
3647 mrReader.rDoc.set(IDocumentSettingAccess::PROTECT_FORM, false );
3651 if (bInsertPageDesc)
3654 If a cont section follows this section then we won't be
3655 creating a page desc with 2+ cols as we cannot host a one
3656 col section in a 2+ col pagedesc and make it look like
3657 word. But if the current section actually has columns then
3658 we are forced to insert a section here as well as a page
3659 descriptor.
3662 bool bIgnoreCols = false;
3663 bool bThisAndNextAreCompatible = (aNext != aEnd) ? ((aIter->GetPageWidth() == aNext->GetPageWidth()) &&
3664 (aIter->GetPageHeight() == aNext->GetPageHeight()) && (aIter->IsLandScape() == aNext->IsLandScape())) : true;
3666 if ((aNext != aEnd && aNext->IsContinous() && bThisAndNextAreCompatible) || bProtected)
3668 bIgnoreCols = true;
3669 if ((aIter->NoCols() > 1) || bProtected)
3670 bInsertSection = true;
3673 SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, bIgnoreCols));
3674 if (!aDesc.GetPageDesc())
3675 continue;
3676 GiveNodePageDesc(aIter->maStart, aDesc, mrReader.rDoc);
3679 SwTxtNode* pTxtNd = 0;
3680 if (bInsertSection)
3682 //Start getting the bounds of this section
3683 SwPaM aSectPaM(*mrReader.pPaM);
3684 SwNodeIndex aAnchor(aSectPaM.GetPoint()->nNode);
3685 if (aNext != aEnd)
3687 aAnchor = aNext->maStart;
3688 aSectPaM.GetPoint()->nNode = aAnchor;
3689 aSectPaM.GetPoint()->nContent.Assign(
3690 aNext->maStart.GetNode().GetCntntNode(), 0);
3691 aSectPaM.Move(fnMoveBackward);
3694 const SwPosition* pPos = aSectPaM.GetPoint();
3695 const SwTxtNode* pSttNd =
3696 mrReader.rDoc.GetNodes()[ pPos->nNode ]->GetTxtNode();
3697 const SwTableNode* pTableNd = pSttNd ? pSttNd->FindTableNode() : 0;
3698 if (pTableNd)
3700 pTxtNd =
3701 mrReader.rDoc.GetNodes().MakeTxtNode(aAnchor,
3702 mrReader.rDoc.GetTxtCollFromPool( RES_POOLCOLL_TEXT ));
3704 aSectPaM.GetPoint()->nNode = SwNodeIndex(*pTxtNd);
3705 aSectPaM.GetPoint()->nContent.Assign(
3706 aSectPaM.GetCntntNode(), 0);
3709 aSectPaM.SetMark();
3711 aSectPaM.GetPoint()->nNode = aIter->maStart;
3712 aSectPaM.GetPoint()->nContent.Assign(
3713 aSectPaM.GetCntntNode(), 0);
3714 //End getting the bounds of this section, quite a job eh ?
3716 SwSectionFmt *pRet = InsertSection(aSectPaM, *aIter);
3717 //The last section if continous is always unbalanced
3718 if (pRet)
3720 //Set the columns to be UnBalanced if that compatability option
3721 //is set
3722 if (mrReader.pWDop->fNoColumnBalance)
3723 pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
3724 else
3726 //Otherwise set to unbalanced if the following section is
3727 //not continuous, (which also means that the last section
3728 //is unbalanced)
3729 if (aNext == aEnd || !aNext->IsContinous())
3730 pRet->SetFmtAttr(SwFmtNoBalancedColumns(true));
3734 bool bHasOwnHdFt = false;
3736 #112027# #110379#
3737 In this nightmare scenario the continuous section has its own
3738 headers and footers so we will try and find a hard page break
3739 between here and the end of the section and put the headers and
3740 footers there.
3742 if (!bInsertPageDesc)
3744 bHasOwnHdFt =
3745 mrReader.HasOwnHeaderFooter(
3746 aIter->maSep.grpfIhdt & ~(WW8_HEADER_FIRST | WW8_FOOTER_FIRST),
3747 aIter->maSep.grpfIhdt, std::distance(aStart, aIter)
3750 if (bHasOwnHdFt)
3752 // #i40766# Need to cache the page descriptor in case there is
3753 // no page break in the section
3754 SwPageDesc *pOrig = aIter->mpPage;
3755 SwPageDesc *pOrigTitle = aIter->mpTitlePage;
3756 bool bFailed = true;
3757 SwFmtPageDesc aDesc(SetSwFmtPageDesc(aIter, aStart, true));
3758 if (aDesc.GetPageDesc())
3760 ULONG nStart = aSectPaM.Start()->nNode.GetIndex();
3761 ULONG nEnd = aSectPaM.End()->nNode.GetIndex();
3762 for(; nStart <= nEnd; ++nStart)
3764 SwNode* pNode = mrReader.rDoc.GetNodes()[nStart];
3765 if (!pNode)
3766 continue;
3767 if (sw::util::HasPageBreak(*pNode))
3769 SwNodeIndex aIdx(*pNode);
3770 GiveNodePageDesc(aIdx, aDesc, mrReader.rDoc);
3771 bFailed = false;
3772 break;
3776 if(bFailed)
3778 aIter->mpPage = pOrig;
3779 aIter->mpTitlePage = pOrigTitle;
3784 if (pTxtNd)
3786 SwNodeIndex aIdx(*pTxtNd);
3787 SwPosition aPos(aIdx);
3788 SwPaM aTest(aPos);
3789 mrReader.rDoc.DelFullPara(aTest);
3790 pTxtNd = 0;
3795 void SwWW8ImplReader::StoreMacroCmds()
3797 if (pWwFib->lcbCmds)
3799 maTracer.Log(sw::log::eContainsWordBasic);
3801 pTableStream->Seek(pWwFib->fcCmds);
3803 uno::Reference < embed::XStorage > xRoot(mpDocShell->GetStorage());
3806 uno::Reference < io::XStream > xStream =
3807 xRoot->openStreamElement( CREATE_CONST_ASC(SL::aMSMacroCmds), embed::ElementModes::READWRITE );
3808 SvStream* pStream = ::utl::UcbStreamHelper::CreateStream( xStream );
3810 sal_uInt8 *pBuffer = new sal_uInt8[pWwFib->lcbCmds];
3811 pTableStream->Read(pBuffer, pWwFib->lcbCmds);
3812 pStream->Write(pBuffer, pWwFib->lcbCmds);
3813 delete[] pBuffer;
3814 delete pStream;
3816 catch ( uno::Exception& )
3822 void SwWW8ImplReader::ReadDocVars()
3824 std::vector<String> aDocVarStrings;
3825 std::vector<ww::bytes> aDocVarStringIds;
3826 std::vector<String> aDocValueStrings;
3827 WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcStwUser,
3828 pWwFib->lcbStwUser, bVer67 ? 2 : 0, eStructCharSet,
3829 aDocVarStrings, &aDocVarStringIds, &aDocValueStrings);
3830 if (!bVer67) {
3831 using namespace ::com::sun::star;
3833 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
3834 mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
3835 uno::Reference<document::XDocumentProperties> xDocProps(
3836 xDPS->getDocumentProperties());
3837 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
3838 uno::Reference<beans::XPropertyContainer> xUserDefinedProps =
3839 xDocProps->getUserDefinedProperties();
3840 DBG_ASSERT(xUserDefinedProps.is(), "UserDefinedProperties is null");
3842 for(size_t i=0; i<aDocVarStrings.size(); i++)
3844 uno::Any aDefaultValue;
3845 ::rtl::OUString name(aDocVarStrings[i]);
3846 uno::Any aValue;
3847 aValue <<= ::rtl::OUString(aDocValueStrings[i]);
3848 try {
3849 xUserDefinedProps->addProperty( name,
3850 beans::PropertyAttribute::REMOVEABLE,
3851 aValue );
3852 } catch (uno::Exception &) {
3853 // ignore
3859 //-----------------------------------------
3860 // Document Info
3861 //-----------------------------------------
3863 void SwWW8ImplReader::ReadDocInfo()
3865 if( pStg )
3867 uno::Reference<document::XDocumentPropertiesSupplier> xDPS(
3868 mpDocShell->GetModel(), uno::UNO_QUERY_THROW);
3869 uno::Reference<document::XDocumentProperties> xDocProps(
3870 xDPS->getDocumentProperties());
3871 DBG_ASSERT(xDocProps.is(), "DocumentProperties is null");
3873 if (xDocProps.is()) {
3874 if ( pWwFib->fDot )
3876 rtl::OUString sTemplateURL;
3877 SfxMedium* pMedium = mpDocShell->GetMedium();
3878 if ( pMedium )
3880 rtl::OUString aName = pMedium->GetName();
3881 INetURLObject aURL( aName );
3882 sTemplateURL = aURL.GetMainURL(INetURLObject::DECODE_TO_IURI);
3883 if ( sTemplateURL.getLength() > 0 )
3884 xDocProps->setTemplateURL( sTemplateURL );
3887 else // not a template
3889 long nCur = pTableStream->Tell();
3890 Sttb aSttb;
3891 pTableStream->Seek( pWwFib->fcSttbfAssoc ); // point at tgc record
3892 if (!aSttb.Read( pTableStream ) )
3893 OSL_TRACE("** Read of SttbAssoc data failed!!!! ");
3894 pTableStream->Seek( nCur ); // return to previous position, is that necessary?
3895 #if DEBUG
3896 aSttb.Print( stderr );
3897 #endif
3898 String sPath = aSttb.getStringAtIndex( 0x1 );
3899 String aURL;
3900 // attempt to convert to url ( won't work for obvious reasons on linux
3901 if ( sPath.Len() )
3902 ::utl::LocalFileHelper::ConvertPhysicalNameToURL( sPath, aURL );
3903 if ( aURL.Len() )
3904 xDocProps->setTemplateURL( aURL );
3905 else
3906 xDocProps->setTemplateURL( sPath );
3909 sfx2::LoadOlePropertySet(xDocProps, pStg);
3914 void lcl_createTemplateToProjectEntry( const uno::Reference< container::XNameContainer >& xPrjNameCache, const rtl::OUString& sTemplatePathOrURL, const rtl::OUString& sVBAProjName )
3916 if ( xPrjNameCache.is() )
3918 INetURLObject aObj;
3919 aObj.SetURL( sTemplatePathOrURL );
3920 bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
3921 rtl::OUString aURL;
3922 if ( bIsURL )
3923 aURL = sTemplatePathOrURL;
3924 else
3926 osl::FileBase::getFileURLFromSystemPath( sTemplatePathOrURL, aURL );
3927 aObj.SetURL( aURL );
3931 rtl::OUString templateNameWithExt = aObj.GetLastName();
3932 rtl::OUString templateName;
3933 sal_Int32 nIndex = templateNameWithExt.lastIndexOf( '.' );
3934 //xPrjNameCache->insertByName( templateNameWithExt, uno::makeAny( sVBAProjName ) );
3935 if ( nIndex != -1 )
3937 templateName = templateNameWithExt.copy( 0, nIndex );
3938 xPrjNameCache->insertByName( templateName, uno::makeAny( sVBAProjName ) );
3941 catch( uno::Exception& )
3947 class WW8Customizations
3949 SvStream* mpTableStream;
3950 WW8Fib mWw8Fib;
3951 public:
3952 WW8Customizations( SvStream*, WW8Fib& );
3953 bool Import( SwDocShell* pShell );
3956 WW8Customizations::WW8Customizations( SvStream* pTableStream, WW8Fib& rFib ) : mpTableStream(pTableStream), mWw8Fib( rFib )
3960 bool WW8Customizations::Import( SwDocShell* pShell )
3962 if ( mWw8Fib.lcbCmds == 0 )
3963 return false;
3964 Tcg aTCG;
3965 long nCur = mpTableStream->Tell();
3966 mpTableStream->Seek( mWw8Fib.fcCmds ); // point at tgc record
3967 if (!aTCG.Read( mpTableStream ) )
3968 OSL_TRACE("** Read of Customization data failed!!!! ");
3969 mpTableStream->Seek( nCur ); // return to previous position, is that necessary?
3970 #if DEBUG
3971 aTCG.Print( stderr );
3972 #endif
3973 return aTCG.ImportCustomToolBar( *pShell );
3976 bool SwWW8ImplReader::ReadGlobalTemplateSettings( const rtl::OUString& sCreatedFrom, const uno::Reference< container::XNameContainer >& xPrjNameCache )
3978 SvtPathOptions aPathOpt;
3979 String aAddinPath = aPathOpt.GetAddinPath();
3980 uno::Sequence< rtl::OUString > sGlobalTemplates;
3982 // first get the autoload addins in the directory STARTUP
3983 uno::Reference< ucb::XSimpleFileAccess > xSFA( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), uno::UNO_QUERY_THROW );
3985 if( xSFA->isFolder( aAddinPath ) )
3986 sGlobalTemplates = xSFA->getFolderContents( aAddinPath, sal_False );
3988 sal_Int32 nEntries = sGlobalTemplates.getLength();
3989 bool bRes = true;
3990 const SvtFilterOptions* pVBAFlags = SvtFilterOptions::Get();
3991 for ( sal_Int32 i=0; i<nEntries; ++i )
3993 INetURLObject aObj;
3994 aObj.SetURL( sGlobalTemplates[ i ] );
3995 bool bIsURL = aObj.GetProtocol() != INET_PROT_NOT_VALID;
3996 rtl::OUString aURL;
3997 if ( bIsURL )
3998 aURL = sGlobalTemplates[ i ];
3999 else
4000 osl::FileBase::getFileURLFromSystemPath( sGlobalTemplates[ i ], aURL );
4001 if ( !aURL.endsWithIgnoreAsciiCaseAsciiL( ".dot", 4 ) || ( sCreatedFrom.getLength() && sCreatedFrom.equals( aURL ) ) )
4002 continue; // don't try and read the same document as ourselves
4004 SotStorageRef rRoot = new SotStorage( aURL, STREAM_STD_READWRITE, STORAGE_TRANSACTED );
4006 // Read Macro Projects
4007 SvxImportMSVBasic aVBasic(*mpDocShell, *rRoot,
4008 pVBAFlags->IsLoadWordBasicCode(),
4009 pVBAFlags->IsLoadWordBasicStorage() );
4012 String s1(CREATE_CONST_ASC("Macros"));
4013 String s2(CREATE_CONST_ASC("VBA"));
4014 int nRet = aVBasic.Import( s1, s2, ! pVBAFlags->IsLoadWordBasicCode() );
4015 lcl_createTemplateToProjectEntry( xPrjNameCache, aURL, aVBasic.GetVBAProjectName() );
4016 // Read toolbars & menus
4017 SvStorageStreamRef refMainStream = rRoot->OpenSotStream( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("WordDocument") ) );
4018 refMainStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
4019 WW8Fib aWwFib( *refMainStream, 8 );
4020 SvStorageStreamRef xTableStream = rRoot->OpenSotStream(String::CreateFromAscii( aWwFib.fWhichTblStm ? SL::a1Table : SL::a0Table), STREAM_STD_READ);
4022 if (xTableStream.Is() && SVSTREAM_OK == xTableStream->GetError())
4024 xTableStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
4025 WW8Customizations aGblCustomisations( xTableStream, aWwFib );
4026 aGblCustomisations.Import( mpDocShell );
4029 return bRes;
4032 ULONG SwWW8ImplReader::CoreLoad(WW8Glossary *pGloss, const SwPosition &rPos)
4034 ULONG nErrRet = 0;
4036 if (mbNewDoc && pStg && !pGloss)
4037 ReadDocInfo();
4039 pPaM = new SwPaM(rPos);
4041 pCtrlStck = new SwWW8FltControlStack( &rDoc, nFieldFlags, *this );
4043 mpRedlineStack = new sw::util::RedlineStack(rDoc);
4046 RefFldStck: Keeps track of bookmarks which may be inserted as
4047 variables intstead.
4049 pReffedStck = new SwFltEndStack(&rDoc, nFieldFlags);
4050 pReffingStck = new SwWW8FltRefStack(&rDoc, nFieldFlags);
4052 pAnchorStck = new SwWW8FltAnchorStack(&rDoc, nFieldFlags);
4054 sal_uInt16 nPageDescOffset = rDoc.GetPageDescCnt();
4056 SwNodeIndex aSttNdIdx( rDoc.GetNodes() );
4057 SwRelNumRuleSpaces aRelNumRule(rDoc, mbNewDoc);
4059 USHORT eMode = nsRedlineMode_t::REDLINE_SHOW_INSERT;
4061 mpSprmParser = new wwSprmParser(pWwFib->GetFIBVersion());
4063 // praktische Hilfsvariablen besetzen:
4064 bVer6 = (6 == pWwFib->nVersion);
4065 bVer7 = (7 == pWwFib->nVersion);
4066 bVer67 = bVer6 || bVer7;
4067 bVer8 = (8 == pWwFib->nVersion);
4069 eTextCharSet = WW8Fib::GetFIBCharset(pWwFib->chse);
4070 eStructCharSet = WW8Fib::GetFIBCharset(pWwFib->chseTables);
4072 bWWBugNormal = pWwFib->nProduct == 0xc03d;
4074 if (!mbNewDoc)
4075 aSttNdIdx = pPaM->GetPoint()->nNode;
4077 ::StartProgress(STR_STATSTR_W4WREAD, 0, 100, mpDocShell);
4079 #ifdef DEBUGDUMP
4080 //experimental embedded ttf dumper
4081 if (pWwFib->lcbSttbttmbd && (7 < pWwFib->nVersion))
4083 pTableStream->Seek(pWwFib->fcSttbttmbd);
4084 sal_uInt16 nZeros;
4085 *pTableStream >> nZeros;
4086 sal_uInt16 nNoEntries;
4087 *pTableStream >> nNoEntries;
4088 sal_uInt32 nUnknown1;
4089 *pTableStream >> nUnknown1;
4090 sal_uInt16 nUnknown2;
4091 *pTableStream >> nUnknown2;
4092 std::vector<sal_uInt32> aOffsets;
4093 for (sal_uInt16 nI = 0; nI < nNoEntries; ++nI)
4095 sal_uInt32 nOffset;
4096 *pTableStream >> nOffset;
4097 aOffsets.push_back(nOffset);
4098 sal_uInt32 nUnknown3;
4099 *pTableStream >> nUnknown3;
4100 sal_uInt32 nUnknown4;
4101 *pTableStream >> nUnknown4;
4103 typedef std::vector<sal_uInt32>::iterator myIter;
4104 myIter aEnd = aOffsets.end();
4105 myIter aIter = aOffsets.begin();
4106 while (aIter != aEnd)
4108 sal_uInt32 nOffset = *aIter;
4109 sal_uInt32 nLen = STREAM_SEEK_TO_END;
4110 ++aIter;
4111 pStrm->Seek(nOffset);
4112 if (aIter != aEnd)
4113 nLen = *aIter - nOffset;
4114 SvStream *pDbg = sw::hack::CreateDebuggingStream(CREATE_CONST_ASC(".ttf.dump"));
4115 sw::hack::DumpStream(*pStrm, *pDbg, nLen);
4116 delete pDbg;
4119 #endif
4121 // read Font Table
4122 pFonts = new WW8Fonts( *pTableStream, *pWwFib );
4124 // Document Properties
4125 pWDop = new WW8Dop( *pTableStream, pWwFib->nFib, pWwFib->fcDop,
4126 pWwFib->lcbDop );
4128 if (mbNewDoc)
4129 ImportDop();
4132 Import revisioning data: author names
4134 if( pWwFib->lcbSttbfRMark )
4136 ReadRevMarkAuthorStrTabl( *pTableStream,
4137 pWwFib->fcSttbfRMark,
4138 pWwFib->lcbSttbfRMark, rDoc );
4141 // M.M. Initialize our String/ID map for Linked Sections
4142 std::vector<String> aLinkStrings;
4143 std::vector<ww::bytes> aStringIds;
4145 WW8ReadSTTBF(!bVer67, *pTableStream, pWwFib->fcSttbFnm,
4146 pWwFib->lcbSttbFnm, bVer67 ? 2 : 0, eStructCharSet,
4147 aLinkStrings, &aStringIds);
4149 for (size_t i=0; i < aLinkStrings.size(); ++i)
4151 ww::bytes stringId = aStringIds[i];
4152 WW8_STRINGID *stringIdStruct = (WW8_STRINGID*)(&stringId[0]);
4153 aLinkStringMap[SVBT16ToShort(stringIdStruct->nStringId)] =
4154 aLinkStrings[i];
4157 ReadDocVars(); // #129053# import document variables as meta information.
4159 ::SetProgressState(nProgress, mpDocShell); // Update
4161 pLstManager = new WW8ListManager( *pTableStream, *this );
4164 zuerst(!) alle Styles importieren (siehe WW8PAR2.CXX)
4165 VOR dem Import der Listen !!
4167 ::SetProgressState(nProgress, mpDocShell); // Update
4168 pStyles = new WW8RStyle( *pWwFib, this ); // Styles
4169 pStyles->Import();
4172 zu guter Letzt: (siehe ebenfalls WW8PAR3.CXX)
4173 ===============
4174 alle Styles durchgehen und ggfs. zugehoeriges Listen-Format
4175 anhaengen NACH dem Import der Styles und NACH dem Import der
4176 Listen !!
4178 ::SetProgressState(nProgress, mpDocShell); // Update
4179 pStyles->PostProcessStyles();
4181 if (pCollA)
4182 SetOutLineStyles();
4184 pSBase = new WW8ScannerBase(pStrm,pTableStream,pDataStream,pWwFib);
4186 static const SvxExtNumType eNumTA[16] =
4188 SVX_NUM_ARABIC, SVX_NUM_ROMAN_UPPER, SVX_NUM_ROMAN_LOWER,
4189 SVX_NUM_CHARS_UPPER_LETTER_N, SVX_NUM_CHARS_LOWER_LETTER_N,
4190 SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
4191 SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
4192 SVX_NUM_ARABIC, SVX_NUM_ARABIC, SVX_NUM_ARABIC,
4193 SVX_NUM_ARABIC, SVX_NUM_ARABIC
4196 if (pSBase->AreThereFootnotes())
4198 static const SwFtnNum eNumA[4] =
4200 FTNNUM_DOC, FTNNUM_CHAPTER, FTNNUM_PAGE, FTNNUM_DOC
4203 SwFtnInfo aInfo;
4204 aInfo = rDoc.GetFtnInfo(); // Copy-Ctor privat
4206 aInfo.ePos = FTNPOS_PAGE;
4207 aInfo.eNum = eNumA[pWDop->rncFtn];
4208 aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcFtnRef]) );
4209 if( pWDop->nFtn )
4210 aInfo.nFtnOffset = pWDop->nFtn - 1;
4211 rDoc.SetFtnInfo( aInfo );
4213 if( pSBase->AreThereEndnotes() )
4215 SwEndNoteInfo aInfo;
4216 aInfo = rDoc.GetEndNoteInfo(); // parallel zu Ftn
4218 // Ich kann nicht setzen, wann neu nummerieren...
4219 // aInfo.eNum = eNumA[pWDop->pDop->rncEdn];
4220 aInfo.aFmt.SetNumberingType( static_cast< sal_uInt16 >(eNumTA[pWDop->nfcEdnRef]) );
4221 if( pWDop->nEdn )
4222 aInfo.nFtnOffset = pWDop->nEdn - 1;
4223 rDoc.SetEndNoteInfo( aInfo );
4226 if( pWwFib->lcbPlcfhdd )
4227 pHdFt = new WW8PLCF_HdFt( pTableStream, *pWwFib, *pWDop );
4229 if (!mbNewDoc)
4231 // in ein Dokument einfuegen ?
4232 // Da immer ganze Zeile eingelesen werden, muessen
4233 // evtl. Zeilen eingefuegt / aufgebrochen werden
4235 const SwPosition* pPos = pPaM->GetPoint();
4236 const SwTxtNode* pSttNd =
4237 rDoc.GetNodes()[ pPos->nNode ]->GetTxtNode();
4239 USHORT nCntPos = pPos->nContent.GetIndex();
4241 // EinfuegePos nicht in leerer Zeile
4242 if( nCntPos && pSttNd->GetTxt().Len() )
4243 rDoc.SplitNode( *pPos, false ); // neue Zeile erzeugen
4245 if( pSttNd->GetTxt().Len() )
4246 { // EinfuegePos nicht am Ende der Zeile
4247 rDoc.SplitNode( *pPos, false ); // neue Zeile
4248 pPaM->Move( fnMoveBackward ); // gehe in leere Zeile
4251 // verhinder das Einlesen von Tabellen in Fussnoten / Tabellen
4252 ULONG nNd = pPos->nNode.GetIndex();
4253 bReadNoTbl = 0 != pSttNd->FindTableNode() ||
4254 ( nNd < rDoc.GetNodes().GetEndOfInserts().GetIndex() &&
4255 rDoc.GetNodes().GetEndOfInserts().StartOfSectionIndex()
4256 < nNd );
4260 ::SetProgressState(nProgress, mpDocShell); // Update
4262 // loop for each glossary entry and add dummy section node
4263 if (pGloss)
4265 WW8PLCF aPlc(pTableStream, pWwFib->fcPlcfglsy, pWwFib->lcbPlcfglsy, 0);
4267 WW8_CP nStart, nEnd;
4268 void* pDummy;
4270 for (int i=0;i<pGloss->GetNoStrings();i++,aPlc++)
4272 SwNodeIndex aIdx( rDoc.GetNodes().GetEndOfContent());
4273 SwTxtFmtColl* pColl =
4274 rDoc.GetTxtCollFromPool(RES_POOLCOLL_STANDARD,
4275 false);
4276 SwStartNode *pNode =
4277 rDoc.GetNodes().MakeTextSection(aIdx,
4278 SwNormalStartNode,pColl);
4279 pPaM->GetPoint()->nNode = pNode->GetIndex()+1;
4280 pPaM->GetPoint()->nContent.Assign(pPaM->GetCntntNode(),0);
4281 aPlc.Get( nStart, nEnd, pDummy );
4282 ReadText(nStart,nEnd-nStart-1,MAN_MAINTEXT);
4285 else //ordinary case
4287 if (mbNewDoc && pStg && !pGloss) /*meaningless for a glossary, cmc*/
4289 mpDocShell->SetIsTemplate( pWwFib->fDot ); // point at tgc record
4290 const SvtFilterOptions* pVBAFlags = SvtFilterOptions::Get();
4291 maTracer.EnterEnvironment(sw::log::eMacros);
4292 // dissable below for 3.1 at the moment, 'cause it's kinda immature
4293 // similarly the project reference in svx/source/msvba
4294 #if 1
4295 uno::Reference< document::XDocumentInfoSupplier > xDocInfoSupp( mpDocShell->GetModel(), uno::UNO_QUERY_THROW );
4296 uno::Reference< document::XDocumentPropertiesSupplier > xDocPropSupp( xDocInfoSupp->getDocumentInfo(), uno::UNO_QUERY_THROW );
4297 uno::Reference< document::XDocumentProperties > xDocProps( xDocPropSupp->getDocumentProperties(), uno::UNO_QUERY_THROW );
4299 rtl::OUString sCreatedFrom = xDocProps->getTemplateURL();
4300 uno::Reference< container::XNameContainer > xPrjNameCache;
4301 uno::Reference< lang::XMultiServiceFactory> xSF(mpDocShell->GetModel(), uno::UNO_QUERY);
4302 if ( xSF.is() )
4303 xPrjNameCache.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAProjectNameProvider" ) ) ), uno::UNO_QUERY );
4305 // Read Global templates
4306 ReadGlobalTemplateSettings( sCreatedFrom, xPrjNameCache );
4307 #endif
4308 // Create and insert Word vba Globals
4309 uno::Any aGlobs;
4310 uno::Sequence< uno::Any > aArgs(1);
4311 aArgs[ 0 ] <<= mpDocShell->GetModel();
4312 aGlobs <<= ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( ::rtl::OUString::createFromAscii( "ooo.vba.word.Globals"), aArgs );
4313 mpDocShell->GetBasicManager()->SetGlobalUNOConstant( "VBAGlobals", aGlobs );
4315 SvxImportMSVBasic aVBasic(*mpDocShell, *pStg,
4316 pVBAFlags->IsLoadWordBasicCode(),
4317 pVBAFlags->IsLoadWordBasicStorage() );
4318 String s1(CREATE_CONST_ASC("Macros"));
4319 String s2(CREATE_CONST_ASC("VBA"));
4320 int nRet = aVBasic.Import( s1, s2, ! pVBAFlags->IsLoadWordBasicCode() );
4321 // dissable below for 3.1 at the moment, 'cause it's kinda immature
4322 // similarly the project reference in svx/source/msvba
4323 #if 1
4324 lcl_createTemplateToProjectEntry( xPrjNameCache, sCreatedFrom, aVBasic.GetVBAProjectName() );
4325 WW8Customizations aCustomisations( pTableStream, *pWwFib );
4326 aCustomisations.Import( mpDocShell );
4327 #endif
4328 if( 2 & nRet )
4330 maTracer.Log(sw::log::eContainsVisualBasic);
4331 rDoc.SetContainsMSVBasic(true);
4334 StoreMacroCmds();
4336 // Hackly to register the document event.
4337 // should be find a better solution to share the codes with Excel Workbook event.
4338 registerDocEvent( mpDocShell );
4340 maTracer.LeaveEnvironment(sw::log::eMacros);
4342 ReadText(0, pWwFib->ccpText, MAN_MAINTEXT);
4346 ::SetProgressState(nProgress, mpDocShell); // Update
4348 if (pDrawPg && pMSDffManager && pMSDffManager->GetShapeOrders())
4350 // Hilfsarray zum Verketten der (statt SdrTxtObj) eingefuegten
4351 // Rahmen
4352 SvxMSDffShapeTxBxSort aTxBxSort;
4354 // korrekte Z-Order der eingelesen Escher-Objekte sicherstellen
4355 USHORT nShapeCount = pMSDffManager->GetShapeOrders()->Count();
4357 for (USHORT nShapeNum=0; nShapeNum < nShapeCount; nShapeNum++)
4359 SvxMSDffShapeOrder *pOrder =
4360 pMSDffManager->GetShapeOrders()->GetObject(nShapeNum);
4361 // Pointer in neues Sort-Array einfuegen
4362 if (pOrder->nTxBxComp && pOrder->pFly)
4363 aTxBxSort.Insert(pOrder);
4365 // zu verkettende Rahmen jetzt verketten
4366 USHORT nTxBxCount = aTxBxSort.Count();
4367 if( nTxBxCount )
4369 SwFmtChain aChain;
4370 for (USHORT nTxBxNum=0; nTxBxNum < nTxBxCount; nTxBxNum++)
4372 SvxMSDffShapeOrder *pOrder =
4373 aTxBxSort.GetObject(nTxBxNum);
4375 // Fly-Frame-Formate initialisieren
4376 SwFlyFrmFmt* pFlyFmt = pOrder->pFly;
4377 SwFlyFrmFmt* pNextFlyFmt = 0;
4378 SwFlyFrmFmt* pPrevFlyFmt = 0;
4379 // ggfs. Nachfolger ermitteln
4380 if( 1+nTxBxNum < nTxBxCount )
4382 SvxMSDffShapeOrder *pNextOrder =
4383 aTxBxSort.GetObject(nTxBxNum+1);
4384 if ((0xFFFF0000 & pOrder->nTxBxComp)
4385 == (0xFFFF0000 & pNextOrder->nTxBxComp))
4386 pNextFlyFmt = pNextOrder->pFly;
4388 // ggfs. Vorgaenger ermitteln
4389 if( nTxBxNum )
4391 SvxMSDffShapeOrder *pPrevOrder =
4392 aTxBxSort.GetObject(nTxBxNum-1);
4393 if ((0xFFFF0000 & pOrder->nTxBxComp)
4394 == (0xFFFF0000 & pPrevOrder->nTxBxComp))
4395 pPrevFlyFmt = pPrevOrder->pFly;
4397 // Falls Nachfolger oder Vorgaenger vorhanden,
4398 // die Verkettung am Fly-Frame-Format eintragen
4399 if (pNextFlyFmt || pPrevFlyFmt)
4401 aChain.SetNext( pNextFlyFmt );
4402 aChain.SetPrev( pPrevFlyFmt );
4403 pFlyFmt->SetFmtAttr( aChain );
4411 if (mbNewDoc)
4413 if( pWDop->fRevMarking )
4414 eMode |= nsRedlineMode_t::REDLINE_ON;
4415 if( pWDop->fRMView )
4416 eMode |= nsRedlineMode_t::REDLINE_SHOW_DELETE;
4419 maInsertedTables.DelAndMakeTblFrms();
4420 maSectionManager.InsertSegments();
4422 if (pCollA)
4423 delete[] pCollA;
4425 DELETEZ( pStyles );
4427 if( pFormImpl )
4428 DeleteFormImpl();
4429 GrafikDtor();
4430 DELETEZ( pMSDffManager );
4431 DELETEZ( pHdFt );
4432 DELETEZ( pLstManager );
4433 DELETEZ( pSBase );
4434 delete pWDop;
4435 DELETEZ( pFonts );
4436 delete mpAtnNames;
4437 DELETEZ( pAuthorInfos );
4438 delete mpSprmParser;
4439 ::EndProgress(mpDocShell);
4441 pDataStream = 0;
4442 pTableStream = 0;
4444 DeleteCtrlStk();
4445 mpRedlineStack->closeall(*pPaM->GetPoint());
4446 delete mpRedlineStack;
4447 DeleteAnchorStk();
4448 DeleteRefStks();
4450 UpdateFields();
4452 // delete the pam before the call for hide all redlines (Bug 73683)
4453 if (mbNewDoc)
4454 rDoc.SetRedlineMode((RedlineMode_t)( eMode ));
4456 UpdatePageDescs(rDoc, nPageDescOffset);
4458 delete pPaM, pPaM = 0;
4459 return nErrRet;
4462 ULONG SwWW8ImplReader::SetSubStreams(SvStorageStreamRef &rTableStream,
4463 SvStorageStreamRef &rDataStream)
4465 ULONG nErrRet = 0;
4466 // 6 stands for "6 OR 7", 7 stand for "ONLY 7"
4467 switch (pWwFib->nVersion)
4469 case 6:
4470 case 7:
4471 pTableStream = pStrm;
4472 pDataStream = pStrm;
4473 break;
4474 case 8:
4475 if(!pStg)
4477 ASSERT( pStg, "Version 8 muss immer einen Storage haben!" );
4478 nErrRet = ERR_SWG_READ_ERROR;
4479 break;
4482 rTableStream = pStg->OpenSotStream( String::CreateFromAscii(
4483 pWwFib->fWhichTblStm ? SL::a1Table : SL::a0Table),
4484 STREAM_STD_READ);
4486 pTableStream = &rTableStream;
4487 pTableStream->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
4489 rDataStream = pStg->OpenSotStream(CREATE_CONST_ASC(SL::aData),
4490 STREAM_STD_READ | STREAM_NOCREATE );
4492 if (rDataStream.Is() && SVSTREAM_OK == rDataStream->GetError())
4494 pDataStream = &rDataStream;
4495 pDataStream->SetNumberFormatInt(NUMBERFORMAT_INT_LITTLEENDIAN);
4497 else
4498 pDataStream = pStrm;
4499 break;
4500 default:
4501 // Programm-Fehler!
4502 ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
4503 nErrRet = ERR_SWG_READ_ERROR;
4504 break;
4506 return nErrRet;
4509 namespace
4511 utl::TempFile *MakeTemp(SvFileStream &rSt)
4513 utl::TempFile *pT = new utl::TempFile;
4514 pT->EnableKillingFile();
4515 rSt.Open(pT->GetFileName(), STREAM_READWRITE | STREAM_SHARE_DENYWRITE);
4516 return pT;
4519 #define WW_BLOCKSIZE 0x200
4521 void DecryptRC4(svx::MSCodec_Std97& rCtx, SvStream &rIn, SvStream &rOut)
4523 rIn.Seek(STREAM_SEEK_TO_END);
4524 ULONG nLen = rIn.Tell();
4525 rIn.Seek(0);
4527 sal_uInt8 in[WW_BLOCKSIZE];
4528 for (ULONG nI = 0, nBlock = 0; nI < nLen; nI += WW_BLOCKSIZE, ++nBlock)
4530 ULONG nBS = (nLen - nI > WW_BLOCKSIZE) ? WW_BLOCKSIZE : nLen - nI;
4531 rIn.Read(in, nBS);
4532 rCtx.InitCipher(nBlock);
4533 rCtx.Decode(in, nBS, in, nBS);
4534 rOut.Write(in, nBS);
4538 void DecryptXOR(svx::MSCodec_XorWord95 &rCtx, SvStream &rIn, SvStream &rOut)
4540 ULONG nSt = rIn.Tell();
4541 rIn.Seek(STREAM_SEEK_TO_END);
4542 ULONG nLen = rIn.Tell();
4543 rIn.Seek(nSt);
4545 rCtx.InitCipher();
4546 rCtx.Skip(nSt);
4548 sal_uInt8 in[0x4096];
4549 for (ULONG nI = nSt; nI < nLen; nI += 0x4096)
4551 ULONG nBS = (nLen - nI > 0x4096 ) ? 0x4096 : nLen - nI;
4552 rIn.Read(in, nBS);
4553 rCtx.Decode(in, nBS);
4554 rOut.Write(in, nBS);
4558 //moan, copy and paste :-(
4559 String QueryPasswordForMedium(SfxMedium& rMedium)
4561 String aPassw;
4563 using namespace com::sun::star;
4565 const SfxItemSet* pSet = rMedium.GetItemSet();
4566 const SfxPoolItem *pPasswordItem;
4568 if(pSet && SFX_ITEM_SET == pSet->GetItemState(SID_PASSWORD, TRUE, &pPasswordItem))
4569 aPassw = ((const SfxStringItem *)pPasswordItem)->GetValue();
4570 else
4574 uno::Reference< task::XInteractionHandler > xHandler( rMedium.GetInteractionHandler() );
4575 if( xHandler.is() )
4577 ::comphelper::DocPasswordRequest* pRequest = new ::comphelper::DocPasswordRequest(
4578 ::comphelper::DocPasswordRequestType_MS, task::PasswordRequestMode_PASSWORD_ENTER,
4579 INetURLObject( rMedium.GetOrigURL() ).GetName( INetURLObject::DECODE_WITH_CHARSET ) );
4580 uno::Reference< task::XInteractionRequest > xRequest( pRequest );
4582 xHandler->handle( xRequest );
4584 if( pRequest->isPassword() )
4585 aPassw = pRequest->getPassword();
4588 catch( uno::Exception& )
4593 return aPassw;
4598 ULONG SwWW8ImplReader::LoadThroughDecryption(SwPaM& rPaM ,WW8Glossary *pGloss)
4600 ULONG nErrRet = 0;
4601 if (pGloss)
4602 pWwFib = pGloss->GetFib();
4603 else
4604 pWwFib = new WW8Fib(*pStrm, nWantedVersion);
4606 if (pWwFib->nFibError)
4607 nErrRet = ERR_SWG_READ_ERROR;
4609 SvStorageStreamRef xTableStream, xDataStream;
4611 if (!nErrRet)
4612 nErrRet = SetSubStreams(xTableStream, xDataStream);
4614 utl::TempFile *pTempMain = 0;
4615 utl::TempFile *pTempTable = 0;
4616 utl::TempFile *pTempData = 0;
4617 SvFileStream aDecryptMain;
4618 SvFileStream aDecryptTable;
4619 SvFileStream aDecryptData;
4621 bool bDecrypt = false;
4622 enum {RC4, XOR, Other} eAlgo = Other;
4623 if (pWwFib->fEncrypted && !nErrRet)
4625 if (!pGloss)
4627 bDecrypt = true;
4628 if (8 != pWwFib->nVersion)
4629 eAlgo = XOR;
4630 else
4632 if (pWwFib->nKey != 0)
4633 eAlgo = XOR;
4634 else
4636 pTableStream->Seek(0);
4637 sal_uInt32 nEncType;
4638 *pTableStream >> nEncType;
4639 if (nEncType == 0x10001)
4640 eAlgo = RC4;
4646 if (bDecrypt)
4648 nErrRet = ERRCODE_SVX_WRONGPASS;
4649 switch (eAlgo)
4651 default:
4652 nErrRet = ERRCODE_SVX_READ_FILTER_CRYPT;
4653 break;
4654 case XOR:
4656 String sUniPassword =
4657 QueryPasswordForMedium(*(mpDocShell->GetMedium()));
4659 ByteString sPassword(sUniPassword,
4660 WW8Fib::GetFIBCharset(pWwFib->chseTables));
4662 xub_StrLen nLen = sPassword.Len();
4663 // DR: do not cut a wrong (too long) password
4664 if( nLen <= 15 )
4666 sal_uInt8 aPassword[16] = {0};
4668 for (xub_StrLen nChar = 0; nChar < sPassword.Len(); ++nChar )
4669 aPassword[nChar] = sPassword.GetChar(nChar);
4671 svx::MSCodec_XorWord95 aCtx;
4672 aCtx.InitKey(aPassword);
4673 if (aCtx.VerifyKey(pWwFib->nKey, pWwFib->nHash))
4675 nErrRet = 0;
4676 pTempMain = MakeTemp(aDecryptMain);
4678 pStrm->Seek(0);
4679 size_t nUnencryptedHdr =
4680 (8 == pWwFib->nVersion) ? 0x44 : 0x34;
4681 sal_uInt8 *pIn = new sal_uInt8[nUnencryptedHdr];
4682 pStrm->Read(pIn, nUnencryptedHdr);
4683 aDecryptMain.Write(pIn, nUnencryptedHdr);
4684 delete pIn;
4686 DecryptXOR(aCtx, *pStrm, aDecryptMain);
4688 if (!pTableStream || pTableStream == pStrm)
4689 pTableStream = &aDecryptMain;
4690 else
4692 pTempTable = MakeTemp(aDecryptTable);
4693 DecryptXOR(aCtx, *pTableStream, aDecryptTable);
4694 pTableStream = &aDecryptTable;
4697 if (!pDataStream || pDataStream == pStrm)
4698 pDataStream = &aDecryptMain;
4699 else
4701 pTempData = MakeTemp(aDecryptData);
4702 DecryptXOR(aCtx, *pDataStream, aDecryptData);
4703 pDataStream = &aDecryptData;
4708 break;
4709 case RC4:
4711 String sUniPassword =
4712 QueryPasswordForMedium(*(mpDocShell->GetMedium()));
4714 xub_StrLen nLen = sUniPassword.Len();
4715 // DR: do not cut a wrong (too long) password
4716 if (nLen <= 15)
4718 sal_Unicode aPassword[16] = {0};
4719 for (xub_StrLen nChar = 0; nChar < nLen; ++nChar )
4720 aPassword[nChar] = sUniPassword.GetChar(nChar);
4722 sal_uInt8 aDocId[ 16 ];
4723 pTableStream->Read(aDocId, 16);
4724 sal_uInt8 aSaltData[ 16 ];
4725 pTableStream->Read(aSaltData, 16);
4726 sal_uInt8 aSaltHash[ 16 ];
4727 pTableStream->Read(aSaltHash, 16);
4729 svx::MSCodec_Std97 aCtx;
4730 aCtx.InitKey(aPassword, aDocId);
4731 if (aCtx.VerifyKey(aSaltData, aSaltHash))
4733 nErrRet = 0;
4735 pTempTable = MakeTemp(aDecryptTable);
4736 DecryptRC4(aCtx, *pTableStream, aDecryptTable);
4737 pTableStream = &aDecryptTable;
4739 pTempMain = MakeTemp(aDecryptMain);
4740 DecryptRC4(aCtx, *pStrm, aDecryptMain);
4742 if (!pDataStream || pDataStream == pStrm)
4743 pDataStream = &aDecryptMain;
4744 else
4746 pTempData = MakeTemp(aDecryptData);
4747 DecryptRC4(aCtx, *pDataStream, aDecryptData);
4748 pDataStream = &aDecryptData;
4750 SfxMedium* pMedium = mpDocShell->GetMedium();
4751 if ( pMedium )
4753 SfxItemSet* pSet = pMedium->GetItemSet();
4754 if ( pSet )
4755 pSet->Put( SfxStringItem(SID_PASSWORD, sUniPassword) );
4760 break;
4763 if (nErrRet == 0)
4765 pStrm = &aDecryptMain;
4767 delete pWwFib;
4768 pWwFib = new WW8Fib(*pStrm, nWantedVersion);
4769 if (pWwFib->nFibError)
4770 nErrRet = ERR_SWG_READ_ERROR;
4774 if (!nErrRet)
4775 nErrRet = CoreLoad(pGloss, *rPaM.GetPoint());
4777 delete pTempMain;
4778 delete pTempTable;
4779 delete pTempData;
4781 if (!pGloss)
4782 delete pWwFib;
4783 return nErrRet;
4786 class outlineeq : public std::unary_function<const SwTxtFmtColl*, bool>
4788 private:
4789 BYTE mnNum;
4790 public:
4791 outlineeq(BYTE nNum) : mnNum(nNum) {}
4792 bool operator()(const SwTxtFmtColl *pTest) const
4794 //return pTest->GetOutlineLevel() == mnNum; //#outline level,zhaojianwei
4795 return pTest->IsAssignedToListLevelOfOutlineStyle() && pTest->GetAssignedOutlineStyleLevel() == mnNum; //<-end,zhaojianwei
4799 void SwWW8ImplReader::SetOutLineStyles()
4802 #i3674# & #101291# Load new document and insert document cases.
4804 SwNumRule aOutlineRule(*rDoc.GetOutlineNumRule());
4805 // --> OD 2005-10-14 #i53044,i53213#
4806 // <mpChosenOutlineNumRule> has to be set to point to local variable
4807 // <aOutlineRule>, because its used below to be compared this <&aOutlineRule>.
4808 // But at the end of the method <mpChosenOutlineNumRule> has to be set to
4809 // <rDoc.GetOutlineNumRule()>, because <aOutlineRule> will be destroyed.
4810 // mpChosenOutlineNumRule = rDoc.GetOutlineNumRule();
4811 mpChosenOutlineNumRule = &aOutlineRule;
4812 // <--
4814 sw::ParaStyles aOutLined(sw::util::GetParaStyles(rDoc));
4815 // --> OD 2009-02-04 #i98791# - sorting algorithm adjusted
4816 sw::util::SortByAssignedOutlineStyleListLevel(aOutLined);
4817 // <--
4819 typedef sw::ParaStyleIter myParaStyleIter;
4821 If we are inserted into a document then don't clobber existing existing
4822 levels.
4824 USHORT nFlagsStyleOutlLevel = 0;
4825 if (!mbNewDoc)
4827 // --> OD 2008-12-16 #i70748#
4828 // backward iteration needed due to the outline level attribute
4829 sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend();
4830 for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter)
4831 // <--
4833 //if ((*aIter)->GetOutlineLevel() < MAXLEVEL) //#outline level,zhaojianwei,
4834 //nFlagsStyleOutlLevel |= 1 << (*aIter)->GetOutlineLevel();
4835 if ((*aIter)->IsAssignedToListLevelOfOutlineStyle())
4836 nFlagsStyleOutlLevel |= 1 << (*aIter)->GetAssignedOutlineStyleLevel();//<-end,zhaojianwei
4837 else
4838 break;
4841 else
4844 #111955#
4845 Only import *one* of the possible multiple outline numbering rules, so
4846 pick the one that affects most styles. If we're not importing a new
4847 document, we got to stick with what is already there.
4849 // --> OD 2005-11-07 #127520# - use index in text format collection
4850 // array <pCollA> as key of the outline numbering map <aRuleMap>
4851 // instead of the memory pointer of the outline numbering rule
4852 // to assure that, if two outline numbering rule affect the same
4853 // count of text formats, always the same outline numbering rule is chosen.
4854 std::map<USHORT, int>aRuleMap;
4855 typedef std::map<USHORT, int>::iterator myIter;
4856 for (USHORT nI = 0; nI < nColls; ++nI)
4858 SwWW8StyInf& rSI = pCollA[ nI ];
4859 if (
4860 (MAXLEVEL > rSI.nOutlineLevel) && rSI.pOutlineNumrule &&
4861 rSI.pFmt
4864 // --> OD 2005-11-07 #127520#
4865 myIter aIter = aRuleMap.find(nI);
4866 // <--
4867 if (aIter == aRuleMap.end())
4869 // --> OD 2005-11-07 #127520#
4870 aRuleMap[nI] = 1;
4871 // <--
4873 else
4874 ++(aIter->second);
4878 int nMax = 0;
4879 myIter aEnd2 = aRuleMap.end();
4880 for (myIter aIter = aRuleMap.begin(); aIter != aEnd2; ++aIter++)
4882 if (aIter->second > nMax)
4884 nMax = aIter->second;
4885 // --> OD 2005-11-07 #127520#
4886 mpChosenOutlineNumRule = pCollA[ aIter->first ].pOutlineNumrule;
4887 // <--
4890 // <--
4892 ASSERT(mpChosenOutlineNumRule, "Impossible");
4893 if (mpChosenOutlineNumRule)
4894 aOutlineRule = *mpChosenOutlineNumRule;
4896 if (mpChosenOutlineNumRule != &aOutlineRule)
4898 // --> OD 2008-12-16 #i70748#
4899 // backward iteration needed due to the outline level attribute
4900 sw::ParaStyles::reverse_iterator aEnd = aOutLined.rend();
4901 for ( sw::ParaStyles::reverse_iterator aIter = aOutLined.rbegin(); aIter < aEnd; ++aIter)
4902 // <--
4904 //if ((*aIter)->GetOutlineLevel() < MAXLEVEL)//#outline level,zhaojianwei
4905 // (*aIter)->SetOutlineLevel(NO_NUMBERING);
4906 if((*aIter)->IsAssignedToListLevelOfOutlineStyle())
4907 (*aIter)->DeleteAssignmentToListLevelOfOutlineStyle(); //<-end
4909 else
4910 break;
4915 USHORT nOldFlags = nFlagsStyleOutlLevel;
4917 for (USHORT nI = 0; nI < nColls; ++nI)
4919 SwWW8StyInf& rSI = pCollA[nI];
4921 if (rSI.IsOutlineNumbered())
4923 USHORT nAktFlags = 1 << rSI.nOutlineLevel;
4924 if (
4925 (nAktFlags & nFlagsStyleOutlLevel) ||
4926 (rSI.pOutlineNumrule != mpChosenOutlineNumRule)
4930 If our spot is already taken by something we can't replace
4931 then don't insert and remove our outline level.
4933 rSI.pFmt->SetFmtAttr(
4934 SwNumRuleItem( rSI.pOutlineNumrule->GetName() ) );
4935 //((SwTxtFmtColl*)rSI.pFmt)->SetOutlineLevel(NO_NUMBERING);
4936 ((SwTxtFmtColl*)rSI.pFmt)->DeleteAssignmentToListLevelOfOutlineStyle();//#outline level,zhaojianwei
4938 else
4941 If there is a style already set for this outline
4942 numbering level and its not a style set by us already
4943 then we can remove it outline numbering.
4944 (its one of the default headings in a new document
4945 so we can clobber it)
4946 Of course if we are being inserted into a document that
4947 already has some set we can't do this, thats covered by
4948 the list of level in nFlagsStyleOutlLevel to ignore.
4950 outlineeq aCmp(rSI.nOutlineLevel);
4951 myParaStyleIter aResult = std::find_if(aOutLined.begin(),
4952 aOutLined.end(), aCmp);
4954 myParaStyleIter aEnd = aOutLined.end();
4955 while (aResult != aEnd && aCmp(*aResult))
4957 //(*aResult)->SetOutlineLevel(NO_NUMBERING);//#outline level,zhaojianwei
4958 (*aResult)->DeleteAssignmentToListLevelOfOutlineStyle();
4959 ++aResult;
4963 #i1886#
4964 I believe that when a list is registered onto a winword
4965 style which is an outline numbering style (i.e.
4966 nOutlineLevel is set) that the style of numbering is for
4967 the level is indexed by the *list* level that was
4968 registered on that style, and not the outlinenumbering
4969 level, which is probably a logical sequencing, and not a
4970 physical mapping into the list style reged on that outline
4971 style.
4973 BYTE nFromLevel = rSI.nListLevel;
4974 BYTE nToLevel = rSI.nOutlineLevel;
4975 const SwNumFmt& rRule=rSI.pOutlineNumrule->Get(nFromLevel);
4976 aOutlineRule.Set(nToLevel, rRule);
4977 // Set my outline level
4978 //((SwTxtFmtColl*)rSI.pFmt)->SetOutlineLevel(nToLevel);//#outline level,zhaojianwei
4979 ((SwTxtFmtColl*)rSI.pFmt)->AssignToListLevelOfOutlineStyle(nToLevel); //<-end,zhaojianwei
4980 // If there are more styles on this level ignore them
4981 nFlagsStyleOutlLevel |= nAktFlags;
4985 if (nOldFlags != nFlagsStyleOutlLevel)
4986 rDoc.SetOutlineNumRule(aOutlineRule);
4987 // --> OD 2005-10-14 #i53044,i53213#
4988 if ( mpChosenOutlineNumRule == &aOutlineRule )
4990 mpChosenOutlineNumRule = rDoc.GetOutlineNumRule();
4992 // <--
4995 const String* SwWW8ImplReader::GetAnnotationAuthor(sal_uInt16 nIdx)
4997 if (!mpAtnNames && pWwFib->lcbGrpStAtnOwners)
4999 // Authoren bestimmen: steht im TableStream
5000 mpAtnNames = new ::std::vector<String>;
5001 SvStream& rStrm = *pTableStream;
5003 long nOldPos = rStrm.Tell();
5004 rStrm.Seek( pWwFib->fcGrpStAtnOwners );
5006 long nRead = 0, nCount = pWwFib->lcbGrpStAtnOwners;
5007 while (nRead < nCount)
5009 if( bVer67 )
5011 mpAtnNames->push_back(WW8ReadPString(rStrm, false));
5012 nRead += mpAtnNames->rbegin()->Len() + 1; // Laenge + BYTE Count
5014 else
5016 mpAtnNames->push_back(WW8Read_xstz(rStrm, 0, false));
5017 // UNICode: doppelte Laenge + USHORT Count
5018 nRead += mpAtnNames->rbegin()->Len() * 2 + 2;
5021 rStrm.Seek( nOldPos );
5024 const String *pRet = 0;
5025 if (mpAtnNames && nIdx < mpAtnNames->size())
5026 pRet = &((*mpAtnNames)[nIdx]);
5027 return pRet;
5030 ULONG SwWW8ImplReader::LoadDoc( SwPaM& rPaM,WW8Glossary *pGloss)
5032 ULONG nErrRet = 0;
5035 static const sal_Char* aNames[ 13 ] = {
5036 "WinWord/WW", "WinWord/WW8", "WinWord/WWFT",
5037 "WinWord/WWFLX", "WinWord/WWFLY",
5038 "WinWord/WWF",
5039 "WinWord/WWFA0", "WinWord/WWFA1", "WinWord/WWFA2",
5040 "WinWord/WWFB0", "WinWord/WWFB1", "WinWord/WWFB2",
5041 "WinWord/RegardHindiDigits"
5043 sal_uInt32 aVal[ 13 ];
5045 SwFilterOptions aOpt( 13, aNames, aVal );
5047 nIniFlags = aVal[ 0 ];
5048 nIniFlags1= aVal[ 1 ];
5049 // schiebt Flys um x twips nach rechts o. links
5050 nIniFlyDx = aVal[ 3 ];
5051 nIniFlyDy = aVal[ 4 ];
5053 nFieldFlags = aVal[ 5 ];
5054 nFieldTagAlways[0] = aVal[ 6 ];
5055 nFieldTagAlways[1] = aVal[ 7 ];
5056 nFieldTagAlways[2] = aVal[ 8 ];
5057 nFieldTagBad[0] = aVal[ 9 ];
5058 nFieldTagBad[1] = aVal[ 10 ];
5059 nFieldTagBad[2] = aVal[ 11 ];
5060 m_bRegardHindiDigits = aVal[ 12 ] > 0;
5063 UINT16 nMagic;
5064 *pStrm >> nMagic;
5066 // beachte: 6 steht fuer "6 ODER 7", 7 steht fuer "NUR 7"
5067 switch (nWantedVersion)
5069 case 6:
5070 case 7:
5071 if (
5072 (0xa5dc != nMagic && 0xa5db != nMagic) &&
5073 (nMagic < 0xa697 || nMagic > 0xa699)
5076 //JP 06.05.99: teste auf eigenen 97-Fake!
5077 if (pStg && 0xa5ec == nMagic)
5079 ULONG nCurPos = pStrm->Tell();
5080 if (pStrm->Seek(nCurPos + 22))
5082 UINT32 nfcMin;
5083 *pStrm >> nfcMin;
5084 if (0x300 != nfcMin)
5085 nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
5087 pStrm->Seek( nCurPos );
5089 else
5090 nErrRet = ERR_WW6_NO_WW6_FILE_ERR;
5092 break;
5093 case 8:
5094 if (0xa5ec != nMagic)
5095 nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
5096 break;
5097 default:
5098 nErrRet = ERR_WW8_NO_WW8_FILE_ERR;
5099 ASSERT( !this, "Es wurde vergessen, nVersion zu kodieren!" );
5100 break;
5103 if (!nErrRet)
5104 nErrRet = LoadThroughDecryption(rPaM ,pGloss);
5106 rDoc.PropagateOutlineRule();
5108 return nErrRet;
5111 extern "C" SAL_DLLPUBLIC_EXPORT Reader* SAL_CALL ImportDOC()
5113 return new WW8Reader();
5116 ULONG WW8Reader::Read(SwDoc &rDoc, const String& rBaseURL, SwPaM &rPam, const String & /* FileName */)
5118 USHORT nOldBuffSize = 32768;
5119 bool bNew = !bInsertMode; // Neues Doc ( kein Einfuegen )
5122 SvStorageStreamRef refStrm; // damit uns keiner den Stream klaut
5123 SvStream* pIn = pStrm;
5125 ULONG nRet = 0;
5126 BYTE nVersion = 8;
5128 String sFltName = GetFltName();
5129 if( sFltName.EqualsAscii( "WW6" ) )
5131 if (pStrm)
5132 nVersion = 6;
5133 else
5135 ASSERT(!this, "WinWord 95 Reader-Read ohne Stream");
5136 nRet = ERR_SWG_READ_ERROR;
5139 else
5141 if( sFltName.EqualsAscii( "CWW6" ) )
5142 nVersion = 6;
5143 else if( sFltName.EqualsAscii( "CWW7" ) )
5144 nVersion = 7;
5146 if( pStg )
5148 nRet = OpenMainStream( refStrm, nOldBuffSize );
5149 pIn = &refStrm;
5151 else
5153 ASSERT(!this, "WinWord 95/97 Reader-Read ohne Storage");
5154 nRet = ERR_SWG_READ_ERROR;
5158 if( !nRet )
5160 //JP 18.01.96: Alle Ueberschriften sind normalerweise ohne
5161 // Kapitelnummer. Darum hier explizit abschalten
5162 // weil das Default jetzt wieder auf AN ist.
5163 if (bNew)
5165 Reader::SetNoOutlineNum( rDoc );
5166 // MIB 27.09.96: Umrandung uns Abstaende aus Frm-Vorlagen entf.
5167 Reader::ResetFrmFmts( rDoc );
5169 SwWW8ImplReader* pRdr = new SwWW8ImplReader(nVersion, pStg, pIn, rDoc,
5170 rBaseURL, bNew);
5171 nRet = pRdr->LoadDoc( rPam );
5172 delete pRdr;
5174 if( refStrm.Is() )
5176 refStrm->SetBufferSize( nOldBuffSize );
5177 refStrm.Clear();
5179 else if (pIn)
5180 pIn->ResetError();
5183 return nRet;
5186 int WW8Reader::GetReaderType()
5188 return SW_STORAGE_READER | SW_STREAM_READER;
5191 BOOL WW8Reader::HasGlossaries() const
5193 return true;
5196 BOOL WW8Reader::ReadGlossaries(SwTextBlocks& rBlocks, BOOL bSaveRelFiles) const
5198 bool bRet=false;
5200 WW8Reader *pThis = const_cast<WW8Reader *>(this);
5202 USHORT nOldBuffSize = 32768;
5203 SvStorageStreamRef refStrm;
5204 if (!pThis->OpenMainStream(refStrm, nOldBuffSize))
5206 WW8Glossary aGloss( refStrm, 8, pStg );
5207 bRet = aGloss.Load( rBlocks, bSaveRelFiles ? true : false);
5209 return bRet ? true : false;
5212 BOOL SwMSDffManager::GetOLEStorageName(long nOLEId, String& rStorageName,
5213 SvStorageRef& rSrcStorage, uno::Reference < embed::XStorage >& rDestStorage) const
5215 bool bRet = false;
5217 long nPictureId = 0;
5218 if (rReader.pStg)
5220 // dann holen wir uns mal ueber den TextBox-PLCF die richtigen
5221 // Char Start-/End-Positionen. In dem Bereich sollte dann
5222 // das EinbettenFeld und die entsprechenden Sprms zu finden
5223 // sein. Wir brauchen hier aber nur das Sprm fuer die Picture Id
5224 long nOldPos = rReader.pStrm->Tell();
5226 // --> OD 2004-12-08 #i32596# - consider return value of method
5227 // <rReader.GetTxbxTextSttEndCp(..)>. If it returns false, method
5228 // wasn't successful. Thus, continue in this case.
5229 // Note: Ask MM for initialization of <nStartCp> and <nEndCp>.
5230 // Note: Ask MM about assertions in method <rReader.GetTxbxTextSttEndCp(..)>.
5231 WW8_CP nStartCp, nEndCp;
5232 if ( rReader.GetTxbxTextSttEndCp(nStartCp, nEndCp,
5233 static_cast<sal_uInt16>((nOLEId >> 16) & 0xFFFF),
5234 static_cast<sal_uInt16>(nOLEId & 0xFFFF)) )
5236 WW8PLCFxSaveAll aSave;
5237 memset( &aSave, 0, sizeof( aSave ) );
5238 rReader.pPlcxMan->SaveAllPLCFx( aSave );
5240 nStartCp += rReader.nDrawCpO;
5241 nEndCp += rReader.nDrawCpO;
5242 WW8PLCFx_Cp_FKP* pChp = rReader.pPlcxMan->GetChpPLCF();
5243 wwSprmParser aSprmParser(rReader.pWwFib->GetFIBVersion());
5244 while (nStartCp <= nEndCp && !nPictureId)
5246 WW8PLCFxDesc aDesc;
5247 pChp->SeekPos( nStartCp );
5248 pChp->GetSprms( &aDesc );
5250 if (aDesc.nSprmsLen && aDesc.pMemPos) // Attribut(e) vorhanden
5252 long nLen = aDesc.nSprmsLen;
5253 const BYTE* pSprm = aDesc.pMemPos;
5255 while (nLen >= 2 && !nPictureId)
5257 USHORT nId = aSprmParser.GetSprmId(pSprm);
5258 USHORT nSL = aSprmParser.GetSprmSize(nId, pSprm);
5260 if( nLen < nSL )
5261 break; // nicht mehr genug Bytes uebrig
5263 if( 0x6A03 == nId && 0 < nLen )
5265 nPictureId = SVBT32ToUInt32(pSprm +
5266 aSprmParser.DistanceToData(nId));
5267 bRet = true;
5269 pSprm += nSL;
5270 nLen -= nSL;
5273 nStartCp = aDesc.nEndPos;
5276 rReader.pPlcxMan->RestoreAllPLCFx( aSave );
5278 // <--
5280 rReader.pStrm->Seek( nOldPos );
5283 if( bRet )
5285 rStorageName = '_';
5286 rStorageName += String::CreateFromInt32(nPictureId);
5287 rSrcStorage = rReader.pStg->OpenSotStorage(CREATE_CONST_ASC(
5288 SL::aObjectPool));
5289 if (!rReader.mpDocShell)
5290 bRet=false;
5291 else
5292 rDestStorage = rReader.mpDocShell->GetStorage();
5294 return bRet;
5297 BOOL SwMSDffManager::ShapeHasText(ULONG, ULONG) const
5299 // Zur Zeit des Einlesens einer einzelnen Box, die womoeglich Teil einer
5300 // Gruppe ist, liegen noch nicht genuegend Informationen vor, um
5301 // entscheiden zu koennen, ob wir sie nicht doch als Textfeld benoetigen.
5302 // Also vorsichtshalber mal alle umwandeln:
5303 return true;
5306 bool SwWW8ImplReader::InEqualOrHigherApo(int nLvl) const
5308 if (nLvl)
5309 --nLvl;
5310 // --> OD 2006-01-19 #i60827#
5311 // check size of <maApos> to assure that <maApos.begin() + nLvl> can be performed.
5312 if ( sal::static_int_cast< sal_Int32>(nLvl) >= sal::static_int_cast< sal_Int32>(maApos.size()) )
5314 return false;
5316 // <--
5317 mycApoIter aIter = std::find(maApos.begin() + nLvl, maApos.end(), true);
5318 if (aIter != maApos.end())
5319 return true;
5320 else
5321 return false;
5324 bool SwWW8ImplReader::InEqualApo(int nLvl) const
5326 //If we are in a table, see if an apo was inserted at the level below
5327 //the table.
5328 if (nLvl)
5329 --nLvl;
5330 return maApos[nLvl];
5333 namespace sw
5335 namespace hack
5337 Position::Position(const SwPosition &rPos)
5338 : maPtNode(rPos.nNode), mnPtCntnt(rPos.nContent.GetIndex())
5342 Position::Position(const Position &rPos)
5343 : maPtNode(rPos.maPtNode), mnPtCntnt(rPos.mnPtCntnt)
5347 Position::operator SwPosition() const
5349 SwPosition aRet(maPtNode);
5350 aRet.nContent.Assign(maPtNode.GetNode().GetCntntNode(), mnPtCntnt);
5351 return aRet;
5356 /* vi:set tabstop=4 shiftwidth=4 expandtab: */