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