1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: edlingu.cxx,v $
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_sw.hxx"
34 #include <com/sun/star/linguistic2/ProofreadingResult.hpp>
35 #include <com/sun/star/linguistic2/XProofreader.hpp>
36 #include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
37 #include <com/sun/star/text/XFlatParagraph.hpp>
39 #include <unoflatpara.hxx>
42 #include <comcore.hrc>
44 #include <hintids.hxx>
45 #include <linguistic/lngprops.hxx>
46 #include <vcl/msgbox.hxx>
47 #include <svx/unolingu.hxx>
48 #include <svx/svxacorr.hxx>
49 #include <svx/langitem.hxx>
50 #include <svx/SpellPortions.hxx>
51 #include <svx/scripttypeitem.hxx>
52 #include <charatr.hxx>
55 #include <rootfrm.hxx> // SwRootFrm
57 #include <swundo.hxx> // fuer die UndoIds
58 #include <ndtxt.hxx> // AdjHyphPos
59 #include <viewopt.hxx> // HyphStart/End
60 #include <viscrs.hxx> // SwShellCrsr
61 #include <SwGrammarMarkUp.hxx> // SwWrongList
62 #include <mdiexp.hxx> // Statusanzeige
64 #include <statstr.hrc> // StatLine-String
67 #include <crsskip.hxx>
68 #include <splargs.hxx>
69 #include <redline.hxx> // SwRedline
70 #include <docary.hxx> // SwRedlineTbl
72 #include <txatbase.hxx>
75 using namespace ::svx
;
76 using namespace ::com::sun::star
;
77 using namespace ::com::sun::star::uno
;
78 using namespace ::com::sun::star::beans
;
79 using namespace ::com::sun::star::linguistic2
;
81 #define C2U(cChar) rtl::OUString::createFromAscii(cChar)
83 extern void repaintTextFrames( SwModify
& rModify
);
85 /*************************************************************************
87 *************************************************************************/
100 inline SwEditShell
*GetSh() { return pSh
; }
101 inline const SwEditShell
*GetSh() const { return pSh
; }
103 inline const SwPosition
*GetEnd() const { return pEnd
; }
104 inline void SetEnd( SwPosition
* pNew
){ delete pEnd
; pEnd
= pNew
; }
106 inline const SwPosition
*GetStart() const { return pStart
; }
107 inline void SetStart( SwPosition
* pNew
){ delete pStart
; pStart
= pNew
; }
109 inline const SwPosition
*GetCurr() const { return pCurr
; }
110 inline void SetCurr( SwPosition
* pNew
){ delete pCurr
; pCurr
= pNew
; }
112 inline const SwPosition
*GetCurrX() const { return pCurrX
; }
113 inline void SetCurrX( SwPosition
* pNew
){ delete pCurrX
; pCurrX
= pNew
; }
115 inline sal_uInt16
& GetCrsrCnt(){ return nCrsrCnt
; }
117 // Der UI-Bauchladen:
118 void _Start( SwEditShell
*pSh
, SwDocPositions eStart
,
119 SwDocPositions eEnd
);
120 void _End(bool bRestoreSelection
= true);
123 /*************************************************************************
125 *************************************************************************/
127 // #i18881# to be able to identify the postions of the changed words
128 // the content positions of each portion need to be saved
129 struct SpellContentPosition
134 typedef std::vector
<SpellContentPosition
> SpellContentPositions
;
135 class SwSpellIter
: public SwLinguIter
137 uno::Reference
< XSpellChecker1
> xSpeller
;
138 ::svx::SpellPortions aLastPortions
;
140 SpellContentPositions aLastPositions
;
141 bool bBackToStartOfSentence
;
144 void CreatePortion(uno::Reference
< XSpellAlternatives
> xAlt
,
145 linguistic2::ProofreadingResult
* pGrammarResult
,
146 bool bIsField
, bool bIsHidden
);
148 void AddPortion(uno::Reference
< XSpellAlternatives
> xAlt
,
149 linguistic2::ProofreadingResult
* pGrammarResult
,
150 const SpellContentPositions
& rDeletedRedlines
);
153 bBackToStartOfSentence(false) {}
155 void Start( SwEditShell
*pSh
, SwDocPositions eStart
, SwDocPositions eEnd
);
157 uno::Any
Continue( sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
);
159 bool SpellSentence(::svx::SpellPortions
& rPortions
, bool bIsGrammarCheck
);
160 void ToSentenceStart();
161 const ::svx::SpellPortions
GetLastPortions(){ return aLastPortions
;}
162 SpellContentPositions
GetLastPositions() {return aLastPositions
;}
165 /*************************************************************************
167 * used for text conversion
168 *************************************************************************/
170 class SwConvIter
: public SwLinguIter
172 SwConversionArgs
&rArgs
;
174 SwConvIter( SwConversionArgs
&rConvArgs
) :
178 void Start( SwEditShell
*pSh
, SwDocPositions eStart
, SwDocPositions eEnd
);
180 uno::Any
Continue( sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
);
183 /*************************************************************************
185 *************************************************************************/
187 class SwHyphIter
: public SwLinguIter
190 void DelSoftHyph( SwPaM
&rPam
);
193 SwHyphIter() : bOldIdle(sal_False
) {}
195 void Start( SwEditShell
*pSh
, SwDocPositions eStart
, SwDocPositions eEnd
);
200 uno::Any
Continue( sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
);
203 void InsertSoftHyph( const xub_StrLen nHyphPos
);
204 void ShowSelection();
207 static SwSpellIter
* pSpellIter
= 0;
208 static SwConvIter
* pConvIter
= 0;
209 static SwHyphIter
* pHyphIter
= 0;
211 // Wir ersparen uns in Hyphenate ein GetFrm()
212 // Achtung: in txtedt.cxx stehen extern-Deklarationen auf diese Pointer!
213 const SwTxtNode
*pLinguNode
;
216 /*************************************************************************
217 * SwLinguIter::SwLinguIter
218 *************************************************************************/
220 SwLinguIter::SwLinguIter()
221 : pSh( 0 ), pStart( 0 ), pEnd( 0 ), pCurr( 0 ), pCurrX( 0 )
223 // @@@ es fehlt: Sicherstellen der Reentrance, ASSERTs etc.
226 /*************************************************************************
228 *************************************************************************/
232 void SwLinguIter::_Start( SwEditShell
*pShell
, SwDocPositions eStart
,
233 SwDocPositions eEnd
)
235 // es fehlt: Sicherstellen der Reentrance, Locking
243 SET_CURR_SHELL( pSh
);
245 ASSERT( !pEnd
, "LinguStart ohne End?");
247 SwPaM
*pCrsr
= pSh
->GetCrsr();
249 // pStk->SetCurCrsr();
250 // if( pCrsr->HasMark() || pCrsr != pCrsr->GetNext() )
251 if( pShell
->HasSelection() || pCrsr
!= pCrsr
->GetNext() )
253 bSetCurr
= 0 != GetCurr();
254 nCrsrCnt
= pSh
->GetCrsrCnt();
255 if( pSh
->IsTableMode() )
256 pSh
->TblCrsrToCursor();
260 for( n
= 0; n
< nCrsrCnt
; ++n
)
265 pSh
->Pop( sal_False
);
269 bSetCurr
= sal_False
;
272 pSh
->SetLinguRange( eStart
, eEnd
);
275 pCrsr
= pSh
->GetCrsr();
276 if ( *pCrsr
->GetPoint() > *pCrsr
->GetMark() )
279 pStart
= new SwPosition( *pCrsr
->GetPoint() );
280 pEnd
= new SwPosition( *pCrsr
->GetMark() );
283 SwPosition
* pNew
= new SwPosition( *GetStart() );
285 pNew
= new SwPosition( *pNew
);
295 /*************************************************************************
297 *************************************************************************/
301 void SwLinguIter::_End(bool bRestoreSelection
)
306 ASSERT( pEnd
, "SwEditShell::SpellEnd() ohne Start?");
307 if(bRestoreSelection
)
310 pSh
->Pop( sal_False
);
322 #ifdef LINGU_STATISTIK
323 aSwLinguStat
.Flush();
327 /*************************************************************************
328 * virtual SwSpellIter::Start()
329 *************************************************************************/
333 void SwSpellIter::Start( SwEditShell
*pShell
, SwDocPositions eStart
,
334 SwDocPositions eEnd
)
339 uno::Reference
< beans::XPropertySet
> xProp( ::GetLinguPropertySet() );
340 xSpeller
= ::GetSpellChecker();
342 _Start( pShell
, eStart
, eEnd
);
343 aLastPortions
.clear();
344 aLastPositions
.clear();
347 /*************************************************************************
348 * SwSpellIter::Continue
349 *************************************************************************/
351 // SwSpellIter::Continue ist das alte Original von
352 // SwEditShell::SpellContinue()
354 uno::Any
SwSpellIter::Continue( sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
)
357 //!! Please check SwConvIter also when modifying this
361 SwEditShell
*pMySh
= GetSh();
365 // const SwPosition *pEnd = GetEnd();
367 ASSERT( GetEnd(), "SwEditShell::SpellContinue() ohne Start?");
369 uno::Reference
< uno::XInterface
> xSpellRet
;
370 sal_Bool bGoOn
= sal_True
;
372 SwPaM
*pCrsr
= pMySh
->GetCrsr();
373 if ( !pCrsr
->HasMark() )
376 uno::Reference
< beans::XPropertySet
> xProp( GetLinguPropertySet() );
377 *pMySh
->GetCrsr()->GetPoint() = *GetCurr();
378 *pMySh
->GetCrsr()->GetMark() = *GetEnd();
379 pMySh
->GetDoc()->Spell(*pMySh
->GetCrsr(),
380 xSpeller
, pPageCnt
, pPageSt
, false ) >>= xSpellRet
;
381 bGoOn
= GetCrsrCnt() > 1;
385 SwPosition
* pNewPoint
= new SwPosition( *pCrsr
->GetPoint() );
386 SwPosition
* pNewMark
= new SwPosition( *pCrsr
->GetMark() );
387 SetCurr( pNewPoint
);
388 SetCurrX( pNewMark
);
392 pMySh
->Pop( sal_False
);
393 pCrsr
= pMySh
->GetCrsr();
394 if ( *pCrsr
->GetPoint() > *pCrsr
->GetMark() )
396 SwPosition
* pNew
= new SwPosition( *pCrsr
->GetPoint() );
398 pNew
= new SwPosition( *pCrsr
->GetMark() );
400 pNew
= new SwPosition( *GetStart() );
402 pNew
= new SwPosition( *pNew
);
408 aSpellRet
<<= xSpellRet
;
412 /*************************************************************************
413 * virtual SwConvIter::Start()
414 *************************************************************************/
418 void SwConvIter::Start( SwEditShell
*pShell
, SwDocPositions eStart
,
419 SwDocPositions eEnd
)
423 _Start( pShell
, eStart
, eEnd
);
426 /*************************************************************************
427 * SwConvIter::Continue
428 *************************************************************************/
430 uno::Any
SwConvIter::Continue( sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
)
433 //!! Please check SwSpellIter also when modifying this
436 uno::Any
aConvRet( makeAny( rtl::OUString() ) );
437 SwEditShell
*pMySh
= GetSh();
441 // const SwPosition *pEnd = GetEnd();
443 ASSERT( GetEnd(), "SwConvIter::Continue() ohne Start?");
445 rtl::OUString aConvText
;
446 sal_Bool bGoOn
= sal_True
;
448 SwPaM
*pCrsr
= pMySh
->GetCrsr();
449 if ( !pCrsr
->HasMark() )
452 *pMySh
->GetCrsr()->GetPoint() = *GetCurr();
453 *pMySh
->GetCrsr()->GetMark() = *GetEnd();
455 // call function to find next text portion to be converted
456 uno::Reference
< linguistic2::XSpellChecker1
> xEmpty
;
457 pMySh
->GetDoc()->Spell( *pMySh
->GetCrsr(),
458 xEmpty
, pPageCnt
, pPageSt
, false, &rArgs
) >>= aConvText
;
460 bGoOn
= GetCrsrCnt() > 1;
461 if( aConvText
.getLength() )
464 SwPosition
* pNewPoint
= new SwPosition( *pCrsr
->GetPoint() );
465 SwPosition
* pNewMark
= new SwPosition( *pCrsr
->GetMark() );
467 SetCurr( pNewPoint
);
468 SetCurrX( pNewMark
);
472 pMySh
->Pop( sal_False
);
473 pCrsr
= pMySh
->GetCrsr();
474 if ( *pCrsr
->GetPoint() > *pCrsr
->GetMark() )
476 SwPosition
* pNew
= new SwPosition( *pCrsr
->GetPoint() );
478 pNew
= new SwPosition( *pCrsr
->GetMark() );
480 pNew
= new SwPosition( *GetStart() );
482 pNew
= new SwPosition( *pNew
);
488 return makeAny( aConvText
);
492 /*************************************************************************
494 *************************************************************************/
497 sal_Bool
SwHyphIter::IsAuto()
499 uno::Reference
< beans::XPropertySet
> xProp( ::GetLinguPropertySet() );
500 return xProp
.is() ? *(sal_Bool
*)xProp
->getPropertyValue(
501 C2U(UPN_IS_HYPH_AUTO
) ).getValue()
506 void SwHyphIter::ShowSelection()
508 SwEditShell
*pMySh
= GetSh();
511 pMySh
->StartAction();
512 // Ganz fatal: durch das EndAction() werden Formatierungen
513 // angeregt, die dazu fuehren koennen, dass im Hyphenator
514 // neue Worte eingestellt werden. Deswegen sichern!
519 /*************************************************************************
520 * virtual SwHyphIter::Start()
521 *************************************************************************/
525 void SwHyphIter::Start( SwEditShell
*pShell
, SwDocPositions eStart
, SwDocPositions eEnd
)
528 if( GetSh() || GetEnd() )
530 ASSERT( !GetSh(), "+SwEditShell::HyphStart: missing HyphEnd()" );
534 // nothing to be done (at least not in the way as in the "else" part)
535 bOldIdle
= pShell
->GetViewOptions()->IsIdle();
536 ((SwViewOption
*)pShell
->GetViewOptions())->SetIdle( sal_False
);
537 _Start( pShell
, eStart
, eEnd
);
540 /*************************************************************************
541 * virtual SwHyphIter::End
542 *************************************************************************/
544 // Selektionen wiederherstellen
548 void SwHyphIter::End()
552 ((SwViewOption
*)GetSh()->GetViewOptions())->SetIdle( bOldIdle
);
556 /*************************************************************************
557 * SwHyphIter::Continue
558 *************************************************************************/
560 uno::Any
SwHyphIter::Continue( sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
)
563 SwEditShell
*pMySh
= GetSh();
567 const sal_Bool bAuto
= IsAuto();
568 uno::Reference
< XHyphenatedWord
> xHyphWord
;
570 sal_Bool bGoOn
= sal_False
;
574 ASSERT( GetEnd(), "SwEditShell::SpellContinue() ohne Start?" );
575 pCrsr
= pMySh
->GetCrsr();
576 if ( !pCrsr
->HasMark() )
578 if ( *pCrsr
->GetPoint() < *pCrsr
->GetMark() )
585 if ( *pCrsr
->End() > *GetEnd() )
589 *pCrsr
->GetMark() = *GetEnd();
591 // Muss an der aktuellen Cursorpos das Wort getrennt werden ?
592 const Point
aCrsrPos( pMySh
->GetCharRect().Pos() );
593 xHyphWord
= pMySh
->GetDoc()->Hyphenate( pCrsr
, aCrsrPos
,
597 if( bAuto
&& xHyphWord
.is() )
599 pMySh
->InsertSoftHyph( xHyphWord
->getHyphenationPos() + 1);
601 } while( bAuto
&& xHyphWord
.is() ); //end of do-while
602 bGoOn
= !xHyphWord
.is() && GetCrsrCnt() > 1;
606 pMySh
->Pop( sal_False
);
607 pCrsr
= pMySh
->GetCrsr();
608 if ( *pCrsr
->GetPoint() > *pCrsr
->GetMark() )
610 SwPosition
* pNew
= new SwPosition(*pCrsr
->End());
616 aHyphRet
<<= xHyphWord
;
620 /*************************************************************************
621 * SwHyphIter::HyphIgnore
622 *************************************************************************/
624 // Beschreibung: Trennstelle ignorieren
626 void SwHyphIter::Ignore()
628 SwEditShell
*pMySh
= GetSh();
629 SwPaM
*pCrsr
= pMySh
->GetCrsr();
631 // Alten SoftHyphen loeschen
632 DelSoftHyph( *pCrsr
);
635 pCrsr
->Start()->nContent
= pCrsr
->End()->nContent
;
639 /*************************************************************************
640 * SwHyphIter::DelSoftHyph
641 *************************************************************************/
643 void SwHyphIter::DelSoftHyph( SwPaM
&rPam
)
645 const SwPosition
* pStt
= rPam
.Start();
646 const xub_StrLen nStart
= pStt
->nContent
.GetIndex();
647 const xub_StrLen nEnd
= rPam
.End()->nContent
.GetIndex();
648 SwTxtNode
*pNode
= pStt
->nNode
.GetNode().GetTxtNode();
649 pNode
->DelSoftHyph( nStart
, nEnd
);
652 /*************************************************************************
653 * SwHyphIter::InsertSoftHyph
654 *************************************************************************/
657 void SwHyphIter::InsertSoftHyph( const xub_StrLen nHyphPos
)
659 SwEditShell
*pMySh
= GetSh();
660 ASSERT( pMySh
, "+SwEditShell::InsertSoftHyph: missing HyphStart()");
664 SwPaM
*pCrsr
= pMySh
->GetCrsr();
665 SwPosition
* pSttPos
= pCrsr
->Start();
666 SwPosition
* pEndPos
= pCrsr
->End();
668 xub_StrLen nLastHyphLen
= GetEnd()->nContent
.GetIndex() -
669 pSttPos
->nContent
.GetIndex();
671 if( pSttPos
->nNode
!= pEndPos
->nNode
|| !nLastHyphLen
)
673 ASSERT( pSttPos
->nNode
== pEndPos
->nNode
,
674 "+SwEditShell::InsertSoftHyph: node warp during hyphenation" );
675 ASSERT(nLastHyphLen
, "+SwEditShell::InsertSoftHyph: missing HyphContinue()");
680 pMySh
->StartAction();
682 SwDoc
*pDoc
= pMySh
->GetDoc();
683 DelSoftHyph( *pCrsr
);
684 pSttPos
->nContent
+= nHyphPos
;
685 SwPaM
aRg( *pSttPos
);
686 pDoc
->InsertString( aRg
, CHAR_SOFTHYPHEN
);
687 // Durch das Einfuegen des SoftHyphs ist ein Zeichen hinzugekommen
688 //JP 18.07.95: warum, ist doch ein SwIndex, dieser wird doch mitverschoben !!
689 // pSttPos->nContent++;
691 // Die Selektion wird wieder aufgehoben
697 // --------------------- Methoden der SwEditShell ------------------------
699 /*************************************************************************
700 * SwEditShell::HasConvIter
701 *************************************************************************/
703 BOOL
SwEditShell::HasConvIter() const
705 return 0 != pConvIter
;
708 /*************************************************************************
709 * SwEditShell::HasHyphIter
710 *************************************************************************/
712 BOOL
SwEditShell::HasHyphIter() const
714 return 0 != pHyphIter
;
717 /*************************************************************************
718 * SwEditShell::SetFindRange
719 *************************************************************************/
721 void SwEditShell::SetLinguRange( SwDocPositions eStart
, SwDocPositions eEnd
)
723 SwPaM
*pCrsr
= GetCrsr();
724 MakeFindRange( static_cast<USHORT
>(eStart
), static_cast<USHORT
>(eEnd
), pCrsr
);
725 if( *pCrsr
->GetPoint() > *pCrsr
->GetMark() )
729 /*************************************************************************
730 * SwEditShell::SpellStart
731 *************************************************************************/
733 void SwEditShell::SpellStart(
734 SwDocPositions eStart
, SwDocPositions eEnd
, SwDocPositions eCurr
,
735 SwConversionArgs
*pConvArgs
)
737 SwLinguIter
*pLinguIter
= 0;
739 // do not spell if interactive spelling is active elsewhere
740 if (!pConvArgs
&& !pSpellIter
)
742 ASSERT( !pSpellIter
, "wer ist da schon am spellen?" );
743 pSpellIter
= new SwSpellIter
;
744 pLinguIter
= pSpellIter
;
746 // do not do text conversion if it is active elsewhere
747 if (pConvArgs
&& !pConvIter
)
749 ASSERT( !pConvIter
, "text conversion already active!" );
750 pConvIter
= new SwConvIter( *pConvArgs
);
751 pLinguIter
= pConvIter
;
756 SwCursor
* pSwCrsr
= GetSwCrsr();
758 SwPosition
*pTmp
= new SwPosition( *pSwCrsr
->GetPoint() );
759 pSwCrsr
->FillFindPos( eCurr
, *pTmp
);
760 pLinguIter
->SetCurr( pTmp
);
762 pTmp
= new SwPosition( *pTmp
);
763 pLinguIter
->SetCurrX( pTmp
);
766 if (!pConvArgs
&& pSpellIter
)
767 pSpellIter
->Start( this, eStart
, eEnd
);
768 if (pConvArgs
&& pConvIter
)
769 pConvIter
->Start( this, eStart
, eEnd
);
772 /*************************************************************************
773 * SwEditShell::SpellEnd
774 *************************************************************************/
776 void SwEditShell::SpellEnd( SwConversionArgs
*pConvArgs
, bool bRestoreSelection
)
778 if (!pConvArgs
&& pSpellIter
&& pSpellIter
->GetSh() == this)
780 ASSERT( pSpellIter
, "wo ist mein Iterator?" );
781 pSpellIter
->_End(bRestoreSelection
);
782 delete pSpellIter
, pSpellIter
= 0;
784 if (pConvArgs
&& pConvIter
&& pConvIter
->GetSh() == this)
786 ASSERT( pConvIter
, "wo ist mein Iterator?" );
788 delete pConvIter
, pConvIter
= 0;
792 /*************************************************************************
793 * SwEditShell::SpellContinue
794 *************************************************************************/
796 // liefert Rueckgabewerte entsprechend SPL_ in splchk.hxx
798 uno::Any
SwEditShell::SpellContinue(
799 sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
,
800 SwConversionArgs
*pConvArgs
)
804 if ((!pConvArgs
&& pSpellIter
->GetSh() != this) ||
805 ( pConvArgs
&& pConvIter
->GetSh() != this))
808 if( pPageCnt
&& !*pPageCnt
)
810 sal_uInt16 nEndPage
= GetLayout()->GetPageNum();
811 nEndPage
+= nEndPage
* 10 / 100;
812 *pPageCnt
= nEndPage
;
814 ::StartProgress( STR_STATSTR_SPELL
, 0, nEndPage
, GetDoc()->GetDocShell() );
817 ASSERT( pConvArgs
|| pSpellIter
, "SpellIter missing" );
818 ASSERT( !pConvArgs
|| pConvIter
, "ConvIter missing" );
819 //JP 18.07.95: verhinder bei Fehlermeldungen die Anzeige der Selektionen
820 // KEIN StartAction, da damit auch die Paints abgeschaltet
824 uno::Reference
< uno::XInterface
> xRet
;
827 pConvIter
->Continue( pPageCnt
, pPageSt
) >>= aRet
;
832 pSpellIter
->Continue( pPageCnt
, pPageSt
) >>= xRet
;
837 if( aRet
.getLength() || xRet
.is() )
839 // dann die awt::Selection sichtbar machen
845 /*************************************************************************
846 * SwEditShell::HyphStart
847 *************************************************************************/
849 /* Interaktive Trennung, BP 10.03.93
852 * - Aufheben aller Selektionen
853 * - Sichern des aktuellen Cursors
854 * - falls keine Selektion vorhanden:
855 * - neue Selektion bis zum Dokumentende
857 * - nLastHyphLen wird auf den Selektionsstart addiert
858 * - iteriert ueber alle selektierten Bereiche
859 * - pDoc->Hyphenate() iteriert ueber alle Nodes der Selektion
860 * - pTxtNode->Hyphenate() ruft das SwTxtFrm::Hyphenate zur EditShell
861 * - SwTxtFrm:Hyphenate() iteriert ueber die Zeilen des Pams
862 * - LineIter::Hyphenate() stellt den Hyphenator
863 * und den Pam auf das zu trennende Wort ein.
864 * - Es gibt nur zwei Returnwerte sal_True, wenn eine Trennstelle anliegt
865 * und sal_False, wenn der Pam abgearbeitet wurde.
866 * - Bei sal_True wird das selektierte Wort zur Anzeige gebracht und
867 * nLastHyphLen gesetzt.
868 * - Bei sal_False wird die aktuelle Selektion geloescht und die naechste
869 * zur aktuellen gewaehlt. Return HYPH_OK, wenn keine mehr vorhanden.
870 * 3) InsertSoftHyph (wird ggf. von der UI gerufen)
871 * - Der aktuelle Cursor wird plaziert und das Attribut eingefuegt.
873 * - Wiederherstellen des alten Cursors, EndAction
878 void SwEditShell::HyphStart( SwDocPositions eStart
, SwDocPositions eEnd
)
880 // do not hyphenate if interactive hyphenationg is active elsewhere
883 ASSERT( !pHyphIter
, "wer ist da schon am hyphinieren?" );
884 pHyphIter
= new SwHyphIter
;
885 pHyphIter
->Start( this, eStart
, eEnd
);
889 /*************************************************************************
890 * SwEditShell::HyphEnd
891 *************************************************************************/
893 // Selektionen wiederherstellen
897 void SwEditShell::HyphEnd()
899 if (pHyphIter
->GetSh() == this)
901 ASSERT( pHyphIter
, "wo ist mein Iterator?" );
903 delete pHyphIter
, pHyphIter
= 0;
907 /*************************************************************************
908 * SwEditShell::HyphContinue
909 *************************************************************************/
911 // Returnwerte: (BP: ich wuerde es genau umdrehen, aber die UI wuenscht es so)
912 // HYPH_CONTINUE, wenn eine Trennstelle anliegt
913 // HYPH_OK, wenn der selektierte Bereich abgearbeitet wurde.
916 uno::Reference
< uno::XInterface
>
917 SwEditShell::HyphContinue( sal_uInt16
* pPageCnt
, sal_uInt16
* pPageSt
)
919 if (pHyphIter
->GetSh() != this)
922 if( pPageCnt
&& !*pPageCnt
&& !*pPageSt
)
924 sal_uInt16 nEndPage
= GetLayout()->GetPageNum();
925 nEndPage
+= nEndPage
* 10 / 100;
928 *pPageCnt
= nEndPage
;
929 ::StartProgress( STR_STATSTR_HYPHEN
, 0, nEndPage
, GetDoc()->GetDocShell());
931 else // Hiermit unterdruecken wir ein fuer allemal
932 *pPageSt
= 1; // das StatLineStartPercent
935 ASSERT( pHyphIter
, "wo ist mein Iterator?" );
936 //JP 18.07.95: verhinder bei Fehlermeldungen die Anzeige der Selektionen
937 // KEIN StartAction, da damit auch die Paints abgeschaltet
940 uno::Reference
< uno::XInterface
> xRet
;
941 pHyphIter
->Continue( pPageCnt
, pPageSt
) >>= xRet
;
945 pHyphIter
->ShowSelection();
951 /*************************************************************************
952 * SwEditShell::InsertSoftHyph
953 *************************************************************************/
955 // Zum Einfuegen des SoftHyphens, Position ist der Offset
956 // innerhalb des getrennten Wortes.
959 void SwEditShell::InsertSoftHyph( const xub_StrLen nHyphPos
)
961 ASSERT( pHyphIter
, "wo ist mein Iterator?" );
962 pHyphIter
->InsertSoftHyph( nHyphPos
);
966 /*************************************************************************
967 * SwEditShell::HyphIgnore
968 *************************************************************************/
970 // Beschreibung: Trennstelle ignorieren
972 void SwEditShell::HyphIgnore()
974 ASSERT( pHyphIter
, "wo ist mein Iterator?" );
975 //JP 18.07.95: verhinder bei Fehlermeldungen die Anzeige der Selektionen
976 // KEIN StartAction, da damit auch die Paints abgeschaltet
982 pHyphIter
->ShowSelection();
985 /*************************************************************************
986 * SwEditShell::GetCorrection()
987 * liefert eine Liste von Vorschlaegen fuer falsch geschriebene Worte,
988 * ein NULL-Pointer signalisiert, dass das Wort richtig geschrieben ist,
989 * eine leere Liste, dass das Wort zwar unbekannt ist, aber keine Alternativen
990 * geliefert werden koennen.
991 *************************************************************************/
994 uno::Reference
< XSpellAlternatives
>
995 SwEditShell::GetCorrection( const Point
* pPt
, SwRect
& rSelectRect
)
997 uno::Reference
< XSpellAlternatives
> xSpellAlt
;
1001 SwPaM
* pCrsr
= GetCrsr();
1002 SwPosition
aPos( *pCrsr
->GetPoint() );
1004 SwCrsrMoveState
eTmpState( MV_SETONLYTEXT
);
1006 SwWrongList
*pWrong
;
1007 if( GetLayout()->GetCrsrOfst( &aPos
, aPt
, &eTmpState
) &&
1008 0 != (pNode
= aPos
.nNode
.GetNode().GetTxtNode()) &&
1009 0 != (pWrong
= pNode
->GetWrong()) &&
1010 !pNode
->IsInProtectSect() )
1012 xub_StrLen nBegin
= aPos
.nContent
.GetIndex();
1013 xub_StrLen nLen
= 1;
1014 if( pWrong
->InWrongWord(nBegin
,nLen
) && !pNode
->IsSymbol(nBegin
) )
1016 String
aText( pNode
->GetTxt().Copy( nBegin
, nLen
) );
1017 String
aWord( aText
);
1018 aWord
.EraseAllChars( CH_TXTATR_BREAKWORD
).EraseAllChars( CH_TXTATR_INWORD
);
1020 uno::Reference
< XSpellChecker1
> xSpell( ::GetSpellChecker() );
1023 LanguageType eActLang
= (LanguageType
)pNode
->GetLang( nBegin
, nLen
);
1024 if( xSpell
->hasLanguage( eActLang
))
1026 // restrict the maximal number of suggestions displayed
1027 // in the context menu.
1028 // Note: That could of course be done by clipping the
1029 // resulting sequence but the current third party
1030 // implementations result differs greatly if the number of
1031 // suggestions to be retuned gets changed. Statistically
1032 // it gets much better if told to return e.g. only 7 strings
1033 // than returning e.g. 16 suggestions and using only the
1034 // first 7. Thus we hand down the value to use to that
1035 // implementation here by providing an additional parameter.
1036 Sequence
< PropertyValue
> aPropVals(1);
1037 PropertyValue
&rVal
= aPropVals
.getArray()[0];
1038 rVal
.Name
= C2U( UPN_MAX_NUMBER_OF_SUGGESTIONS
);
1039 rVal
.Value
<<= (INT16
) 7;
1041 xSpellAlt
= xSpell
->spell( aWord
, eActLang
, aPropVals
);
1045 if ( xSpellAlt
.is() ) // error found?
1047 //save the start and end positons of the line and the starting point
1050 xub_StrLen nLineStart
= GetCrsr()->GetPoint()->nContent
.GetIndex();
1052 xub_StrLen nLineEnd
= GetCrsr()->GetPoint()->nContent
.GetIndex();
1055 // make sure the selection build later from the
1056 // data below does not include footnotes and other
1057 // "in word" character to the left and right in order
1058 // to preserve those. Therefore count those "in words"
1059 // in order to modify the selection accordingly.
1060 const sal_Unicode
* pChar
= aText
.GetBuffer();
1061 xub_StrLen nLeft
= 0;
1062 while (pChar
&& *pChar
++ == CH_TXTATR_INWORD
)
1064 pChar
= aText
.Len() ? aText
.GetBuffer() + aText
.Len() - 1 : 0;
1065 xub_StrLen nRight
= 0;
1066 while (pChar
&& *pChar
-- == CH_TXTATR_INWORD
)
1069 aPos
.nContent
= nBegin
+ nLeft
;
1071 *pCrsr
->GetPoint() = aPos
;
1073 ExtendSelection( sal_True
, nLen
- nLeft
- nRight
);
1074 //no determine the rectangle in the current line
1075 xub_StrLen nWordStart
= (nBegin
+ nLeft
) < nLineStart
? nLineStart
: nBegin
+ nLeft
;
1076 //take one less than the line end - otherwise the next line would be calculated
1077 xub_StrLen nWordEnd
= (nBegin
+ nLen
- nLeft
- nRight
) > nLineEnd
? nLineEnd
- 1: (nBegin
+ nLen
- nLeft
- nRight
);
1079 pCrsr
->DeleteMark();
1080 SwIndex
& rContent
= GetCrsr()->GetPoint()->nContent
;
1081 rContent
= nWordStart
;
1083 SwCrsrMoveState aState
;
1084 aState
.bRealWidth
= TRUE
;
1085 SwCntntNode
* pCntntNode
= pCrsr
->GetCntntNode();
1086 SwCntntFrm
*pCntntFrame
= pCntntNode
->GetFrm(pPt
, pCrsr
->GetPoint(), FALSE
);
1088 pCntntFrame
->GetCharRect( aStartRect
, *pCrsr
->GetPoint(), &aState
);
1089 rContent
= nWordEnd
;
1091 pCntntFrame
->GetCharRect( aEndRect
, *pCrsr
->GetPoint(),&aState
);
1092 rSelectRect
= aStartRect
.Union( aEndRect
);
1100 /*-------------------------------------------------------------------------
1102 -----------------------------------------------------------------------*/
1104 bool SwEditShell::GetGrammarCorrection(
1105 linguistic2::ProofreadingResult
/*out*/ &rResult
, // the complete result
1106 sal_Int32
/*out*/ &rErrorPosInText
, // offset of error position in string that was grammar checked...
1107 sal_Int32
/*out*/ &rErrorIndexInResult
, // index of error in rResult.aGrammarErrors
1108 uno::Sequence
< rtl::OUString
> /*out*/ &rSuggestions
, // suggestions to be used for the error found
1109 const Point
*pPt
, SwRect
&rSelectRect
)
1116 SwPaM
* pCrsr
= GetCrsr();
1117 SwPosition
aPos( *pCrsr
->GetPoint() );
1119 SwCrsrMoveState
eTmpState( MV_SETONLYTEXT
);
1121 SwGrammarMarkUp
*pWrong
;
1122 if( GetLayout()->GetCrsrOfst( &aPos
, aPt
, &eTmpState
) &&
1123 0 != (pNode
= aPos
.nNode
.GetNode().GetTxtNode()) &&
1124 0 != (pWrong
= pNode
->GetGrammarCheck()) &&
1125 !pNode
->IsInProtectSect() )
1127 xub_StrLen nBegin
= aPos
.nContent
.GetIndex();
1128 xub_StrLen nLen
= 1;
1129 if (pWrong
->InWrongWord(nBegin
, nLen
))
1131 String
aText( pNode
->GetTxt().Copy( nBegin
, nLen
) );
1132 String
aWord( aText
);
1133 aWord
.EraseAllChars( CH_TXTATR_BREAKWORD
).EraseAllChars( CH_TXTATR_INWORD
);
1135 uno::Reference
< linguistic2::XProofreadingIterator
> xGCIterator( pDoc
->GetGCIterator() );
1136 if (xGCIterator
.is())
1138 // LanguageType eActLang = (LanguageType)pNode->GetLang( nBegin, nLen );
1139 uno::Reference
< lang::XComponent
> xDoc( pDoc
->GetDocShell()->GetBaseModel(), uno::UNO_QUERY
);
1141 // Expand the string:
1142 rtl::OUString aExpandText
;
1143 const ModelToViewHelper::ConversionMap
* pConversionMap
=
1144 pNode
->BuildConversionMap( aExpandText
);
1145 // get XFlatParagraph to use...
1146 uno::Reference
< text::XFlatParagraph
> xFlatPara
= new SwXFlatParagraph( *pNode
, aExpandText
, pConversionMap
);
1148 // get error position of cursor in XFlatParagraph
1149 rErrorPosInText
= ModelToViewHelper::ConvertToViewPosition( pConversionMap
, nBegin
);
1151 sal_Int32 nStartOfSentence
= ModelToViewHelper::ConvertToViewPosition( pConversionMap
, pWrong
->getSentenceStart( nBegin
) );
1152 sal_Int32 nEndOfSentence
= ModelToViewHelper::ConvertToViewPosition( pConversionMap
, pWrong
->getSentenceEnd( nBegin
) );
1153 if( nEndOfSentence
== STRING_LEN
)
1155 /* if( nStartOfSentence == 0 )
1157 nStartOfSentence = -1;
1158 nEndOfSentence = -1;
1161 nEndOfSentence
= aExpandText
.getLength();
1164 rResult
= xGCIterator
->checkSentenceAtPosition(
1165 xDoc
, xFlatPara
, aExpandText
, lang::Locale(), nStartOfSentence
, nEndOfSentence
, rErrorPosInText
);
1168 // get suggestions to use for the specific error position
1169 sal_Int32 nErrors
= rResult
.aErrors
.getLength();
1170 rSuggestions
.realloc( 0 );
1171 for (sal_Int32 i
= 0; i
< nErrors
; ++i
)
1173 // return suggestions for first error that includes the given error position
1174 const linguistic2::SingleProofreadingError
&rError
= rResult
.aErrors
[i
];
1175 if (rError
.nErrorStart
<= rErrorPosInText
&&
1176 rErrorPosInText
< rError
.nErrorStart
+ rError
.nErrorLength
)
1178 rSuggestions
= rError
.aSuggestions
;
1179 rErrorIndexInResult
= i
;
1185 if (rResult
.aErrors
.getLength() > 0) // error found?
1187 //save the start and end positons of the line and the starting point
1190 xub_StrLen nLineStart
= GetCrsr()->GetPoint()->nContent
.GetIndex();
1192 xub_StrLen nLineEnd
= GetCrsr()->GetPoint()->nContent
.GetIndex();
1195 #if OSL_DEBUG_LEVEL > 1
1196 // pNode->GetGrammarCheck()->Invalidate( 0, STRING_LEN );
1197 // pNode->SetGrammarCheckDirty( true );
1199 // make sure the selection build later from the
1200 // data below does not include footnotes and other
1201 // "in word" character to the left and right in order
1202 // to preserve those. Therefore count those "in words"
1203 // in order to modify the selection accordingly.
1204 const sal_Unicode
* pChar
= aText
.GetBuffer();
1205 xub_StrLen nLeft
= 0;
1206 while (pChar
&& *pChar
++ == CH_TXTATR_INWORD
)
1208 pChar
= aText
.Len() ? aText
.GetBuffer() + aText
.Len() - 1 : 0;
1209 xub_StrLen nRight
= 0;
1210 while (pChar
&& *pChar
-- == CH_TXTATR_INWORD
)
1213 aPos
.nContent
= nBegin
+ nLeft
;
1215 *pCrsr
->GetPoint() = aPos
;
1217 ExtendSelection( sal_True
, nLen
- nLeft
- nRight
);
1218 //no determine the rectangle in the current line
1219 xub_StrLen nWordStart
= (nBegin
+ nLeft
) < nLineStart
? nLineStart
: nBegin
+ nLeft
;
1220 //take one less than the line end - otherwise the next line would be calculated
1221 xub_StrLen nWordEnd
= (nBegin
+ nLen
- nLeft
- nRight
) > nLineEnd
? nLineEnd
- 1: (nBegin
+ nLen
- nLeft
- nRight
);
1223 pCrsr
->DeleteMark();
1224 SwIndex
& rContent
= GetCrsr()->GetPoint()->nContent
;
1225 rContent
= nWordStart
;
1227 SwCrsrMoveState aState
;
1228 aState
.bRealWidth
= TRUE
;
1229 SwCntntNode
* pCntntNode
= pCrsr
->GetCntntNode();
1230 SwCntntFrm
*pCntntFrame
= pCntntNode
->GetFrm(pPt
, pCrsr
->GetPoint(), FALSE
);
1232 pCntntFrame
->GetCharRect( aStartRect
, *pCrsr
->GetPoint(), &aState
);
1233 rContent
= nWordEnd
;
1235 pCntntFrame
->GetCharRect( aEndRect
, *pCrsr
->GetPoint(),&aState
);
1236 rSelectRect
= aStartRect
.Union( aEndRect
);
1245 /*-- 18.09.2003 15:08:18---------------------------------------------------
1247 -----------------------------------------------------------------------*/
1248 bool SwEditShell::SpellSentence(::svx::SpellPortions
& rPortions
, bool bIsGrammarCheck
)
1250 ASSERT( pSpellIter
, "SpellIter missing" );
1253 bool bRet
= pSpellIter
->SpellSentence(rPortions
, bIsGrammarCheck
);
1255 // make Selection visible - this should simply move the
1256 // cursor to the end of the sentence
1261 /*-- 08.09.2008 09:35:19---------------------------------------------------
1262 make SpellIter start with the current sentence when called next time
1263 -----------------------------------------------------------------------*/
1264 void SwEditShell::PutSpellingToSentenceStart()
1266 ASSERT( pSpellIter
, "SpellIter missing" );
1269 pSpellIter
->ToSentenceStart();
1271 /*-- 02.02.2005 14:34:41---------------------------------------------------
1273 -----------------------------------------------------------------------*/
1274 sal_uInt32
lcl_CountRedlines(
1275 const ::svx::SpellPortions
& rLastPortions
)
1277 sal_uInt32 nRet
= 0;
1278 SpellPortions::const_iterator aIter
= rLastPortions
.begin();
1279 for( ; aIter
!= rLastPortions
.end(); ++aIter
)
1281 if( aIter
->bIsHidden
)
1286 /*-- 18.09.2003 15:08:20---------------------------------------------------
1288 -----------------------------------------------------------------------*/
1289 void SwEditShell::ApplyChangedSentence(const ::svx::SpellPortions
& rNewPortions
, bool bIsGrammarCheck
)
1291 ASSERT( pSpellIter
, "SpellIter missing" );
1294 const SpellPortions
& rLastPortions
= pSpellIter
->GetLastPortions();
1295 const SpellContentPositions rLastPositions
= pSpellIter
->GetLastPositions();
1296 ASSERT(rLastPortions
.size() > 0 &&
1297 rLastPortions
.size() == rLastPositions
.size(),
1298 "last vectors of spelling results are not set or not equal")
1300 // iterate over the new portions, beginning at the end to take advantage of the previously
1301 // saved content positions
1303 if(!rLastPortions
.size())
1306 SwPaM
*pCrsr
= GetCrsr();
1307 pDoc
->StartUndo( UNDO_OVERWRITE
, NULL
);
1309 sal_uInt32 nRedlinePortions
= lcl_CountRedlines(rLastPortions
);
1310 if((rLastPortions
.size() - nRedlinePortions
) == rNewPortions
.size())
1312 //the simple case: the same number of elements on both sides
1313 //each changed element has to be applied to the corresponding source element
1314 svx::SpellPortions::const_iterator aCurrentNewPortion
= rNewPortions
.end();
1315 SpellPortions::const_iterator aCurrentOldPortion
= rLastPortions
.end();
1316 SpellContentPositions::const_iterator aCurrentOldPosition
= rLastPositions
.end();
1319 --aCurrentNewPortion
;
1320 --aCurrentOldPortion
;
1321 --aCurrentOldPosition
;
1322 //jump over redline portions
1323 while(aCurrentOldPortion
->bIsHidden
)
1325 --aCurrentOldPortion
;
1326 --aCurrentOldPosition
;
1328 if ( !pCrsr
->HasMark() )
1330 pCrsr
->GetPoint()->nContent
= aCurrentOldPosition
->nLeft
;
1331 pCrsr
->GetMark()->nContent
= aCurrentOldPosition
->nRight
;
1332 USHORT nScriptType
= GetI18NScriptTypeOfLanguage( aCurrentNewPortion
->eLanguage
);
1333 USHORT nLangWhichId
= RES_CHRATR_LANGUAGE
;
1336 case SCRIPTTYPE_ASIAN
: nLangWhichId
= RES_CHRATR_CJK_LANGUAGE
; break;
1337 case SCRIPTTYPE_COMPLEX
: nLangWhichId
= RES_CHRATR_CTL_LANGUAGE
; break;
1339 if(aCurrentNewPortion
->sText
!= aCurrentOldPortion
->sText
)
1342 pDoc
->DeleteAndJoin(*pCrsr
);
1343 // ... and apply language if necessary
1344 if(aCurrentNewPortion
->eLanguage
!= aCurrentOldPortion
->eLanguage
)
1345 SetAttr( SvxLanguageItem(aCurrentNewPortion
->eLanguage
, nLangWhichId
), nLangWhichId
);
1346 pDoc
->InsertString(*pCrsr
, aCurrentNewPortion
->sText
);
1348 else if(aCurrentNewPortion
->eLanguage
!= aCurrentOldPortion
->eLanguage
)
1351 SetAttr( SvxLanguageItem(aCurrentNewPortion
->eLanguage
, nLangWhichId
), nLangWhichId
);
1353 else if( aCurrentNewPortion
->bIgnoreThisError
)
1355 //add the 'ignore' markup to the TextNode's grammar ignore markup list
1356 IgnoreGrammarErrorAt( *pCrsr
);
1357 DBG_ERROR("TODO: add ignore mark to text node");
1359 if(aCurrentNewPortion
== rNewPortions
.begin())
1362 while(aCurrentNewPortion
!= rNewPortions
.begin());
1366 //select the complete sentence
1367 SpellContentPositions::const_iterator aCurrentEndPosition
= rLastPositions
.end();
1368 --aCurrentEndPosition
;
1369 SpellContentPositions::const_iterator aCurrentStartPosition
= rLastPositions
.begin();
1370 pCrsr
->GetPoint()->nContent
= aCurrentStartPosition
->nLeft
;
1371 pCrsr
->GetMark()->nContent
= aCurrentEndPosition
->nRight
;
1373 //delete the sentence completely
1374 pDoc
->DeleteAndJoin(*pCrsr
);
1375 svx::SpellPortions::const_iterator aCurrentNewPortion
= rNewPortions
.begin();
1376 while(aCurrentNewPortion
!= rNewPortions
.end())
1378 //set the language attribute
1379 USHORT nScriptType
= GetScriptType();
1380 USHORT nLangWhichId
= RES_CHRATR_LANGUAGE
;
1383 case SCRIPTTYPE_ASIAN
: nLangWhichId
= RES_CHRATR_CJK_LANGUAGE
; break;
1384 case SCRIPTTYPE_COMPLEX
: nLangWhichId
= RES_CHRATR_CTL_LANGUAGE
; break;
1386 SfxItemSet
aSet(GetAttrPool(), nLangWhichId
, nLangWhichId
, 0);
1388 const SvxLanguageItem
& rLang
= static_cast<const SvxLanguageItem
& >(aSet
.Get(nLangWhichId
));
1389 if(rLang
.GetLanguage() != aCurrentNewPortion
->eLanguage
)
1390 SetAttr( SvxLanguageItem(aCurrentNewPortion
->eLanguage
, nLangWhichId
) );
1391 //insert the new string
1392 pDoc
->InsertString(*pCrsr
, aCurrentNewPortion
->sText
);
1394 //set the cursor to the end of the inserted string
1395 *pCrsr
->Start() = *pCrsr
->End();
1396 ++aCurrentNewPortion
;
1400 //set the cursor to the end of the new sentence
1401 *pCrsr
->Start() = *pCrsr
->End();
1402 if( bIsGrammarCheck
)
1404 //in grammar check the current sentence has to be checked again
1407 pDoc
->EndUndo( UNDO_OVERWRITE
, NULL
);
1411 /*-- 02.02.2005 10:46:45---------------------------------------------------
1412 collect all deleted redlines of the current text node beginning at the
1413 start of the cursor position
1414 -----------------------------------------------------------------------*/
1415 SpellContentPositions
lcl_CollectDeletedRedlines(SwEditShell
* pSh
)
1417 SpellContentPositions aRedlines
;
1418 SwDoc
* pDoc
= pSh
->GetDoc();
1419 const bool bShowChg
= IDocumentRedlineAccess::IsShowChanges( pDoc
->GetRedlineMode() );
1422 SwPaM
*pCrsr
= pSh
->GetCrsr();
1423 const SwPosition
* pStartPos
= pCrsr
->Start();
1424 const SwTxtNode
* pTxtNode
= pCrsr
->GetNode()->GetTxtNode();
1426 USHORT nAct
= pDoc
->GetRedlinePos( *pTxtNode
, USHRT_MAX
);
1427 const xub_StrLen nStartIndex
= pStartPos
->nContent
.GetIndex();
1428 for ( ; nAct
< pDoc
->GetRedlineTbl().Count(); nAct
++ )
1430 const SwRedline
* pRed
= pDoc
->GetRedlineTbl()[ nAct
];
1432 if ( pRed
->Start()->nNode
> pTxtNode
->GetIndex() )
1435 if( nsRedlineType_t::REDLINE_DELETE
== pRed
->GetType() )
1437 xub_StrLen nStart
, nEnd
;
1438 pRed
->CalcStartEnd( pTxtNode
->GetIndex(), nStart
, nEnd
);
1439 if(nStart
>= nStartIndex
|| nEnd
>= nStartIndex
)
1441 SpellContentPosition aAdd
;
1442 aAdd
.nLeft
= nStart
;
1444 aRedlines
.push_back(aAdd
);
1451 /*-- 02.02.2005 11:06:12---------------------------------------------------
1452 remove the redline positions after the current selection
1453 -----------------------------------------------------------------------*/
1454 void lcl_CutRedlines( SpellContentPositions
& aDeletedRedlines
, SwEditShell
* pSh
)
1456 if(!aDeletedRedlines
.empty())
1458 SwPaM
*pCrsr
= pSh
->GetCrsr();
1459 const SwPosition
* pEndPos
= pCrsr
->End();
1460 xub_StrLen nEnd
= pEndPos
->nContent
.GetIndex();
1461 while(!aDeletedRedlines
.empty() &&
1462 aDeletedRedlines
.back().nLeft
> nEnd
)
1464 aDeletedRedlines
.pop_back();
1468 /*-- 02.02.2005 11:43:00---------------------------------------------------
1470 -----------------------------------------------------------------------*/
1471 SpellContentPosition
lcl_FindNextDeletedRedline(
1472 const SpellContentPositions
& rDeletedRedlines
,
1473 xub_StrLen nSearchFrom
)
1475 SpellContentPosition aRet
;
1476 aRet
.nLeft
= aRet
.nRight
= STRING_MAXLEN
;
1477 if(!rDeletedRedlines
.empty())
1479 SpellContentPositions::const_iterator aIter
= rDeletedRedlines
.begin();
1480 for( ; aIter
!= rDeletedRedlines
.end(); ++aIter
)
1482 if(aIter
->nLeft
< nSearchFrom
)
1490 /*-- 18.09.2003 15:08:20---------------------------------------------------
1492 -----------------------------------------------------------------------*/
1493 bool SwSpellIter::SpellSentence(::svx::SpellPortions
& rPortions
, bool bIsGrammarCheck
)
1496 aLastPortions
.clear();
1497 aLastPositions
.clear();
1499 SwEditShell
*pMySh
= GetSh();
1503 ASSERT( GetEnd(), "SwEditShell::SpellSentence() ohne Start?");
1505 uno::Reference
< XSpellAlternatives
> xSpellRet
;
1506 linguistic2::ProofreadingResult aGrammarResult
;
1507 sal_Bool bGoOn
= sal_True
;
1508 bool bGrammarErrorFound
= false;
1510 SwPaM
*pCrsr
= pMySh
->GetCrsr();
1511 if ( !pCrsr
->HasMark() )
1514 *pCrsr
->GetPoint() = *GetCurr();
1515 *pCrsr
->GetMark() = *GetEnd();
1517 if( bBackToStartOfSentence
)
1519 pMySh
->GoStartSentence();
1520 bBackToStartOfSentence
= false;
1522 uno::Any aSpellRet
=
1523 pMySh
->GetDoc()->Spell(*pCrsr
,
1524 xSpeller
, 0, 0, bIsGrammarCheck
);
1525 aSpellRet
>>= xSpellRet
;
1526 aSpellRet
>>= aGrammarResult
;
1527 bGoOn
= GetCrsrCnt() > 1;
1528 bGrammarErrorFound
= aGrammarResult
.aErrors
.getLength() > 0;
1529 if( xSpellRet
.is() || bGrammarErrorFound
)
1532 SwPosition
* pNewPoint
= new SwPosition( *pCrsr
->GetPoint() );
1533 SwPosition
* pNewMark
= new SwPosition( *pCrsr
->GetMark() );
1535 SetCurr( pNewPoint
);
1536 SetCurrX( pNewMark
);
1540 pMySh
->Pop( sal_False
);
1541 pCrsr
= pMySh
->GetCrsr();
1542 if ( *pCrsr
->GetPoint() > *pCrsr
->GetMark() )
1544 SwPosition
* pNew
= new SwPosition( *pCrsr
->GetPoint() );
1546 pNew
= new SwPosition( *pCrsr
->GetMark() );
1548 pNew
= new SwPosition( *GetStart() );
1550 pNew
= new SwPosition( *pNew
);
1557 if(xSpellRet
.is() || bGrammarErrorFound
)
1559 //an error has been found
1560 //To fill the spell portions the beginning of the sentence has to be found
1561 SwPaM
*pCrsr
= pMySh
->GetCrsr();
1562 //set the mark to the right if necessary
1563 if ( *pCrsr
->GetPoint() > *pCrsr
->GetMark() )
1565 //the cursor has to be collapsed on the left to go to the start of the sentence - if sentence ends inside of the error
1566 pCrsr
->DeleteMark();
1568 BOOL bStartSent
= 0 != pMySh
->GoStartSentence();
1569 SpellContentPositions aDeletedRedlines
= lcl_CollectDeletedRedlines(pMySh
);
1572 //create a portion from the start part
1573 AddPortion(0, 0, aDeletedRedlines
);
1575 //Set the cursor to the error already found
1576 *pCrsr
->GetPoint() = *GetCurrX();
1577 *pCrsr
->GetMark() = *GetCurr();
1578 AddPortion(xSpellRet
, &aGrammarResult
, aDeletedRedlines
);
1581 //save the end position of the error to continue from here
1582 SwPosition aSaveStartPos
= *pCrsr
->End();
1583 //determine the end of the current sentence
1584 if ( *pCrsr
->GetPoint() < *pCrsr
->GetMark() )
1586 //again collapse to start marking after the end of the error
1587 pCrsr
->DeleteMark();
1590 pMySh
->GoEndSentence();
1591 if( bGrammarErrorFound
)
1593 rtl::OUString aExpandText
;
1594 const ModelToViewHelper::ConversionMap
* pConversionMap
= ((SwTxtNode
*)pCrsr
->GetNode())->BuildConversionMap( aExpandText
);
1595 xub_StrLen nSentenceEnd
= (xub_StrLen
)ModelToViewHelper::ConvertToViewPosition( pConversionMap
, aGrammarResult
.nBehindEndOfSentencePosition
);
1596 // remove trailing space
1597 if( aExpandText
[nSentenceEnd
- 1] == ' ' )
1599 if( pCrsr
->End()->nContent
.GetIndex() < nSentenceEnd
)
1601 pCrsr
->End()->nContent
.Assign(
1602 pCrsr
->End()->nNode
.GetNode().GetCntntNode(), nSentenceEnd
);
1606 lcl_CutRedlines( aDeletedRedlines
, pMySh
);
1607 //save the 'global' end of the spellchecking
1608 const SwPosition aSaveEndPos
= *GetEnd();
1609 //set the sentence end as 'local' end
1610 SetEnd( new SwPosition( *pCrsr
->End() ));
1612 *pCrsr
->GetPoint() = aSaveStartPos
;
1613 *pCrsr
->GetMark() = *GetEnd();
1614 //now the rest of the sentence has to be searched for errors
1615 // for each error the non-error text between the current and the last error has
1616 // to be added to the portions - if necessary broken into same-language-portions
1617 if( !bGrammarErrorFound
) //in grammar check there's only one error returned
1622 // don't search for grammar errors here anymore!
1623 pMySh
->GetDoc()->Spell(*pCrsr
,
1624 xSpeller
, 0, 0, false ) >>= xSpellRet
;
1625 if ( *pCrsr
->GetPoint() > *pCrsr
->GetMark() )
1627 SetCurr( new SwPosition( *pCrsr
->GetPoint() ));
1628 SetCurrX( new SwPosition( *pCrsr
->GetMark() ));
1630 //if an error has been found go back to the text
1631 //preceeding the error
1634 *pCrsr
->GetPoint() = aSaveStartPos
;
1635 *pCrsr
->GetMark() = *GetCurr();
1638 AddPortion(0, 0, aDeletedRedlines
);
1642 *pCrsr
->GetPoint() = *GetCurr();
1643 *pCrsr
->GetMark() = *GetCurrX();
1644 AddPortion(xSpellRet
, 0, aDeletedRedlines
);
1645 //move the cursor to the end of the error string
1646 *pCrsr
->GetPoint() = *GetCurrX();
1647 //and save the end of the error as new start position
1648 aSaveStartPos
= *GetCurrX();
1649 //and the end of the sentence
1650 *pCrsr
->GetMark() = *GetEnd();
1652 // if the end of the sentence has already been reached then break here
1653 if(*GetCurrX() >= *GetEnd())
1656 while(xSpellRet
.is());
1660 //go to the end of sentence as the grammar check returned it
1661 // at this time the Point is behind the grammar error
1662 // and the mark points to the sentence end as
1663 if ( *pCrsr
->GetPoint() < *pCrsr
->GetMark() )
1667 // the part between the last error and the end of the sentence has to be added
1668 *pMySh
->GetCrsr()->GetPoint() = *GetEnd();
1669 if(*GetCurrX() < *GetEnd())
1671 AddPortion(0, 0, aDeletedRedlines
);
1673 //set the shell cursor to the end of the sentence to prevent a visible selection
1674 *pCrsr
->GetMark() = *GetEnd();
1675 if( !bIsGrammarCheck
)
1677 //set the current position to the end of the sentence
1678 SetCurr( new SwPosition(*GetEnd()) );
1680 //restore the 'global' end
1681 SetEnd( new SwPosition(aSaveEndPos
) );
1682 rPortions
= aLastPortions
;
1687 //if no error could be found the selection has to be corrected - at least if it's not in the body
1688 *pMySh
->GetCrsr()->GetPoint() = *GetEnd();
1689 pMySh
->GetCrsr()->DeleteMark();
1695 /*-- 08.09.2008 09:37:15---------------------------------------------------
1697 -----------------------------------------------------------------------*/
1698 void SwSpellIter::ToSentenceStart()
1700 bBackToStartOfSentence
= true;
1702 /*-- 08.10.2003 08:49:56---------------------------------------------------
1704 -----------------------------------------------------------------------*/
1705 LanguageType
lcl_GetLanguage(SwEditShell
& rSh
)
1707 USHORT nScriptType
= rSh
.GetScriptType();
1708 USHORT nLangWhichId
= RES_CHRATR_LANGUAGE
;
1712 case SCRIPTTYPE_ASIAN
: nLangWhichId
= RES_CHRATR_CJK_LANGUAGE
; break;
1713 case SCRIPTTYPE_COMPLEX
: nLangWhichId
= RES_CHRATR_CTL_LANGUAGE
; break;
1715 SfxItemSet
aSet(rSh
.GetAttrPool(), nLangWhichId
, nLangWhichId
, 0);
1716 rSh
.GetCurAttr( aSet
);
1717 const SvxLanguageItem
& rLang
= static_cast<const SvxLanguageItem
& >(aSet
.Get(nLangWhichId
));
1718 return rLang
.GetLanguage();
1720 /*-- 08.10.2003 08:53:27---------------------------------------------------
1721 create a text portion at the given position
1722 -----------------------------------------------------------------------*/
1723 void SwSpellIter::CreatePortion(uno::Reference
< XSpellAlternatives
> xAlt
,
1724 linguistic2::ProofreadingResult
* pGrammarResult
,
1725 bool bIsField
, bool bIsHidden
)
1727 svx::SpellPortion aPortion
;
1729 GetSh()->GetSelectedText( sText
);
1732 //in case of redlined deletions the selection of an error is not
1733 //the same as the _real_ word
1735 aPortion
.sText
= xAlt
->getWord();
1736 else if(pGrammarResult
)
1738 aPortion
.bIsGrammarError
= true;
1739 if(pGrammarResult
->aErrors
.getLength())
1741 aPortion
.aGrammarError
= pGrammarResult
->aErrors
[0];
1742 aPortion
.sText
= pGrammarResult
->aText
.copy( aPortion
.aGrammarError
.nErrorStart
, aPortion
.aGrammarError
.nErrorLength
);
1743 aPortion
.xGrammarChecker
= pGrammarResult
->xProofreader
;
1744 const beans::PropertyValue
* pProperties
= pGrammarResult
->aProperties
.getConstArray();
1745 for( sal_Int32 nProp
= 0; nProp
< pGrammarResult
->aProperties
.getLength(); ++nProp
)
1747 if( pProperties
->Name
.equalsAscii("DialogTitle") )
1749 pProperties
->Value
>>= aPortion
.sDialogTitle
;
1756 aPortion
.sText
= sText
;
1757 aPortion
.eLanguage
= lcl_GetLanguage(*GetSh());
1758 aPortion
.bIsField
= bIsField
;
1759 aPortion
.bIsHidden
= bIsHidden
;
1760 aPortion
.xAlternatives
= xAlt
;
1761 SpellContentPosition aPosition
;
1762 SwPaM
*pCrsr
= GetSh()->GetCrsr();
1763 aPosition
.nLeft
= pCrsr
->Start()->nContent
.GetIndex();
1764 aPosition
.nRight
= pCrsr
->End()->nContent
.GetIndex();
1765 aLastPortions
.push_back(aPortion
);
1766 aLastPositions
.push_back(aPosition
);
1769 /*-- 19.09.2003 13:05:43---------------------------------------------------
1771 -----------------------------------------------------------------------*/
1772 void SwSpellIter::AddPortion(uno::Reference
< XSpellAlternatives
> xAlt
,
1773 linguistic2::ProofreadingResult
* pGrammarResult
,
1774 const SpellContentPositions
& rDeletedRedlines
)
1776 SwEditShell
*pMySh
= GetSh();
1778 pMySh
->GetSelectedText( sText
);
1781 if(xAlt
.is() || pGrammarResult
!= 0)
1783 CreatePortion(xAlt
, pGrammarResult
, false, false);
1787 SwPaM
*pCrsr
= GetSh()->GetCrsr();
1788 if ( *pCrsr
->GetPoint() > *pCrsr
->GetMark() )
1790 //save the start and end positions
1791 SwPosition
aStart(*pCrsr
->GetPoint());
1792 SwPosition
aEnd(*pCrsr
->GetMark());
1793 //iterate over the text to find changes in language
1794 //set the mark equal to the point
1795 *pCrsr
->GetMark() = aStart
;
1796 SwTxtNode
* pTxtNode
= pCrsr
->GetNode()->GetTxtNode();
1797 LanguageType eStartLanguage
= lcl_GetLanguage(*GetSh());
1798 SpellContentPosition aNextRedline
= lcl_FindNextDeletedRedline(
1799 rDeletedRedlines
, aStart
.nContent
.GetIndex() );
1800 if( aNextRedline
.nLeft
== aStart
.nContent
.GetIndex() )
1802 //select until the end of the current redline
1803 xub_StrLen nEnd
= aEnd
.nContent
.GetIndex() < aNextRedline
.nRight
?
1804 aEnd
.nContent
.GetIndex() : aNextRedline
.nRight
;
1805 pCrsr
->GetPoint()->nContent
.Assign( pTxtNode
, nEnd
);
1806 CreatePortion(xAlt
, pGrammarResult
, false, true);
1807 aStart
= *pCrsr
->End();
1808 //search for next redline
1809 aNextRedline
= lcl_FindNextDeletedRedline(
1810 rDeletedRedlines
, aStart
.nContent
.GetIndex() );
1812 while(*pCrsr
->GetPoint() < aEnd
)
1814 //#125786 in table cell with fixed row height the cursor might not move forward
1815 if(!GetSh()->Right(1, CRSR_SKIP_CELLS
))
1818 bool bField
= false;
1819 //read the character at the current position to check if it's a field
1820 xub_Unicode cChar
= pTxtNode
->GetTxt().GetChar( pCrsr
->GetMark()->nContent
.GetIndex() );
1821 if( CH_TXTATR_BREAKWORD
== cChar
|| CH_TXTATR_INWORD
== cChar
)
1823 const SwTxtAttr
* pTxtAttr
= pTxtNode
->GetTxtAttrForCharAt(
1824 pCrsr
->GetMark()->nContent
.GetIndex() );
1825 const USHORT nWhich
= pTxtAttr
1827 : static_cast<USHORT
>(RES_TXTATR_END
);
1830 case RES_TXTATR_FIELD
:
1831 case RES_TXTATR_FTN
:
1832 case RES_TXTATR_FLYCNT
:
1838 LanguageType eCurLanguage
= lcl_GetLanguage(*GetSh());
1839 bool bRedline
= aNextRedline
.nLeft
== pCrsr
->GetPoint()->nContent
.GetIndex();
1840 // create a portion if the next character
1842 // - is at the beginning of a deleted redline
1843 // - has a different language
1844 if(bField
|| bRedline
|| eCurLanguage
!= eStartLanguage
)
1846 eStartLanguage
= eCurLanguage
;
1847 //go one step back - the cursor currently selects the first character
1848 //with a different language
1849 //in the case of redlining it's different
1850 if(eCurLanguage
!= eStartLanguage
|| bField
)
1851 *pCrsr
->GetPoint() = *pCrsr
->GetMark();
1852 //set to the last start
1853 *pCrsr
->GetMark() = aStart
;
1854 //create portion should only be called if a selection exists
1855 //there's no selection if there's a field at the beginning
1856 if(*pCrsr
->Start() != *pCrsr
->End())
1857 CreatePortion(xAlt
, pGrammarResult
, false, false);
1858 aStart
= *pCrsr
->End();
1859 //now export the field - if there is any
1862 *pCrsr
->GetMark() = *pCrsr
->GetPoint();
1863 GetSh()->Right(1, CRSR_SKIP_CELLS
);
1864 CreatePortion(xAlt
, pGrammarResult
, true, false);
1865 aStart
= *pCrsr
->End();
1868 // if a redline start then create a portion for it
1871 *pCrsr
->GetMark() = *pCrsr
->GetPoint();
1872 //select until the end of the current redline
1873 xub_StrLen nEnd
= aEnd
.nContent
.GetIndex() < aNextRedline
.nRight
?
1874 aEnd
.nContent
.GetIndex() : aNextRedline
.nRight
;
1875 pCrsr
->GetPoint()->nContent
.Assign( pTxtNode
, nEnd
);
1876 CreatePortion(xAlt
, pGrammarResult
, false, true);
1877 aStart
= *pCrsr
->End();
1878 //search for next redline
1879 aNextRedline
= lcl_FindNextDeletedRedline(
1880 rDeletedRedlines
, aStart
.nContent
.GetIndex() );
1882 *pCrsr
->GetMark() = *pCrsr
->GetPoint();
1885 *pCrsr
->GetMark() = aStart
;
1886 CreatePortion(xAlt
, pGrammarResult
, false, false);
1890 /*-- 07.08.2008 15:01:25---------------------------------------------------
1892 -----------------------------------------------------------------------*/
1893 void SwEditShell::IgnoreGrammarErrorAt( SwPaM
& rErrorPosition
)
1896 SwWrongList
*pWrong
;
1897 SwNodeIndex aIdx
= rErrorPosition
.Start()->nNode
;
1898 SwNodeIndex aEndIdx
= rErrorPosition
.Start()->nNode
;
1899 xub_StrLen nStart
= rErrorPosition
.Start()->nContent
.GetIndex();
1900 xub_StrLen nEnd
= STRING_LEN
;
1901 while( aIdx
<= aEndIdx
)
1903 pNode
= aIdx
.GetNode().GetTxtNode();
1905 if( aIdx
== aEndIdx
)
1906 nEnd
= rErrorPosition
.End()->nContent
.GetIndex();
1907 pWrong
= pNode
->GetGrammarCheck();
1909 pWrong
->RemoveEntry( nStart
, nEnd
);
1910 pWrong
= pNode
->GetWrong();
1912 pWrong
->RemoveEntry( nStart
, nEnd
);
1913 ::repaintTextFrames( *pNode
);