xref: /trunk/main/editeng/source/uno/unofored.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_editeng.hxx"
30 
31 #include <algorithm>
32 #include <editeng/eeitem.hxx>
33 #include <com/sun/star/i18n/WordType.hpp>
34 
35 #include <svl/itemset.hxx>
36 #include <editeng/editeng.hxx>
37 #include <editeng/editview.hxx>
38 #include <editeng/unoedhlp.hxx>
39 #include <editeng/editdata.hxx>
40 #include <editeng/outliner.hxx>
41 #include <editeng/editobj.hxx>		// nur fuer die GetText-Kruecke
42 
43 #include <editeng/unofored.hxx>
44 
45 using namespace ::com::sun::star;
46 
47 //------------------------------------------------------------------------
48 
49 SvxEditEngineForwarder::SvxEditEngineForwarder( EditEngine& rEngine ) :
50 	rEditEngine( rEngine )
51 {
52 }
53 
54 SvxEditEngineForwarder::~SvxEditEngineForwarder()
55 {
56 	//	die EditEngine muss ggf. von aussen geloescht werden
57 }
58 
59 sal_uInt16 SvxEditEngineForwarder::GetParagraphCount() const
60 {
61 	return rEditEngine.GetParagraphCount();
62 }
63 
64 sal_uInt16 SvxEditEngineForwarder::GetTextLen( sal_uInt16 nParagraph ) const
65 {
66 	return rEditEngine.GetTextLen( nParagraph );
67 }
68 
69 String SvxEditEngineForwarder::GetText( const ESelection& rSel ) const
70 {
71 	String aRet = rEditEngine.GetText( rSel, LINEEND_LF );
72 	aRet.ConvertLineEnd();
73 	return aRet;
74 }
75 
76 SfxItemSet SvxEditEngineForwarder::GetAttribs( const ESelection& rSel, sal_Bool bOnlyHardAttrib ) const
77 {
78 	if( rSel.nStartPara == rSel.nEndPara )
79 	{
80 		sal_uInt8 nFlags = 0;
81 		switch( bOnlyHardAttrib )
82 		{
83 		case EditEngineAttribs_All:
84 			nFlags = GETATTRIBS_ALL;
85 			break;
86 		case EditEngineAttribs_HardAndPara:
87 			nFlags = GETATTRIBS_PARAATTRIBS|GETATTRIBS_CHARATTRIBS;
88 			break;
89 		case EditEngineAttribs_OnlyHard:
90 			nFlags = GETATTRIBS_CHARATTRIBS;
91 			break;
92 		default:
93 			DBG_ERROR("unknown flags for SvxOutlinerForwarder::GetAttribs");
94 		}
95 
96 		return rEditEngine.GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags );
97 	}
98 	else
99 	{
100 		return rEditEngine.GetAttribs( rSel, bOnlyHardAttrib );
101 	}
102 }
103 
104 SfxItemSet SvxEditEngineForwarder::GetParaAttribs( sal_uInt16 nPara ) const
105 {
106 	SfxItemSet aSet( rEditEngine.GetParaAttribs( nPara ) );
107 
108 	sal_uInt16 nWhich = EE_PARA_START;
109 	while( nWhich <= EE_PARA_END )
110 	{
111 		if( aSet.GetItemState( nWhich, sal_True ) != SFX_ITEM_ON )
112 		{
113 			if( rEditEngine.HasParaAttrib( nPara, nWhich ) )
114 				aSet.Put( rEditEngine.GetParaAttrib( nPara, nWhich ) );
115 		}
116 		nWhich++;
117 	}
118 
119 	return aSet;
120 }
121 
122 void SvxEditEngineForwarder::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet )
123 {
124 	rEditEngine.SetParaAttribs( nPara, rSet );
125 }
126 
127 void SvxEditEngineForwarder::RemoveAttribs( const ESelection& rSelection, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich )
128 {
129     rEditEngine.RemoveAttribs( rSelection, bRemoveParaAttribs, nWhich );
130 }
131 
132 SfxItemPool* SvxEditEngineForwarder::GetPool() const
133 {
134 	return rEditEngine.GetEmptyItemSet().GetPool();
135 }
136 
137 void SvxEditEngineForwarder::GetPortions( sal_uInt16 nPara, SvUShorts& rList ) const
138 {
139 	rEditEngine.GetPortions( nPara, rList );
140 }
141 
142 void SvxEditEngineForwarder::QuickInsertText( const String& rText, const ESelection& rSel )
143 {
144 	rEditEngine.QuickInsertText( rText, rSel );
145 }
146 
147 void SvxEditEngineForwarder::QuickInsertLineBreak( const ESelection& rSel )
148 {
149 	rEditEngine.QuickInsertLineBreak( rSel );
150 }
151 
152 void SvxEditEngineForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
153 {
154 	rEditEngine.QuickInsertField( rFld, rSel );
155 }
156 
157 void SvxEditEngineForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
158 {
159 	rEditEngine.QuickSetAttribs( rSet, rSel );
160 }
161 
162 sal_Bool SvxEditEngineForwarder::IsValid() const
163 {
164     // cannot reliably query EditEngine state
165     // while in the middle of an update
166     return rEditEngine.GetUpdateMode();
167 }
168 
169 XubString SvxEditEngineForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_uInt16 nPara, sal_uInt16 nPos, Color*& rpTxtColor, Color*& rpFldColor )
170 {
171 	return rEditEngine.CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor );
172 }
173 
174 void SvxEditEngineForwarder::FieldClicked( const SvxFieldItem& rField, sal_uInt16 nPara, xub_StrLen nPos )
175 {
176     rEditEngine.FieldClicked( rField, nPara, nPos );
177 }
178 
179 sal_uInt16 GetSvxEditEngineItemState( EditEngine& rEditEngine, const ESelection& rSel, sal_uInt16 nWhich )
180 {
181 	EECharAttribArray aAttribs;
182 
183 	const SfxPoolItem*	pLastItem = NULL;
184 
185 	SfxItemState eState = SFX_ITEM_DEFAULT;
186 
187 	// check all paragraphs inside the selection
188 	for( sal_uInt16 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ )
189 	{
190 		SfxItemState eParaState = SFX_ITEM_DEFAULT;
191 
192 		// calculate start and endpos for this paragraph
193 		sal_uInt16 nPos = 0;
194 		if( rSel.nStartPara == nPara )
195 			nPos = rSel.nStartPos;
196 
197 		sal_uInt16 nEndPos = rSel.nEndPos;
198 		if( rSel.nEndPara != nPara )
199 			nEndPos = rEditEngine.GetTextLen( nPara );
200 
201 
202 		// get list of char attribs
203 		rEditEngine.GetCharAttribs( nPara, aAttribs );
204 
205 		sal_Bool bEmpty = sal_True;		// we found no item inside the selektion of this paragraph
206 		sal_Bool bGaps  = sal_False;	// we found items but theire gaps between them
207 		sal_uInt16 nLastEnd = nPos;
208 
209 		const SfxPoolItem* pParaItem = NULL;
210 
211 		for( sal_uInt16 nAttrib = 0; nAttrib < aAttribs.Count(); nAttrib++ )
212 		{
213 			struct EECharAttrib aAttrib = aAttribs.GetObject( nAttrib );
214 			DBG_ASSERT( aAttrib.pAttr, "GetCharAttribs gives corrupt data" );
215 
216 			const sal_Bool bEmptyPortion = aAttrib.nStart == aAttrib.nEnd;
217 			if( (!bEmptyPortion && (aAttrib.nStart >= nEndPos)) || (bEmptyPortion && (aAttrib.nStart > nEndPos)) )
218 				break;	// break if we are already behind our selektion
219 
220 			if( (!bEmptyPortion && (aAttrib.nEnd <= nPos)) || (bEmptyPortion && (aAttrib.nEnd < nPos)) )
221 				continue;	// or if the attribute ends before our selektion
222 
223 			if( aAttrib.pAttr->Which() != nWhich )
224 				continue; // skip if is not the searched item
225 
226 			// if we already found an item
227 			if( pParaItem )
228 			{
229 				// ... and its different to this one than the state is dont care
230 				if( *pParaItem != *aAttrib.pAttr )
231 					return SFX_ITEM_DONTCARE;
232 			}
233 			else
234 			{
235 				pParaItem = aAttrib.pAttr;
236 			}
237 
238 			if( bEmpty )
239 				bEmpty = sal_False;
240 
241 			if( !bGaps && aAttrib.nStart > nLastEnd )
242 				bGaps = sal_True;
243 
244 			nLastEnd = aAttrib.nEnd;
245 		}
246 
247 		if( !bEmpty && !bGaps && nLastEnd < ( nEndPos - 1 ) )
248 			bGaps = sal_True;
249 /*
250 		// since we have no portion with our item or if there were gaps
251 		if( bEmpty || bGaps )
252 		{
253 			// we need to check the paragraph item
254 			const SfxItemSet& rParaSet = rEditEngine.GetParaAttribs( nPara );
255 			if( rParaSet.GetItemState( nWhich ) == SFX_ITEM_SET )
256 			{
257 				eState = SFX_ITEM_SET;
258 				// get item from the paragraph
259 				const SfxPoolItem* pTempItem = rParaSet.GetItem( nWhich );
260 				if( pParaItem )
261 				{
262 					if( *pParaItem != *pTempItem )
263 						return SFX_ITEM_DONTCARE;
264 				}
265 				else
266 				{
267 					pParaItem = pTempItem;
268 				}
269 
270 				// set if theres no last item or if its the same
271 				eParaState = SFX_ITEM_SET;
272 			}
273 			else if( bEmpty )
274 			{
275 				eParaState = SFX_ITEM_DEFAULT;
276 			}
277 			else if( bGaps )
278 			{
279 				// gaps and item not set in paragraph, thats a dont care
280 				return SFX_ITEM_DONTCARE;
281 			}
282 		}
283 		else
284 		{
285 			eParaState = SFX_ITEM_SET;
286 		}
287 */
288 		if( bEmpty )
289 			eParaState = SFX_ITEM_DEFAULT;
290 		else if( bGaps )
291 			eParaState = SFX_ITEM_DONTCARE;
292 		else
293 			eParaState = SFX_ITEM_SET;
294 
295 		// if we already found an item check if we found the same
296 		if( pLastItem )
297 		{
298 			if( (pParaItem == NULL) || (*pLastItem != *pParaItem) )
299 				return SFX_ITEM_DONTCARE;
300 		}
301 		else
302 		{
303 			pLastItem = pParaItem;
304 			eState = eParaState;
305 		}
306 	}
307 
308 	return eState;
309 }
310 
311 sal_uInt16 SvxEditEngineForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const
312 {
313 	return GetSvxEditEngineItemState( rEditEngine, rSel, nWhich );
314 }
315 
316 sal_uInt16 SvxEditEngineForwarder::GetItemState( sal_uInt16 nPara, sal_uInt16 nWhich ) const
317 {
318 	const SfxItemSet& rSet = rEditEngine.GetParaAttribs( nPara );
319 	return rSet.GetItemState( nWhich );
320 }
321 
322 LanguageType SvxEditEngineForwarder::GetLanguage( sal_uInt16 nPara, sal_uInt16 nIndex ) const
323 {
324     return rEditEngine.GetLanguage(nPara, nIndex);
325 }
326 
327 sal_uInt16 SvxEditEngineForwarder::GetFieldCount( sal_uInt16 nPara ) const
328 {
329     return rEditEngine.GetFieldCount(nPara);
330 }
331 
332 EFieldInfo SvxEditEngineForwarder::GetFieldInfo( sal_uInt16 nPara, sal_uInt16 nField ) const
333 {
334     return rEditEngine.GetFieldInfo( nPara, nField );
335 }
336 
337 EBulletInfo SvxEditEngineForwarder::GetBulletInfo( sal_uInt16 ) const
338 {
339     return EBulletInfo();
340 }
341 
342 Rectangle SvxEditEngineForwarder::GetCharBounds( sal_uInt16 nPara, sal_uInt16 nIndex ) const
343 {
344     // #101701#
345     // EditEngine's 'internal' methods like GetCharacterBounds()
346     // don't rotate for vertical text.
347     Size aSize( rEditEngine.CalcTextWidth(), rEditEngine.GetTextHeight() );
348     ::std::swap( aSize.Width(), aSize.Height() );
349     bool bIsVertical( rEditEngine.IsVertical() == sal_True );
350 
351     // #108900# Handle virtual position one-past-the end of the string
352     if( nIndex >= rEditEngine.GetTextLen(nPara) )
353     {
354         Rectangle aLast;
355 
356         if( nIndex )
357         {
358             // use last character, if possible
359             aLast = rEditEngine.GetCharacterBounds( EPosition(nPara, nIndex-1) );
360 
361             // move at end of this last character, make one pixel wide
362             aLast.Move( aLast.Right() - aLast.Left(), 0 );
363             aLast.SetSize( Size(1, aLast.GetHeight()) );
364 
365             // take care for CTL
366             aLast = SvxEditSourceHelper::EEToUserSpace( aLast, aSize, bIsVertical );
367         }
368         else
369         {
370             // #109864# Bounds must lie within the paragraph
371             aLast = GetParaBounds( nPara );
372 
373             // #109151# Don't use paragraph height, but line height
374             // instead. aLast is already CTL-correct
375             if( bIsVertical)
376                 aLast.SetSize( Size( rEditEngine.GetLineHeight(nPara,0), 1 ) );
377             else
378                 aLast.SetSize( Size( 1, rEditEngine.GetLineHeight(nPara,0) ) );
379         }
380 
381         return aLast;
382     }
383     else
384     {
385         return SvxEditSourceHelper::EEToUserSpace( rEditEngine.GetCharacterBounds( EPosition(nPara, nIndex) ),
386                                                    aSize, bIsVertical );
387     }
388 }
389 
390 Rectangle SvxEditEngineForwarder::GetParaBounds( sal_uInt16 nPara ) const
391 {
392     const Point aPnt = rEditEngine.GetDocPosTopLeft( nPara );
393     sal_uLong nWidth;
394     sal_uLong nHeight;
395     sal_uLong nTextWidth;
396 
397     if( rEditEngine.IsVertical() )
398     {
399         // #101701#
400         // Hargl. EditEngine's 'external' methods return the rotated
401         // dimensions, 'internal' methods like GetTextHeight( n )
402         // don't rotate.
403         nWidth = rEditEngine.GetTextHeight( nPara );
404         nHeight = rEditEngine.GetTextHeight();
405         nTextWidth = rEditEngine.GetTextHeight();
406 
407         return Rectangle( nTextWidth - aPnt.Y() - nWidth, 0, nTextWidth - aPnt.Y(), nHeight );
408     }
409     else
410     {
411         nWidth = rEditEngine.CalcTextWidth();
412         nHeight = rEditEngine.GetTextHeight( nPara );
413 
414         return Rectangle( 0, aPnt.Y(), nWidth, aPnt.Y() + nHeight );
415     }
416 }
417 
418 MapMode SvxEditEngineForwarder::GetMapMode() const
419 {
420     return rEditEngine.GetRefMapMode();
421 }
422 
423 OutputDevice* SvxEditEngineForwarder::GetRefDevice() const
424 {
425     return rEditEngine.GetRefDevice();
426 }
427 
428 sal_Bool SvxEditEngineForwarder::GetIndexAtPoint( const Point& rPos, sal_uInt16& nPara, sal_uInt16& nIndex ) const
429 {
430     // #101701#
431     Size aSize( rEditEngine.CalcTextWidth(), rEditEngine.GetTextHeight() );
432     ::std::swap( aSize.Width(), aSize.Height() );
433     Point aEEPos( SvxEditSourceHelper::UserSpaceToEE( rPos,
434                                                       aSize,
435                                                       rEditEngine.IsVertical() == sal_True ));
436 
437     EPosition aDocPos = rEditEngine.FindDocPosition( aEEPos );
438 
439     nPara = aDocPos.nPara;
440     nIndex = aDocPos.nIndex;
441 
442     return sal_True;
443 }
444 
445 sal_Bool SvxEditEngineForwarder::GetWordIndices( sal_uInt16 nPara, sal_uInt16 nIndex, sal_uInt16& nStart, sal_uInt16& nEnd ) const
446 {
447     ESelection aRes = rEditEngine.GetWord( ESelection(nPara, nIndex, nPara, nIndex), com::sun::star::i18n::WordType::DICTIONARY_WORD );
448 
449     if( aRes.nStartPara == nPara &&
450         aRes.nStartPara == aRes.nEndPara )
451     {
452         nStart = aRes.nStartPos;
453         nEnd = aRes.nEndPos;
454 
455         return sal_True;
456     }
457 
458     return sal_False;
459 }
460 
461 sal_Bool SvxEditEngineForwarder::GetAttributeRun( sal_uInt16& nStartIndex, sal_uInt16& nEndIndex, sal_uInt16 nPara, sal_uInt16 nIndex ) const
462 {
463     return SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, rEditEngine, nPara, nIndex );
464 }
465 
466 sal_uInt16 SvxEditEngineForwarder::GetLineCount( sal_uInt16 nPara ) const
467 {
468     return rEditEngine.GetLineCount(nPara);
469 }
470 
471 sal_uInt16 SvxEditEngineForwarder::GetLineLen( sal_uInt16 nPara, sal_uInt16 nLine ) const
472 {
473     return rEditEngine.GetLineLen(nPara, nLine);
474 }
475 
476 void SvxEditEngineForwarder::GetLineBoundaries( /*out*/sal_uInt16 &rStart, /*out*/sal_uInt16 &rEnd, sal_uInt16 nPara, sal_uInt16 nLine ) const
477 {
478     rEditEngine.GetLineBoundaries(rStart, rEnd, nPara, nLine);
479 }
480 
481 sal_uInt16 SvxEditEngineForwarder::GetLineNumberAtIndex( sal_uInt16 nPara, sal_uInt16 nIndex ) const
482 {
483     return rEditEngine.GetLineNumberAtIndex(nPara, nIndex);
484 }
485 
486 
487 sal_Bool SvxEditEngineForwarder::QuickFormatDoc( sal_Bool )
488 {
489     rEditEngine.QuickFormatDoc();
490 
491     return sal_True;
492 }
493 
494 sal_Bool SvxEditEngineForwarder::Delete( const ESelection& rSelection )
495 {
496     rEditEngine.QuickDelete( rSelection );
497     rEditEngine.QuickFormatDoc();
498 
499     return sal_True;
500 }
501 
502 sal_Bool SvxEditEngineForwarder::InsertText( const String& rStr, const ESelection& rSelection )
503 {
504     rEditEngine.QuickInsertText( rStr, rSelection );
505     rEditEngine.QuickFormatDoc();
506 
507     return sal_True;
508 }
509 
510 sal_Int16 SvxEditEngineForwarder::GetDepth( sal_uInt16 ) const
511 {
512     // EditEngine does not support outline depth
513     return -1;
514 }
515 
516 sal_Bool SvxEditEngineForwarder::SetDepth( sal_uInt16, sal_Int16 nNewDepth )
517 {
518     // EditEngine does not support outline depth
519     return nNewDepth == -1 ? sal_True : sal_False;
520 }
521 
522 const SfxItemSet * SvxEditEngineForwarder::GetEmptyItemSetPtr()
523 {
524     return &rEditEngine.GetEmptyItemSet();
525 }
526 
527 void SvxEditEngineForwarder::AppendParagraph()
528 {
529     rEditEngine.InsertParagraph( rEditEngine.GetParagraphCount(), String::EmptyString() );
530 }
531 
532 xub_StrLen SvxEditEngineForwarder::AppendTextPortion( sal_uInt16 nPara, const String &rText, const SfxItemSet & /*rSet*/ )
533 {
534     xub_StrLen nLen = 0;
535 
536     sal_uInt16 nParaCount = rEditEngine.GetParagraphCount();
537     DBG_ASSERT( nPara < nParaCount, "paragraph index out of bounds" );
538     if (/*0 <= nPara && */nPara < nParaCount)
539     {
540         nLen = rEditEngine.GetTextLen( nPara );
541         rEditEngine.QuickInsertText( rText, ESelection( nPara, nLen, nPara, nLen ) );
542     }
543 
544     return nLen;
545 }
546 
547 void SvxEditEngineForwarder::CopyText(const SvxTextForwarder& rSource)
548 {
549     const SvxEditEngineForwarder* pSourceForwarder = dynamic_cast< const SvxEditEngineForwarder* >( &rSource );
550     if( !pSourceForwarder )
551         return;
552     EditTextObject* pNewTextObject = pSourceForwarder->rEditEngine.CreateTextObject();
553     rEditEngine.SetText( *pNewTextObject );
554     delete pNewTextObject;
555 }
556 
557 //------------------------------------------------------------------------
558