xref: /aoo42x/main/svx/source/svdraw/svdetc.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 #include "editeng/forbiddencharacterstable.hxx"
31 #include <com/sun/star/embed/XEmbeddedObject.hpp>
32 #include <com/sun/star/embed/EmbedStates.hpp>
33 #include <svx/svdetc.hxx>
34 #include "svx/svditext.hxx"
35 #include <svx/svdmodel.hxx>
36 #include <svx/svdtrans.hxx>
37 #include "svx/svdglob.hxx"
38 #include "svx/svdstr.hrc"
39 #include "svx/svdviter.hxx"
40 #include <svx/svdview.hxx>
41 #include <svx/svdoutl.hxx>
42 #include <vcl/bmpacc.hxx>
43 #include <editeng/eeitem.hxx>
44 #include <svl/itemset.hxx>
45 #include <tools/config.hxx>
46 #include <unotools/cacheoptions.hxx>
47 #include <svl/whiter.hxx>
48 #include <tools/bigint.hxx>
49 #include "editeng/fontitem.hxx"
50 #include <editeng/colritem.hxx>
51 #include <editeng/fhgtitem.hxx>
52 #include <svx/xgrad.hxx>
53 #include <svx/xfillit0.hxx>
54 #include <svx/xflclit.hxx>
55 #include <svx/xflhtit.hxx>
56 #include <svx/xbtmpit.hxx>
57 #include <svx/xflgrit.hxx>
58 #include <svx/svdoole2.hxx>
59 #include <svl/itempool.hxx>
60 #include <unotools/localedatawrapper.hxx>
61 #include <com/sun/star/lang/Locale.hpp>
62 #include <comphelper/processfactory.hxx>
63 #include <i18npool/lang.h>
64 #include <unotools/charclass.hxx>
65 #include <unotools/syslocale.hxx>
66 #include <svx/xflbckit.hxx>
67 #include <svx/extrusionbar.hxx>
68 #include <svx/fontworkbar.hxx>
69 #include <vcl/svapp.hxx> //add CHINA001
70 #include <svx/sdr/contact/viewcontact.hxx>
71 #include <svx/svdpage.hxx>
72 #include <svx/svdotable.hxx>
73 #include <svx/sdrhittesthelper.hxx>
74 
75 using namespace ::com::sun::star;
76 
77 /******************************************************************************
78 * Globale Daten der DrawingEngine
79 ******************************************************************************/
80 
81 SdrGlobalData::SdrGlobalData() :
82     pSysLocale(NULL),
83     pCharClass(NULL),
84     pLocaleData(NULL),
85 	pOutliner(NULL),
86 	pDefaults(NULL),
87 	pResMgr(NULL),
88 	nExchangeFormat(0)
89 {
90     //pSysLocale = new SvtSysLocale;
91     //pCharClass = pSysLocale->GetCharClassPtr();
92     //pLocaleData = pSysLocale->GetLocaleDataPtr();
93 
94 	svx::ExtrusionBar::RegisterInterface();
95 	svx::FontworkBar::RegisterInterface();
96 }
97 
98 SdrGlobalData::~SdrGlobalData()
99 {
100 	delete pOutliner;
101 	delete pDefaults;
102 	delete pResMgr;
103     //! do NOT delete pCharClass and pLocaleData
104     delete pSysLocale;
105 }
106 const SvtSysLocale*         SdrGlobalData::GetSysLocale()
107 {
108     if ( !pSysLocale )
109         pSysLocale = new SvtSysLocale;
110     return pSysLocale;
111 }
112 const CharClass*            SdrGlobalData::GetCharClass()
113 {
114     if ( !pCharClass )
115         pCharClass = GetSysLocale()->GetCharClassPtr();
116     return pCharClass;
117 }
118 const LocaleDataWrapper*    SdrGlobalData::GetLocaleData()
119 {
120     if ( !pLocaleData )
121         pLocaleData = GetSysLocale()->GetLocaleDataPtr();
122     return pLocaleData;
123 }
124 ////////////////////////////////////////////////////////////////////////////////////////////////////
125 
126 OLEObjCache::OLEObjCache()
127 :	Container( 0 )
128 {
129 	SvtCacheOptions aCacheOptions;
130 
131 	nSize = aCacheOptions.GetDrawingEngineOLE_Objects();
132 	pTimer = new AutoTimer();
133     Link aLink = LINK(this, OLEObjCache, UnloadCheckHdl);
134 
135     pTimer->SetTimeoutHdl(aLink);
136     pTimer->SetTimeout(20000);
137     pTimer->Start();
138 
139 	aLink.Call(pTimer);
140 }
141 
142 OLEObjCache::~OLEObjCache()
143 {
144 	pTimer->Stop();
145 	delete pTimer;
146 }
147 
148 void OLEObjCache::UnloadOnDemand()
149 {
150     if ( nSize < Count() )
151 	{
152         // more objects than configured cache size try to remove objects
153         // of course not the freshly inserted one at nIndex=0
154         sal_uIntPtr nCount2 = Count();
155         sal_uIntPtr nIndex = nCount2-1;
156         while( nIndex && nCount2 > nSize )
157 		{
158             SdrOle2Obj* pUnloadObj = (SdrOle2Obj*) GetObject(nIndex--);
159             if ( pUnloadObj )
160             {
161                 try
162                 {
163                     // it is important to get object without reinitialization to avoid reentrance
164                     uno::Reference< embed::XEmbeddedObject > xUnloadObj = pUnloadObj->GetObjRef_NoInit();
165 
166                     sal_Bool bUnload = SdrOle2Obj::CanUnloadRunningObj( xUnloadObj, pUnloadObj->GetAspect() );
167 
168                     // check whether the object can be unloaded before looking for the parent objects
169                     if ( xUnloadObj.is() && bUnload )
170                     {
171                         uno::Reference< frame::XModel > xUnloadModel( xUnloadObj->getComponent(), uno::UNO_QUERY );
172                         if ( xUnloadModel.is() )
173                         {
174                             for ( sal_uIntPtr nCheckInd = 0; nCheckInd < Count(); nCheckInd++ )
175                             {
176                                 SdrOle2Obj* pCacheObj = (SdrOle2Obj*) GetObject(nCheckInd);
177                                 if ( pCacheObj && pCacheObj != pUnloadObj )
178                                 {
179                                     uno::Reference< frame::XModel > xParentModel = pCacheObj->GetParentXModel();
180                                     if ( xUnloadModel == xParentModel )
181                                         bUnload = sal_False; // the object has running embedded objects
182                                 }
183                             }
184                         }
185                     }
186 
187                     if ( bUnload && UnloadObj(pUnloadObj) )
188                         // object was successfully unloaded
189                         nCount2--;
190                 }
191                 catch( uno::Exception& )
192                 {}
193             }
194 		}
195 	}
196 }
197 
198 void OLEObjCache::SetSize(sal_uIntPtr nNewSize)
199 {
200 	nSize = nNewSize;
201 }
202 
203 void OLEObjCache::InsertObj(SdrOle2Obj* pObj)
204 {
205 	if ( Count() )
206 	{
207 		SdrOle2Obj* pExistingObj = (SdrOle2Obj*)GetObject( 0 );
208 		if ( pObj == pExistingObj )
209 			// the object is already on the top, nothing has to be changed
210 			return;
211 	}
212 
213     // get the old position of the object to know whether it is already in container
214     sal_uIntPtr nOldPos = GetPos( pObj );
215 
216     // insert object into first position
217 	Remove( nOldPos );
218 	Insert(pObj, (sal_uIntPtr) 0L);
219 
220     if ( nOldPos == CONTAINER_ENTRY_NOTFOUND )
221     {
222         // a new object was inserted, recalculate the cache
223         UnloadOnDemand();
224     }
225 }
226 
227 void OLEObjCache::RemoveObj(SdrOle2Obj* pObj)
228 {
229     Remove(pObj);
230 }
231 
232 sal_Bool OLEObjCache::UnloadObj(SdrOle2Obj* pObj)
233 {
234 	sal_Bool bUnloaded = sal_False;
235 	if (pObj)
236 	{
237         //#i80528# The old mechanism is completely useless, only taking into account if
238         // in all views the GrafDraft feature is used. This will nearly never have been the
239         // case since no one ever used this option.
240         //
241         // A much better (and working) criteria would be the VOC contact count.
242         // The quesion is what will happen whe i make it work now suddenly? I
243         // will try it for 2.4.
244     	const sdr::contact::ViewContact& rViewContact = pObj->GetViewContact();
245 		const bool bVisible(rViewContact.HasViewObjectContacts(true));
246 
247 		if(!bVisible)
248         {
249     		bUnloaded = pObj->Unload();
250         }
251 	}
252 
253 	return bUnloaded;
254 }
255 
256 IMPL_LINK(OLEObjCache, UnloadCheckHdl, AutoTimer*, /*pTim*/)
257 {
258     UnloadOnDemand();
259     return 0;
260 }
261 
262 void ContainerSorter::DoSort(sal_uIntPtr a, sal_uIntPtr b) const
263 {
264 	sal_uIntPtr nAnz=rCont.Count();
265 	if (b>nAnz) b=nAnz;
266 	if (b>0) b--;
267 	if (a<b) ImpSubSort(a,b);
268 }
269 
270 void ContainerSorter::Is1stLessThan2nd(const void* /*pElem1*/, const void* /*pElem2*/) const
271 {
272 }
273 
274 void ContainerSorter::ImpSubSort(long nL, long nR) const
275 {
276 	long i,j;
277 	const void* pX;
278 	void* pI;
279 	void* pJ;
280 	i=nL;
281 	j=nR;
282 	pX=rCont.GetObject((nL+nR)/2);
283 	do {
284 		pI=rCont.Seek(i);
285 		while (pI!=pX && Compare(pI,pX)<0) { i++; pI=rCont.Next(); }
286 		pJ=rCont.Seek(j);
287 		while (pJ!=pX && Compare(pX,pJ)<0) { j--; pJ=rCont.Prev(); }
288 		if (i<=j) {
289 			rCont.Replace(pJ,i);
290 			rCont.Replace(pI,j);
291 			i++;
292 			j--;
293 		}
294 	} while (i<=j);
295 	if (nL<j) ImpSubSort(nL,j);
296 	if (i<nR) ImpSubSort(i,nR);
297 }
298 
299 ////////////////////////////////////////////////////////////////////////////////////////////////////
300 
301 class ImpUShortContainerSorter: public ContainerSorter {
302 public:
303 	ImpUShortContainerSorter(Container& rNewCont): ContainerSorter(rNewCont) {}
304 	virtual int Compare(const void* pElem1, const void* pElem2) const;
305 };
306 
307 int ImpUShortContainerSorter::Compare(const void* pElem1, const void* pElem2) const
308 {
309 	sal_uInt16 n1=sal_uInt16(sal_uIntPtr(pElem1));
310 	sal_uInt16 n2=sal_uInt16(sal_uIntPtr(pElem2));
311 	return n1<n2 ? -1 : n1>n2 ? 1 : 0;
312 }
313 
314 void UShortCont::Sort()
315 {
316 	ImpUShortContainerSorter aSorter(aArr);
317 	aSorter.DoSort();
318 }
319 
320 ////////////////////////////////////////////////////////////////////////////////////////////////////
321 
322 class ImpClipMerk {
323 	Region aClip;
324 	FASTBOOL   bClip;
325 public:
326 	ImpClipMerk(const OutputDevice& rOut): aClip(rOut.GetClipRegion()),bClip(rOut.IsClipRegion()) {}
327 	void Restore(OutputDevice& rOut)
328 	{
329 		// Kein Clipping in die Metafileaufzeichnung
330 		GDIMetaFile* pMtf=rOut.GetConnectMetaFile();
331 		if (pMtf!=NULL && (!pMtf->IsRecord() || pMtf->IsPause())) pMtf=NULL;
332 		if (pMtf!=NULL) pMtf->Pause(sal_True);
333 		if (bClip) rOut.SetClipRegion(aClip);
334 		else rOut.SetClipRegion();
335 		if (pMtf!=NULL) pMtf->Pause(sal_False);
336 	}
337 };
338 
339 class ImpColorMerk {
340 	Color aLineColor;
341 	Color aFillColor;
342 	Color aBckgrdColor;
343 	Font  aFont;
344 public:
345 	ImpColorMerk(const OutputDevice& rOut):
346 		aLineColor( rOut.GetLineColor() ),
347 		aFillColor( rOut.GetFillColor() ),
348 		aBckgrdColor( rOut.GetBackground().GetColor() ),
349 		aFont (rOut.GetFont()) {}
350 
351 	ImpColorMerk(const OutputDevice& rOut, sal_uInt16 nMode)
352 	{
353 		if ( (nMode & SDRHDC_SAVEPEN) == SDRHDC_SAVEPEN )
354 			aLineColor = rOut.GetLineColor();
355 
356 		if ( (nMode & SDRHDC_SAVEBRUSH) == SDRHDC_SAVEBRUSH)
357 		{
358 			aFillColor = rOut.GetFillColor();
359 			aBckgrdColor = rOut.GetBackground().GetColor();
360 		}
361 
362 		if ( (nMode & SDRHDC_SAVEFONT) == SDRHDC_SAVEFONT)
363 			aFont=rOut.GetFont();
364 	}
365 
366 	void Restore(OutputDevice& rOut, sal_uInt16 nMode=SDRHDC_SAVEPENANDBRUSHANDFONT)
367 	{
368 		if ( (nMode & SDRHDC_SAVEPEN) == SDRHDC_SAVEPEN)
369 			rOut.SetLineColor( aLineColor );
370 
371 		if ( (nMode & SDRHDC_SAVEBRUSH) == SDRHDC_SAVEBRUSH)
372 		{
373 			rOut.SetFillColor( aFillColor );
374 			rOut.SetBackground( Wallpaper( aBckgrdColor ) );
375 		}
376 		if ((nMode & SDRHDC_SAVEFONT) ==SDRHDC_SAVEFONT)
377 		{
378 			if (!rOut.GetFont().IsSameInstance(aFont))
379 			{
380 				rOut.SetFont(aFont);
381 			}
382 		}
383 	}
384 
385 	const Color& GetLineColor() const { return aLineColor; }
386 };
387 
388 ImpSdrHdcMerk::ImpSdrHdcMerk(const OutputDevice& rOut, sal_uInt16 nNewMode, FASTBOOL bAutoMerk):
389 	pFarbMerk(NULL),
390 	pClipMerk(NULL),
391 	pLineColorMerk(NULL),
392 	nMode(nNewMode)
393 {
394 	if (bAutoMerk) Save(rOut);
395 }
396 
397 ImpSdrHdcMerk::~ImpSdrHdcMerk()
398 {
399 	if (pFarbMerk!=NULL) delete pFarbMerk;
400 	if (pClipMerk!=NULL) delete pClipMerk;
401 	if (pLineColorMerk !=NULL) delete pLineColorMerk;
402 }
403 
404 void ImpSdrHdcMerk::Save(const OutputDevice& rOut)
405 {
406 	if (pFarbMerk!=NULL)
407 	{
408 		delete pFarbMerk;
409 		pFarbMerk=NULL;
410 	}
411 	if (pClipMerk!=NULL)
412 	{
413 		delete pClipMerk;
414 		pClipMerk=NULL;
415 	}
416 	if (pLineColorMerk !=NULL)
417 	{
418 		delete pLineColorMerk ;
419 		pLineColorMerk =NULL;
420 	}
421 	if ((nMode & SDRHDC_SAVECLIPPING) ==SDRHDC_SAVECLIPPING)
422 		pClipMerk=new ImpClipMerk(rOut);
423 
424 	sal_uInt16 nCol=nMode & SDRHDC_SAVEPENANDBRUSHANDFONT;
425 
426 	if (nCol==SDRHDC_SAVEPEN)
427 		pLineColorMerk=new Color( rOut.GetLineColor() );
428 	else if (nCol==SDRHDC_SAVEPENANDBRUSHANDFONT)
429 		pFarbMerk=new ImpColorMerk(rOut);
430 	else if (nCol!=0)
431 		pFarbMerk=new ImpColorMerk(rOut,nCol);
432 }
433 
434 void ImpSdrHdcMerk::Restore(OutputDevice& rOut, sal_uInt16 nMask) const
435 {
436 	nMask&=nMode; // nur restaurieren, was auch gesichert wurde
437 
438 	if ((nMask & SDRHDC_SAVECLIPPING) ==SDRHDC_SAVECLIPPING && pClipMerk!=NULL)
439 		pClipMerk->Restore(rOut);
440 
441 	sal_uInt16 nCol=nMask & SDRHDC_SAVEPENANDBRUSHANDFONT;
442 
443 	if (nCol==SDRHDC_SAVEPEN)
444 	{
445 		if (pLineColorMerk!=NULL)
446 			rOut.SetLineColor(*pLineColorMerk);
447 		else if (pFarbMerk!=NULL)
448 			rOut.SetLineColor( pFarbMerk->GetLineColor() );
449 	} else if (nCol!=0 && pFarbMerk!=NULL)
450 		pFarbMerk->Restore(rOut,nCol);
451 }
452 
453 ////////////////////////////////////////////////////////////////////////////////////////////////////
454 
455 void SdrLinkList::Clear()
456 {
457 	unsigned nAnz=GetLinkCount();
458 	for (unsigned i=0; i<nAnz; i++) {
459 		delete (Link*)aList.GetObject(i);
460 	}
461 	aList.Clear();
462 }
463 
464 unsigned SdrLinkList::FindEntry(const Link& rLink) const
465 {
466 	unsigned nAnz=GetLinkCount();
467 	for (unsigned i=0; i<nAnz; i++) {
468 		if (GetLink(i)==rLink) return i;
469 	}
470 	return 0xFFFF;
471 }
472 
473 void SdrLinkList::InsertLink(const Link& rLink, unsigned nPos)
474 {
475 	unsigned nFnd=FindEntry(rLink);
476 	if (nFnd==0xFFFF) {
477 		if (rLink.IsSet()) {
478 			aList.Insert(new Link(rLink),nPos);
479 		} else {
480 			DBG_ERROR("SdrLinkList::InsertLink(): Versuch, einen nicht gesetzten Link einzufuegen");
481 		}
482 	} else {
483 		DBG_ERROR("SdrLinkList::InsertLink(): Link schon vorhanden");
484 	}
485 }
486 
487 void SdrLinkList::RemoveLink(const Link& rLink)
488 {
489 	unsigned nFnd=FindEntry(rLink);
490 	if (nFnd!=0xFFFF) {
491 		Link* pLink=(Link*)aList.Remove(nFnd);
492 		delete pLink;
493 	} else {
494 		DBG_ERROR("SdrLinkList::RemoveLink(): Link nicht gefunden");
495 	}
496 }
497 
498 ////////////////////////////////////////////////////////////////////////////////////////////////////
499 // #98988# Re-implement GetDraftFillColor(...)
500 
501 FASTBOOL GetDraftFillColor(const SfxItemSet& rSet, Color& rCol)
502 {
503 	XFillStyle eFill=((XFillStyleItem&)rSet.Get(XATTR_FILLSTYLE)).GetValue();
504 	FASTBOOL bRetval(sal_False);
505 
506 	switch(eFill)
507 	{
508 		case XFILL_SOLID:
509 		{
510 			rCol = ((XFillColorItem&)rSet.Get(XATTR_FILLCOLOR)).GetColorValue();
511 			bRetval = sal_True;
512 
513 			break;
514 		}
515 		case XFILL_HATCH:
516 		{
517 			Color aCol1(((XFillHatchItem&)rSet.Get(XATTR_FILLHATCH)).GetHatchValue().GetColor());
518 			Color aCol2(COL_WHITE);
519 
520 			// #97870# when hatch background is activated, use object fill color as hatch color
521 			sal_Bool bFillHatchBackground = ((const XFillBackgroundItem&)(rSet.Get(XATTR_FILLBACKGROUND))).GetValue();
522 			if(bFillHatchBackground)
523 			{
524 				aCol2 = ((const XFillColorItem&)(rSet.Get(XATTR_FILLCOLOR))).GetColorValue();
525 			}
526 
527             const basegfx::BColor aAverageColor(basegfx::average(aCol1.getBColor(), aCol2.getBColor()));
528 			rCol = Color(aAverageColor);
529 			bRetval = sal_True;
530 
531 			break;
532 		}
533 		case XFILL_GRADIENT: {
534 			const XGradient& rGrad=((XFillGradientItem&)rSet.Get(XATTR_FILLGRADIENT)).GetGradientValue();
535 			Color aCol1(rGrad.GetStartColor());
536 			Color aCol2(rGrad.GetEndColor());
537             const basegfx::BColor aAverageColor(basegfx::average(aCol1.getBColor(), aCol2.getBColor()));
538 			rCol = Color(aAverageColor);
539 			bRetval = sal_True;
540 
541 			break;
542 		}
543 		case XFILL_BITMAP:
544 		{
545 			const Bitmap& rBitmap = ((XFillBitmapItem&)rSet.Get(XATTR_FILLBITMAP)).GetBitmapValue().GetBitmap();
546 			const Size aSize(rBitmap.GetSizePixel());
547 			const sal_uInt32 nWidth = aSize.Width();
548 			const sal_uInt32 nHeight = aSize.Height();
549 			Bitmap aBitmap(rBitmap);
550 			BitmapReadAccess* pAccess = aBitmap.AcquireReadAccess();
551 
552 			if(pAccess && nWidth > 0 && nHeight > 0)
553 			{
554 				sal_uInt32 nRt(0L);
555 				sal_uInt32 nGn(0L);
556 				sal_uInt32 nBl(0L);
557 				const sal_uInt32 nMaxSteps(8L);
558 				const sal_uInt32 nXStep((nWidth > nMaxSteps) ? nWidth / nMaxSteps : 1L);
559 				const sal_uInt32 nYStep((nHeight > nMaxSteps) ? nHeight / nMaxSteps : 1L);
560 				sal_uInt32 nAnz(0L);
561 
562 				for(sal_uInt32 nY(0L); nY < nHeight; nY += nYStep)
563 				{
564 					for(sal_uInt32 nX(0L); nX < nWidth; nX += nXStep)
565 					{
566 						const BitmapColor& rCol2 = (pAccess->HasPalette())
567 							? pAccess->GetPaletteColor((sal_uInt8)pAccess->GetPixel(nY, nX))
568 							: pAccess->GetPixel(nY, nX);
569 
570 						nRt += rCol2.GetRed();
571 						nGn += rCol2.GetGreen();
572 						nBl += rCol2.GetBlue();
573 						nAnz++;
574 					}
575 				}
576 
577 				nRt /= nAnz;
578 				nGn /= nAnz;
579 				nBl /= nAnz;
580 
581 				rCol = Color(sal_uInt8(nRt), sal_uInt8(nGn), sal_uInt8(nBl));
582 
583 				bRetval = sal_True;
584 			}
585 
586 			if(pAccess)
587 			{
588 				aBitmap.ReleaseAccess(pAccess);
589 			}
590 
591 			break;
592 		}
593 		default: break;
594 	}
595 
596 	return bRetval;
597 }
598 
599 ////////////////////////////////////////////////////////////////////////////////////////////////////
600 
601 SdrEngineDefaults::SdrEngineDefaults():
602 	aFontName( OutputDevice::GetDefaultFont( DEFAULTFONT_SERIF, LANGUAGE_SYSTEM, DEFAULTFONT_FLAGS_ONLYONE ).GetName() ),
603 	eFontFamily(FAMILY_ROMAN),
604 	aFontColor(COL_AUTO),
605 	nFontHeight(847),			  // 847/100mm = ca. 24 Point
606 	eMapUnit(MAP_100TH_MM),
607 	aMapFraction(1,1)
608 {
609 }
610 
611 SdrEngineDefaults& SdrEngineDefaults::GetDefaults()
612 {
613 	SdrGlobalData& rGlobalData=GetSdrGlobalData();
614 	if (rGlobalData.pDefaults==NULL) {
615 		rGlobalData.pDefaults=new SdrEngineDefaults;
616 	}
617 	return *rGlobalData.pDefaults;
618 }
619 
620 ////////////////////////////////////////////////////////////////////////////////////////////////////
621 
622 void SdrEngineDefaults::LanguageHasChanged()
623 {
624 	SdrGlobalData& rGlobalData=GetSdrGlobalData();
625 	if (rGlobalData.pResMgr!=NULL) {
626 		delete rGlobalData.pResMgr;
627 		rGlobalData.pResMgr=NULL;
628 	}
629 }
630 
631 ////////////////////////////////////////////////////////////////////////////////////////////////////
632 
633 SdrOutliner* SdrMakeOutliner( sal_uInt16 nOutlinerMode, SdrModel* pModel )
634 {
635 	//SdrEngineDefaults& rDefaults = SdrEngineDefaults::GetDefaults();
636 
637 	SfxItemPool* pPool = &pModel->GetItemPool();
638 	SdrOutliner* pOutl = new SdrOutliner( pPool, nOutlinerMode );
639 	pOutl->SetEditTextObjectPool( pPool );
640 	pOutl->SetStyleSheetPool( (SfxStyleSheetPool*) pModel->GetStyleSheetPool() );
641 	pOutl->SetDefTab( pModel->GetDefaultTabulator() );
642 	pOutl->SetForbiddenCharsTable( pModel->GetForbiddenCharsTable() );
643 	pOutl->SetAsianCompressionMode( pModel->GetCharCompressType() );
644 	pOutl->SetKernAsianPunctuation( pModel->IsKernAsianPunctuation() );
645     pOutl->SetAddExtLeading( pModel->IsAddExtLeading() );
646 
647 	return pOutl;
648 }
649 
650 ////////////////////////////////////////////////////////////////////////////////////////////////////
651 
652 
653 SdrLinkList& ImpGetUserMakeObjHdl()
654 {
655 	SdrGlobalData& rGlobalData=GetSdrGlobalData();
656 	return rGlobalData.aUserMakeObjHdl;
657 }
658 
659 SdrLinkList& ImpGetUserMakeObjUserDataHdl()
660 {
661 	SdrGlobalData& rGlobalData=GetSdrGlobalData();
662 	return rGlobalData.aUserMakeObjUserDataHdl;
663 }
664 
665 ////////////////////////////////////////////////////////////////////////////////////////////////////
666 
667 ResMgr* ImpGetResMgr()
668 {
669 	SdrGlobalData& rGlobalData = GetSdrGlobalData();
670 
671 	if(!rGlobalData.pResMgr)
672 	{
673 		ByteString aName("svx");
674 		rGlobalData.pResMgr =
675             ResMgr::CreateResMgr( aName.GetBuffer(), Application::GetSettings().GetUILocale() );
676 	}
677 
678 	return rGlobalData.pResMgr;
679 }
680 
681 ////////////////////////////////////////////////////////////////////////////////////////////////////
682 
683 String ImpGetResStr(sal_uInt16 nResID)
684 {
685 	return String(ResId(nResID, *ImpGetResMgr()));
686 }
687 
688 ////////////////////////////////////////////////////////////////////////////////////////////////////
689 
690 namespace sdr
691 {
692 String GetResourceString(sal_uInt16 nResID)
693 {
694 	return ImpGetResStr( nResID );
695 }
696 }
697 
698 ////////////////////////////////////////////////////////////////////////////////////////////////////
699 
700 sal_Bool SearchOutlinerItems(const SfxItemSet& rSet, sal_Bool bInklDefaults, sal_Bool* pbOnlyEE)
701 {
702 	sal_Bool bHas=sal_False;
703 	sal_Bool bOnly=sal_True;
704 	sal_Bool bLookOnly=pbOnlyEE!=NULL;
705 	SfxWhichIter aIter(rSet);
706 	sal_uInt16 nWhich=aIter.FirstWhich();
707 	while (((bLookOnly && bOnly) || !bHas) && nWhich!=0) {
708 		// bei bInklDefaults ist der gesamte Which-Range
709 		// ausschlaggebend, ansonsten nur die gesetzten Items
710 		// Disabled und DontCare wird als Loch im Which-Range betrachtet
711 		SfxItemState eState=rSet.GetItemState(nWhich);
712 		if ((eState==SFX_ITEM_DEFAULT && bInklDefaults) || eState==SFX_ITEM_SET) {
713 			if (nWhich<EE_ITEMS_START || nWhich>EE_ITEMS_END) bOnly=sal_False;
714 			else bHas=sal_True;
715 		}
716 		nWhich=aIter.NextWhich();
717 	}
718 	if (!bHas) bOnly=sal_False;
719 	if (pbOnlyEE!=NULL) *pbOnlyEE=bOnly;
720 	return bHas;
721 }
722 
723 sal_uInt16* RemoveWhichRange(const sal_uInt16* pOldWhichTable, sal_uInt16 nRangeBeg, sal_uInt16 nRangeEnd)
724 {
725 	// insgesamt sind 6 Faelle moeglich (je Range):
726 	//		   [Beg..End]		   zu entfernender Range
727 	// [b..e]	 [b..e]    [b..e]  Fall 1,3,2: egal, ganz weg, egal  + Ranges
728 	// [b........e]  [b........e]  Fall 4,5  : Bereich verkleinern	 | in
729 	// [b......................e]  Fall 6	 : Splitting			 + pOldWhichTable
730 	sal_uInt16 nAnz=0;
731 	while (pOldWhichTable[nAnz]!=0) nAnz++;
732 	nAnz++; // nAnz muesste nun in jedem Fall eine ungerade Zahl sein (0 am Ende des Arrays)
733 	DBG_ASSERT((nAnz&1)==1,"Joe: RemoveWhichRange: WhichTable hat keine ungerade Anzahl von Eintraegen");
734 	sal_uInt16 nAlloc=nAnz;
735 	// benoetigte Groesse des neuen Arrays ermitteln
736 	sal_uInt16 nNum=nAnz-1;
737 	while (nNum!=0) {
738 		nNum-=2;
739 		sal_uInt16 nBeg=pOldWhichTable[nNum];
740 		sal_uInt16 nEnd=pOldWhichTable[nNum+1];
741 		if (nEnd<nRangeBeg)  /*nCase=1*/ ;
742 		else if (nBeg>nRangeEnd) /* nCase=2 */ ;
743 		else if (nBeg>=nRangeBeg && nEnd<=nRangeEnd) /* nCase=3 */ nAlloc-=2;
744 		else if (nEnd<=nRangeEnd) /* nCase=4 */;
745 		else if (nBeg>=nRangeBeg) /* nCase=5*/ ;
746 		else /* nCase=6 */ nAlloc+=2;
747 	}
748 
749 	sal_uInt16* pNewWhichTable=new sal_uInt16[nAlloc];
750 	memcpy(pNewWhichTable,pOldWhichTable,nAlloc*sizeof(sal_uInt16));
751 	pNewWhichTable[nAlloc-1]=0; // im Falle 3 fehlt die 0 am Ende
752 	// nun die unerwuenschten Ranges entfernen
753 	nNum=nAlloc-1;
754 	while (nNum!=0) {
755 		nNum-=2;
756 		sal_uInt16 nBeg=pNewWhichTable[nNum];
757 		sal_uInt16 nEnd=pNewWhichTable[nNum+1];
758 		unsigned nCase=0;
759 		if (nEnd<nRangeBeg) nCase=1;
760 		else if (nBeg>nRangeEnd) nCase=2;
761 		else if (nBeg>=nRangeBeg && nEnd<=nRangeEnd) nCase=3;
762 		else if (nEnd<=nRangeEnd) nCase=4;
763 		else if (nBeg>=nRangeBeg) nCase=5;
764 		else nCase=6;
765 		switch (nCase) {
766 			case 3: {
767 				unsigned nTailBytes=(nAnz-(nNum+2))*sizeof(sal_uInt16);
768 				memcpy(&pNewWhichTable[nNum],&pNewWhichTable[nNum+2],nTailBytes);
769 				nAnz-=2; // Merken: Array hat sich verkleinert
770 			} break;
771 			case 4: pNewWhichTable[nNum+1]=nRangeBeg-1; break;
772 			case 5: pNewWhichTable[nNum]=nRangeEnd+1;	  break;
773 			case 6: {
774 				unsigned nTailBytes=(nAnz-(nNum+2))*sizeof(sal_uInt16);
775 				memcpy(&pNewWhichTable[nNum+4],&pNewWhichTable[nNum+2],nTailBytes);
776 				nAnz+=2; // Merken: Array hat sich vergroessert
777 				pNewWhichTable[nNum+2]=nRangeEnd+1;
778 				pNewWhichTable[nNum+3]=pNewWhichTable[nNum+1];
779 				pNewWhichTable[nNum+1]=nRangeBeg-1;
780 			} break;
781 		} // switch
782 	}
783 	return pNewWhichTable;
784 }
785 
786 ////////////////////////////////////////////////////////////////////////////////////////////////////
787 
788 SvdProgressInfo::SvdProgressInfo( Link *_pLink )
789 {
790 	DBG_ASSERT(_pLink!=NULL,"SvdProgressInfo(): Kein Link angegeben!!");
791 
792 	pLink = _pLink;
793 	nSumActionCount = 0;
794 	nSumCurAction	= 0;
795 
796 	nObjCount = 0;
797 	nCurObj   = 0;
798 
799 	nActionCount = 0;
800 	nCurAction	 = 0;
801 
802 	nInsertCount = 0;
803 	nCurInsert	 = 0;
804 }
805 
806 void SvdProgressInfo::Init( sal_uIntPtr _nSumActionCount, sal_uIntPtr _nObjCount )
807 {
808 	nSumActionCount = _nSumActionCount;
809 	nObjCount = _nObjCount;
810 }
811 
812 sal_Bool SvdProgressInfo::ReportActions( sal_uIntPtr nAnzActions )
813 {
814 	nSumCurAction += nAnzActions;
815 	nCurAction += nAnzActions;
816 	if(nCurAction > nActionCount)
817 		nCurAction = nActionCount;
818 
819 	return pLink->Call(NULL) == 1L;
820 }
821 
822 sal_Bool SvdProgressInfo::ReportInserts( sal_uIntPtr nAnzInserts )
823 {
824 	nSumCurAction += nAnzInserts;
825 	nCurInsert += nAnzInserts;
826 
827 	return pLink->Call(NULL) == 1L;
828 }
829 
830 sal_Bool SvdProgressInfo::ReportRescales( sal_uIntPtr nAnzRescales )
831 {
832 	nSumCurAction += nAnzRescales;
833 	return pLink->Call(NULL) == 1L;
834 }
835 
836 void SvdProgressInfo::SetActionCount( sal_uIntPtr _nActionCount )
837 {
838 	nActionCount = _nActionCount;
839 }
840 
841 void SvdProgressInfo::SetInsertCount( sal_uIntPtr _nInsertCount )
842 {
843 	nInsertCount = _nInsertCount;
844 }
845 
846 sal_Bool SvdProgressInfo::SetNextObject()
847 {
848 	nActionCount = 0;
849 	nCurAction	 = 0;
850 
851 	nInsertCount = 0;
852 	nCurInsert	 = 0;
853 
854 	nCurObj++;
855 	return ReportActions(0);
856 }
857 
858 void SvdProgressInfo::ReportError()
859 {
860 	pLink->Call((void *)1L);
861 }
862 
863 ////////////////////////////////////////////////////////////////////////////////////////////////////
864 // #i101872# isolate GetTextEditBackgroundColor to tooling; it woll anyways only be used as long
865 // as text edit is not running on overlay
866 
867 namespace
868 {
869     bool impGetSdrObjListFillColor(
870         const SdrObjList& rList,
871         const Point& rPnt,
872         const SdrPageView& rTextEditPV,
873         const SetOfByte& rVisLayers,
874         Color& rCol)
875     {
876 	    if(!rList.GetModel())
877             return false;
878 
879 	    bool bRet(false);
880 	    bool bMaster(rList.GetPage() ? rList.GetPage()->IsMasterPage() : false);
881 
882 	    for(sal_uIntPtr no(rList.GetObjCount()); !bRet && no > 0; )
883         {
884 		    no--;
885 		    SdrObject* pObj = rList.GetObj(no);
886 		    SdrObjList* pOL = pObj->GetSubList();
887 
888             if(pOL)
889             {
890                 // group object
891 			    bRet = impGetSdrObjListFillColor(*pOL, rPnt, rTextEditPV, rVisLayers, rCol);
892 		    }
893             else
894             {
895         		SdrTextObj* pText = dynamic_cast< SdrTextObj * >(pObj);
896 
897                 // #108867# Exclude zero master page object (i.e. background shape) from color query
898 			    if(pText
899                     && pObj->IsClosedObj()
900                     && (!bMaster || (!pObj->IsNotVisibleAsMaster() && 0 != no))
901                     && pObj->GetCurrentBoundRect().IsInside(rPnt)
902                     && !pText->IsHideContour()
903                     && SdrObjectPrimitiveHit(*pObj, rPnt, 0, rTextEditPV, &rVisLayers, false))
904 			    {
905             	    bRet = GetDraftFillColor(pObj->GetMergedItemSet(), rCol);
906 			    }
907 		    }
908 	    }
909 
910         return bRet;
911     }
912 
913     bool impGetSdrPageFillColor(
914         const SdrPage& rPage,
915         const Point& rPnt,
916         const SdrPageView& rTextEditPV,
917         const SetOfByte& rVisLayers,
918         Color& rCol,
919         bool bSkipBackgroundShape)
920     {
921 	    if(!rPage.GetModel())
922 		    return false;
923 
924 	    bool bRet(impGetSdrObjListFillColor(rPage, rPnt, rTextEditPV, rVisLayers, rCol));
925 
926 	    if(!bRet && !rPage.IsMasterPage())
927 	    {
928 		    if(rPage.TRG_HasMasterPage())
929 		    {
930 			    SetOfByte aSet(rVisLayers);
931 			    aSet &= rPage.TRG_GetMasterPageVisibleLayers();
932 			    SdrPage& rMasterPage = rPage.TRG_GetMasterPage();
933 
934 			    // #108867# Don't fall back to background shape on
935                 // master pages. This is later handled by
936                 // GetBackgroundColor, and is necessary to cater for
937                 // the silly ordering: 1. shapes, 2. master page
938                 // shapes, 3. page background, 4. master page
939                 // background.
940 			    bRet = impGetSdrPageFillColor(rMasterPage, rPnt, rTextEditPV, aSet, rCol, true);
941 		    }
942 	    }
943 
944         // #108867# Only now determine background color from background shapes
945         if(!bRet && !bSkipBackgroundShape)
946         {
947             rCol = rPage.GetPageBackgroundColor();
948 		    return true;
949         }
950 
951 	    return bRet;
952     }
953 
954     Color impCalcBackgroundColor(
955         const Rectangle& rArea,
956         const SdrPageView& rTextEditPV,
957         const SdrPage& rPage)
958     {
959         svtools::ColorConfig aColorConfig;
960         Color aBackground(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor);
961 	    const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
962 
963 	    if(!rStyleSettings.GetHighContrastMode())
964 	    {
965             // search in page
966             const sal_uInt16 SPOTCOUNT(5);
967             Point aSpotPos[SPOTCOUNT];
968             Color aSpotColor[SPOTCOUNT];
969             sal_uIntPtr nHeight( rArea.GetSize().Height() );
970             sal_uIntPtr nWidth( rArea.GetSize().Width() );
971             sal_uIntPtr nWidth14  = nWidth / 4;
972             sal_uIntPtr nHeight14 = nHeight / 4;
973             sal_uIntPtr nWidth34  = ( 3 * nWidth ) / 4;
974             sal_uIntPtr nHeight34 = ( 3 * nHeight ) / 4;
975 
976             sal_uInt16 i;
977             for ( i = 0; i < SPOTCOUNT; i++ )
978             {
979                 // five spots are used
980                 switch ( i )
981                 {
982                     case 0 :
983                     {
984                         // Center-Spot
985                         aSpotPos[i] = rArea.Center();
986                     }
987                     break;
988 
989                     case 1 :
990                     {
991                         // TopLeft-Spot
992                         aSpotPos[i] = rArea.TopLeft();
993                         aSpotPos[i].X() += nWidth14;
994                         aSpotPos[i].Y() += nHeight14;
995                     }
996                     break;
997 
998                     case 2 :
999                     {
1000                         // TopRight-Spot
1001                         aSpotPos[i] = rArea.TopLeft();
1002                         aSpotPos[i].X() += nWidth34;
1003                         aSpotPos[i].Y() += nHeight14;
1004                     }
1005                     break;
1006 
1007                     case 3 :
1008                     {
1009                         // BottomLeft-Spot
1010                         aSpotPos[i] = rArea.TopLeft();
1011                         aSpotPos[i].X() += nWidth14;
1012                         aSpotPos[i].Y() += nHeight34;
1013                     }
1014                     break;
1015 
1016                     case 4 :
1017                     {
1018                         // BottomRight-Spot
1019                         aSpotPos[i] = rArea.TopLeft();
1020                         aSpotPos[i].X() += nWidth34;
1021                         aSpotPos[i].Y() += nHeight34;
1022                     }
1023                     break;
1024 
1025                 }
1026 
1027                 aSpotColor[i] = Color( COL_WHITE );
1028                 impGetSdrPageFillColor(rPage, aSpotPos[i], rTextEditPV, rTextEditPV.GetVisibleLayers(), aSpotColor[i], false);
1029             }
1030 
1031             sal_uInt16 aMatch[SPOTCOUNT];
1032 
1033             for ( i = 0; i < SPOTCOUNT; i++ )
1034             {
1035                 // were same spot colors found?
1036                 aMatch[i] = 0;
1037 
1038                 for ( sal_uInt16 j = 0; j < SPOTCOUNT; j++ )
1039                 {
1040                     if( j != i )
1041                     {
1042                         if( aSpotColor[i] == aSpotColor[j] )
1043                         {
1044                             aMatch[i]++;
1045                         }
1046                     }
1047                 }
1048             }
1049 
1050             // highest weight to center spot
1051             aBackground = aSpotColor[0];
1052 
1053             for ( sal_uInt16 nMatchCount = SPOTCOUNT - 1; nMatchCount > 1; nMatchCount-- )
1054             {
1055                 // which spot color was found most?
1056                 for ( i = 0; i < SPOTCOUNT; i++ )
1057                 {
1058                     if( aMatch[i] == nMatchCount )
1059                     {
1060                         aBackground = aSpotColor[i];
1061                         nMatchCount = 1;   // break outer for-loop
1062                         break;
1063                     }
1064                 }
1065             }
1066 	    }
1067 
1068         return aBackground;
1069     }
1070 } // end of anonymous namespace
1071 
1072 Color GetTextEditBackgroundColor(const SdrObjEditView& rView)
1073 {
1074     svtools::ColorConfig aColorConfig;
1075     Color aBackground(aColorConfig.GetColorValue(svtools::DOCCOLOR).nColor);
1076 	const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1077 
1078 	if(!rStyleSettings.GetHighContrastMode())
1079 	{
1080 		bool bFound(false);
1081 		SdrTextObj* pText = dynamic_cast< SdrTextObj * >(rView.GetTextEditObject());
1082 
1083         if(pText && pText->IsClosedObj())
1084 		{
1085 			::sdr::table::SdrTableObj* pTable = dynamic_cast< ::sdr::table::SdrTableObj * >( pText );
1086 
1087             if( pTable )
1088 				bFound = GetDraftFillColor(pTable->GetActiveCellItemSet(), aBackground );
1089 
1090 			if( !bFound )
1091 				bFound=GetDraftFillColor(pText->GetMergedItemSet(), aBackground);
1092 		}
1093 
1094         if(!bFound && pText)
1095 		{
1096             SdrPageView* pTextEditPV = rView.GetTextEditPageView();
1097 
1098             if(pTextEditPV)
1099 		    {
1100 			    Point aPvOfs(pText->GetTextEditOffset());
1101 			    const SdrPage* pPg = pTextEditPV->GetPage();
1102 
1103 			    if(pPg)
1104 			    {
1105 				    Rectangle aSnapRect( pText->GetSnapRect() );
1106 				    aSnapRect.Move(aPvOfs.X(), aPvOfs.Y());
1107 
1108 				    return impCalcBackgroundColor(aSnapRect, *pTextEditPV, *pPg);
1109 			    }
1110             }
1111         }
1112     }
1113 
1114     return aBackground;
1115 }
1116 
1117 ////////////////////////////////////////////////////////////////////////////////////////////////////
1118 // eof
1119