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