| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_editeng.hxx" |
| |
| #include <vcl/wrkwin.hxx> |
| #include <vcl/dialog.hxx> |
| #include <vcl/msgbox.hxx> |
| #include <vcl/svapp.hxx> |
| |
| #include <impedit.hxx> |
| #include <editeng/editview.hxx> |
| #include <editeng/editeng.hxx> |
| #include <edtspell.hxx> |
| #include <editeng/flditem.hxx> |
| #include <editeng/fontitem.hxx> |
| #include <svl/intitem.hxx> |
| #include <svl/eitem.hxx> |
| #include <editeng/unolingu.hxx> |
| #include <linguistic/lngprops.hxx> |
| #include <com/sun/star/beans/XPropertySet.hpp> |
| |
| using ::rtl::OUString; |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::beans; |
| using namespace com::sun::star::linguistic2; |
| |
| |
| EditSpellWrapper::EditSpellWrapper( Window* _pWin, |
| Reference< XSpellChecker1 > &xChecker, |
| sal_Bool bIsStart, sal_Bool bIsAllRight, EditView* pView ) : |
| SvxSpellWrapper( _pWin, xChecker, bIsStart, bIsAllRight ) |
| { |
| DBG_ASSERT( pView, "Es muss eine View uebergeben werden!" ); |
| // IgnoreList behalten, ReplaceList loeschen... |
| if (SvxGetChangeAllList().is()) |
| SvxGetChangeAllList()->clear(); |
| pEditView = pView; |
| } |
| |
| void __EXPORT EditSpellWrapper::SpellStart( SvxSpellArea eArea ) |
| { |
| ImpEditEngine* pImpEE = pEditView->GetImpEditEngine(); |
| SpellInfo* pSpellInfo = pImpEE->GetSpellInfo(); |
| |
| if ( eArea == SVX_SPELL_BODY_START ) |
| { |
| // Wird gerufen, wenn |
| // a) Spell-Forwad ist am Ende angekomment und soll von vorne beginnen |
| // IsEndDone() liefert auch sal_True, wenn Rueckwaerts-Spelling am Ende gestartet wird! |
| if ( IsEndDone() ) |
| { |
| pSpellInfo->bSpellToEnd = sal_False; |
| pSpellInfo->aSpellTo = pSpellInfo->aSpellStart; |
| pEditView->GetImpEditView()->SetEditSelection( |
| pImpEE->GetEditDoc().GetStartPaM() ); |
| } |
| else |
| { |
| pSpellInfo->bSpellToEnd = sal_True; |
| pSpellInfo->aSpellTo = pImpEE->CreateEPaM( |
| pImpEE->GetEditDoc().GetStartPaM() ); |
| } |
| } |
| else if ( eArea == SVX_SPELL_BODY_END ) |
| { |
| // Wird gerufen, wenn |
| // a) Spell-Forwad wird gestartet |
| // IsStartDone() liefert auch sal_True, wenn Vorwaerts-Spelling am Anfang gestartet wird! |
| if ( !IsStartDone() ) |
| { |
| pSpellInfo->bSpellToEnd = sal_True; |
| pSpellInfo->aSpellTo = pImpEE->CreateEPaM( |
| pImpEE->GetEditDoc().GetEndPaM() ); |
| } |
| else |
| { |
| pSpellInfo->bSpellToEnd = sal_False; |
| pSpellInfo->aSpellTo = pSpellInfo->aSpellStart; |
| pEditView->GetImpEditView()->SetEditSelection( |
| pImpEE->GetEditDoc().GetEndPaM() ); |
| } |
| } |
| else if ( eArea == SVX_SPELL_BODY ) |
| { |
| ; // Wird ueber SpellNextDocument von App gehandelt |
| |
| // pSpellInfo->bSpellToEnd = sal_True; |
| // pSpellInfo->aSpellTo = pImpEE->CreateEPaM( pImpEE->GetEditDoc().GetEndPaM() ); |
| } |
| else |
| { |
| DBG_ERROR( "SpellStart: Unknown Area!" ); |
| } |
| } |
| |
| sal_Bool EditSpellWrapper::SpellContinue() |
| { |
| SetLast( pEditView->GetImpEditEngine()->ImpSpell( pEditView ) ); |
| return GetLast().is(); |
| } |
| |
| void __EXPORT EditSpellWrapper::SpellEnd() |
| { |
| // Base class will show language errors... |
| SvxSpellWrapper::SpellEnd(); |
| } |
| |
| sal_Bool __EXPORT EditSpellWrapper::HasOtherCnt() |
| { |
| return sal_False; |
| } |
| |
| sal_Bool __EXPORT EditSpellWrapper::SpellMore() |
| { |
| ImpEditEngine* pImpEE = pEditView->GetImpEditEngine(); |
| SpellInfo* pSpellInfo = pImpEE->GetSpellInfo(); |
| sal_Bool bMore = sal_False; |
| if ( pSpellInfo->bMultipleDoc ) |
| { |
| bMore = pImpEE->GetEditEnginePtr()->SpellNextDocument(); |
| SetCurTextObj( pImpEE->GetEditEnginePtr()->GetCurTextObj() ); |
| if ( bMore ) |
| { |
| // Der Text wurde in diese Engine getreten, bei Rueckwaerts |
| // muss die Selektion hinten sein. |
| Reference< XPropertySet > xProp( SvxGetLinguPropertySet() ); |
| pEditView->GetImpEditView()->SetEditSelection( |
| pImpEE->GetEditDoc().GetStartPaM() ); |
| } |
| } |
| return bMore; |
| } |
| |
| void __EXPORT EditSpellWrapper::ScrollArea() |
| { |
| // Keine weitere Aktion noetig... |
| // Es sei denn, der Bereich soll in die Mitte gescrollt werden, |
| // und nicht irgendwo stehen. |
| } |
| |
| void __EXPORT EditSpellWrapper::ReplaceAll( const String &rNewText, |
| sal_Int16 ) |
| { |
| // Wird gerufen, wenn Wort in ReplaceList des SpellCheckers |
| pEditView->InsertText( rNewText ); |
| CheckSpellTo(); |
| } |
| |
| void __EXPORT EditSpellWrapper::ChangeWord( const String& rNewWord, |
| const sal_uInt16 ) |
| { |
| // Wird gerufen, wenn Wort Button Change |
| // bzw. intern von mir bei ChangeAll |
| |
| // Wenn Punkt hinterm Wort, wird dieser nicht mitgegeben. |
| // Falls '"' => PreStripped. |
| String aNewWord( rNewWord ); |
| pEditView->InsertText( aNewWord ); |
| CheckSpellTo(); |
| } |
| |
| void __EXPORT EditSpellWrapper::ChangeThesWord( const String& rNewWord ) |
| { |
| pEditView->InsertText( rNewWord ); |
| CheckSpellTo(); |
| } |
| |
| void __EXPORT EditSpellWrapper::AutoCorrect( const String&, const String& ) |
| { |
| } |
| |
| void EditSpellWrapper::CheckSpellTo() |
| { |
| ImpEditEngine* pImpEE = pEditView->GetImpEditEngine(); |
| SpellInfo* pSpellInfo = pImpEE->GetSpellInfo(); |
| EditPaM aPaM( pEditView->GetImpEditView()->GetEditSelection().Max() ); |
| EPaM aEPaM = pImpEE->CreateEPaM( aPaM ); |
| if ( aEPaM.nPara == pSpellInfo->aSpellTo.nPara ) |
| { |
| // prueffen, ob SpellToEnd noch gueltiger Index, falls in dem Absatz |
| // ersetzt wurde. |
| if ( pSpellInfo->aSpellTo.nIndex > aPaM.GetNode()->Len() ) |
| pSpellInfo->aSpellTo.nIndex = aPaM.GetNode()->Len(); |
| } |
| } |
| |
| ////////////////////////////////////////////////////////////////////// |
| |
| SV_IMPL_VARARR( WrongRanges, WrongRange ); |
| |
| WrongList::WrongList() |
| { |
| nInvalidStart = 0; |
| nInvalidEnd = 0xFFFF; |
| } |
| |
| WrongList::~WrongList() |
| { |
| } |
| |
| void WrongList::MarkInvalid( sal_uInt16 nS, sal_uInt16 nE ) |
| { |
| if ( ( nInvalidStart == NOT_INVALID ) || ( nInvalidStart > nS ) ) |
| nInvalidStart = nS; |
| if ( nInvalidEnd < nE ) |
| nInvalidEnd = nE; |
| } |
| |
| void WrongList::TextInserted( sal_uInt16 nPos, sal_uInt16 nNew, sal_Bool bPosIsSep ) |
| { |
| if ( !IsInvalid() ) |
| { |
| nInvalidStart = nPos; |
| nInvalidEnd = nPos+nNew; |
| } |
| else |
| { |
| if ( nInvalidStart > nPos ) |
| nInvalidStart = nPos; |
| if ( nInvalidEnd >= nPos ) |
| nInvalidEnd = nInvalidEnd + nNew; |
| else |
| nInvalidEnd = nPos+nNew; |
| } |
| |
| for ( sal_uInt16 n = 0; n < Count(); n++ ) |
| { |
| WrongRange& rWrong = GetObject( n ); |
| sal_Bool bRefIsValid = sal_True; |
| if ( rWrong.nEnd >= nPos ) |
| { |
| // Alle Wrongs hinter der Einfuegeposition verschieben... |
| if ( rWrong.nStart > nPos ) |
| { |
| rWrong.nStart = rWrong.nStart + nNew; |
| rWrong.nEnd = rWrong.nEnd + nNew; |
| } |
| // 1: Startet davor, geht bis nPos... |
| else if ( rWrong.nEnd == nPos ) |
| { |
| // Sollte bei einem Blank unterbunden werden! |
| if ( !bPosIsSep ) |
| rWrong.nEnd = rWrong.nEnd + nNew; |
| } |
| // 2: Startet davor, geht hinter Pos... |
| else if ( ( rWrong.nStart < nPos ) && ( rWrong.nEnd > nPos ) ) |
| { |
| rWrong.nEnd = rWrong.nEnd + nNew; |
| // Bei einem Trenner das Wrong entfernen und neu pruefen |
| if ( bPosIsSep ) |
| { |
| // Wrong aufteilen... |
| WrongRange aNewWrong( rWrong.nStart, nPos ); |
| rWrong.nStart = nPos+1; |
| Insert( aNewWrong, n ); |
| bRefIsValid = sal_False; // Referenz nach Insert nicht mehr gueltig, der andere wurde davor an dessen Position eingefuegt |
| n++; // Diesen nicht nochmal... |
| } |
| } |
| // 3: Attribut startet auf Pos... |
| else if ( rWrong.nStart == nPos ) |
| { |
| rWrong.nEnd = rWrong.nEnd + nNew; |
| if ( bPosIsSep ) |
| rWrong.nStart++; |
| } |
| } |
| DBG_ASSERT( !bRefIsValid || ( rWrong.nStart < rWrong.nEnd ), |
| "TextInserted, WrongRange: Start >= End?!" ); |
| } |
| |
| DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" ); |
| } |
| |
| void WrongList::TextDeleted( sal_uInt16 nPos, sal_uInt16 nDeleted ) |
| { |
| sal_uInt16 nEndChanges = nPos+nDeleted; |
| if ( !IsInvalid() ) |
| { |
| sal_uInt16 nNewInvalidStart = nPos ? nPos - 1 : 0; |
| nInvalidStart = nNewInvalidStart; |
| nInvalidEnd = nNewInvalidStart + 1; |
| } |
| else |
| { |
| if ( nInvalidStart > nPos ) |
| nInvalidStart = nPos; |
| if ( nInvalidEnd > nPos ) |
| { |
| if ( nInvalidEnd > nEndChanges ) |
| nInvalidEnd = nInvalidEnd - nDeleted; |
| else |
| nInvalidEnd = nPos+1; |
| } |
| } |
| |
| for ( sal_uInt16 n = 0; n < Count(); n++ ) |
| { |
| WrongRange& rWrong = GetObject( n ); |
| sal_Bool bDelWrong = sal_False; |
| if ( rWrong.nEnd >= nPos ) |
| { |
| // Alles Wrongs hinter der Einfuegeposition verschieben... |
| if ( rWrong.nStart >= nEndChanges ) |
| { |
| rWrong.nStart = rWrong.nStart - nDeleted; |
| rWrong.nEnd = rWrong.nEnd - nDeleted; |
| } |
| // 1. Innenliegende Wrongs loeschen... |
| else if ( ( rWrong.nStart >= nPos ) && ( rWrong.nEnd <= nEndChanges ) ) |
| { |
| bDelWrong = sal_True; |
| } |
| // 2. Wrong beginnt davor, endet drinnen oder dahinter... |
| else if ( ( rWrong.nStart <= nPos ) && ( rWrong.nEnd > nPos ) ) |
| { |
| if ( rWrong.nEnd <= nEndChanges ) // endet drinnen |
| rWrong.nEnd = nPos; |
| else |
| rWrong.nEnd = rWrong.nEnd - nDeleted; // endet dahinter |
| } |
| // 3. Wrong beginnt drinnen, endet dahinter... |
| else if ( ( rWrong.nStart >= nPos ) && ( rWrong.nEnd > nEndChanges ) ) |
| { |
| rWrong.nStart = nEndChanges; |
| rWrong.nStart = rWrong.nStart - nDeleted; |
| rWrong.nEnd = rWrong.nEnd - nDeleted; |
| } |
| } |
| DBG_ASSERT( rWrong.nStart < rWrong.nEnd, |
| "TextInserted, WrongRange: Start >= End?!" ); |
| if ( bDelWrong ) |
| { |
| Remove( n, 1 ); |
| n--; |
| } |
| } |
| |
| DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" ); |
| } |
| |
| sal_Bool WrongList::NextWrong( sal_uInt16& rnStart, sal_uInt16& rnEnd ) const |
| { |
| /* |
| rnStart enthaelt die Startposition, wird ggf. auf Wrong-Start korrigiert |
| rnEnd braucht nicht inizialisiert sein. |
| */ |
| for ( sal_uInt16 n = 0; n < Count(); n++ ) |
| { |
| WrongRange& rWrong = GetObject( n ); |
| if ( rWrong.nEnd > rnStart ) |
| { |
| rnStart = rWrong.nStart; |
| rnEnd = rWrong.nEnd; |
| return sal_True; |
| } |
| } |
| return sal_False; |
| } |
| |
| sal_Bool WrongList::HasWrong( sal_uInt16 nStart, sal_uInt16 nEnd ) const |
| { |
| for ( sal_uInt16 n = 0; n < Count(); n++ ) |
| { |
| WrongRange& rWrong = GetObject( n ); |
| if ( ( rWrong.nStart == nStart ) && ( rWrong.nEnd == nEnd ) ) |
| return sal_True; |
| else if ( rWrong.nStart >= nStart ) |
| break; |
| } |
| return sal_False; |
| } |
| |
| sal_Bool WrongList::HasAnyWrong( sal_uInt16 nStart, sal_uInt16 nEnd ) const |
| { |
| for ( sal_uInt16 n = 0; n < Count(); n++ ) |
| { |
| WrongRange& rWrong = GetObject( n ); |
| if ( ( rWrong.nEnd >= nStart ) && ( rWrong.nStart < nEnd ) ) |
| return sal_True; |
| else if ( rWrong.nStart >= nEnd ) |
| break; |
| } |
| return sal_False; |
| } |
| |
| void WrongList::ClearWrongs( sal_uInt16 nStart, sal_uInt16 nEnd, |
| const ContentNode* pNode ) |
| { |
| for ( sal_uInt16 n = 0; n < Count(); n++ ) |
| { |
| WrongRange& rWrong = GetObject( n ); |
| if ( ( rWrong.nEnd > nStart ) && ( rWrong.nStart < nEnd ) ) |
| { |
| if ( rWrong.nEnd > nEnd ) // // Laeuft raus |
| { |
| rWrong.nStart = nEnd; |
| // Blanks? |
| while ( ( rWrong.nStart < pNode->Len() ) && |
| ( ( pNode->GetChar( rWrong.nStart ) == ' ' ) || |
| ( pNode->IsFeature( rWrong.nStart ) ) ) ) |
| { |
| rWrong.nStart++; |
| } |
| } |
| else |
| { |
| Remove( n, 1 ); |
| n--; |
| } |
| } |
| } |
| |
| DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" ); |
| } |
| |
| void WrongList::InsertWrong( sal_uInt16 nStart, sal_uInt16 nEnd, |
| sal_Bool bClearRange ) |
| { |
| sal_uInt16 nPos = Count(); |
| for ( sal_uInt16 n = 0; n < Count(); n++ ) |
| { |
| WrongRange& rWrong = GetObject( n ); |
| if ( rWrong.nStart >= nStart ) |
| { |
| nPos = n; |
| if ( bClearRange ) |
| { |
| // Es kann eigentlich nur Passieren, dass der Wrong genau |
| // hier beginnt und weiter rauslauft, aber nicht, dass hier |
| // mehrere im Bereich liegen... |
| // Genau im Bereich darf keiner liegen, sonst darf diese Methode |
| // garnicht erst gerufen werden! |
| DBG_ASSERT( ( ( rWrong.nStart == nStart ) && ( rWrong.nEnd > nEnd ) ) |
| || ( rWrong.nStart > nEnd ), "InsertWrong: RangeMismatch!" ); |
| if ( ( rWrong.nStart == nStart ) && ( rWrong.nEnd > nEnd ) ) |
| rWrong.nStart = nEnd+1; |
| } |
| break; |
| } |
| } |
| Insert( WrongRange( nStart, nEnd ), nPos ); |
| |
| DBG_ASSERT( !DbgIsBuggy(), "InsertWrong: WrongList kaputt!" ); |
| } |
| |
| void WrongList::MarkWrongsInvalid() |
| { |
| if ( Count() ) |
| MarkInvalid( GetObject( 0 ).nStart, GetObject( Count()-1 ).nEnd ); |
| } |
| |
| WrongList* WrongList::Clone() const |
| { |
| WrongList* pNew = new WrongList; |
| for ( sal_uInt16 n = 0; n < Count(); n++ ) |
| { |
| WrongRange& rWrong = GetObject( n ); |
| pNew->Insert( rWrong, pNew->Count() ); |
| } |
| |
| return pNew; |
| } |
| |
| // #i102062# |
| bool WrongList::operator==(const WrongList& rCompare) const |
| { |
| // cleck direct members |
| if(GetInvalidStart() != rCompare.GetInvalidStart() |
| || GetInvalidEnd() != rCompare.GetInvalidEnd() |
| || Count() != rCompare.Count()) |
| { |
| return false; |
| } |
| |
| for(sal_uInt16 a(0); a < Count(); a++) |
| { |
| const WrongRange& rCandA(GetObject(a)); |
| const WrongRange& rCandB(rCompare.GetObject(a)); |
| |
| if(rCandA.nStart != rCandB.nStart |
| || rCandA.nEnd != rCandB.nEnd) |
| { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| #ifdef DBG_UTIL |
| sal_Bool WrongList::DbgIsBuggy() const |
| { |
| // Pruefen, ob sich Bereiche ueberlappen |
| sal_Bool bError = sal_False; |
| for ( sal_uInt16 _nA = 0; !bError && ( _nA < Count() ); _nA++ ) |
| { |
| WrongRange& rWrong = GetObject( _nA ); |
| for ( sal_uInt16 nB = _nA+1; !bError && ( nB < Count() ); nB++ ) |
| { |
| WrongRange& rNextWrong = GetObject( nB ); |
| // 1) Start davor, End hinterm anderen Start |
| if ( ( rWrong.nStart <= rNextWrong.nStart ) |
| && ( rWrong.nEnd >= rNextWrong.nStart ) ) |
| bError = sal_True; |
| // 2) Start hinter anderen Start, aber noch vorm anderen End |
| else if ( ( rWrong.nStart >= rNextWrong.nStart) |
| && ( rWrong.nStart <= rNextWrong.nEnd ) ) |
| bError = sal_True; |
| } |
| } |
| return bError; |
| } |
| #endif |
| |
| ////////////////////////////////////////////////////////////////////// |
| |
| EdtAutoCorrDoc::EdtAutoCorrDoc( ImpEditEngine* pE, ContentNode* pN, |
| sal_uInt16 nCrsr, xub_Unicode cIns ) |
| { |
| pImpEE = pE; |
| pCurNode = pN; |
| nCursor = nCrsr; |
| |
| bUndoAction = sal_False; |
| bAllowUndoAction = cIns ? sal_True : sal_False; |
| } |
| |
| EdtAutoCorrDoc::~EdtAutoCorrDoc() |
| { |
| if ( bUndoAction ) |
| pImpEE->UndoActionEnd( EDITUNDO_INSERT ); |
| } |
| |
| sal_Bool EdtAutoCorrDoc::Delete( sal_uInt16 nStt, sal_uInt16 nEnd ) |
| { |
| EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) ); |
| pImpEE->ImpDeleteSelection( aSel ); |
| DBG_ASSERT( nCursor >= nEnd, "Cursor mitten im Geschehen ?!" ); |
| nCursor -= ( nEnd-nStt ); |
| bAllowUndoAction = sal_False; |
| return sal_True; |
| } |
| |
| sal_Bool EdtAutoCorrDoc::Insert( sal_uInt16 nPos, const String& rTxt ) |
| { |
| EditSelection aSel = EditPaM( pCurNode, nPos ); |
| pImpEE->ImpInsertText( aSel, rTxt ); |
| DBG_ASSERT( nCursor >= nPos, "Cursor mitten im Geschehen ?!" ); |
| nCursor = nCursor + rTxt.Len(); |
| |
| if ( bAllowUndoAction && ( rTxt.Len() == 1 ) ) |
| ImplStartUndoAction(); |
| bAllowUndoAction = sal_False; |
| |
| return sal_True; |
| } |
| |
| sal_Bool EdtAutoCorrDoc::Replace( sal_uInt16 nPos, const String& rTxt ) |
| { |
| return ReplaceRange( nPos, rTxt.Len(), rTxt ); |
| } |
| |
| sal_Bool EdtAutoCorrDoc::ReplaceRange( xub_StrLen nPos, xub_StrLen nSourceLength, const String& rTxt ) |
| { |
| // Eigentlich ein Replace einfuehren => Entspr. UNDO |
| sal_uInt16 nEnd = nPos+nSourceLength; |
| if ( nEnd > pCurNode->Len() ) |
| nEnd = pCurNode->Len(); |
| |
| // #i5925# First insert new text behind to be deleted text, for keeping attributes. |
| pImpEE->ImpInsertText( EditSelection( EditPaM( pCurNode, nEnd ) ), rTxt ); |
| pImpEE->ImpDeleteSelection( EditSelection( EditPaM( pCurNode, nPos ), EditPaM( pCurNode, nEnd ) ) ); |
| |
| if ( nPos == nCursor ) |
| nCursor = nCursor + rTxt.Len(); |
| |
| if ( bAllowUndoAction && ( rTxt.Len() == 1 ) ) |
| ImplStartUndoAction(); |
| |
| bAllowUndoAction = sal_False; |
| |
| return sal_True; |
| } |
| |
| sal_Bool EdtAutoCorrDoc::SetAttr( sal_uInt16 nStt, sal_uInt16 nEnd, |
| sal_uInt16 nSlotId, SfxPoolItem& rItem ) |
| { |
| SfxItemPool* pPool = &pImpEE->GetEditDoc().GetItemPool(); |
| while ( pPool->GetSecondaryPool() && |
| !pPool->GetName().EqualsAscii( "EditEngineItemPool" ) ) |
| { |
| pPool = pPool->GetSecondaryPool(); |
| |
| } |
| sal_uInt16 nWhich = pPool->GetWhich( nSlotId ); |
| if ( nWhich ) |
| { |
| rItem.SetWhich( nWhich ); |
| |
| SfxItemSet aSet( pImpEE->GetEmptyItemSet() ); |
| aSet.Put( rItem ); |
| |
| EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) ); |
| aSel.Max().SetIndex( nEnd ); // ??? |
| pImpEE->SetAttribs( aSel, aSet, ATTRSPECIAL_EDGE ); |
| bAllowUndoAction = sal_False; |
| } |
| return sal_True; |
| } |
| |
| sal_Bool EdtAutoCorrDoc::SetINetAttr( sal_uInt16 nStt, sal_uInt16 nEnd, |
| const String& rURL ) |
| { |
| // Aus dem Text ein Feldbefehl machen... |
| EditSelection aSel( EditPaM( pCurNode, nStt ), EditPaM( pCurNode, nEnd ) ); |
| String aText = pImpEE->GetSelected( aSel ); |
| aSel = pImpEE->ImpDeleteSelection( aSel ); |
| DBG_ASSERT( nCursor >= nEnd, "Cursor mitten im Geschehen ?!" ); |
| nCursor -= ( nEnd-nStt ); |
| SvxFieldItem aField( SvxURLField( rURL, aText, SVXURLFORMAT_REPR ), |
| EE_FEATURE_FIELD ); |
| pImpEE->InsertField( aSel, aField ); |
| nCursor++; |
| pImpEE->UpdateFields(); |
| bAllowUndoAction = sal_False; |
| return sal_True; |
| } |
| |
| sal_Bool EdtAutoCorrDoc::HasSymbolChars( sal_uInt16 nStt, sal_uInt16 nEnd ) |
| { |
| sal_uInt16 nScriptType = pImpEE->GetScriptType( EditPaM( pCurNode, nStt ) ); |
| sal_uInt16 nScriptFontInfoItemId = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ); |
| |
| CharAttribArray& rAttribs = pCurNode->GetCharAttribs().GetAttribs(); |
| sal_uInt16 nAttrs = rAttribs.Count(); |
| for ( sal_uInt16 n = 0; n < nAttrs; n++ ) |
| { |
| EditCharAttrib* pAttr = rAttribs.GetObject( n ); |
| if ( pAttr->GetStart() >= nEnd ) |
| return sal_False; |
| |
| if ( ( pAttr->Which() == nScriptFontInfoItemId ) && |
| ( ((SvxFontItem*)pAttr->GetItem())->GetCharSet() == RTL_TEXTENCODING_SYMBOL ) ) |
| { |
| // Pruefen, ob das Attribt im Bereich liegt... |
| if ( pAttr->GetEnd() >= nStt ) |
| return sal_True; |
| } |
| } |
| return sal_False; |
| } |
| |
| const String* EdtAutoCorrDoc::GetPrevPara( sal_Bool ) |
| { |
| // Vorherigen Absatz zurueck geben, damit ermittel werden kann, |
| // ob es sich beim aktuellen Wort um einen Satzanfang handelt. |
| |
| bAllowUndoAction = sal_False; // Jetzt nicht mehr... |
| |
| ContentList& rNodes = pImpEE->GetEditDoc(); |
| sal_uInt16 nPos = rNodes.GetPos( pCurNode ); |
| |
| // Sonderbehandlung: Bullet => Absatzanfang => einfach NULL returnen... |
| const SfxBoolItem& rBulletState = (const SfxBoolItem&) |
| pImpEE->GetParaAttrib( nPos, EE_PARA_BULLETSTATE ); |
| sal_Bool bBullet = rBulletState.GetValue() ? sal_True : sal_False; |
| if ( !bBullet && ( pImpEE->aStatus.GetControlWord() & EE_CNTRL_OUTLINER ) ) |
| { |
| // Der Outliner hat im Gliederungsmodus auf Ebene 0 immer ein Bullet. |
| const SfxInt16Item& rLevel = (const SfxInt16Item&) |
| pImpEE->GetParaAttrib( nPos, EE_PARA_OUTLLEVEL ); |
| if ( rLevel.GetValue() == 0 ) |
| bBullet = sal_True; |
| } |
| if ( bBullet ) |
| return NULL; |
| |
| for ( sal_uInt16 n = nPos; n; ) |
| { |
| n--; |
| ContentNode* pNode = rNodes[n]; |
| if ( pNode->Len() ) |
| return pNode; |
| } |
| return NULL; |
| |
| } |
| |
| sal_Bool EdtAutoCorrDoc::ChgAutoCorrWord( sal_uInt16& rSttPos, |
| sal_uInt16 nEndPos, SvxAutoCorrect& rACorrect, |
| const String** ppPara ) |
| { |
| // Absatz-Anfang oder ein Blank gefunden, suche nach dem Wort |
| // Kuerzel im Auto |
| |
| bAllowUndoAction = sal_False; // Jetzt nicht mehr... |
| |
| String aShort( pCurNode->Copy( rSttPos, nEndPos - rSttPos ) ); |
| sal_Bool bRet = sal_False; |
| |
| if( !aShort.Len() ) |
| return bRet; |
| |
| LanguageType eLang = pImpEE->GetLanguage( EditPaM( pCurNode, rSttPos+1 ) ); |
| const SvxAutocorrWord* pFnd = rACorrect.SearchWordsInList( *pCurNode, rSttPos, nEndPos, *this, eLang ); |
| if( pFnd && pFnd->IsTextOnly() ) |
| { |
| // dann mal ersetzen |
| EditSelection aSel( EditPaM( pCurNode, rSttPos ), |
| EditPaM( pCurNode, nEndPos ) ); |
| aSel = pImpEE->ImpDeleteSelection( aSel ); |
| DBG_ASSERT( nCursor >= nEndPos, "Cursor mitten im Geschehen ?!" ); |
| nCursor -= ( nEndPos-rSttPos ); |
| pImpEE->ImpInsertText( aSel, pFnd->GetLong() ); |
| nCursor = nCursor + pFnd->GetLong().Len(); |
| if( ppPara ) |
| *ppPara = pCurNode; |
| bRet = sal_True; |
| } |
| |
| return bRet; |
| } |
| |
| LanguageType EdtAutoCorrDoc::GetLanguage( sal_uInt16 nPos, sal_Bool ) const |
| { |
| return pImpEE->GetLanguage( EditPaM( pCurNode, nPos+1 ) ); |
| } |
| |
| void EdtAutoCorrDoc::ImplStartUndoAction() |
| { |
| sal_uInt16 nPara = pImpEE->GetEditDoc().GetPos( pCurNode ); |
| ESelection aSel( nPara, nCursor, nPara, nCursor ); |
| pImpEE->UndoActionStart( EDITUNDO_INSERT, aSel ); |
| bUndoAction = sal_True; |
| bAllowUndoAction = sal_False; |
| } |
| |