update dev300-m58
[ooovba.git] / sw / source / filter / ww8 / ww8par4.cxx
blobf36ebeda5deb67ee77fcb12ad0e7ae0dfa4caa4c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: ww8par4.cxx,v $
10 * $Revision: 1.62 $
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 -*- */
34 #include <doc.hxx>
35 #include "writerhelper.hxx"
36 #include <com/sun/star/embed/XClassifiedObject.hpp>
38 #ifndef __SGI_STL_ALGORITHM
39 #include <algorithm>
40 #endif
41 #ifndef __SGI_STL_FUNCTIONAL
42 #include <functional>
43 #endif
44 #include <osl/endian.h>
45 #include <sot/storage.hxx>
46 #include <com/sun/star/drawing/XShape.hpp>
47 #include <hintids.hxx>
48 #include <svx/svdoole2.hxx>
49 #include <svx/msdffimp.hxx>
50 #include <svx/impgrf.hxx>
51 #include <svx/unoapi.hxx>
52 #include <svx/msocximex.hxx>
54 #include <sot/exchange.hxx>
55 #include <swtypes.hxx>
56 #include <fmtanchr.hxx>
57 #include <fmtcntnt.hxx>
58 #include <dcontact.hxx>
59 #include <frmfmt.hxx>
60 #include <pam.hxx>
61 #include <ndgrf.hxx>
62 #ifndef _DOCSH_HXX
63 #include <docsh.hxx> // fuer Ole-Node
64 #endif
65 #include <mdiexp.hxx> // Progress
66 #include <redline.hxx>
67 #include <fltshell.hxx>
68 #include <unodraw.hxx>
69 #include <shellio.hxx>
70 #include <ndole.hxx>
73 #include "ww8scan.hxx"
74 #include "ww8par.hxx"
75 #include "ww8par2.hxx" // WWFlyPara::BoxUpWidth()
77 struct OLE_MFP
79 INT16 mm; // 0x6 int
80 INT16 xExt; // 0x8 int in 1/100 mm
81 INT16 yExt; // 0xa int in 1/100 mm
82 INT16 hMF; // 0xc int
85 using namespace ::com::sun::star;
87 // SV_IMPL_OP_PTRARR_SORT(WW8AuthorInfos, WW8AuthorInfo_Ptr)
88 SV_IMPL_OP_PTRARR_SORT(WW8OleMaps, WW8OleMap_Ptr)
90 static bool SwWw8ReadScaling(long& rX, long& rY, SvStorageRef& rSrc1)
92 // Skalierungsfaktoren holen:
93 // Informationen in PIC-Stream ( durch ausprobieren )
94 // 0x0 (l)cb
95 // 0x08 .. 0x0a Flags ??
96 // 0x08 Inh: 1 / 0
97 // 0x09 Inh: 0,8,0x18
98 // 0x0a Inh: immer 8, MAP_ANISOTROPIC ???
99 // 0x0b Inh: immer 0
100 // 0x0c, 0x10 Originalgroesse x,y in 1/100 mm
101 // 0x14, 0x16 Originalgroesse x,y in tw
102 // 0x2c, 0x30 Skalierung x,y in Promille
103 // 0x34, 0x38, 0x3c, 0x40 Crop Left, Top, Right, Bot in tw
105 SvStorageStreamRef xSrc3 = rSrc1->OpenSotStream( CREATE_CONST_ASC( "\3PIC" ),
106 STREAM_STD_READ | STREAM_NOCREATE);
107 SvStorageStream* pS = xSrc3;
108 pS->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
109 pS->Seek( STREAM_SEEK_TO_END );
111 ASSERT( pS->Tell() >= 76, "+OLE-PIC-Stream is shorter than 76 Byte" );
113 INT32 nOrgWidth,
114 nOrgHeight,
115 nScaleX,
116 nScaleY,
117 nCropLeft,
118 nCropTop,
119 nCropRight,
120 nCropBottom;
121 pS->Seek( 0x14 );
122 *pS >> nOrgWidth // Original Size in 1/100 mm
123 >> nOrgHeight;
124 pS->Seek( 0x2c );
125 *pS >> nScaleX // Scaling in Promille
126 >> nScaleY
127 >> nCropLeft // Cropping in 1/100 mm
128 >> nCropTop
129 >> nCropRight
130 >> nCropBottom;
132 rX = nOrgWidth - nCropLeft - nCropRight;
133 rY = nOrgHeight - nCropTop - nCropBottom;
134 if (10 > nScaleX || 65536 < nScaleX || 10 > nScaleY || 65536 < nScaleY)
136 ASSERT( !pS, "+OLE-Scalinginformation in PIC-Stream wrong" );
137 return false;
139 else
141 rX = (rX * nScaleX) / 1000;
142 rY = (rY * nScaleY) / 1000;
144 return true;
147 static bool SwWw6ReadMetaStream(GDIMetaFile& rWMF, OLE_MFP* pMfp,
148 SvStorageRef& rSrc1)
150 SvStorageStreamRef xSrc2 = rSrc1->OpenSotStream( CREATE_CONST_ASC("\3META"),
151 STREAM_STD_READ | STREAM_NOCREATE);
152 SvStorageStream* pSt = xSrc2;
153 pSt->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
154 ULONG nRead = pSt->Read( pMfp, sizeof(*pMfp ) );
155 // Mini-Placable-Header lesen
156 if (nRead != sizeof(*pMfp))
157 return false;
159 #if defined OSL_BIGENDIAN
160 pMfp->mm = SWAPSHORT( pMfp->mm );
161 pMfp->xExt = SWAPSHORT( pMfp->xExt );
162 pMfp->yExt = SWAPSHORT( pMfp->yExt );
163 #endif // OSL_BIGENDIAN
165 if( pMfp->mm == 94 || pMfp->mm == 99 )
167 ASSERT( !pSt, "+OLE: Falscher Metafile-Typ" );
168 return false;
170 if( pMfp->mm != 8 )
172 ASSERT( !pSt, "+OLE: Falscher Metafile-Typ ( nicht Anisotropic )" );
174 if( !pMfp->xExt || !pMfp->yExt )
176 ASSERT( !pSt, "+OLE: Groesse von 0 ???" );
177 return false;
179 bool bOk = ReadWindowMetafile( *pSt, rWMF, NULL ) ? true : false; // WMF lesen
180 // *pSt >> aWMF geht nicht ohne placable Header
181 if (!bOk || pSt->GetError() || rWMF.GetActionCount() == 0)
183 ASSERT( !pSt, "+OLE: Konnte Metafile nicht lesen" );
184 return false;
187 rWMF.SetPrefMapMode( MapMode( MAP_100TH_MM ) );
190 // MetaFile auf neue Groesse skalieren und
191 // neue Groesse am MetaFile setzen
192 Size aOldSiz( rWMF.GetPrefSize() );
193 Size aNewSiz( pMfp->xExt, pMfp->yExt );
194 Fraction aFracX( aNewSiz.Width(), aOldSiz.Width() );
195 Fraction aFracY( aNewSiz.Height(), aOldSiz.Height() );
197 rWMF.Scale( aFracX, aFracY );
198 rWMF.SetPrefSize( aNewSiz );
200 return true;
203 static bool SwWw6ReadMacPICTStream(Graphic& rGraph, SvStorageRef& rSrc1)
205 // 03-META-Stream nicht da. Vielleicht ein 03-PICT ?
206 SvStorageStreamRef xSrc4 = rSrc1->OpenSotStream( CREATE_CONST_ASC( "\3PICT" ));
207 SvStorageStream* pStp = xSrc4;
208 pStp->SetNumberFormatInt( NUMBERFORMAT_INT_LITTLEENDIAN );
209 BYTE aTestA[10]; // Ist der 01Ole-Stream ueberhaupt vorhanden
210 ULONG nReadTst = pStp->Read( aTestA, sizeof( aTestA ) );
211 if (nReadTst != sizeof(aTestA))
212 return false;
214 pStp->Seek( STREAM_SEEK_TO_BEGIN );
216 #ifdef DEBUGDUMP
217 SvStream *pDbg = sw::hack::CreateDebuggingStream(CREATE_CONST_ASC(".pct"));
218 pDbg->Seek(0x200); //Prepend extra 0x200 of zeros to make this a valid PICT
219 sw::hack::DumpStream(*pStp, *pDbg);
220 delete pDbg;
221 #endif
223 // Mac-Pict steht im 03PICT-StorageStream allerdings ohne die ersten 512
224 // Bytes, die bei einem MAC-PICT egal sind ( werden nicht ausgewertet )
225 return SwWW8ImplReader::GetPictGrafFromStream(rGraph, *pStp);
228 SwFlyFrmFmt* SwWW8ImplReader::InsertOle(SdrOle2Obj &rObject,
229 const SfxItemSet &rFlySet, const SfxItemSet &rGrfSet)
231 SfxObjectShell *pPersist = rDoc.GetPersist();
232 ASSERT(pPersist, "No persist, cannot insert objects correctly");
233 if (!pPersist)
234 return 0;
236 SwFlyFrmFmt *pRet = 0;
238 SfxItemSet *pMathFlySet = 0;
239 uno::Reference < embed::XClassifiedObject > xClass( rObject.GetObjRef(), uno::UNO_QUERY );
240 if( xClass.is() )
242 SvGlobalName aClassName( xClass->getClassID() );
243 if (SotExchange::IsMath(aClassName))
246 StarMath sets it own fixed size, so its counter productive to use the
247 size word says it is. i.e. Don't attempt to override its size.
249 pMathFlySet = new SfxItemSet(rFlySet);
250 pMathFlySet->ClearItem(RES_FRM_SIZE);
255 Take complete responsibility of the object away from SdrOle2Obj and to
256 me here locally. This utility class now owns the object.
259 // TODO/MBA: is the object inserted multiple times here? Testing!
260 // And is it a problem that we now use the same naming scheme as in the other apps?
261 sw::hack::DrawingOLEAdaptor aOLEObj(rObject, *pPersist);
262 ::rtl::OUString sNewName;
263 bool bSuccess = aOLEObj.TransferToDoc(sNewName);
265 ASSERT(bSuccess, "Insert OLE failed");
266 if (bSuccess)
268 const SfxItemSet *pFlySet = pMathFlySet ? pMathFlySet : &rFlySet;
269 pRet = rDoc.InsertOLE(*pPaM, sNewName, rObject.GetAspect(), pFlySet, &rGrfSet, 0);
271 delete pMathFlySet;
272 return pRet;
275 SwFrmFmt* SwWW8ImplReader::ImportOle(const Graphic* pGrf,
276 const SfxItemSet* pFlySet, const SfxItemSet *pGrfSet, const Rectangle& aVisArea )
278 ::SetProgressState(nProgress, mpDocShell); // Update
279 SwFrmFmt* pFmt = 0;
281 GrafikCtor();
283 Graphic aGraph;
284 SdrObject* pRet = ImportOleBase(aGraph, pGrf, pFlySet, aVisArea );
286 // create flyset
287 SfxItemSet* pTempSet = 0;
288 if( !pFlySet )
290 pTempSet = new SfxItemSet( rDoc.GetAttrPool(), RES_FRMATR_BEGIN,
291 RES_FRMATR_END-1);
293 pFlySet = pTempSet;
295 // Abstand/Umrandung raus
296 if (!mbNewDoc)
297 Reader::ResetFrmFmtAttrs( *pTempSet );
299 SwFmtAnchor aAnchor( FLY_IN_CNTNT );
300 aAnchor.SetAnchor( pPaM->GetPoint() );
301 pTempSet->Put( aAnchor );
303 const Size aSizeTwip = OutputDevice::LogicToLogic(
304 aGraph.GetPrefSize(), aGraph.GetPrefMapMode(), MAP_TWIP );
306 pTempSet->Put( SwFmtFrmSize( ATT_FIX_SIZE, aSizeTwip.Width(),
307 aSizeTwip.Height() ) );
308 pTempSet->Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ));
310 if( pSFlyPara )
312 // OLE im Rahmen ? ok, Rahmen auf Bildgroesse vergroessern (
313 // nur wenn Auto-Breite )
314 pSFlyPara->BoxUpWidth( aSizeTwip.Width() );
318 if (pRet) // Ole-Object wurde eingefuegt
320 if (pRet->ISA(SdrOle2Obj))
322 pFmt = InsertOle(*((SdrOle2Obj*)pRet), *pFlySet, *pGrfSet);
323 SdrObject::Free( pRet ); // das brauchen wir nicht mehr
325 else
326 pFmt = rDoc.Insert(*pPaM, *pRet, pFlySet, NULL);
328 else if (
329 GRAPHIC_GDIMETAFILE == aGraph.GetType() ||
330 GRAPHIC_BITMAP == aGraph.GetType()
333 pFmt = rDoc.Insert(*pPaM, aEmptyStr, aEmptyStr, &aGraph, pFlySet,
334 pGrfSet, NULL);
336 delete pTempSet;
337 return pFmt;
340 bool SwWW8ImplReader::ImportOleWMF(SvStorageRef xSrc1,GDIMetaFile &rWMF,
341 long &rX,long &rY)
343 bool bOk = false;
344 OLE_MFP aMfp;
345 if( SwWw6ReadMetaStream( rWMF, &aMfp, xSrc1 ) )
348 take scaling factor as found in PIC and apply it to graphic.
350 SwWw8ReadScaling( rX, rY, xSrc1 );
351 Size aFinalSize, aOrigSize;
352 aFinalSize.Width() = rX;
353 aFinalSize.Height() = rY;
354 aFinalSize = OutputDevice::LogicToLogic(
355 aFinalSize, MAP_TWIP, rWMF.GetPrefMapMode() );
356 aOrigSize = rWMF.GetPrefSize();
357 Fraction aScaleX(aFinalSize.Width(),aOrigSize.Width());
358 Fraction aScaleY(aFinalSize.Height(),aOrigSize.Height());
359 rWMF.Scale( aScaleX, aScaleY );
360 bOk = true;
362 return bOk;
365 SdrObject* SwWW8ImplReader::ImportOleBase( Graphic& rGraph,
366 const Graphic* pGrf, const SfxItemSet* pFlySet, const Rectangle& aVisArea )
368 SdrObject* pRet = 0;
369 ASSERT( pStg, "ohne storage geht hier fast gar nichts!" );
371 ::SetProgressState( nProgress, rDoc.GetDocShell() ); // Update
373 long nX=0, nY=0; // nX, nY is graphic size
374 bool bOleOk = true;
376 String aSrcStgName = '_';
377 // ergibt Name "_4711"
378 aSrcStgName += String::CreateFromInt32( nObjLocFc );
380 SvStorageRef xSrc0 = pStg->OpenSotStorage(CREATE_CONST_ASC(SL::aObjectPool));
381 SvStorageRef xSrc1 = xSrc0->OpenSotStorage( aSrcStgName,
382 STREAM_READWRITE| STREAM_SHARE_DENYALL );
385 if (pGrf)
387 rGraph = *pGrf;
388 const Size aSizeTwip = OutputDevice::LogicToLogic(
389 rGraph.GetPrefSize(), rGraph.GetPrefMapMode(), MAP_TWIP );
390 nX = aSizeTwip.Width();
391 nY = aSizeTwip.Height();
393 else
395 GDIMetaFile aWMF;
397 if (ImportOleWMF(xSrc1,aWMF,nX,nY))
398 rGraph = Graphic( aWMF );
399 else if( SwWw6ReadMacPICTStream( rGraph, xSrc1 ) )
401 // 03-META-Stream nicht da. Vielleicht ein 03-PICT ?
402 const Size aSizeTwip = OutputDevice::LogicToLogic(
403 rGraph.GetPrefSize(), rGraph.GetPrefMapMode(), MAP_TWIP );
404 nX = aSizeTwip.Width();
405 nY = aSizeTwip.Height();
406 // PICT: kein WMF da -> Grafik statt OLE
407 bOleOk = false;
409 } // StorageStreams wieder zu
412 Rectangle aRect(0, 0, nX, nY);
414 if (pFlySet)
416 if (const SwFmtFrmSize* pSize =
417 (const SwFmtFrmSize*)pFlySet->GetItem(RES_FRM_SIZE, false))
419 aRect.SetSize(pSize->GetSize());
423 if (!(bIsHeader || bIsFooter))
425 //Can't put them in headers/footers :-(
426 uno::Reference< drawing::XShape > xRef;
427 ASSERT(pFormImpl, "Impossible");
428 if (pFormImpl && pFormImpl->ReadOCXStream(xSrc1, &xRef, false))
430 pRet = GetSdrObjectFromXShape(xRef);
431 ASSERT(pRet, "Impossible");
432 if (pRet)
433 pRet->SetLogicRect(aRect);
434 return pRet;
438 if (GRAPHIC_GDIMETAFILE == rGraph.GetType() ||
439 GRAPHIC_BITMAP == rGraph.GetType())
441 ::SetProgressState(nProgress, mpDocShell); // Update
443 if (bOleOk)
445 ULONG nOldPos = pDataStream->Tell();
446 pDataStream->Seek(STREAM_SEEK_TO_END);
447 SvStream *pTmpData = 0;
448 if (nObjLocFc < pDataStream->Tell())
450 pTmpData = pDataStream;
451 pTmpData->Seek( nObjLocFc );
454 sal_Int64 nAspect = embed::Aspects::MSOLE_CONTENT;
457 SvStorageStreamRef xObjInfoSrc = xSrc1->OpenSotStream( CREATE_CONST_ASC( "\3ObjInfo" ),
458 STREAM_STD_READ | STREAM_NOCREATE );
459 if ( xObjInfoSrc.Is() && !xObjInfoSrc->GetError() )
461 BYTE nByte = 0;
462 *xObjInfoSrc >> nByte;
463 if ( ( nByte >> 4 ) & embed::Aspects::MSOLE_ICON )
464 nAspect = embed::Aspects::MSOLE_ICON;
468 ErrCode nError = ERRCODE_NONE;
469 pRet = SvxMSDffManager::CreateSdrOLEFromStorage(
470 aSrcStgName, xSrc0, mpDocShell->GetStorage(), rGraph, aRect, aVisArea, pTmpData, nError,
471 SwMSDffManager::GetFilterFlags(), nAspect );
472 pDataStream->Seek( nOldPos );
475 return pRet;
478 void SwWW8ImplReader::ReadRevMarkAuthorStrTabl( SvStream& rStrm,
479 INT32 nTblPos, INT32 nTblSiz, SwDoc& rDocOut )
481 ::std::vector<String> aAuthorNames;
482 WW8ReadSTTBF( !bVer67, rStrm, nTblPos, nTblSiz, bVer67 ? 2 : 0,
483 eStructCharSet, aAuthorNames );
485 USHORT nCount = static_cast< USHORT >(aAuthorNames.size());
486 for( USHORT nAuthor = 0; nAuthor < nCount; ++nAuthor )
488 // Store author in doc
489 USHORT nSWId = rDocOut.InsertRedlineAuthor(aAuthorNames[nAuthor]);
490 // Store matchpair
491 if( !pAuthorInfos )
492 pAuthorInfos = new sw::util::AuthorInfos;
493 sw::util::AuthorInfo* pAutorInfo = new sw::util::AuthorInfo( nAuthor, nSWId );
494 if( 0 == pAuthorInfos->Insert( pAutorInfo ) )
495 delete pAutorInfo;
500 Revision Marks ( == Redlining )
502 // insert or delete content (change char attributes resp.)
503 void SwWW8ImplReader::Read_CRevisionMark(RedlineType_t eType,
504 const BYTE* pData, short nLen )
506 // there *must* be a SprmCIbstRMark[Del] and a SprmCDttmRMark[Del]
507 // pointing to the very same char position as our SprmCFRMark[Del]
508 if (!pPlcxMan)
509 return;
510 const BYTE* pSprmCIbstRMark;
511 const BYTE* pSprmCDttmRMark;
512 if( nsRedlineType_t::REDLINE_FORMAT == eType )
514 pSprmCIbstRMark = pData+1;
515 pSprmCDttmRMark = pData+3;
517 else
520 #101578#
521 It is possible to have a number of date stamps for the created time
522 of the change, (possibly a word bug) so we must use the "get a full
523 list" varient of HasCharSprm and take the last one as the true one.
525 std::vector<const BYTE *> aResult;
526 bool bIns = (nsRedlineType_t::REDLINE_INSERT == eType);
527 if( bVer67 )
529 pPlcxMan->HasCharSprm(69, aResult);
530 pSprmCIbstRMark = aResult.empty() ? 0 : aResult.back();
531 aResult.clear();
532 pPlcxMan->HasCharSprm(70, aResult);
533 pSprmCDttmRMark = aResult.empty() ? 0 : aResult.back();
535 else
537 pPlcxMan->HasCharSprm( bIns ? 0x4804 : 0x4863, aResult);
538 pSprmCIbstRMark = aResult.empty() ? 0 : aResult.back();
539 aResult.clear();
540 pPlcxMan->HasCharSprm( bIns ? 0x6805 : 0x6864, aResult);
541 pSprmCDttmRMark = aResult.empty() ? 0 : aResult.back();
545 if (nLen < 0)
546 mpRedlineStack->close(*pPaM->GetPoint(), eType, pTableDesc );
547 else
549 // start of new revision mark, if not there default to first entry
550 USHORT nWWAutNo = pSprmCIbstRMark ? SVBT16ToShort( pSprmCIbstRMark ) : 0;
551 sw::util::AuthorInfo aEntry(nWWAutNo);
552 USHORT nPos;
553 if (pAuthorInfos && pAuthorInfos->Seek_Entry(&aEntry, &nPos))
555 if (const sw::util::AuthorInfo* pAuthor = pAuthorInfos->GetObject(nPos))
557 UINT32 nWWDate = pSprmCDttmRMark ? SVBT32ToUInt32(pSprmCDttmRMark): 0;
558 DateTime aStamp(sw::ms::DTTM2DateTime(nWWDate));
559 USHORT nAutorNo = pAuthor->nOurId;
560 SwFltRedline aNewAttr(eType, nAutorNo, aStamp);
562 NewAttr(aNewAttr);
568 // insert new content
569 void SwWW8ImplReader::Read_CFRMark(USHORT , const BYTE* pData, short nLen)
571 Read_CRevisionMark( nsRedlineType_t::REDLINE_INSERT, pData, nLen );
574 // delete old content
575 void SwWW8ImplReader::Read_CFRMarkDel(USHORT , const BYTE* pData, short nLen)
577 Read_CRevisionMark( nsRedlineType_t::REDLINE_DELETE, pData, nLen );
580 // change properties of content ( == char formating)
581 void SwWW8ImplReader::Read_CPropRMark(USHORT , const BYTE* pData, short nLen)
583 // complex (len is always 7)
584 // 1 byte - chp.fPropRMark
585 // 2 bytes - chp.ibstPropRMark
586 // 4 bytes - chp.dttmPropRMark;
587 Read_CRevisionMark( nsRedlineType_t::REDLINE_FORMAT, pData, nLen );
590 /* vi:set tabstop=4 shiftwidth=4 expandtab: */