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 3478 : void ImpEditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool )
31 : {
32 3478 : if ( pStylePool != pSPool )
33 : {
34 1738 : pStylePool = pSPool;
35 : }
36 3478 : }
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 1471 : SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_uInt16 nPara )
45 : {
46 1471 : ContentNode* pNode = aEditDoc.GetObject( nPara );
47 1471 : 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 10469 : void ImpEditEngine::SetStyleSheet( sal_uInt16 nPara, SfxStyleSheet* pStyle )
67 : {
68 : DBG_ASSERT( GetStyleSheetPool() || !pStyle, "SetStyleSheet: No StyleSheetPool registered!" );
69 10469 : ContentNode* pNode = aEditDoc.GetObject( nPara );
70 10469 : SfxStyleSheet* pCurStyle = pNode->GetStyleSheet();
71 10469 : if ( pStyle != pCurStyle )
72 : {
73 7428 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
74 : {
75 1076 : XubString aPrevStyleName;
76 1076 : if ( pCurStyle )
77 388 : aPrevStyleName = pCurStyle->GetName();
78 :
79 1076 : XubString aNewStyleName;
80 1076 : if ( pStyle )
81 1076 : aNewStyleName = pStyle->GetName();
82 :
83 : InsertUndo(
84 1076 : new EditUndoSetStyleSheet(pEditEngine, aEditDoc.GetPos( pNode ),
85 388 : aPrevStyleName, pCurStyle ? pCurStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
86 1076 : aNewStyleName, pStyle ? pStyle->GetFamily() : SFX_STYLE_FAMILY_PARA,
87 2540 : pNode->GetContentAttribs().GetItems() ) );
88 : }
89 7428 : if ( pCurStyle )
90 406 : EndListening( *pCurStyle, sal_False );
91 7428 : pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() );
92 7428 : if ( pStyle )
93 7428 : StartListening( *pStyle, sal_False );
94 7428 : ParaAttribsChanged( pNode );
95 : }
96 10469 : FormatAndUpdate();
97 10469 : }
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 2161 : EditUndoSetAttribs* ImpEditEngine::CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet )
181 : {
182 : DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateAttribUndo: Incorrect selection ");
183 2161 : aSel.Adjust( aEditDoc );
184 :
185 2161 : ESelection aESel( CreateESel( aSel ) );
186 :
187 2161 : sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
188 2161 : sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
189 :
190 : DBG_ASSERT( nStartNode <= nEndNode, "CreateAttribUndo: Start > End ?!" );
191 :
192 2161 : EditUndoSetAttribs* pUndo = NULL;
193 2161 : 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 2161 : pUndo = new EditUndoSetAttribs(pEditEngine, aESel, rSet);
202 : }
203 :
204 2161 : SfxItemPool* pPool = pUndo->GetNewAttribs().GetPool();
205 :
206 4322 : for ( sal_uInt16 nPara = nStartNode; nPara <= nEndNode; nPara++ )
207 : {
208 2161 : ContentNode* pNode = aEditDoc.GetObject( nPara );
209 : DBG_ASSERT( aEditDoc.GetObject( nPara ), "Node not found: CreateAttribUndo" );
210 2161 : ContentAttribsInfo* pInf = new ContentAttribsInfo( pNode->GetContentAttribs().GetItems() );
211 2161 : pUndo->AppendContentInfo(pInf);
212 :
213 15100 : for ( sal_uInt16 nAttr = 0; nAttr < pNode->GetCharAttribs().Count(); nAttr++ )
214 : {
215 12939 : const EditCharAttrib& rAttr = pNode->GetCharAttribs().GetAttribs()[nAttr];
216 12939 : if (rAttr.GetLen())
217 : {
218 11780 : EditCharAttrib* pNew = MakeCharAttrib(*pPool, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd());
219 11780 : pInf->AppendCharAttrib(pNew);
220 : }
221 : }
222 : }
223 2161 : 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 44465 : void ImpEditEngine::UndoActionStart( sal_uInt16 nId )
237 : {
238 44465 : if ( IsUndoEnabled() && !IsInUndo() )
239 : {
240 42680 : GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), XubString(), nId );
241 : DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" );
242 : }
243 44465 : }
244 :
245 44465 : void ImpEditEngine::UndoActionEnd( sal_uInt16 )
246 : {
247 44465 : if ( IsUndoEnabled() && !IsInUndo() )
248 : {
249 42680 : GetUndoManager().LeaveListAction();
250 42680 : delete pUndoMarkSelection;
251 42680 : pUndoMarkSelection = NULL;
252 : }
253 44465 : }
254 :
255 24778 : void ImpEditEngine::InsertUndo( EditUndo* pUndo, bool bTryMerge )
256 : {
257 : DBG_ASSERT( !IsInUndo(), "InsertUndo in Undomodus!" );
258 24778 : 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 24778 : GetUndoManager().AddUndoAction( pUndo, bTryMerge );
266 :
267 24778 : mbLastTryMerge = bTryMerge;
268 24778 : }
269 :
270 69174 : void ImpEditEngine::ResetUndoManager()
271 : {
272 69174 : if ( HasUndoManager() )
273 64162 : GetUndoManager().Clear();
274 69174 : }
275 :
276 82246 : void ImpEditEngine::EnableUndo( bool bEnable )
277 : {
278 : // When switching the mode Delete list:
279 82246 : if ( bEnable != IsUndoEnabled() )
280 27824 : ResetUndoManager();
281 :
282 82246 : bUndoEnabled = bEnable;
283 82246 : }
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 496 : SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, sal_Bool bOnlyHardAttrib )
308 : {
309 : DBG_CHKOBJ( GetEditEnginePtr(), EditEngine, 0 );
310 :
311 496 : aSel.Adjust( aEditDoc );
312 :
313 496 : SfxItemSet aCurSet( GetEmptyItemSet() );
314 :
315 496 : sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
316 496 : sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
317 :
318 : // iterate over the paragraphs ...
319 998 : for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
320 : {
321 502 : ContentNode* pNode = aEditDoc.GetObject( nNode );
322 : DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: GetAttrib" );
323 :
324 502 : xub_StrLen nStartPos = 0;
325 502 : xub_StrLen nEndPos = pNode->Len();
326 502 : if ( nNode == nStartNode )
327 496 : nStartPos = aSel.Min().GetIndex();
328 502 : if ( nNode == nEndNode ) // Can also be == nStart!
329 496 : 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 502 : aEditDoc.FindAttribs( pNode, nStartPos, nEndPos, aCurSet );
338 :
339 502 : if( bOnlyHardAttrib != EditEngineAttribs_OnlyHard )
340 : {
341 : // and then paragraph formatting and template...
342 24206 : for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
343 : {
344 23712 : if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
345 : {
346 22432 : if ( bOnlyHardAttrib == EditEngineAttribs_All )
347 : {
348 22432 : const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
349 22432 : 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 1280 : else if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_ON )
358 : {
359 1269 : const SfxPoolItem* pItem = NULL;
360 1269 : if ( bOnlyHardAttrib == EditEngineAttribs_All )
361 : {
362 1269 : 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 1269 : 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 559 : if ( nWhich <= EE_PARA_END )
378 1 : aCurSet.InvalidateItem( nWhich );
379 : }
380 : }
381 : }
382 : }
383 : }
384 :
385 : // fill empty slots with defaults ...
386 496 : if ( bOnlyHardAttrib == EditEngineAttribs_All )
387 : {
388 23912 : for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++ )
389 : {
390 23424 : if ( aCurSet.GetItemState( nWhich ) == SFX_ITEM_OFF )
391 : {
392 0 : aCurSet.Put( aEditDoc.GetItemPool().GetDefaultItem( nWhich ) );
393 : }
394 : }
395 : }
396 496 : return aCurSet;
397 : }
398 :
399 :
400 756 : 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 756 : 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 756 : SfxItemSet aAttribs( ((ImpEditEngine*)this)->GetEmptyItemSet() );
412 :
413 756 : if ( pNode )
414 : {
415 756 : if ( nEnd > pNode->Len() )
416 0 : nEnd = pNode->Len();
417 :
418 756 : if ( nStart > nEnd )
419 0 : nStart = nEnd;
420 :
421 : // StyleSheet / Parattribs...
422 :
423 756 : if ( pNode->GetStyleSheet() && ( nFlags & GETATTRIBS_STYLESHEET ) )
424 338 : aAttribs.Set(pNode->GetStyleSheet()->GetItemSet(), true);
425 :
426 756 : if ( nFlags & GETATTRIBS_PARAATTRIBS )
427 659 : aAttribs.Put( pNode->GetContentAttribs().GetItems() );
428 :
429 : // CharAttribs...
430 :
431 756 : if ( nFlags & GETATTRIBS_CHARATTRIBS )
432 : {
433 : // Make testing easier...
434 756 : const SfxItemPool& rPool = GetEditDoc().GetItemPool();
435 756 : pNode->GetCharAttribs().OptimizeRanges(const_cast<SfxItemPool&>(rPool));
436 :
437 756 : const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
438 3276 : for (size_t nAttr = 0; nAttr < rAttrs.size(); ++nAttr)
439 : {
440 2565 : const EditCharAttrib& rAttr = rAttrs[nAttr];
441 :
442 2565 : if ( nStart == nEnd )
443 : {
444 1786 : sal_uInt16 nCursorPos = nStart;
445 1786 : 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 1760 : 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 1760 : aAttribs.Put( *rAttr.GetItem() );
454 : }
455 : }
456 : }
457 : else
458 : {
459 : // Check every attribute covering the area, partial or full.
460 779 : if ( ( rAttr.GetStart() < nEnd ) && ( rAttr.GetEnd() > nStart ) )
461 : {
462 535 : if ( ( rAttr.GetStart() <= nStart ) && ( rAttr.GetEnd() >= nEnd ) )
463 : {
464 : // full coverage
465 360 : 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 350 : if ( !( nFlags & (GETATTRIBS_PARAATTRIBS|GETATTRIBS_STYLESHEET) ) ||
472 175 : ( *rAttr.GetItem() != aAttribs.Get( rAttr.Which() ) ) )
473 : {
474 173 : aAttribs.InvalidateItem( rAttr.Which() );
475 : }
476 : }
477 : }
478 : }
479 :
480 2565 : if ( rAttr.GetStart() > nEnd )
481 : {
482 45 : break;
483 : }
484 : }
485 : }
486 : }
487 :
488 756 : return aAttribs;
489 : }
490 :
491 :
492 2507 : void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, sal_uInt8 nSpecial )
493 : {
494 2507 : 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 2507 : if ( ( nSpecial == ATTRSPECIAL_WHOLEWORD ) && !aSel.HasRange() )
499 14 : aSel = SelectWord( aSel, ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_False );
500 :
501 2507 : sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
502 2507 : sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
503 :
504 2507 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
505 : {
506 2130 : EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, rSet );
507 2130 : pUndo->SetSpecial( nSpecial );
508 2130 : InsertUndo( pUndo );
509 : }
510 :
511 2507 : sal_Bool bCheckLanguage = sal_False;
512 2507 : if ( GetStatus().DoOnlineSpelling() )
513 : {
514 1969 : bCheckLanguage = ( rSet.GetItemState( EE_CHAR_LANGUAGE ) == SFX_ITEM_ON ) ||
515 776 : ( rSet.GetItemState( EE_CHAR_LANGUAGE_CJK ) == SFX_ITEM_ON ) ||
516 2745 : ( rSet.GetItemState( EE_CHAR_LANGUAGE_CTL ) == SFX_ITEM_ON );
517 : }
518 :
519 : // iterate over the paragraphs ...
520 5021 : for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
521 : {
522 2514 : sal_Bool bParaAttribFound = sal_False;
523 2514 : 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 2514 : ContentNode* pNode = aEditDoc.GetObject( nNode );
529 2514 : ParaPortion* pPortion = GetParaPortions()[nNode];
530 :
531 2514 : xub_StrLen nStartPos = 0;
532 2514 : xub_StrLen nEndPos = pNode->Len();
533 2514 : if ( nNode == nStartNode )
534 2507 : nStartPos = aSel.Min().GetIndex();
535 2514 : if ( nNode == nEndNode ) // can also be == nStart!
536 2507 : nEndPos = aSel.Max().GetIndex();
537 :
538 : // Iterate over the Items...
539 123186 : for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
540 : {
541 120672 : if ( rSet.GetItemState( nWhich ) == SFX_ITEM_ON )
542 : {
543 20037 : const SfxPoolItem& rItem = rSet.Get( nWhich );
544 20037 : if ( nWhich <= EE_PARA_END )
545 : {
546 4252 : pNode->GetContentAttribs().GetItems().Put( rItem );
547 4252 : bParaAttribFound = sal_True;
548 : }
549 : else
550 : {
551 15785 : aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem );
552 15785 : bCharAttribFound = sal_True;
553 15785 : 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 2514 : if ( bParaAttribFound )
574 : {
575 908 : ParaAttribsChanged( pPortion->GetNode() );
576 : }
577 1606 : else if ( bCharAttribFound )
578 : {
579 1521 : bFormatted = false;
580 1521 : if ( !pNode->Len() || ( nStartPos != nEndPos ) )
581 : {
582 1513 : pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
583 1513 : if ( bCheckLanguage )
584 1187 : pNode->GetWrongList()->MarkInvalid( nStartPos, nEndPos );
585 : }
586 : }
587 : }
588 2507 : }
589 :
590 28 : void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, sal_Bool bRemoveParaAttribs, sal_uInt16 nWhich )
591 : {
592 28 : aSel.Adjust( aEditDoc );
593 :
594 28 : sal_uInt16 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() );
595 28 : sal_uInt16 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() );
596 :
597 28 : const SfxItemSet* _pEmptyItemSet = bRemoveParaAttribs ? &GetEmptyItemSet() : 0;
598 :
599 28 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
600 : {
601 : // Possibly a special Undo, or itemset*
602 28 : EditUndoSetAttribs* pUndo = CreateAttribUndo( aSel, GetEmptyItemSet() );
603 28 : pUndo->SetRemoveAttribs( sal_True );
604 28 : pUndo->SetRemoveParaAttribs( bRemoveParaAttribs );
605 28 : pUndo->SetRemoveWhich( nWhich );
606 28 : InsertUndo( pUndo );
607 : }
608 :
609 : // iterate over the paragraphs ...
610 56 : for ( sal_uInt16 nNode = nStartNode; nNode <= nEndNode; nNode++ )
611 : {
612 28 : ContentNode* pNode = aEditDoc.GetObject( nNode );
613 28 : 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 28 : xub_StrLen nStartPos = 0;
619 28 : xub_StrLen nEndPos = pNode->Len();
620 28 : if ( nNode == nStartNode )
621 28 : nStartPos = aSel.Min().GetIndex();
622 28 : if ( nNode == nEndNode ) // can also be == nStart!
623 28 : nEndPos = aSel.Max().GetIndex();
624 :
625 : // Optimize: If whole paragraph, then RemoveCharAttribs (nPara)?
626 28 : sal_Bool bChanged = aEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich );
627 28 : if ( bRemoveParaAttribs )
628 : {
629 14 : 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 14 : if ( !nWhich )
640 : {
641 14 : SfxItemSet aAttribs( GetParaAttribs( nNode ) );
642 434 : for ( sal_uInt16 nW = EE_CHAR_START; nW <= EE_CHAR_END; nW++ )
643 420 : aAttribs.ClearItem( nW );
644 14 : SetParaAttribs( nNode, aAttribs );
645 : }
646 : }
647 :
648 28 : if ( bChanged && !bRemoveParaAttribs )
649 : {
650 6 : bFormatted = false;
651 6 : pPortion->MarkSelectionInvalid( nStartPos, nEndPos-nStartPos );
652 : }
653 : }
654 28 : }
655 :
656 6422 : void ImpEditEngine::RemoveCharAttribs( sal_uInt16 nPara, sal_uInt16 nWhich, sal_Bool bRemoveFeatures )
657 : {
658 6422 : ContentNode* pNode = aEditDoc.GetObject( nPara );
659 6422 : ParaPortion* pPortion = GetParaPortions().SafeGetObject( nPara );
660 :
661 : DBG_ASSERT( pNode, "Node not found: RemoveCharAttribs" );
662 : DBG_ASSERT( pPortion, "Portion not found: RemoveCharAttribs" );
663 :
664 6422 : if ( !pNode )
665 6422 : return;
666 :
667 6422 : size_t nAttr = 0;
668 6422 : CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs();
669 6422 : EditCharAttrib* pAttr = GetAttrib(rAttrs, nAttr);
670 16145 : while ( pAttr )
671 : {
672 5038 : if ( ( !pAttr->IsFeature() || bRemoveFeatures ) &&
673 1737 : ( !nWhich || ( pAttr->GetItem()->Which() == nWhich ) ) )
674 : {
675 1175 : pNode->GetCharAttribs().Remove(nAttr);
676 1175 : nAttr--;
677 : }
678 3301 : nAttr++;
679 3301 : pAttr = GetAttrib(rAttrs, nAttr);
680 : }
681 :
682 6422 : pPortion->MarkSelectionInvalid( 0, pNode->Len() );
683 : }
684 :
685 66760 : void ImpEditEngine::SetParaAttribs( sal_uInt16 nPara, const SfxItemSet& rSet )
686 : {
687 66760 : ContentNode* pNode = aEditDoc.GetObject( nPara );
688 :
689 66760 : if ( !pNode )
690 66760 : return;
691 :
692 66760 : if ( !( pNode->GetContentAttribs().GetItems() == rSet ) )
693 : {
694 35802 : if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() )
695 : {
696 18980 : 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 18980 : InsertUndo(new EditUndoSetParaAttribs(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), rSet));
705 : }
706 : }
707 35802 : pNode->GetContentAttribs().GetItems().Set( rSet );
708 35802 : if ( aStatus.UseCharAttribs() )
709 35802 : pNode->CreateDefFont();
710 :
711 35802 : ParaAttribsChanged( pNode );
712 : }
713 : }
714 :
715 55693 : const SfxItemSet& ImpEditEngine::GetParaAttribs( sal_uInt16 nPara ) const
716 : {
717 55693 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
718 : DBG_ASSERT( pNode, "Node not found: GetParaAttribs" );
719 55693 : return pNode->GetContentAttribs().GetItems();
720 : }
721 :
722 1566 : bool ImpEditEngine::HasParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) const
723 : {
724 1566 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
725 : DBG_ASSERT( pNode, "Node not found: HasParaAttrib" );
726 :
727 1566 : return pNode->GetContentAttribs().HasItem( nWhich );
728 : }
729 :
730 110584 : const SfxPoolItem& ImpEditEngine::GetParaAttrib( sal_uInt16 nPara, sal_uInt16 nWhich ) const
731 : {
732 110584 : const ContentNode* pNode = aEditDoc.GetObject( nPara );
733 : DBG_ASSERT( pNode, "Node not found: GetParaAttrib" );
734 :
735 110584 : 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 4318 : IdleFormattter::IdleFormattter()
790 : {
791 4318 : pView = 0;
792 4318 : nRestarts = 0;
793 4318 : }
794 :
795 7834 : IdleFormattter::~IdleFormattter()
796 : {
797 3917 : pView = 0;
798 3917 : }
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 134 : void IdleFormattter::ForceTimeout()
814 : {
815 134 : if ( IsActive() )
816 : {
817 0 : Stop();
818 0 : ((Link&)GetTimeoutHdl()).Call( this );
819 : }
820 134 : }
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: */
|