Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <vcl/wrkwin.hxx>
21 : #include <vcl/dialog.hxx>
22 : #include <vcl/msgbox.hxx>
23 : #include <vcl/svapp.hxx>
24 : #include <impedit.hxx>
25 : #include <editeng/editeng.hxx>
26 : #include <editdbg.hxx>
27 : #include <svl/smplhint.hxx>
28 : #include <editeng/lrspitem.hxx>
29 :
30 7028 : void ImpEditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool )
31 : {
32 7028 : if ( pStylePool != pSPool )
33 : {
34 3476 : pStylePool = pSPool;
35 : }
36 7028 : }
37 :
38 0 : const SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_uInt16 nPara ) const
39 : {
40 0 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
41 0 : return pNode ? pNode->GetContentAttribs().GetStyleSheet() : NULL;
42 : }
43 :
44 2890 : SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_uInt16 nPara )
45 : {
46 2890 : ContentNode* pNode = aEditDoc.GetObject( nPara );
47 2890 : return pNode ? pNode->GetContentAttribs().GetStyleSheet() : NULL;
48 : }
49 :
50 0 : void ImpEditEngine::SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle )
51 : {
52 0 : aSel.Adjust( aEditDoc );
53 :
54 0 : sal_uInt16 nStartPara = aEditDoc.GetPos( aSel.Min().GetNode() );
55 0 : sal_uInt16 nEndPara = aEditDoc.GetPos( aSel.Max().GetNode() );
56 :
57 0 : sal_Bool _bUpdate = GetUpdateMode();
58 0 : SetUpdateMode( sal_False );
59 :
60 0 : for ( sal_uInt16 n = nStartPara; n <= nEndPara; n++ )
61 0 : SetStyleSheet( n, pStyle );
62 :
63 0 : SetUpdateMode( _bUpdate, 0 );
64 0 : }
65 :
66 20928 : void ImpEditEngine::SetStyleSheet( sal_uInt16 nPara, SfxStyleSheet* pStyle )
67 : {
68 : DBG_ASSERT( GetStyleSheetPool() || !pStyle, "SetStyleSheet: No StyleSheetPool registered!" );
69 20928 : ContentNode* pNode = aEditDoc.GetObject( nPara );
70 20928 : SfxStyleSheet* pCurStyle = pNode->GetStyleSheet();
71 20928 : if ( pStyle != pCurStyle )
72 : {
73 14856 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
74 : {
75 2152 : XubString aPrevStyleName;
76 2152 : if ( pCurStyle )
77 776 : aPrevStyleName = pCurStyle->GetName();
78 :
79 2152 : XubString aNewStyleName;
80 2152 : if ( pStyle )
81 2152 : aNewStyleName = pStyle->GetName();
82 :
83 : InsertUndo(
84 2152 : new EditUndoSetStyleSheet(pEditEngine, aEditDoc.GetPos( pNode ),
85 776 : aPrevStyleName, pCurStyle ? pCurStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
86 2152 : aNewStyleName, pStyle ? pStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
87 5080 : pNode->GetContentAttribs().GetItems() ) );
88 : }
89 14856 : if ( pCurStyle )
90 812 : EndListening( *pCurStyle, sal_False );
91 14856 : pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() );
92 14856 : if ( pStyle )
93 14856 : StartListening( *pStyle, sal_False );
94 14856 : ParaAttribsChanged( pNode );
95 : }
96 20928 : FormatAndUpdate();
97 20928 : }
98 :
99 0 : void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle )
100 : {
101 0 : SvxFont aFontFromStyle;
102 0 : CreateFont( aFontFromStyle, pStyle->GetItemSet() );
103 :
104 0 : sal_Bool bUsed = sal_False;
105 0 : for ( sal_uInt16 nNode = 0; nNode < aEditDoc.Count(); nNode++ )
106 : {
107 0 : ContentNode* pNode = aEditDoc.GetObject( nNode );
108 0 : if ( pNode->GetStyleSheet() == pStyle )
109 : {
110 0 : bUsed = sal_True;
111 0 : if ( aStatus.UseCharAttribs() )
112 0 : pNode->SetStyleSheet( pStyle, aFontFromStyle );
113 : else
114 0 : pNode->SetStyleSheet( pStyle, sal_False );
115 :
116 0 : ParaAttribsChanged( pNode );
117 : }
118 : }
119 0 : if ( bUsed )
120 : {
121 0 : GetEditEnginePtr()->StyleSheetChanged( pStyle );
122 0 : FormatAndUpdate();
123 0 : }
124 0 : }
125 :
126 0 : void ImpEditEngine::RemoveStyleFromParagraphs( SfxStyleSheet* pStyle )
127 : {
128 0 : for ( sal_uInt16 nNode = 0; nNode < aEditDoc.Count(); nNode++ )
129 : {
130 0 : ContentNode* pNode = aEditDoc.GetObject(nNode);
131 0 : if ( pNode->GetStyleSheet() == pStyle )
132 : {
133 0 : pNode->SetStyleSheet( NULL );
134 0 : ParaAttribsChanged( pNode );
135 : }
136 : }
137 0 : FormatAndUpdate();
138 0 : }
139 :
140 0 : void ImpEditEngine::Notify( SfxBroadcaster& rBC, const SfxHint& rHint )
141 : {
142 : // So that not a lot of unnecessary formatting is done when destructing:
143 0 : if ( !bDowning )
144 : {
145 : DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
146 :
147 0 : SfxStyleSheet* pStyle = NULL;
148 0 : sal_uLong nId = 0;
149 :
150 0 : if ( rHint.ISA( SfxStyleSheetHint ) )
151 : {
152 0 : const SfxStyleSheetHint& rH = (const SfxStyleSheetHint&) rHint;
153 : DBG_ASSERT( rH.GetStyleSheet()->ISA( SfxStyleSheet ), "No SfxStyleSheet!" );
154 0 : pStyle = (SfxStyleSheet*) rH.GetStyleSheet();
155 0 : nId = rH.GetHint();
156 : }
157 0 : else if ( ( rHint.Type() == TYPE(SfxSimpleHint ) ) && ( rBC.ISA( SfxStyleSheet ) ) )
158 : {
159 0 : pStyle = (SfxStyleSheet*)&rBC;
160 0 : nId = ((SfxSimpleHint&)rHint).GetId();
161 : }
162 :
163 0 : if ( pStyle )
164 : {
165 0 : if ( ( nId == SFX_HINT_DYING ) ||
166 : ( nId == SFX_STYLESHEET_INDESTRUCTION ) ||
167 : ( nId == SFX_STYLESHEET_ERASED ) )
168 : {
169 0 : RemoveStyleFromParagraphs( pStyle );
170 : }
171 0 : else if ( ( nId == SFX_HINT_DATACHANGED ) ||
172 : ( nId == SFX_STYLESHEET_MODIFIED ) )
173 : {
174 0 : UpdateParagraphsWithStyleSheet( pStyle );
175 : }
176 : }
177 : }
178 0 : }
179 :
180 4252 : EditUndoSetAttribs* ImpEditEngine::CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet )
181 : {
182 : DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateAttribUndo: Incorrect selection ");
183 4252 : aSel.Adjust( aEditDoc );
184 :
185 4252 : ESelection aESel( CreateESel( aSel ) );
186 :
187 4252 : sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
188 4252 : sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
189 :
190 : DBG_ASSERT( nStartNode <= nEndNode, "CreateAttribUndo: Start > End ?!" );
191 :
192 4252 : EditUndoSetAttribs* pUndo = NULL;
193 4252 : if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
194 : {
195 0 : SfxItemSet aTmpSet( GetEmptyItemSet() );
196 0 : aTmpSet.Put( rSet );
197 0 : pUndo = new EditUndoSetAttribs(pEditEngine, aESel, aTmpSet);
198 : }
199 : else
200 : {
201 4252 : pUndo = new EditUndoSetAttribs(pEditEngine, aESel, rSet);
202 : }
203 :
204 4252 : SfxItemPool* pPool = pUndo->GetNewAttribs().GetPool();
205 :
206 8504 : for ( sal_uInt16 nPara = nStartNode; nPara <= nEndNode; nPara++ )
207 : {
208 4252 : ContentNode* pNode = aEditDoc.GetObject( nPara );
209 : DBG_ASSERT( aEditDoc.GetObject( nPara ), "Node not found: CreateAttribUndo" );
210 4252 : ContentAttribsInfo* pInf = new ContentAttribsInfo( pNode->GetContentAttribs().GetItems() );
211 4252 : pUndo->AppendContentInfo(pInf);
212 :
213 29952 : for ( sal_uInt16 nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
214 : {
215 25700 : const EditCharAttrib& rAttr = pNode->GetCharAttribs().GetAttribs()[nAttr];
216 25700 : if (rAttr.GetLen())
217 : {
218 23382 : EditCharAttrib* pNew = MakeCharAttrib(*pPool, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd());
219 23382 : pInf->AppendCharAttrib(pNew);
220 : }
221 : }
222 : }
223 4252 : return pUndo;
224 : }
225 :
226 0 : void ImpEditEngine::UndoActionStart( sal_uInt16 nId, const ESelection& aSel )
227 : {
228 0 : if ( IsUndoEnabled() && !IsInUndo() )
229 : {
230 0 : GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
231 : DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
232 0 : pUndoMarkSelection = new ESelection( aSel );
233 : }
234 0 : }
235 :
236 89406 : void ImpEditEngine::UndoActionStart( sal_uInt16 nId )
237 : {
238 89406 : if ( IsUndoEnabled() && !IsInUndo() )
239 : {
240 85292 : GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
241 : DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
242 : }
243 89406 : }
244 :
245 89406 : void ImpEditEngine::UndoActionEnd( sal_uInt16 )
246 : {
247 89406 : if ( IsUndoEnabled() && !IsInUndo() )
248 : {
249 85292 : GetUndoManager().LeaveListAction();
250 85292 : delete pUndoMarkSelection;
251 85292 : pUndoMarkSelection = NULL;
252 : }
253 89406 : }
254 :
255 49720 : void ImpEditEngine::InsertUndo( EditUndo* pUndo, bool bTryMerge )
256 : {
257 : DBG_ASSERT( !IsInUndo(), "InsertUndo in Undomodus!" );
258 49720 : if ( pUndoMarkSelection )
259 : {
260 0 : EditUndoMarkSelection* pU = new EditUndoMarkSelection(pEditEngine, *pUndoMarkSelection);
261 0 : GetUndoManager().AddUndoAction( pU, false );
262 0 : delete pUndoMarkSelection;
263 0 : pUndoMarkSelection = NULL;
264 : }
265 49720 : GetUndoManager().AddUndoAction( pUndo, bTryMerge );
266 :
267 49720 : mbLastTryMerge = bTryMerge;
268 49720 : }
269 :
270 143932 : void ImpEditEngine::ResetUndoManager()
271 : {
272 143932 : if ( HasUndoManager() )
273 128530 : GetUndoManager().Clear();
274 143932 : }
275 :
276 171628 : void ImpEditEngine::EnableUndo( bool bEnable )
277 : {
278 : // When switching the mode Delete list:
279 171628 : if ( bEnable != IsUndoEnabled() )
280 58322 : ResetUndoManager();
281 :
282 171628 : bUndoEnabled = bEnable;
283 171628 : }
284 :
285 0 : sal_Bool ImpEditEngine::Undo( EditView* pView )
286 : {
287 0 : if ( HasUndoManager() && GetUndoManager().GetUndoActionCount() )
288 : {
289 0 : SetActiveView( pView );
290 0 : GetUndoManager().Undo();
291 0 : return sal_True;
292 : }
293 0 : return sal_False;
294 : }
295 :
296 0 : sal_Bool ImpEditEngine::Redo( EditView* pView )
297 : {
298 0 : if ( HasUndoManager() && GetUndoManager().GetRedoActionCount() )
299 : {
300 0 : SetActiveView( pView );
301 0 : GetUndoManager().Redo();
302 0 : return sal_True;
303 : }
304 0 : return sal_False;
305 : }
306 :
307 1028 : SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, sal_Bool bOnlyHardAttrib )
308 : {
309 : DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
310 :
311 1028 : aSel.Adjust( aEditDoc );
312 :
313 1028 : SfxItemSet aCurSet( GetEmptyItemSet() );
314 :
315 1028 : sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
316 1028 : sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
317 :
318 : // iterate over the paragraphs ...
319 2068 : for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
320 : {
321 1040 : ContentNode* pNode = aEditDoc.GetObject( nNode );
322 : DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: GetAttrib" );
323 :
324 1040 : xub_StrLen nStartPos = 0;
325 1040 : xub_StrLen nEndPos = pNode->Len();
326 1040 : if ( nNode == nStartNode )
327 1028 : nStartPos = aSel.Min().GetIndex();
328 1040 : if ( nNode == nEndNode ) // Can also be == nStart!
329 1028 : nEndPos = aSel.Max().GetIndex();
330 :
331 : // Problem: Templates ....
332 : // => Other way:
333 : // 1) Hard character attributes, as usual ...
334 : // 2) Examine Style and paragraph attributes only when OFF ...
335 :
336 : // First the very hard formatting ...
337 1040 : aEditDoc.FindAttribs( pNode, nStartPos, nEndPos, aCurSet );
338 :
339 1040 : if( bOnlyHardAttrib != EditEngineAttribs_OnlyHard )
340 : {
341 : // and then paragraph formatting and template...
342 48804 : for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
343 : {
344 47808 : if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
345 : {
346 45248 : if ( bOnlyHardAttrib == EditEngineAttribs_All )
347 : {
348 45248 : const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
349 45248 : aCurSet.Put( rItem );
350 : }
351 0 : else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SFX_ITEM_ON )
352 : {
353 0 : const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItems().Get( nWhich );
354 0 : aCurSet.Put( rItem );
355 : }
356 : }
357 2560 : else if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
358 : {
359 2538 : const SfxPoolItem* pItem = NULL;
360 2538 : if ( bOnlyHardAttrib == EditEngineAttribs_All )
361 : {
362 2538 : pItem = &pNode->GetContentAttribs().GetItem( nWhich );
363 : }
364 0 : else if ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich ) == SFX_ITEM_ON )
365 : {
366 0 : pItem = &pNode->GetContentAttribs().GetItems().Get( nWhich );
367 : }
368 : // pItem can only be NULL when bOnlyHardAttrib...
369 2538 : if ( !pItem || ( *pItem != aCurSet.Get( nWhich ) ) )
370 : {
371 : // Problem: When Paragraph style with for example font,
372 : // but the Font is hard and completely different,
373 : // wrong in selection if invalidated....
374 : // => better not invalidate, instead CHANGE!
375 : // It would be better to fill each paragraph with
376 : // a itemset and compare this in large.
377 1118 : if ( nWhich <= EE_PARA_END )
378 2 : aCurSet.InvalidateItem( nWhich );
379 : }
380 : }
381 : }
382 : }
383 : }
384 :
385 : // fill empty slots with defaults ...
386 1028 : if ( bOnlyHardAttrib == EditEngineAttribs_All )
387 : {
388 48216 : for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++ )
389 : {
390 47232 : if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
391 : {
392 0 : aCurSet.Put( aEditDoc.GetItemPool().GetDefaultItem( nWhich ) );
393 : }
394 : }
395 : }
396 1028 : return aCurSet;
397 : }
398 :
399 :
400 2014 : SfxItemSet ImpEditEngine::GetAttribs( sal_uInt16 nPara, sal_uInt16 nStart, sal_uInt16 nEnd, sal_uInt8 nFlags ) const
401 : {
402 : // Optimized function with less Puts(), which cause unnecessary cloning from default items.
403 : // If this works, change GetAttribs( EditSelection ) to use this for each paragraph and merge the results!
404 :
405 : DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
406 :
407 2014 : ContentNode* pNode = const_cast<ContentNode*>(aEditDoc.GetObject(nPara));
408 : DBG_ASSERT( pNode, "GetAttribs - unknown paragraph!" );
409 : DBG_ASSERT( nStart <= nEnd, "getAttribs: Start > End not supported!" );
410 :
411 2014 : SfxItemSet aAttribs( ((ImpEditEngine*)this)->GetEmptyItemSet() );
412 :
413 2014 : if ( pNode )
414 : {
415 2014 : if ( nEnd > pNode->Len() )
416 0 : nEnd = pNode->Len();
417 :
418 2014 : if ( nStart > nEnd )
419 0 : nStart = nEnd;
420 :
421 : // StyleSheet / Parattribs...
422 :
423 2014 : if ( pNode->GetStyleSheet() && ( nFlags & GETATTRIBS_STYLESHEET ) )
424 676 : aAttribs.Set(pNode->GetStyleSheet()->GetItemSet(), true);
425 :
426 2014 : if ( nFlags & GETATTRIBS_PARAATTRIBS )
427 1820 : aAttribs.Put( pNode->GetContentAttribs().GetItems() );
428 :
429 : // CharAttribs...
430 :
431 2014 : if ( nFlags & GETATTRIBS_CHARATTRIBS )
432 : {
433 : // Make testing easier...
434 2014 : const SfxItemPool& rPool = GetEditDoc().GetItemPool();
435 2014 : pNode->GetCharAttribs().OptimizeRanges(const_cast<SfxItemPool&>(rPool));
436 :
437 2014 : const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
438 7380 : for (size_t nAttr = 0; nAttr < rAttrs.size(); ++nAttr)
439 : {
440 5456 : const EditCharAttrib& rAttr = rAttrs[nAttr];
441 :
442 5456 : if ( nStart == nEnd )
443 : {
444 3572 : sal_uInt16 nCursorPos = nStart;
445 3572 : if ( ( rAttr.GetStart() <= nCursorPos ) && ( rAttr.GetEnd() >= nCursorPos ) )
446 : {
447 : // To be used the attribute has to start BEFORE the position, or it must be a
448 : // new empty attr AT the position, or we are on position 0.
449 3520 : if ( ( rAttr.GetStart() < nCursorPos ) || rAttr.IsEmpty() || !nCursorPos )
450 : {
451 : // maybe this attrib ends here and a new attrib with 0 Len may follow and be valid here,
452 : // but that s no problem, the empty item will come later and win.
453 3520 : aAttribs.Put( *rAttr.GetItem() );
454 : }
455 : }
456 : }
457 : else
458 : {
459 : // Check every attribute covering the area, partial or full.
460 1884 : if ( ( rAttr.GetStart() < nEnd ) && ( rAttr.GetEnd() > nStart ) )
461 : {
462 1228 : if ( ( rAttr.GetStart() <= nStart ) && ( rAttr.GetEnd() >= nEnd ) )
463 : {
464 : // full coverage
465 712 : aAttribs.Put( *rAttr.GetItem() );
466 : }
467 : else
468 : {
469 : // OptimizeRagnge() assures that not the same attr can follow for full coverage
470 : // only partial, check with current, when using para/styhe, otherwise invalid.
471 1032 : if ( !( nFlags & (GETATTRIBS_PARAATTRIBS|GETATTRIBS_STYLESHEET) ) ||
472 516 : ( *rAttr.GetItem() != aAttribs.Get( rAttr.Which() ) ) )
473 : {
474 512 : aAttribs.InvalidateItem( rAttr.Which() );
475 : }
476 : }
477 : }
478 : }
479 :
480 5456 : if ( rAttr.GetStart() > nEnd )
481 : {
482 90 : break;
483 : }
484 : }
485 : }
486 : }
487 :
488 2014 : return aAttribs;
489 : }
490 :
491 :
492 4998 : void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, sal_uInt8 nSpecial )
493 : {
494 4998 : aSel.Adjust( aEditDoc );
495 :
496 : // When no selection => use the Attribute on the word.
497 : // ( the RTF-parser should actually never call the Method whithout a Range )
498 4998 : if ( ( nSpecial == ATTRSPECIAL_WHOLEWORD ) && !aSel.HasRange() )
499 28 : aSel = SelectWord( aSel, ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_False );
500 :
501 4998 : sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
502 4998 : sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
503 :
504 4998 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
505 : {
506 4208 : EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, rSet );
507 4208 : pUndo->SetSpecial( nSpecial );
508 4208 : InsertUndo( pUndo );
509 : }
510 :
511 4998 : sal_Bool bCheckLanguage = sal_False;
512 4998 : if ( GetStatus().DoOnlineSpelling() )
513 : {
514 3938 : bCheckLanguage = ( rSet.GetItemState( EE_CHAR_LANGUAGE ) == SFX_ITEM_ON ) ||
515 1552 : ( rSet.GetItemState( EE_CHAR_LANGUAGE_CJK ) == SFX_ITEM_ON ) ||
516 5490 : ( rSet.GetItemState( EE_CHAR_LANGUAGE_CTL ) == SFX_ITEM_ON );
517 : }
518 :
519 : // iterate over the paragraphs ...
520 10010 : for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
521 : {
522 5012 : sal_Bool bParaAttribFound = sal_False;
523 5012 : sal_Bool bCharAttribFound = sal_False;
524 :
525 : DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not founden: SetAttribs" );
526 : DBG_ASSERT( GetParaPortions().SafeGetObject( nNode ), "Portion not found: SetAttribs" );
527 :
528 5012 : ContentNode* pNode = aEditDoc.GetObject( nNode );
529 5012 : ParaPortion* pPortion = GetParaPortions()[nNode];
530 :
531 5012 : xub_StrLen nStartPos = 0;
532 5012 : xub_StrLen nEndPos = pNode->Len();
533 5012 : if ( nNode == nStartNode )
534 4998 : nStartPos = aSel.Min().GetIndex();
535 5012 : if ( nNode == nEndNode ) // can also be == nStart!
536 4998 : nEndPos = aSel.Max().GetIndex();
537 :
538 : // Iterate over the Items...
539 245588 : for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
540 : {
541 240576 : if ( rSet.GetItemState( nWhich ) == SFX_ITEM_ON )
542 : {
543 40582 : const SfxPoolItem& rItem = rSet.Get( nWhich );
544 40582 : if ( nWhich <= EE_PARA_END )
545 : {
546 8504 : pNode->GetContentAttribs().GetItems().Put( rItem );
547 8504 : bParaAttribFound = sal_True;
548 : }
549 : else
550 : {
551 32078 : aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem );
552 32078 : bCharAttribFound = sal_True;
553 32078 : if ( nSpecial == ATTRSPECIAL_EDGE )
554 : {
555 0 : CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs();
556 0 : for (size_t i = 0, n = rAttribs.size(); i < n; ++i)
557 : {
558 0 : EditCharAttrib& rAttr = rAttribs[i];
559 0 : if (rAttr.GetStart() > nEndPos)
560 0 : break;
561 :
562 0 : if (rAttr.GetEnd() == nEndPos && rAttr.Which() == nWhich)
563 : {
564 0 : rAttr.SetEdge(true);
565 0 : break;
566 : }
567 : }
568 : }
569 : }
570 : }
571 : }
572 :
573 5012 : if ( bParaAttribFound )
574 : {
575 1816 : ParaAttribsChanged( pPortion->GetNode() );
576 : }
577 3196 : else if ( bCharAttribFound )
578 : {
579 3026 : bFormatted = false;
580 3026 : if ( !pNode->Len() || ( nStartPos != nEndPos ) )
581 : {
582 3010 : pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
583 3010 : if ( bCheckLanguage )
584 2374 : pNode->GetWrongList()->MarkInvalid( nStartPos, nEndPos );
585 : }
586 : }
587 : }
588 4998 : }
589 :
590 38 : void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich )
591 : {
592 38 : aSel.Adjust( aEditDoc );
593 :
594 38 : sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
595 38 : sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
596 :
597 38 : const SfxItemSet* _pEmptyItemSet = bRemoveParaAttribs ? &GetEmptyItemSet() : 0;
598 :
599 38 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
600 : {
601 : // Possibly a special Undo, or itemset*
602 38 : EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
603 38 : pUndo->SetRemoveAttribs( sal_True );
604 38 : pUndo->SetRemoveParaAttribs( bRemoveParaAttribs );
605 38 : pUndo->SetRemoveWhich( nWhich );
606 38 : InsertUndo( pUndo );
607 : }
608 :
609 : // iterate over the paragraphs ...
610 76 : for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
611 : {
612 38 : ContentNode* pNode = aEditDoc.GetObject( nNode );
613 38 : ParaPortion* pPortion = GetParaPortions()[nNode];
614 :
615 : DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: SetAttribs" );
616 : DBG_ASSERT( GetParaPortions().SafeGetObject( nNode ), "Portion not found: SetAttribs" );
617 :
618 38 : xub_StrLen nStartPos = 0;
619 38 : xub_StrLen nEndPos = pNode->Len();
620 38 : if ( nNode == nStartNode )
621 38 : nStartPos = aSel.Min().GetIndex();
622 38 : if ( nNode == nEndNode ) // can also be == nStart!
623 38 : nEndPos = aSel.Max().GetIndex();
624 :
625 : // Optimize: If whole paragraph, then RemoveCharAttribs (nPara)?
626 38 : sal_Bool bChanged = aEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich );
627 38 : if ( bRemoveParaAttribs )
628 : {
629 28 : SetParaAttribs( nNode, *_pEmptyItemSet ); // Invalidated
630 : }
631 : else
632 : {
633 : // For 'Format-Standard' also the character attributes should
634 : // disappear, which were set as paragraph attributes by the
635 : // DrawingEngine. These could not have been set by the user anyway.
636 :
637 : // #106871# Not when nWhich
638 : // Would have been better to offer a separate method for format/standard...
639 10 : if ( !nWhich )
640 : {
641 10 : SfxItemSet aAttribs( GetParaAttribs( nNode ) );
642 310 : for ( sal_uInt16 nW = EE_CHAR_START; nW <= EE_CHAR_END; nW++ )
643 300 : aAttribs.ClearItem( nW );
644 10 : SetParaAttribs( nNode, aAttribs );
645 : }
646 : }
647 :
648 38 : if ( bChanged && !bRemoveParaAttribs )
649 : {
650 0 : bFormatted = false;
651 0 : pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
652 : }
653 : }
654 38 : }
655 :
656 12844 : void ImpEditEngine::RemoveCharAttribs( sal_uInt16 nPara, sal_uInt16 nWhich, sal_Bool bRemoveFeatures )
657 : {
658 12844 : ContentNode* pNode = aEditDoc.GetObject( nPara );
659 12844 : ParaPortion* pPortion = GetParaPortions().SafeGetObject( nPara );
660 :
661 : DBG_ASSERT( pNode, "Node not found: RemoveCharAttribs" );
662 : DBG_ASSERT( pPortion, "Portion not found: RemoveCharAttribs" );
663 :
664 12844 : if ( !pNode )
665 12844 : return;
666 :
667 12844 : size_t nAttr = 0;
668 12844 : CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
669 12844 : EditCharAttrib* pAttr = GetAttrib(rAttrs, nAttr);
670 32290 : while ( pAttr )
671 : {
672 10076 : if ( ( !pAttr->IsFeature() || bRemoveFeatures ) &&
673 3474 : ( !nWhich || ( pAttr->GetItem()->Which() == nWhich ) ) )
674 : {
675 2350 : pNode->GetCharAttribs().Remove(nAttr);
676 2350 : nAttr--;
677 : }
678 6602 : nAttr++;
679 6602 : pAttr = GetAttrib(rAttrs, nAttr);
680 : }
681 :
682 12844 : pPortion->MarkSelectionInvalid( 0, pNode->Len() );
683 : }
684 :
685 135894 : void ImpEditEngine::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet )
686 : {
687 135894 : ContentNode* pNode = aEditDoc.GetObject( nPara );
688 :
689 135894 : if ( !pNode )
690 135894 : return;
691 :
692 135894 : if ( !( pNode->GetContentAttribs().GetItems() == rSet ) )
693 : {
694 73914 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
695 : {
696 37982 : if ( rSet.GetPool() != &aEditDoc.GetItemPool() )
697 : {
698 0 : SfxItemSet aTmpSet( GetEmptyItemSet() );
699 0 : aTmpSet.Put( rSet );
700 0 : InsertUndo(new EditUndoSetParaAttribs(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet));
701 : }
702 : else
703 : {
704 37982 : InsertUndo(new EditUndoSetParaAttribs(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), rSet));
705 : }
706 : }
707 73914 : pNode->GetContentAttribs().GetItems().Set( rSet );
708 73914 : if ( aStatus.UseCharAttribs() )
709 73914 : pNode->CreateDefFont();
710 :
711 73914 : ParaAttribsChanged( pNode );
712 : }
713 : }
714 :
715 111498 : const SfxItemSet& ImpEditEngine::GetParaAttribs( sal_uInt16 nPara ) const
716 : {
717 111498 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
718 : DBG_ASSERT( pNode, "Node not found: GetParaAttribs" );
719 111498 : return pNode->GetContentAttribs().GetItems();
720 : }
721 :
722 5008 : bool ImpEditEngine::HasParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) const
723 : {
724 5008 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
725 : DBG_ASSERT( pNode, "Node not found: HasParaAttrib" );
726 :
727 5008 : return pNode->GetContentAttribs().HasItem( nWhich );
728 : }
729 :
730 227620 : const SfxPoolItem& ImpEditEngine::GetParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) const
731 : {
732 227620 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
733 : DBG_ASSERT( pNode, "Node not found: GetParaAttrib" );
734 :
735 227620 : return pNode->GetContentAttribs().GetItem( nWhich );
736 : }
737 :
738 0 : void ImpEditEngine::GetCharAttribs( sal_uInt16 nPara, std::vector<EECharAttrib>& rLst ) const
739 : {
740 0 : rLst.clear();
741 0 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
742 0 : if ( pNode )
743 : {
744 0 : rLst.reserve(pNode->GetCharAttribs().Count());
745 0 : const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
746 0 : for (size_t i = 0; i < rAttrs.size(); ++i)
747 : {
748 0 : const EditCharAttrib& rAttr = rAttrs[i];
749 : EECharAttrib aEEAttr;
750 0 : aEEAttr.pAttr = rAttr.GetItem();
751 0 : aEEAttr.nPara = nPara;
752 0 : aEEAttr.nStart = rAttr.GetStart();
753 0 : aEEAttr.nEnd = rAttr.GetEnd();
754 0 : rLst.push_back(aEEAttr);
755 : }
756 : }
757 0 : }
758 :
759 0 : void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode )
760 : {
761 0 : pNode->GetCharAttribs().DeleteEmptyAttribs( GetEditDoc().GetItemPool() );
762 0 : xub_StrLen nEndPos = pNode->Len();
763 0 : for ( sal_uInt16 nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ )
764 : {
765 0 : if ( pNode->GetContentAttribs().HasItem( nWhich ) )
766 : {
767 0 : const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
768 : // Fill the gap:
769 0 : sal_uInt16 nLastEnd = 0;
770 0 : const EditCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd );
771 0 : while ( pAttr )
772 : {
773 0 : nLastEnd = pAttr->GetEnd();
774 0 : if ( pAttr->GetStart() > nLastEnd )
775 0 : aEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem );
776 : // #112831# Last Attr might go from 0xffff to 0x0000
777 0 : pAttr = nLastEnd ? pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ) : NULL;
778 : }
779 :
780 : // And the Rest:
781 0 : if ( nLastEnd < nEndPos )
782 0 : aEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem );
783 : }
784 : }
785 0 : bFormatted = false;
786 : // Portion does not need to be invalidated here, happens elsewhere.
787 0 : }
788 :
789 9747 : IdleFormattter::IdleFormattter()
790 : {
791 9747 : pView = 0;
792 9747 : nRestarts = 0;
793 9747 : }
794 :
795 17610 : IdleFormattter::~IdleFormattter()
796 : {
797 8805 : pView = 0;
798 8805 : }
799 :
800 0 : void IdleFormattter::DoIdleFormat( EditView* pV )
801 : {
802 0 : pView = pV;
803 :
804 0 : if ( IsActive() )
805 0 : nRestarts++;
806 :
807 0 : if ( nRestarts > 4 )
808 0 : ForceTimeout();
809 : else
810 0 : Start();
811 0 : }
812 :
813 300 : void IdleFormattter::ForceTimeout()
814 : {
815 300 : if ( IsActive() )
816 : {
817 0 : Stop();
818 0 : ((Link&)GetTimeoutHdl()).Call( this );
819 : }
820 300 : }
821 :
822 0 : ImplIMEInfos::ImplIMEInfos( const EditPaM& rPos, const String& rOldTextAfterStartPos )
823 0 : : aOldTextAfterStartPos( rOldTextAfterStartPos )
824 : {
825 0 : aPos = rPos;
826 0 : nLen = 0;
827 0 : bCursor = sal_True;
828 0 : pAttribs = NULL;
829 0 : bWasCursorOverwrite = sal_False;
830 0 : }
831 :
832 0 : ImplIMEInfos::~ImplIMEInfos()
833 : {
834 0 : delete[] pAttribs;
835 0 : }
836 :
837 0 : void ImplIMEInfos::CopyAttribs( const sal_uInt16* pA, sal_uInt16 nL )
838 : {
839 0 : nLen = nL;
840 0 : delete[] pAttribs;
841 0 : pAttribs = new sal_uInt16[ nL ];
842 0 : memcpy( pAttribs, pA, nL*sizeof(sal_uInt16) );
843 0 : }
844 :
845 0 : void ImplIMEInfos::DestroyAttribs()
846 : {
847 0 : delete[] pAttribs;
848 0 : pAttribs = NULL;
849 0 : nLen = 0;
850 0 : }
851 :
852 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|