xref: /aoo41x/main/sc/source/ui/unoobj/textuno.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_sc.hxx"
30 
31 
32 
33 #include "scitems.hxx"
34 #include <editeng/eeitem.hxx>
35 #include <svx/svdpool.hxx>
36 #include <svx/svdobj.hxx>
37 #include <editeng/editeng.hxx>
38 #include <editeng/editobj.hxx>
39 #include <editeng/flditem.hxx>
40 #include <svx/unomid.hxx>
41 #include <editeng/unoprnms.hxx>
42 #include <editeng/unofored.hxx>
43 #include <rtl/uuid.h>
44 #include <vcl/virdev.hxx>
45 #include <com/sun/star/awt/FontSlant.hpp>
46 
47 #include <com/sun/star/beans/PropertyAttribute.hpp>
48 #include <editeng/unoipset.hxx>
49 #include "textuno.hxx"
50 #include "fielduno.hxx"
51 #include "servuno.hxx"
52 #include "editsrc.hxx"
53 #include "docsh.hxx"
54 #include "editutil.hxx"
55 #include "unoguard.hxx"
56 #include "miscuno.hxx"
57 #include "cellsuno.hxx"
58 #include "hints.hxx"
59 #include "patattr.hxx"
60 #include "cell.hxx"
61 #include "docfunc.hxx"
62 #include "scmod.hxx"
63 
64 using namespace com::sun::star;
65 
66 //------------------------------------------------------------------------
67 
68 const SvxItemPropertySet * lcl_GetHdFtPropertySet()
69 {
70     static SfxItemPropertyMapEntry aHdFtPropertyMap_Impl[] =
71 	{
72 		SVX_UNOEDIT_CHAR_PROPERTIES,
73 		SVX_UNOEDIT_FONT_PROPERTIES,
74 		SVX_UNOEDIT_PARA_PROPERTIES,
75 		SVX_UNOEDIT_NUMBERING_PROPERTIE,	// for completeness of service ParagraphProperties
76         {0,0,0,0,0,0}
77 	};
78 	static sal_Bool bTwipsSet = sal_False;
79 
80 	if (!bTwipsSet)
81 	{
82 		//	modify PropertyMap to include CONVERT_TWIPS flag for font height
83 		//	(headers/footers are in twips)
84 
85         SfxItemPropertyMapEntry* pEntry = aHdFtPropertyMap_Impl;
86 		while (pEntry->pName)
87 		{
88 			if ( ( pEntry->nWID == EE_CHAR_FONTHEIGHT ||
89 				   pEntry->nWID == EE_CHAR_FONTHEIGHT_CJK ||
90 				   pEntry->nWID == EE_CHAR_FONTHEIGHT_CTL ) &&
91 				 pEntry->nMemberId == MID_FONTHEIGHT )
92 			{
93 				pEntry->nMemberId |= CONVERT_TWIPS;
94 			}
95 
96 			++pEntry;
97 		}
98 		bTwipsSet = sal_True;
99 	}
100     static SvxItemPropertySet aHdFtPropertySet_Impl( aHdFtPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() );
101 	return &aHdFtPropertySet_Impl;
102 }
103 
104 //------------------------------------------------------------------------
105 
106 SC_SIMPLE_SERVICE_INFO( ScHeaderFooterContentObj, "ScHeaderFooterContentObj", "com.sun.star.sheet.HeaderFooterContent" )
107 SC_SIMPLE_SERVICE_INFO( ScHeaderFooterTextObj, "ScHeaderFooterTextObj", "stardiv.one.Text.Text" )
108 
109 //------------------------------------------------------------------------
110 
111 ScHeaderFooterContentObj::ScHeaderFooterContentObj( const EditTextObject* pLeft,
112 													const EditTextObject* pCenter,
113 													const EditTextObject* pRight ) :
114 	pLeftText	( NULL ),
115 	pCenterText	( NULL ),
116 	pRightText	( NULL )
117 {
118 	if ( pLeft )
119 		pLeftText	= pLeft->Clone();
120 	if ( pCenter )
121 		pCenterText	= pCenter->Clone();
122 	if ( pRight )
123 		pRightText	= pRight->Clone();
124 }
125 
126 ScHeaderFooterContentObj::~ScHeaderFooterContentObj()
127 {
128 	delete pLeftText;
129 	delete pCenterText;
130 	delete pRightText;
131 }
132 
133 void ScHeaderFooterContentObj::AddListener( SfxListener& rListener )
134 {
135 	rListener.StartListening( aBC );
136 }
137 
138 void ScHeaderFooterContentObj::RemoveListener( SfxListener& rListener )
139 {
140 	rListener.EndListening( aBC );
141 }
142 
143 void ScHeaderFooterContentObj::UpdateText( sal_uInt16 nPart, EditEngine& rSource )
144 {
145 	EditTextObject* pNew = rSource.CreateTextObject();
146 	switch (nPart)
147 	{
148 		case SC_HDFT_LEFT:
149 			delete pLeftText;
150 			pLeftText = pNew;
151 			break;
152 		case SC_HDFT_CENTER:
153 			delete pCenterText;
154 			pCenterText = pNew;
155 			break;
156 		default:				// SC_HDFT_RIGHT
157 			delete pRightText;
158 			pRightText = pNew;
159 			break;
160 	}
161 
162 	aBC.Broadcast( ScHeaderFooterChangedHint( nPart ) );
163 }
164 
165 // XHeaderFooterContent
166 
167 uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getLeftText()
168 												throw(uno::RuntimeException)
169 {
170 	ScUnoGuard aGuard;
171 	return new ScHeaderFooterTextObj( *this, SC_HDFT_LEFT );
172 }
173 
174 uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getCenterText()
175 												throw(uno::RuntimeException)
176 {
177 	ScUnoGuard aGuard;
178 	return new ScHeaderFooterTextObj( *this, SC_HDFT_CENTER );
179 }
180 
181 uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getRightText()
182 												throw(uno::RuntimeException)
183 {
184 	ScUnoGuard aGuard;
185 	return new ScHeaderFooterTextObj( *this, SC_HDFT_RIGHT );
186 }
187 
188 // XUnoTunnel
189 
190 sal_Int64 SAL_CALL ScHeaderFooterContentObj::getSomething(
191 				const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
192 {
193 	if ( rId.getLength() == 16 &&
194           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
195 									rId.getConstArray(), 16 ) )
196 	{
197         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
198 	}
199 	return 0;
200 }
201 
202 // static
203 const uno::Sequence<sal_Int8>& ScHeaderFooterContentObj::getUnoTunnelId()
204 {
205 	static uno::Sequence<sal_Int8> * pSeq = 0;
206 	if( !pSeq )
207 	{
208 		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
209 		if( !pSeq )
210 		{
211 			static uno::Sequence< sal_Int8 > aSeq( 16 );
212 			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
213 			pSeq = &aSeq;
214 		}
215 	}
216 	return *pSeq;
217 }
218 
219 // static
220 ScHeaderFooterContentObj* ScHeaderFooterContentObj::getImplementation(
221 								const uno::Reference<sheet::XHeaderFooterContent> xObj )
222 {
223 	ScHeaderFooterContentObj* pRet = NULL;
224 	uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
225 	if (xUT.is())
226         pRet = reinterpret_cast<ScHeaderFooterContentObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
227 	return pRet;
228 }
229 
230 
231 //------------------------------------------------------------------------
232 
233 ScHeaderFooterTextData::ScHeaderFooterTextData( ScHeaderFooterContentObj& rContent,
234 													sal_uInt16 nP ) :
235 	rContentObj( rContent ),
236 	nPart( nP ),
237 	pEditEngine( NULL ),
238 	pForwarder( NULL ),
239 	bDataValid( sal_False ),
240 	bInUpdate( sal_False )
241 {
242 	rContentObj.acquire();				// must not go away
243 	rContentObj.AddListener( *this );
244 }
245 
246 ScHeaderFooterTextData::~ScHeaderFooterTextData()
247 {
248 	ScUnoGuard aGuard;		//	needed for EditEngine dtor
249 
250 	rContentObj.RemoveListener( *this );
251 
252 	delete pForwarder;
253 	delete pEditEngine;
254 
255 	rContentObj.release();
256 }
257 
258 void ScHeaderFooterTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
259 {
260 	if ( rHint.ISA( ScHeaderFooterChangedHint ) )
261 	{
262 		if ( ((const ScHeaderFooterChangedHint&)rHint).GetPart() == nPart )
263 		{
264 			if (!bInUpdate)				// not for own updates
265 				bDataValid = sal_False;		// text has to be fetched again
266 		}
267 	}
268 }
269 
270 SvxTextForwarder* ScHeaderFooterTextData::GetTextForwarder()
271 {
272 	if (!pEditEngine)
273 	{
274 		SfxItemPool* pEnginePool = EditEngine::CreatePool();
275 		pEnginePool->FreezeIdRanges();
276 		ScHeaderEditEngine* pHdrEngine = new ScHeaderEditEngine( pEnginePool, sal_True );
277 
278 		pHdrEngine->EnableUndo( sal_False );
279 		pHdrEngine->SetRefMapMode( MAP_TWIP );
280 
281 		//	default font must be set, independently of document
282 		//	-> use global pool from module
283 
284 		SfxItemSet aDefaults( pHdrEngine->GetEmptyItemSet() );
285 		const ScPatternAttr& rPattern = (const ScPatternAttr&)SC_MOD()->GetPool().GetDefaultItem(ATTR_PATTERN);
286 		rPattern.FillEditItemSet( &aDefaults );
287 		//	FillEditItemSet adjusts font height to 1/100th mm,
288 		//	but for header/footer twips is needed, as in the PatternAttr:
289 		aDefaults.Put( rPattern.GetItem(ATTR_FONT_HEIGHT), EE_CHAR_FONTHEIGHT );
290 		aDefaults.Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CJK );
291 		aDefaults.Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CTL );
292 		pHdrEngine->SetDefaults( aDefaults );
293 
294 		ScHeaderFieldData aData;
295 		ScHeaderFooterTextObj::FillDummyFieldData( aData );
296 		pHdrEngine->SetData( aData );
297 
298 		pEditEngine = pHdrEngine;
299 		pForwarder = new SvxEditEngineForwarder(*pEditEngine);
300 	}
301 
302 	if (bDataValid)
303 		return pForwarder;
304 
305 	const EditTextObject* pData;
306 	if (nPart == SC_HDFT_LEFT)
307 		pData = rContentObj.GetLeftEditObject();
308 	else if (nPart == SC_HDFT_CENTER)
309 		pData = rContentObj.GetCenterEditObject();
310 	else
311 		pData = rContentObj.GetRightEditObject();
312 
313 	if (pData)
314 		pEditEngine->SetText(*pData);
315 
316 	bDataValid = sal_True;
317 	return pForwarder;
318 }
319 
320 void ScHeaderFooterTextData::UpdateData()
321 {
322 	if ( pEditEngine )
323 	{
324 		bInUpdate = sal_True;	// don't reset bDataValid during UpdateText
325 
326 		rContentObj.UpdateText( nPart, *pEditEngine );
327 
328 		bInUpdate = sal_False;
329 	}
330 }
331 
332 //------------------------------------------------------------------------
333 
334 ScHeaderFooterTextObj::ScHeaderFooterTextObj( ScHeaderFooterContentObj& rContent,
335 												sal_uInt16 nP ) :
336 	aTextData( rContent, nP ),
337 	pUnoText( NULL )
338 {
339 	//	ScHeaderFooterTextData acquires rContent
340 	//	pUnoText is created on demand (getString/setString work without it)
341 }
342 
343 void ScHeaderFooterTextObj::CreateUnoText_Impl()
344 {
345 	if ( !pUnoText )
346 	{
347 		//	can't be aggregated because getString/setString is handled here
348 		ScSharedHeaderFooterEditSource aEditSource( &aTextData );
349 		pUnoText = new SvxUnoText( &aEditSource, lcl_GetHdFtPropertySet(), uno::Reference<text::XText>() );
350 		pUnoText->acquire();
351 	}
352 }
353 
354 ScHeaderFooterTextObj::~ScHeaderFooterTextObj()
355 {
356 	if (pUnoText)
357 		pUnoText->release();
358 }
359 
360 const SvxUnoText& ScHeaderFooterTextObj::GetUnoText()
361 {
362 	if (!pUnoText)
363 		CreateUnoText_Impl();
364 	return *pUnoText;
365 }
366 
367 // XText
368 
369 uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursor()
370 													throw(uno::RuntimeException)
371 {
372 	ScUnoGuard aGuard;
373 	return new ScHeaderFooterTextCursor( *this );
374 }
375 
376 uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursorByRange(
377 									const uno::Reference<text::XTextRange>& aTextPosition )
378 													throw(uno::RuntimeException)
379 {
380 	ScUnoGuard aGuard;
381 	if (!pUnoText)
382 		CreateUnoText_Impl();
383 	return pUnoText->createTextCursorByRange(aTextPosition);
384 	//!	wie ScCellObj::createTextCursorByRange, wenn SvxUnoTextRange_getReflection verfuegbar
385 }
386 
387 void ScHeaderFooterTextObj::FillDummyFieldData( ScHeaderFieldData& rData )	// static
388 {
389 	String aDummy(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( "???" )));
390 	rData.aTitle		= aDummy;
391 	rData.aLongDocName	= aDummy;
392 	rData.aShortDocName	= aDummy;
393 	rData.aTabName		= aDummy;
394 	rData.nPageNo		= 1;
395 	rData.nTotalPages	= 99;
396 }
397 
398 rtl::OUString SAL_CALL ScHeaderFooterTextObj::getString() throw(uno::RuntimeException)
399 {
400 	ScUnoGuard aGuard;
401 	rtl::OUString aRet;
402 	const EditTextObject* pData;
403 
404 	sal_uInt16 nPart = aTextData.GetPart();
405 	ScHeaderFooterContentObj& rContentObj = aTextData.GetContentObj();
406 
407 	if (nPart == SC_HDFT_LEFT)
408 		pData = rContentObj.GetLeftEditObject();
409 	else if (nPart == SC_HDFT_CENTER)
410 		pData = rContentObj.GetCenterEditObject();
411 	else
412 		pData = rContentObj.GetRightEditObject();
413 	if (pData)
414 	{
415 		// for pure text, no font info is needed in pool defaults
416 		ScHeaderEditEngine aEditEngine( EditEngine::CreatePool(), sal_True );
417 
418 		ScHeaderFieldData aData;
419 		FillDummyFieldData( aData );
420 		aEditEngine.SetData( aData );
421 
422 		aEditEngine.SetText(*pData);
423 		aRet = ScEditUtil::GetSpaceDelimitedString( aEditEngine );
424 	}
425 	return aRet;
426 }
427 
428 void SAL_CALL ScHeaderFooterTextObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException)
429 {
430 	ScUnoGuard aGuard;
431 	String aString(aText);
432 
433 	// for pure text, no font info is needed in pool defaults
434 	ScHeaderEditEngine aEditEngine( EditEngine::CreatePool(), sal_True );
435 	aEditEngine.SetText( aString );
436 
437 	aTextData.GetContentObj().UpdateText( aTextData.GetPart(), aEditEngine );
438 }
439 
440 void SAL_CALL ScHeaderFooterTextObj::insertString( const uno::Reference<text::XTextRange>& xRange,
441 											const rtl::OUString& aString, sal_Bool bAbsorb )
442 								throw(uno::RuntimeException)
443 {
444 	ScUnoGuard aGuard;
445 	if (!pUnoText)
446 		CreateUnoText_Impl();
447 	pUnoText->insertString( xRange, aString, bAbsorb );
448 }
449 
450 void SAL_CALL ScHeaderFooterTextObj::insertControlCharacter(
451 											const uno::Reference<text::XTextRange>& xRange,
452 											sal_Int16 nControlCharacter, sal_Bool bAbsorb )
453 								throw(lang::IllegalArgumentException, uno::RuntimeException)
454 {
455 	ScUnoGuard aGuard;
456 	if (!pUnoText)
457 		CreateUnoText_Impl();
458 	pUnoText->insertControlCharacter( xRange, nControlCharacter, bAbsorb );
459 }
460 
461 void SAL_CALL ScHeaderFooterTextObj::insertTextContent(
462 											const uno::Reference<text::XTextRange >& xRange,
463 											const uno::Reference<text::XTextContent >& xContent,
464 											sal_Bool bAbsorb )
465 								throw(lang::IllegalArgumentException, uno::RuntimeException)
466 {
467 	ScUnoGuard aGuard;
468 	if ( xContent.is() && xRange.is() )
469 	{
470 		ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent );
471 
472 		SvxUnoTextRangeBase* pTextRange =
473 			ScHeaderFooterTextCursor::getImplementation( xRange );
474 
475 #if 0
476 		if (!pTextRange)
477 			pTextRange = (SvxUnoTextRange*)xRange->getImplementation(
478 											SvxUnoTextRange_getReflection() );
479 		//!	bei SvxUnoTextRange testen, ob in passendem Objekt !!!
480 #endif
481 
482 		if ( pHeaderField && !pHeaderField->IsInserted() && pTextRange )
483 		{
484 			SvxEditSource* pEditSource = pTextRange->GetEditSource();
485 			ESelection aSelection(pTextRange->GetSelection());
486 
487 			if (!bAbsorb)
488 			{
489 				//	don't replace -> append at end
490 				aSelection.Adjust();
491 				aSelection.nStartPara = aSelection.nEndPara;
492 				aSelection.nStartPos  = aSelection.nEndPos;
493 			}
494 
495 			SvxFieldItem aItem(pHeaderField->CreateFieldItem());
496 
497 			SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder();
498 			pForwarder->QuickInsertField( aItem, aSelection );
499 			pEditSource->UpdateData();
500 
501 			//	neue Selektion: ein Zeichen
502 			aSelection.Adjust();
503 			aSelection.nEndPara = aSelection.nStartPara;
504 			aSelection.nEndPos = aSelection.nStartPos + 1;
505 			pHeaderField->InitDoc( &aTextData.GetContentObj(), aTextData.GetPart(), aSelection );
506 
507 			//	#91431# for bAbsorb=sal_False, the new selection must be behind the inserted content
508 			//	(the xml filter relies on this)
509 			if (!bAbsorb)
510 				aSelection.nStartPos = aSelection.nEndPos;
511 
512 			pTextRange->SetSelection( aSelection );
513 
514 			return;
515 		}
516 	}
517 
518 	if (!pUnoText)
519 		CreateUnoText_Impl();
520 	pUnoText->insertTextContent( xRange, xContent, bAbsorb );
521 }
522 
523 void SAL_CALL ScHeaderFooterTextObj::removeTextContent(
524 											const uno::Reference<text::XTextContent>& xContent )
525 								throw(container::NoSuchElementException, uno::RuntimeException)
526 {
527 	ScUnoGuard aGuard;
528 	if ( xContent.is() )
529 	{
530 		ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent );
531 		if ( pHeaderField && pHeaderField->IsInserted() )
532 		{
533 			//!	Testen, ob das Feld in dieser Zelle ist
534 			pHeaderField->DeleteField();
535 			return;
536 		}
537 	}
538 	if (!pUnoText)
539 		CreateUnoText_Impl();
540 	pUnoText->removeTextContent( xContent );
541 }
542 
543 uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextObj::getText() throw(uno::RuntimeException)
544 {
545 	ScUnoGuard aGuard;
546 	if (!pUnoText)
547 		CreateUnoText_Impl();
548 	return pUnoText->getText();
549 }
550 
551 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getStart() throw(uno::RuntimeException)
552 {
553 	ScUnoGuard aGuard;
554 	if (!pUnoText)
555 		CreateUnoText_Impl();
556 	return pUnoText->getStart();
557 }
558 
559 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getEnd() throw(uno::RuntimeException)
560 {
561 	ScUnoGuard aGuard;
562 	if (!pUnoText)
563 		CreateUnoText_Impl();
564 	return pUnoText->getEnd();
565 }
566 
567 // XTextFieldsSupplier
568 
569 uno::Reference<container::XEnumerationAccess> SAL_CALL ScHeaderFooterTextObj::getTextFields()
570 												throw(uno::RuntimeException)
571 {
572 	ScUnoGuard aGuard;
573 	// all fields
574 	return new ScHeaderFieldsObj( &aTextData.GetContentObj(), aTextData.GetPart(), SC_SERVICE_INVALID );
575 }
576 
577 uno::Reference<container::XNameAccess> SAL_CALL ScHeaderFooterTextObj::getTextFieldMasters()
578 												throw(uno::RuntimeException)
579 {
580 	//	sowas gibts nicht im Calc (?)
581 	return NULL;
582 }
583 
584 // XTextRangeMover
585 
586 void SAL_CALL ScHeaderFooterTextObj::moveTextRange(
587 										const uno::Reference<text::XTextRange>& xRange,
588 										sal_Int16 nParagraphs )
589 										throw(uno::RuntimeException)
590 {
591 	ScUnoGuard aGuard;
592 	if (!pUnoText)
593 		CreateUnoText_Impl();
594 	pUnoText->moveTextRange( xRange, nParagraphs );
595 }
596 
597 // XEnumerationAccess
598 
599 uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFooterTextObj::createEnumeration()
600 												throw(uno::RuntimeException)
601 {
602 	ScUnoGuard aGuard;
603 	if (!pUnoText)
604 		CreateUnoText_Impl();
605 	return pUnoText->createEnumeration();
606 }
607 
608 // XElementAccess
609 
610 uno::Type SAL_CALL ScHeaderFooterTextObj::getElementType() throw(uno::RuntimeException)
611 {
612 	ScUnoGuard aGuard;
613 	if (!pUnoText)
614 		CreateUnoText_Impl();
615 	return pUnoText->getElementType();
616 }
617 
618 sal_Bool SAL_CALL ScHeaderFooterTextObj::hasElements() throw(uno::RuntimeException)
619 {
620 	ScUnoGuard aGuard;
621 	if (!pUnoText)
622 		CreateUnoText_Impl();
623 	return pUnoText->hasElements();
624 }
625 
626 //------------------------------------------------------------------------
627 
628 ScCellTextCursor::ScCellTextCursor(const ScCellTextCursor& rOther) :
629 	SvxUnoTextCursor( rOther ),
630 	rTextObj( rOther.rTextObj )
631 {
632 	rTextObj.acquire();
633 }
634 
635 ScCellTextCursor::ScCellTextCursor(ScCellObj& rText) :
636 	SvxUnoTextCursor( rText.GetUnoText() ),
637 	rTextObj( rText )
638 {
639 	rTextObj.acquire();
640 }
641 
642 ScCellTextCursor::~ScCellTextCursor() throw()
643 {
644 	rTextObj.release();
645 }
646 
647 // SvxUnoTextCursor methods reimplemented here to return the right objects:
648 
649 uno::Reference<text::XText> SAL_CALL ScCellTextCursor::getText() throw(uno::RuntimeException)
650 {
651 	ScUnoGuard aGuard;
652 	return &rTextObj;
653 }
654 
655 uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getStart() throw(uno::RuntimeException)
656 {
657 	ScUnoGuard aGuard;
658 
659 	//!	use other object for range than cursor?
660 
661     ScCellTextCursor* pNew = new ScCellTextCursor( *this );
662 	uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
663 
664 	ESelection aNewSel(GetSelection());
665 	aNewSel.nEndPara = aNewSel.nStartPara;
666 	aNewSel.nEndPos  = aNewSel.nStartPos;
667 	pNew->SetSelection( aNewSel );
668 
669 	return xRange;
670 }
671 
672 uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getEnd() throw(uno::RuntimeException)
673 {
674 	ScUnoGuard aGuard;
675 
676 	//!	use other object for range than cursor?
677 
678     ScCellTextCursor* pNew = new ScCellTextCursor( *this );
679     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
680 
681 	ESelection aNewSel(GetSelection());
682 	aNewSel.nStartPara = aNewSel.nEndPara;
683 	aNewSel.nStartPos  = aNewSel.nEndPos;
684 	pNew->SetSelection( aNewSel );
685 
686 	return xRange;
687 }
688 
689 // XUnoTunnel
690 
691 sal_Int64 SAL_CALL ScCellTextCursor::getSomething(
692 				const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
693 {
694 	if ( rId.getLength() == 16 &&
695           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
696 									rId.getConstArray(), 16 ) )
697 	{
698         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
699 	}
700 	return SvxUnoTextCursor::getSomething( rId );
701 }
702 
703 // static
704 const uno::Sequence<sal_Int8>& ScCellTextCursor::getUnoTunnelId()
705 {
706 	static uno::Sequence<sal_Int8> * pSeq = 0;
707 	if( !pSeq )
708 	{
709 		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
710 		if( !pSeq )
711 		{
712 			static uno::Sequence< sal_Int8 > aSeq( 16 );
713 			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
714 			pSeq = &aSeq;
715 		}
716 	}
717 	return *pSeq;
718 }
719 
720 // static
721 ScCellTextCursor* ScCellTextCursor::getImplementation( const uno::Reference<uno::XInterface> xObj )
722 {
723 	ScCellTextCursor* pRet = NULL;
724 	uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
725 	if (xUT.is())
726         pRet = reinterpret_cast<ScCellTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
727 	return pRet;
728 }
729 
730 //------------------------------------------------------------------------
731 
732 ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(const ScHeaderFooterTextCursor& rOther) :
733 	SvxUnoTextCursor( rOther ),
734 	rTextObj( rOther.rTextObj )
735 {
736 	rTextObj.acquire();
737 }
738 
739 ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(ScHeaderFooterTextObj& rText) :
740 	SvxUnoTextCursor( rText.GetUnoText() ),
741 	rTextObj( rText )
742 {
743 	rTextObj.acquire();
744 }
745 
746 ScHeaderFooterTextCursor::~ScHeaderFooterTextCursor() throw()
747 {
748 	rTextObj.release();
749 }
750 
751 // SvxUnoTextCursor methods reimplemented here to return the right objects:
752 
753 uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextCursor::getText() throw(uno::RuntimeException)
754 {
755 	ScUnoGuard aGuard;
756 	return &rTextObj;
757 }
758 
759 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getStart() throw(uno::RuntimeException)
760 {
761 	ScUnoGuard aGuard;
762 
763 	//!	use other object for range than cursor?
764 
765     ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this );
766     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
767 
768 	ESelection aNewSel(GetSelection());
769 	aNewSel.nEndPara = aNewSel.nStartPara;
770 	aNewSel.nEndPos  = aNewSel.nStartPos;
771 	pNew->SetSelection( aNewSel );
772 
773 	return xRange;
774 }
775 
776 uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getEnd() throw(uno::RuntimeException)
777 {
778 	ScUnoGuard aGuard;
779 
780 	//!	use other object for range than cursor?
781 
782     ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this );
783 	uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
784 
785 	ESelection aNewSel(GetSelection());
786 	aNewSel.nStartPara = aNewSel.nEndPara;
787 	aNewSel.nStartPos  = aNewSel.nEndPos;
788 	pNew->SetSelection( aNewSel );
789 
790 	return xRange;
791 }
792 
793 // XUnoTunnel
794 
795 sal_Int64 SAL_CALL ScHeaderFooterTextCursor::getSomething(
796 				const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
797 {
798 	if ( rId.getLength() == 16 &&
799           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
800 									rId.getConstArray(), 16 ) )
801 	{
802         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
803 	}
804 	return SvxUnoTextCursor::getSomething( rId );
805 }
806 
807 // static
808 const uno::Sequence<sal_Int8>& ScHeaderFooterTextCursor::getUnoTunnelId()
809 {
810 	static uno::Sequence<sal_Int8> * pSeq = 0;
811 	if( !pSeq )
812 	{
813 		osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
814 		if( !pSeq )
815 		{
816 			static uno::Sequence< sal_Int8 > aSeq( 16 );
817 			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
818 			pSeq = &aSeq;
819 		}
820 	}
821 	return *pSeq;
822 }
823 
824 // static
825 ScHeaderFooterTextCursor* ScHeaderFooterTextCursor::getImplementation(
826 								const uno::Reference<uno::XInterface> xObj )
827 {
828 	ScHeaderFooterTextCursor* pRet = NULL;
829 	uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
830 	if (xUT.is())
831         pRet = reinterpret_cast<ScHeaderFooterTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
832 	return pRet;
833 }
834 
835 //------------------------------------------------------------------------
836 
837 ScDrawTextCursor::ScDrawTextCursor(const ScDrawTextCursor& rOther) :
838 	SvxUnoTextCursor( rOther ),
839 	xParentText( rOther.xParentText )
840 {
841 }
842 
843 ScDrawTextCursor::ScDrawTextCursor( const uno::Reference<text::XText>& xParent,
844 									const SvxUnoTextBase& rText ) :
845 	SvxUnoTextCursor( rText ),
846 	xParentText( xParent )
847 
848 {
849 }
850 
851 ScDrawTextCursor::~ScDrawTextCursor() throw()
852 {
853 }
854 
855 // SvxUnoTextCursor methods reimplemented here to return the right objects:
856 
857 uno::Reference<text::XText> SAL_CALL ScDrawTextCursor::getText() throw(uno::RuntimeException)
858 {
859 	ScUnoGuard aGuard;
860 	return xParentText;
861 }
862 
863 uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getStart() throw(uno::RuntimeException)
864 {
865 	ScUnoGuard aGuard;
866 
867 	//!	use other object for range than cursor?
868 
869 	ScDrawTextCursor* pNew = new ScDrawTextCursor( *this );
870     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
871 
872 	ESelection aNewSel(GetSelection());
873 	aNewSel.nEndPara = aNewSel.nStartPara;
874 	aNewSel.nEndPos  = aNewSel.nStartPos;
875 	pNew->SetSelection( aNewSel );
876 
877 	return xRange;
878 }
879 
880 uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getEnd() throw(uno::RuntimeException)
881 {
882 	ScUnoGuard aGuard;
883 
884 	//!	use other object for range than cursor?
885 
886 	ScDrawTextCursor* pNew = new ScDrawTextCursor( *this );
887     uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) );
888 
889 	ESelection aNewSel(GetSelection());
890 	aNewSel.nStartPara = aNewSel.nEndPara;
891 	aNewSel.nStartPos  = aNewSel.nEndPos;
892 	pNew->SetSelection( aNewSel );
893 
894 	return xRange;
895 }
896 
897 // XUnoTunnel
898 
899 sal_Int64 SAL_CALL ScDrawTextCursor::getSomething(
900                 const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException)
901 {
902     if ( rId.getLength() == 16 &&
903           0 == rtl_compareMemory( getUnoTunnelId().getConstArray(),
904                                     rId.getConstArray(), 16 ) )
905     {
906         return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this));
907     }
908     return SvxUnoTextCursor::getSomething( rId );
909 }
910 
911 // static
912 const uno::Sequence<sal_Int8>& ScDrawTextCursor::getUnoTunnelId()
913 {
914     static uno::Sequence<sal_Int8> * pSeq = 0;
915     if( !pSeq )
916     {
917         osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() );
918         if( !pSeq )
919         {
920             static uno::Sequence< sal_Int8 > aSeq( 16 );
921             rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
922             pSeq = &aSeq;
923         }
924     }
925     return *pSeq;
926 }
927 
928 // static
929 ScDrawTextCursor* ScDrawTextCursor::getImplementation( const uno::Reference<uno::XInterface> xObj )
930 {
931     ScDrawTextCursor* pRet = NULL;
932     uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY );
933     if (xUT.is())
934         pRet = reinterpret_cast<ScDrawTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId())));
935     return pRet;
936 }
937 
938 //------------------------------------------------------------------------
939 
940 ScSimpleEditSourceHelper::ScSimpleEditSourceHelper()
941 {
942 	SfxItemPool* pEnginePool = EditEngine::CreatePool();
943 	pEnginePool->SetDefaultMetric( SFX_MAPUNIT_100TH_MM );
944 	pEnginePool->FreezeIdRanges();
945 
946 	pEditEngine = new ScFieldEditEngine( pEnginePool, NULL, sal_True );		// TRUE: become owner of pool
947 	pForwarder = new SvxEditEngineForwarder( *pEditEngine );
948 	pOriginalSource = new ScSimpleEditSource( pForwarder );
949 }
950 
951 ScSimpleEditSourceHelper::~ScSimpleEditSourceHelper()
952 {
953 	ScUnoGuard aGuard;		//	needed for EditEngine dtor
954 
955 	delete pOriginalSource;
956 	delete pForwarder;
957 	delete pEditEngine;
958 }
959 
960 ScEditEngineTextObj::ScEditEngineTextObj() :
961 	SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() )
962 {
963 }
964 
965 ScEditEngineTextObj::~ScEditEngineTextObj() throw()
966 {
967 }
968 
969 void ScEditEngineTextObj::SetText( const EditTextObject& rTextObject )
970 {
971 	GetEditEngine()->SetText( rTextObject );
972 
973 	ESelection aSel;
974 	::GetSelection( aSel, GetEditSource()->GetTextForwarder() );
975 	SetSelection( aSel );
976 }
977 
978 EditTextObject* ScEditEngineTextObj::CreateTextObject()
979 {
980 	return GetEditEngine()->CreateTextObject();
981 }
982 
983 //------------------------------------------------------------------------
984 
985 ScCellTextData::ScCellTextData(ScDocShell* pDocSh, const ScAddress& rP) :
986 	pDocShell( pDocSh ),
987 	aCellPos( rP ),
988 	pEditEngine( NULL ),
989 	pForwarder( NULL ),
990 	pOriginalSource( NULL ),
991 	bDataValid( sal_False ),
992 	bInUpdate( sal_False ),
993 	bDirty( sal_False ),
994 	bDoUpdate( sal_True )
995 {
996 	if (pDocShell)
997 		pDocShell->GetDocument()->AddUnoObject(*this);
998 }
999 
1000 ScCellTextData::~ScCellTextData()
1001 {
1002 	ScUnoGuard aGuard;		//	needed for EditEngine dtor
1003 
1004 	if (pDocShell)
1005 	{
1006 		pDocShell->GetDocument()->RemoveUnoObject(*this);
1007 		pDocShell->GetDocument()->DisposeFieldEditEngine(pEditEngine);
1008 	}
1009 	else
1010 		delete pEditEngine;
1011 
1012 	delete pForwarder;
1013 
1014 	delete pOriginalSource;
1015 }
1016 
1017 ScSharedCellEditSource* ScCellTextData::GetOriginalSource()
1018 {
1019 	if (!pOriginalSource)
1020 		pOriginalSource = new ScSharedCellEditSource( this );
1021 	return pOriginalSource;
1022 }
1023 
1024 void ScCellTextData::GetCellText(const ScAddress& rCellPos, String& rText)
1025 {
1026 	if (pDocShell)
1027 	{
1028 		ScDocument* pDoc = pDocShell->GetDocument();
1029 		pDoc->GetInputString( rCellPos.Col(), rCellPos.Row(), rCellPos.Tab(), rText );
1030     }
1031 }
1032 
1033 SvxTextForwarder* ScCellTextData::GetTextForwarder()
1034 {
1035 	if (!pEditEngine)
1036 	{
1037 		if ( pDocShell )
1038 		{
1039 			ScDocument* pDoc = pDocShell->GetDocument();
1040 			pEditEngine = pDoc->CreateFieldEditEngine();
1041 		}
1042 		else
1043 		{
1044 			SfxItemPool* pEnginePool = EditEngine::CreatePool();
1045 			pEnginePool->FreezeIdRanges();
1046 			pEditEngine = new ScFieldEditEngine( pEnginePool, NULL, sal_True );
1047 		}
1048 		//	currently, GetPortions doesn't work if UpdateMode is sal_False,
1049 		//	this will be fixed (in EditEngine) by src600
1050 //		pEditEngine->SetUpdateMode( sal_False );
1051 		pEditEngine->EnableUndo( sal_False );
1052 		if (pDocShell)
1053 			pEditEngine->SetRefDevice(pDocShell->GetRefDevice());
1054 		else
1055 			pEditEngine->SetRefMapMode( MAP_100TH_MM );
1056 		pForwarder = new SvxEditEngineForwarder(*pEditEngine);
1057 	}
1058 
1059 	if (bDataValid)
1060 		return pForwarder;
1061 
1062 	String aText;
1063 
1064 	if (pDocShell)
1065 	{
1066 		ScDocument* pDoc = pDocShell->GetDocument();
1067 
1068 		SfxItemSet aDefaults( pEditEngine->GetEmptyItemSet() );
1069         if( const ScPatternAttr* pPattern =
1070                 pDoc->GetPattern( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) )
1071         {
1072             pPattern->FillEditItemSet( &aDefaults );
1073             pPattern->FillEditParaItems( &aDefaults );  // including alignment etc. (for reading)
1074         }
1075 
1076 		const ScBaseCell* pCell = pDoc->GetCell( aCellPos );
1077 		if ( pCell && pCell->GetCellType() == CELLTYPE_EDIT )
1078 			pEditEngine->SetTextNewDefaults( *((const ScEditCell*)pCell)->GetData(), aDefaults );
1079 		else
1080 		{
1081 			GetCellText( aCellPos, aText );
1082 			if (aText.Len())
1083 				pEditEngine->SetTextNewDefaults( aText, aDefaults );
1084 			else
1085 				pEditEngine->SetDefaults(aDefaults);
1086 		}
1087 	}
1088 
1089 	bDataValid = sal_True;
1090 	return pForwarder;
1091 }
1092 
1093 void ScCellTextData::UpdateData()
1094 {
1095 	if ( bDoUpdate )
1096 	{
1097 		DBG_ASSERT(pEditEngine != NULL, "no EditEngine for UpdateData()");
1098 		if ( pDocShell && pEditEngine )
1099 		{
1100 			//	during the own UpdateData call, bDataValid must not be reset,
1101 			//	or things like attributes after the text would be lost
1102 			//	(are not stored in the cell)
1103 
1104 			bInUpdate = sal_True;	// prevents bDataValid from being reset
1105 
1106 			ScDocFunc aFunc(*pDocShell);
1107 			aFunc.PutData( aCellPos, *pEditEngine, sal_False, sal_True );	// always as text
1108 
1109 			bInUpdate = sal_False;
1110 			bDirty = sal_False;
1111 		}
1112 	}
1113 	else
1114 		bDirty = sal_True;
1115 }
1116 
1117 void ScCellTextData::Notify( SfxBroadcaster&, const SfxHint& rHint )
1118 {
1119 	if ( rHint.ISA( ScUpdateRefHint ) )
1120 	{
1121 //        const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint;
1122 
1123 		//!	Ref-Update
1124 	}
1125 	else if ( rHint.ISA( SfxSimpleHint ) )
1126 	{
1127 		sal_uLong nId = ((const SfxSimpleHint&)rHint).GetId();
1128 		if ( nId == SFX_HINT_DYING )
1129 		{
1130 			pDocShell = NULL;						// invalid now
1131 
1132 			DELETEZ( pForwarder );
1133 			DELETEZ( pEditEngine );		// EditEngine uses document's pool
1134 		}
1135 		else if ( nId == SFX_HINT_DATACHANGED )
1136 		{
1137 			if (!bInUpdate)							// not for own UpdateData calls
1138 				bDataValid = sal_False;					// text has to be read from the cell again
1139 		}
1140 	}
1141 }
1142 
1143 ScCellTextObj::ScCellTextObj(ScDocShell* pDocSh, const ScAddress& rP) :
1144 	ScCellTextData( pDocSh, rP ),
1145 	SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() )
1146 {
1147 }
1148 
1149 ScCellTextObj::~ScCellTextObj() throw()
1150 {
1151 }
1152 
1153