Update ooo320-m1
[ooovba.git] / svx / source / editeng / edtspell.cxx
blob2fb92641ef839c4dea85a863b06c45c8be860db6
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: edtspell.cxx,v $
10 * $Revision: 1.16 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svx.hxx"
34 #include <eeng_pch.hxx>
36 #include <impedit.hxx>
37 #include <svx/editview.hxx>
38 #include <svx/editeng.hxx>
39 #include <edtspell.hxx>
40 #include <svx/flditem.hxx>
41 #include <fontitem.hxx>
42 #include <svtools/intitem.hxx>
43 #include <svtools/eitem.hxx>
44 #include <unolingu.hxx>
45 #include <linguistic/lngprops.hxx>
46 #include <com/sun/star/beans/XPropertySet.hpp>
48 using ::rtl::OUString;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::beans;
51 using namespace com::sun::star::linguistic2;
54 EditSpellWrapper::EditSpellWrapper( Window* _pWin,
55 Reference< XSpellChecker1 > &xChecker,
56 sal_Bool bIsStart, sal_Bool bIsAllRight, EditView* pView ) :
57 SvxSpellWrapper( _pWin, xChecker, bIsStart, bIsAllRight )
59 DBG_ASSERT( pView, "Es muss eine View uebergeben werden!" );
60 // IgnoreList behalten, ReplaceList loeschen...
61 if (SvxGetChangeAllList().is())
62 SvxGetChangeAllList()->clear();
63 pEditView = pView;
66 void __EXPORT EditSpellWrapper::SpellStart( SvxSpellArea eArea )
68 ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
69 SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
71 if ( eArea == SVX_SPELL_BODY_START )
73 // Wird gerufen, wenn
74 // a) Spell-Forwad ist am Ende angekomment und soll von vorne beginnen
75 // IsEndDone() liefert auch sal_True, wenn Rueckwaerts-Spelling am Ende gestartet wird!
76 if ( IsEndDone() )
78 pSpellInfo->bSpellToEnd = sal_False;
79 pSpellInfo->aSpellTo = pSpellInfo->aSpellStart;
80 pEditView->GetImpEditView()->SetEditSelection(
81 pImpEE->GetEditDoc().GetStartPaM() );
83 else
85 pSpellInfo->bSpellToEnd = sal_True;
86 pSpellInfo->aSpellTo = pImpEE->CreateEPaM(
87 pImpEE->GetEditDoc().GetStartPaM() );
90 else if ( eArea == SVX_SPELL_BODY_END )
92 // Wird gerufen, wenn
93 // a) Spell-Forwad wird gestartet
94 // IsStartDone() liefert auch sal_True, wenn Vorwaerts-Spelling am Anfang gestartet wird!
95 if ( !IsStartDone() )
97 pSpellInfo->bSpellToEnd = sal_True;
98 pSpellInfo->aSpellTo = pImpEE->CreateEPaM(
99 pImpEE->GetEditDoc().GetEndPaM() );
101 else
103 pSpellInfo->bSpellToEnd = sal_False;
104 pSpellInfo->aSpellTo = pSpellInfo->aSpellStart;
105 pEditView->GetImpEditView()->SetEditSelection(
106 pImpEE->GetEditDoc().GetEndPaM() );
109 else if ( eArea == SVX_SPELL_BODY )
111 ; // Wird ueber SpellNextDocument von App gehandelt
113 // pSpellInfo->bSpellToEnd = sal_True;
114 // pSpellInfo->aSpellTo = pImpEE->CreateEPaM( pImpEE->GetEditDoc().GetEndPaM() );
116 else
118 DBG_ERROR( "SpellStart: Unknown Area!" );
122 sal_Bool EditSpellWrapper::SpellContinue()
124 SetLast( pEditView->GetImpEditEngine()->ImpSpell( pEditView ) );
125 return GetLast().is();
128 void __EXPORT EditSpellWrapper::SpellEnd()
130 // Base class will show language errors...
131 SvxSpellWrapper::SpellEnd();
134 sal_Bool __EXPORT EditSpellWrapper::HasOtherCnt()
136 return sal_False;
139 sal_Bool __EXPORT EditSpellWrapper::SpellMore()
141 ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
142 SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
143 sal_Bool bMore = sal_False;
144 if ( pSpellInfo->bMultipleDoc )
146 bMore = pImpEE->GetEditEnginePtr()->SpellNextDocument();
147 if ( bMore )
149 // Der Text wurde in diese Engine getreten, bei Rueckwaerts
150 // muss die Selektion hinten sein.
151 Reference< XPropertySet > xProp( SvxGetLinguPropertySet() );
152 pEditView->GetImpEditView()->SetEditSelection(
153 pImpEE->GetEditDoc().GetStartPaM() );
156 return bMore;
159 void __EXPORT EditSpellWrapper::ScrollArea()
161 // Keine weitere Aktion noetig...
162 // Es sei denn, der Bereich soll in die Mitte gescrollt werden,
163 // und nicht irgendwo stehen.
166 void __EXPORT EditSpellWrapper::ReplaceAll( const String &rNewText,
167 sal_Int16 )
169 // Wird gerufen, wenn Wort in ReplaceList des SpellCheckers
170 pEditView->InsertText( rNewText );
171 CheckSpellTo();
174 void __EXPORT EditSpellWrapper::ChangeWord( const String& rNewWord,
175 const sal_uInt16 )
177 // Wird gerufen, wenn Wort Button Change
178 // bzw. intern von mir bei ChangeAll
180 // Wenn Punkt hinterm Wort, wird dieser nicht mitgegeben.
181 // Falls '"' => PreStripped.
182 String aNewWord( rNewWord );
183 pEditView->InsertText( aNewWord );
184 CheckSpellTo();
187 void __EXPORT EditSpellWrapper::ChangeThesWord( const String& rNewWord )
189 pEditView->InsertText( rNewWord );
190 CheckSpellTo();
193 void __EXPORT EditSpellWrapper::AutoCorrect( const String&, const String& )
197 void EditSpellWrapper::CheckSpellTo()
199 ImpEditEngine* pImpEE = pEditView->GetImpEditEngine();
200 SpellInfo* pSpellInfo = pImpEE->GetSpellInfo();
201 EditPaM aPaM( pEditView->GetImpEditView()->GetEditSelection().Max() );
202 EPaM aEPaM = pImpEE->CreateEPaM( aPaM );
203 if ( aEPaM.nPara == pSpellInfo->aSpellTo.nPara )
205 // prueffen, ob SpellToEnd noch gueltiger Index, falls in dem Absatz
206 // ersetzt wurde.
207 if ( pSpellInfo->aSpellTo.nIndex > aPaM.GetNode()->Len() )
208 pSpellInfo->aSpellTo.nIndex = aPaM.GetNode()->Len();
211 SV_IMPL_VARARR( WrongRanges, WrongRange );
213 WrongList::WrongList()
215 nInvalidStart = 0;
216 nInvalidEnd = 0xFFFF;
219 WrongList::~WrongList()
223 void WrongList::TextInserted( sal_uInt16 nPos, sal_uInt16 nNew, sal_Bool bPosIsSep )
225 if ( !IsInvalid() )
227 nInvalidStart = nPos;
228 nInvalidEnd = nPos+nNew;
230 else
232 if ( nInvalidStart > nPos )
233 nInvalidStart = nPos;
234 if ( nInvalidEnd >= nPos )
235 nInvalidEnd = nInvalidEnd + nNew;
236 else
237 nInvalidEnd = nPos+nNew;
240 for ( sal_uInt16 n = 0; n < Count(); n++ )
242 WrongRange& rWrong = GetObject( n );
243 sal_Bool bRefIsValid = sal_True;
244 if ( rWrong.nEnd >= nPos )
246 // Alle Wrongs hinter der Einfuegeposition verschieben...
247 if ( rWrong.nStart > nPos )
249 rWrong.nStart = rWrong.nStart + nNew;
250 rWrong.nEnd = rWrong.nEnd + nNew;
252 // 1: Startet davor, geht bis nPos...
253 else if ( rWrong.nEnd == nPos )
255 // Sollte bei einem Blank unterbunden werden!
256 if ( !bPosIsSep )
257 rWrong.nEnd = rWrong.nEnd + nNew;
259 // 2: Startet davor, geht hinter Pos...
260 else if ( ( rWrong.nStart < nPos ) && ( rWrong.nEnd > nPos ) )
262 rWrong.nEnd = rWrong.nEnd + nNew;
263 // Bei einem Trenner das Wrong entfernen und neu pruefen
264 if ( bPosIsSep )
266 // Wrong aufteilen...
267 WrongRange aNewWrong( rWrong.nStart, nPos );
268 rWrong.nStart = nPos+1;
269 Insert( aNewWrong, n );
270 bRefIsValid = sal_False; // Referenz nach Insert nicht mehr gueltig, der andere wurde davor an dessen Position eingefuegt
271 n++; // Diesen nicht nochmal...
274 // 3: Attribut startet auf Pos...
275 else if ( rWrong.nStart == nPos )
277 rWrong.nEnd = rWrong.nEnd + nNew;
278 if ( bPosIsSep )
279 rWrong.nStart++;
282 DBG_ASSERT( !bRefIsValid || ( rWrong.nStart < rWrong.nEnd ),
283 "TextInserted, WrongRange: Start >= End?!" );
286 DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" );
289 void WrongList::TextDeleted( sal_uInt16 nPos, sal_uInt16 nDeleted )
291 sal_uInt16 nEndChanges = nPos+nDeleted;
292 if ( !IsInvalid() )
294 sal_uInt16 nNewInvalidStart = nPos ? nPos - 1 : 0;
295 nInvalidStart = nNewInvalidStart;
296 nInvalidEnd = nNewInvalidStart + 1;
298 else
300 if ( nInvalidStart > nPos )
301 nInvalidStart = nPos;
302 if ( nInvalidEnd > nPos )
304 if ( nInvalidEnd > nEndChanges )
305 nInvalidEnd = nInvalidEnd - nDeleted;
306 else
307 nInvalidEnd = nPos+1;
311 for ( sal_uInt16 n = 0; n < Count(); n++ )
313 WrongRange& rWrong = GetObject( n );
314 sal_Bool bDelWrong = sal_False;
315 if ( rWrong.nEnd >= nPos )
317 // Alles Wrongs hinter der Einfuegeposition verschieben...
318 if ( rWrong.nStart >= nEndChanges )
320 rWrong.nStart = rWrong.nStart - nDeleted;
321 rWrong.nEnd = rWrong.nEnd - nDeleted;
323 // 1. Innenliegende Wrongs loeschen...
324 else if ( ( rWrong.nStart >= nPos ) && ( rWrong.nEnd <= nEndChanges ) )
326 bDelWrong = sal_True;
328 // 2. Wrong beginnt davor, endet drinnen oder dahinter...
329 else if ( ( rWrong.nStart <= nPos ) && ( rWrong.nEnd > nPos ) )
331 if ( rWrong.nEnd <= nEndChanges ) // endet drinnen
332 rWrong.nEnd = nPos;
333 else
334 rWrong.nEnd = rWrong.nEnd - nDeleted; // endet dahinter
336 // 3. Wrong beginnt drinnen, endet dahinter...
337 else if ( ( rWrong.nStart >= nPos ) && ( rWrong.nEnd > nEndChanges ) )
339 rWrong.nStart = nEndChanges;
340 rWrong.nStart = rWrong.nStart - nDeleted;
341 rWrong.nEnd = rWrong.nEnd - nDeleted;
344 DBG_ASSERT( rWrong.nStart < rWrong.nEnd,
345 "TextInserted, WrongRange: Start >= End?!" );
346 if ( bDelWrong )
348 Remove( n, 1 );
349 n--;
353 DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" );
356 sal_Bool WrongList::NextWrong( sal_uInt16& rnStart, sal_uInt16& rnEnd ) const
359 rnStart enthaelt die Startposition, wird ggf. auf Wrong-Start korrigiert
360 rnEnd braucht nicht inizialisiert sein.
362 for ( sal_uInt16 n = 0; n < Count(); n++ )
364 WrongRange& rWrong = GetObject( n );
365 if ( rWrong.nEnd > rnStart )
367 rnStart = rWrong.nStart;
368 rnEnd = rWrong.nEnd;
369 return sal_True;
372 return sal_False;
375 sal_Bool WrongList::HasWrong( sal_uInt16 nStart, sal_uInt16 nEnd ) const
377 for ( sal_uInt16 n = 0; n < Count(); n++ )
379 WrongRange& rWrong = GetObject( n );
380 if ( ( rWrong.nStart == nStart ) && ( rWrong.nEnd == nEnd ) )
381 return sal_True;
382 else if ( rWrong.nStart >= nStart )
383 break;
385 return sal_False;
388 sal_Bool WrongList::HasAnyWrong( sal_uInt16 nStart, sal_uInt16 nEnd ) const
390 for ( sal_uInt16 n = 0; n < Count(); n++ )
392 WrongRange& rWrong = GetObject( n );
393 if ( ( rWrong.nEnd >= nStart ) && ( rWrong.nStart < nEnd ) )
394 return sal_True;
395 else if ( rWrong.nStart >= nEnd )
396 break;
398 return sal_False;
401 void WrongList::ClearWrongs( sal_uInt16 nStart, sal_uInt16 nEnd,
402 const ContentNode* pNode )
404 for ( sal_uInt16 n = 0; n < Count(); n++ )
406 WrongRange& rWrong = GetObject( n );
407 if ( ( rWrong.nEnd > nStart ) && ( rWrong.nStart < nEnd ) )
409 if ( rWrong.nEnd > nEnd ) // // Laeuft raus
411 rWrong.nStart = nEnd;
412 // Blanks?
413 while ( ( rWrong.nStart < pNode->Len() ) &&
414 ( ( pNode->GetChar( rWrong.nStart ) == ' ' ) ||
415 ( pNode->IsFeature( rWrong.nStart ) ) ) )
417 rWrong.nStart++;
420 else
422 Remove( n, 1 );
423 n--;
428 DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" );
431 void WrongList::InsertWrong( sal_uInt16 nStart, sal_uInt16 nEnd,
432 sal_Bool bClearRange )
434 sal_uInt16 nPos = Count();
435 for ( sal_uInt16 n = 0; n < Count(); n++ )
437 WrongRange& rWrong = GetObject( n );
438 if ( rWrong.nStart >= nStart )
440 nPos = n;
441 if ( bClearRange )
443 // Es kann eigentlich nur Passieren, dass der Wrong genau
444 // hier beginnt und weiter rauslauft, aber nicht, dass hier
445 // mehrere im Bereich liegen...
446 // Genau im Bereich darf keiner liegen, sonst darf diese Methode
447 // garnicht erst gerufen werden!
448 DBG_ASSERT( ( ( rWrong.nStart == nStart ) && ( rWrong.nEnd > nEnd ) )
449 || ( rWrong.nStart > nEnd ), "InsertWrong: RangeMismatch!" );
450 if ( ( rWrong.nStart == nStart ) && ( rWrong.nEnd > nEnd ) )
451 rWrong.nStart = nEnd+1;
453 break;
456 Insert( WrongRange( nStart, nEnd ), nPos );
458 DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" );
461 void WrongList::MarkWrongsInvalid()
463 if ( Count() )
464 MarkInvalid( GetObject( 0 ).nStart, GetObject( Count()-1 ).nEnd );
467 WrongList* WrongList::Clone() const
469 WrongList* pNew = new WrongList;
470 for ( sal_uInt16 n = 0; n < Count(); n++ )
472 WrongRange& rWrong = GetObject( n );
473 pNew->Insert( rWrong, pNew->Count() );
476 return pNew;
479 // #i102062#
480 bool WrongList::operator==(const WrongList& rCompare) const
482 // cleck direct members
483 if(GetInvalidStart() != rCompare.GetInvalidStart()
484 || GetInvalidEnd() != rCompare.GetInvalidEnd()
485 || Count() != rCompare.Count())
487 return false;
490 for(USHORT a(0); a < Count(); a++)
492 const WrongRange& rCandA(GetObject(a));
493 const WrongRange& rCandB(rCompare.GetObject(a));
495 if(rCandA.nStart != rCandB.nStart
496 || rCandA.nEnd != rCandB.nEnd)
498 return false;
502 return true;
505 #ifdef DBG_UTIL
506 sal_Bool WrongList::DbgIsBuggy() const
508 // Pruefen, ob sich Bereiche ueberlappen
509 sal_Bool bError = sal_False;
510 for ( sal_uInt16 _nA = 0; !bError && ( _nA < Count() ); _nA++ )
512 WrongRange& rWrong = GetObject( _nA );
513 for ( sal_uInt16 nB = _nA+1; !bError && ( nB < Count() ); nB++ )
515 WrongRange& rNextWrong = GetObject( nB );
516 // 1) Start davor, End hinterm anderen Start
517 if ( ( rWrong.nStart <= rNextWrong.nStart )
518 && ( rWrong.nEnd >= rNextWrong.nStart ) )
519 bError = sal_True;
520 // 2) Start hinter anderen Start, aber noch vorm anderen End
521 else if ( ( rWrong.nStart >= rNextWrong.nStart)
522 && ( rWrong.nStart <= rNextWrong.nEnd ) )
523 bError = sal_True;
526 return bError;
528 #endif
531 EdtAutoCorrDoc::EdtAutoCorrDoc( ImpEditEngine* pE, ContentNode* pN,
532 sal_uInt16 nCrsr, xub_Unicode cIns )
534 pImpEE = pE;
535 pCurNode = pN;
536 nCursor = nCrsr;
538 bUndoAction = sal_False;
539 bAllowUndoAction = cIns ? sal_True : sal_False;
542 EdtAutoCorrDoc::~EdtAutoCorrDoc()
544 if ( bUndoAction )
545 pImpEE->UndoActionEnd( EDITUNDO_INSERT );
548 sal_Bool EdtAutoCorrDoc::Delete( sal_uInt16 nStt, sal_uInt16 nEnd )
550 EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
551 pImpEE->ImpDeleteSelection( aSel );
552 DBG_ASSERT( nCursor >= nEnd, "Cursor mitten im Geschehen ?!" );
553 nCursor -= ( nEnd-nStt );
554 bAllowUndoAction = sal_False;
555 return sal_True;
558 sal_Bool EdtAutoCorrDoc::Insert( sal_uInt16 nPos, const String& rTxt )
560 EditSelection aSel = EditPaM( pCurNode, nPos );
561 pImpEE->ImpInsertText( aSel, rTxt );
562 DBG_ASSERT( nCursor >= nPos, "Cursor mitten im Geschehen ?!" );
563 nCursor = nCursor + rTxt.Len();
565 if ( bAllowUndoAction && ( rTxt.Len() == 1 ) )
566 ImplStartUndoAction();
567 bAllowUndoAction = sal_False;
569 return sal_True;
572 sal_Bool EdtAutoCorrDoc::Replace( sal_uInt16 nPos, const String& rTxt )
574 // Eigentlich ein Replace einfuehren => Entspr. UNDO
575 sal_uInt16 nEnd = nPos+rTxt.Len();
576 if ( nEnd > pCurNode->Len() )
577 nEnd = pCurNode->Len();
579 // #i5925# First insert new text behind to be deleted text, for keeping attributes.
580 pImpEE->ImpInsertText( EditSelection( EditPaM( pCurNode, nEnd ) ), rTxt );
581 pImpEE->ImpDeleteSelection( EditSelection( EditPaM( pCurNode, nPos ), EditPaM( pCurNode, nEnd ) ) );
583 if ( nPos == nCursor )
584 nCursor = nCursor + rTxt.Len();
586 if ( bAllowUndoAction && ( rTxt.Len() == 1 ) )
587 ImplStartUndoAction();
589 bAllowUndoAction = sal_False;
591 return sal_True;
594 sal_Bool EdtAutoCorrDoc::SetAttr( sal_uInt16 nStt, sal_uInt16 nEnd,
595 sal_uInt16 nSlotId, SfxPoolItem& rItem )
597 SfxItemPool* pPool = &pImpEE->GetEditDoc().GetItemPool();
598 while ( pPool->GetSecondaryPool() &&
599 !pPool->GetName().EqualsAscii( "EditEngineItemPool" ) )
601 pPool = pPool->GetSecondaryPool();
604 sal_uInt16 nWhich = pPool->GetWhich( nSlotId );
605 if ( nWhich )
607 rItem.SetWhich( nWhich );
609 SfxItemSet aSet( pImpEE->GetEmptyItemSet() );
610 aSet.Put( rItem );
612 EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
613 aSel.Max().SetIndex( nEnd ); // ???
614 pImpEE->SetAttribs( aSel, aSet, ATTRSPECIAL_EDGE );
615 bAllowUndoAction = sal_False;
617 return sal_True;
620 sal_Bool EdtAutoCorrDoc::SetINetAttr( sal_uInt16 nStt, sal_uInt16 nEnd,
621 const String& rURL )
623 // Aus dem Text ein Feldbefehl machen...
624 EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) );
625 String aText = pImpEE->GetSelected( aSel );
626 aSel = pImpEE->ImpDeleteSelection( aSel );
627 DBG_ASSERT( nCursor >= nEnd, "Cursor mitten im Geschehen ?!" );
628 nCursor -= ( nEnd-nStt );
629 SvxFieldItem aField( SvxURLField( rURL, aText, SVXURLFORMAT_REPR ),
630 EE_FEATURE_FIELD );
631 pImpEE->InsertField( aSel, aField );
632 nCursor++;
633 pImpEE->UpdateFields();
634 bAllowUndoAction = sal_False;
635 return sal_True;
638 sal_Bool EdtAutoCorrDoc::HasSymbolChars( sal_uInt16 nStt, sal_uInt16 nEnd )
640 USHORT nScriptType = pImpEE->GetScriptType( EditPaM( pCurNode, nStt ) );
641 USHORT nScriptFontInfoItemId = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType );
643 CharAttribArray& rAttribs = pCurNode->GetCharAttribs().GetAttribs();
644 sal_uInt16 nAttrs = rAttribs.Count();
645 for ( sal_uInt16 n = 0; n < nAttrs; n++ )
647 EditCharAttrib* pAttr = rAttribs.GetObject( n );
648 if ( pAttr->GetStart() >= nEnd )
649 return sal_False;
651 if ( ( pAttr->Which() == nScriptFontInfoItemId ) &&
652 ( ((SvxFontItem*)pAttr->GetItem())->GetCharSet() == RTL_TEXTENCODING_SYMBOL ) )
654 // Pruefen, ob das Attribt im Bereich liegt...
655 if ( pAttr->GetEnd() >= nStt )
656 return sal_True;
659 return sal_False;
662 const String* EdtAutoCorrDoc::GetPrevPara( sal_Bool )
664 // Vorherigen Absatz zurueck geben, damit ermittel werden kann,
665 // ob es sich beim aktuellen Wort um einen Satzanfang handelt.
667 bAllowUndoAction = sal_False; // Jetzt nicht mehr...
669 ContentList& rNodes = pImpEE->GetEditDoc();
670 sal_uInt16 nPos = rNodes.GetPos( pCurNode );
672 // Sonderbehandlung: Bullet => Absatzanfang => einfach NULL returnen...
673 const SfxBoolItem& rBulletState = (const SfxBoolItem&)
674 pImpEE->GetParaAttrib( nPos, EE_PARA_BULLETSTATE );
675 sal_Bool bBullet = rBulletState.GetValue() ? sal_True : sal_False;
676 if ( !bBullet && ( pImpEE->aStatus.GetControlWord() & EE_CNTRL_OUTLINER ) )
678 // Der Outliner hat im Gliederungsmodus auf Ebene 0 immer ein Bullet.
679 const SfxInt16Item& rLevel = (const SfxInt16Item&)
680 pImpEE->GetParaAttrib( nPos, EE_PARA_OUTLLEVEL );
681 if ( rLevel.GetValue() == 0 )
682 bBullet = sal_True;
684 if ( bBullet )
685 return NULL;
687 for ( sal_uInt16 n = nPos; n; )
689 n--;
690 ContentNode* pNode = rNodes[n];
691 if ( pNode->Len() )
692 return pNode;
694 return NULL;
698 sal_Bool EdtAutoCorrDoc::ChgAutoCorrWord( sal_uInt16& rSttPos,
699 sal_uInt16 nEndPos, SvxAutoCorrect& rACorrect,
700 const String** ppPara )
702 // Absatz-Anfang oder ein Blank gefunden, suche nach dem Wort
703 // Kuerzel im Auto
705 bAllowUndoAction = sal_False; // Jetzt nicht mehr...
707 String aShort( pCurNode->Copy( rSttPos, nEndPos - rSttPos ) );
708 sal_Bool bRet = sal_False;
710 if( !aShort.Len() )
711 return bRet;
713 LanguageType eLang = pImpEE->GetLanguage( EditPaM( pCurNode, rSttPos+1 ) );
714 const SvxAutocorrWord* pFnd = rACorrect.SearchWordsInList( *pCurNode, rSttPos, nEndPos, *this, eLang );
715 if( pFnd && pFnd->IsTextOnly() )
717 // dann mal ersetzen
718 EditSelection aSel( EditPaM( pCurNode, rSttPos ),
719 EditPaM( pCurNode, nEndPos ) );
720 aSel = pImpEE->ImpDeleteSelection( aSel );
721 DBG_ASSERT( nCursor >= nEndPos, "Cursor mitten im Geschehen ?!" );
722 nCursor -= ( nEndPos-rSttPos );
723 pImpEE->ImpInsertText( aSel, pFnd->GetLong() );
724 nCursor = nCursor + pFnd->GetLong().Len();
725 if( ppPara )
726 *ppPara = pCurNode;
727 bRet = sal_True;
730 return bRet;
733 LanguageType EdtAutoCorrDoc::GetLanguage( sal_uInt16 nPos, sal_Bool ) const
735 return pImpEE->GetLanguage( EditPaM( pCurNode, nPos+1 ) );
738 void EdtAutoCorrDoc::ImplStartUndoAction()
740 sal_uInt16 nPara = pImpEE->GetEditDoc().GetPos( pCurNode );
741 ESelection aSel( nPara, nCursor, nPara, nCursor );
742 pImpEE->UndoActionStart( EDITUNDO_INSERT, aSel );
743 bUndoAction = sal_True;
744 bAllowUndoAction = sal_False;