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
SvxEditEngineForwarder(EditEngine & rEngine)45 SvxEditEngineForwarder::SvxEditEngineForwarder( EditEngine& rEngine ) :
46 rEditEngine( rEngine )
47 {
48 }
49
~SvxEditEngineForwarder()50 SvxEditEngineForwarder::~SvxEditEngineForwarder()
51 {
52 // die EditEngine muss ggf. von aussen geloescht werden
53 }
54
GetParagraphCount() const55 sal_uInt32 SvxEditEngineForwarder::GetParagraphCount() const
56 {
57 return rEditEngine.GetParagraphCount();
58 }
59
GetTextLen(sal_uInt32 nParagraph) const60 sal_uInt16 SvxEditEngineForwarder::GetTextLen( sal_uInt32 nParagraph ) const
61 {
62 return rEditEngine.GetTextLen( nParagraph );
63 }
64
GetText(const ESelection & rSel) const65 String SvxEditEngineForwarder::GetText( const ESelection& rSel ) const
66 {
67 String aRet = rEditEngine.GetText( rSel, LINEEND_LF );
68 aRet.ConvertLineEnd();
69 return aRet;
70 }
71
GetAttribs(const ESelection & rSel,sal_Bool bOnlyHardAttrib) const72 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
GetParaAttribs(sal_uInt32 nPara) const100 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
SetParaAttribs(sal_uInt32 nPara,const SfxItemSet & rSet)118 void SvxEditEngineForwarder::SetParaAttribs( sal_uInt32 nPara, const SfxItemSet& rSet )
119 {
120 rEditEngine.SetParaAttribs( nPara, rSet );
121 }
122
RemoveAttribs(const ESelection & rSelection,sal_Bool bRemoveParaAttribs,sal_uInt16 nWhich)123 void SvxEditEngineForwarder::RemoveAttribs( const ESelection& rSelection, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich )
124 {
125 rEditEngine.RemoveAttribs( rSelection, bRemoveParaAttribs, nWhich );
126 }
127
GetPool() const128 SfxItemPool* SvxEditEngineForwarder::GetPool() const
129 {
130 return rEditEngine.GetEmptyItemSet().GetPool();
131 }
132
GetPortions(sal_uInt32 nPara,SvUShorts & rList) const133 void SvxEditEngineForwarder::GetPortions( sal_uInt32 nPara, SvUShorts& rList ) const
134 {
135 rEditEngine.GetPortions( nPara, rList );
136 }
137
QuickInsertText(const String & rText,const ESelection & rSel)138 void SvxEditEngineForwarder::QuickInsertText( const String& rText, const ESelection& rSel )
139 {
140 rEditEngine.QuickInsertText( rText, rSel );
141 }
142
QuickInsertLineBreak(const ESelection & rSel)143 void SvxEditEngineForwarder::QuickInsertLineBreak( const ESelection& rSel )
144 {
145 rEditEngine.QuickInsertLineBreak( rSel );
146 }
147
QuickInsertField(const SvxFieldItem & rFld,const ESelection & rSel)148 void SvxEditEngineForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
149 {
150 rEditEngine.QuickInsertField( rFld, rSel );
151 }
152
QuickSetAttribs(const SfxItemSet & rSet,const ESelection & rSel)153 void SvxEditEngineForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
154 {
155 rEditEngine.QuickSetAttribs( rSet, rSel );
156 }
157
IsValid() const158 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
CalcFieldValue(const SvxFieldItem & rField,sal_uInt32 nPara,sal_uInt16 nPos,Color * & rpTxtColor,Color * & rpFldColor)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
FieldClicked(const SvxFieldItem & rField,sal_uInt32 nPara,xub_StrLen nPos)170 void SvxEditEngineForwarder::FieldClicked( const SvxFieldItem& rField, sal_uInt32 nPara, xub_StrLen nPos )
171 {
172 rEditEngine.FieldClicked( rField, nPara, nPos );
173 }
174
GetSvxEditEngineItemState(EditEngine & rEditEngine,const ESelection & rSel,sal_uInt16 nWhich)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
GetItemState(const ESelection & rSel,sal_uInt16 nWhich) const307 sal_uInt16 SvxEditEngineForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const
308 {
309 return GetSvxEditEngineItemState( rEditEngine, rSel, nWhich );
310 }
311
GetItemState(sal_uInt32 nPara,sal_uInt16 nWhich) const312 sal_uInt16 SvxEditEngineForwarder::GetItemState( sal_uInt32 nPara, sal_uInt16 nWhich ) const
313 {
314 const SfxItemSet& rSet = rEditEngine.GetParaAttribs( nPara );
315 return rSet.GetItemState( nWhich );
316 }
317
GetLanguage(sal_uInt32 nPara,sal_uInt16 nIndex) const318 LanguageType SvxEditEngineForwarder::GetLanguage( sal_uInt32 nPara, sal_uInt16 nIndex ) const
319 {
320 return rEditEngine.GetLanguage(nPara, nIndex);
321 }
322
GetFieldCount(sal_uInt32 nPara) const323 sal_uInt16 SvxEditEngineForwarder::GetFieldCount( sal_uInt32 nPara ) const
324 {
325 return rEditEngine.GetFieldCount(nPara);
326 }
327
GetFieldInfo(sal_uInt32 nPara,sal_uInt16 nField) const328 EFieldInfo SvxEditEngineForwarder::GetFieldInfo( sal_uInt32 nPara, sal_uInt16 nField ) const
329 {
330 return rEditEngine.GetFieldInfo( nPara, nField );
331 }
332
GetBulletInfo(sal_uInt32) const333 EBulletInfo SvxEditEngineForwarder::GetBulletInfo( sal_uInt32 ) const
334 {
335 return EBulletInfo();
336 }
337
GetCharBounds(sal_uInt32 nPara,sal_uInt16 nIndex) const338 Rectangle SvxEditEngineForwarder::GetCharBounds( sal_uInt32 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
GetParaBounds(sal_uInt32 nPara) const386 Rectangle SvxEditEngineForwarder::GetParaBounds( sal_uInt32 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
GetMapMode() const414 MapMode SvxEditEngineForwarder::GetMapMode() const
415 {
416 return rEditEngine.GetRefMapMode();
417 }
418
GetRefDevice() const419 OutputDevice* SvxEditEngineForwarder::GetRefDevice() const
420 {
421 return rEditEngine.GetRefDevice();
422 }
423
GetIndexAtPoint(const Point & rPos,sal_uInt32 & nPara,sal_uInt16 & nIndex) const424 sal_Bool SvxEditEngineForwarder::GetIndexAtPoint( const Point& rPos, sal_uInt32& 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
GetWordIndices(sal_uInt32 nPara,sal_uInt16 nIndex,sal_uInt16 & nStart,sal_uInt16 & nEnd) const441 sal_Bool SvxEditEngineForwarder::GetWordIndices( sal_uInt32 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 }
GetAttributeRun(sal_uInt16 & nStartIndex,sal_uInt16 & nEndIndex,sal_uInt32 nPara,sal_uInt16 nIndex,sal_Bool bInCell) const456 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
GetLineCount(sal_uInt32 nPara) const461 sal_uInt16 SvxEditEngineForwarder::GetLineCount( sal_uInt32 nPara ) const
462 {
463 return rEditEngine.GetLineCount(nPara);
464 }
465
GetLineLen(sal_uInt32 nPara,sal_uInt16 nLine) const466 sal_uInt16 SvxEditEngineForwarder::GetLineLen( sal_uInt32 nPara, sal_uInt16 nLine ) const
467 {
468 return rEditEngine.GetLineLen(nPara, nLine);
469 }
470
GetLineBoundaries(sal_uInt16 & rStart,sal_uInt16 & rEnd,sal_uInt32 nPara,sal_uInt16 nLine) const471 void SvxEditEngineForwarder::GetLineBoundaries( /*out*/sal_uInt16 &rStart, /*out*/sal_uInt16 &rEnd, sal_uInt32 nPara, sal_uInt16 nLine ) const
472 {
473 rEditEngine.GetLineBoundaries(rStart, rEnd, nPara, nLine);
474 }
475
GetLineNumberAtIndex(sal_uInt32 nPara,sal_uInt16 nIndex) const476 sal_uInt16 SvxEditEngineForwarder::GetLineNumberAtIndex( sal_uInt32 nPara, sal_uInt16 nIndex ) const
477 {
478 return rEditEngine.GetLineNumberAtIndex(nPara, nIndex);
479 }
480
481
QuickFormatDoc(sal_Bool)482 sal_Bool SvxEditEngineForwarder::QuickFormatDoc( sal_Bool )
483 {
484 rEditEngine.QuickFormatDoc();
485
486 return sal_True;
487 }
488
Delete(const ESelection & rSelection)489 sal_Bool SvxEditEngineForwarder::Delete( const ESelection& rSelection )
490 {
491 rEditEngine.QuickDelete( rSelection );
492 rEditEngine.QuickFormatDoc();
493
494 return sal_True;
495 }
496
InsertText(const String & rStr,const ESelection & rSelection)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
GetDepth(sal_uInt32) const505 sal_Int16 SvxEditEngineForwarder::GetDepth( sal_uInt32 ) const
506 {
507 // EditEngine does not support outline depth
508 return -1;
509 }
510
SetDepth(sal_uInt32,sal_Int16 nNewDepth)511 sal_Bool SvxEditEngineForwarder::SetDepth( sal_uInt32, sal_Int16 nNewDepth )
512 {
513 // EditEngine does not support outline depth
514 return nNewDepth == -1 ? sal_True : sal_False;
515 }
516
GetEmptyItemSetPtr()517 const SfxItemSet * SvxEditEngineForwarder::GetEmptyItemSetPtr()
518 {
519 return &rEditEngine.GetEmptyItemSet();
520 }
521
AppendParagraph()522 void SvxEditEngineForwarder::AppendParagraph()
523 {
524 rEditEngine.InsertParagraph( rEditEngine.GetParagraphCount(), String::EmptyString() );
525 }
526
AppendTextPortion(sal_uInt32 nPara,const String & rText,const SfxItemSet &)527 xub_StrLen SvxEditEngineForwarder::AppendTextPortion( sal_uInt32 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
CopyText(const SvxTextForwarder & rSource)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