1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26
27 #include <com/sun/star/linguistic2/ProofreadingResult.hpp>
28 #include <com/sun/star/linguistic2/XProofreader.hpp>
29 #include <com/sun/star/linguistic2/XProofreadingIterator.hpp>
30 #include <com/sun/star/text/XFlatParagraph.hpp>
31
32 #include <unoflatpara.hxx>
33
34 #include <comcore.hrc>
35 #include <hintids.hxx>
36 #include <linguistic/lngprops.hxx>
37 #include <vcl/msgbox.hxx>
38 #include <editeng/unolingu.hxx>
39 #include <editeng/svxacorr.hxx>
40 #include <editeng/langitem.hxx>
41 #include <editeng/SpellPortions.hxx>
42 #include <editeng/scripttypeitem.hxx>
43 #include <charatr.hxx>
44 #include <editsh.hxx>
45 #include <doc.hxx>
46 #include <IDocumentUndoRedo.hxx>
47 #include <rootfrm.hxx> // SwRootFrm
48 #include <pam.hxx>
49 #include <swundo.hxx> // fuer die UndoIds
50 #include <ndtxt.hxx> // AdjHyphPos
51 #include <viewopt.hxx> // HyphStart/End
52 #include <viscrs.hxx> // SwShellCrsr
53 #include <SwGrammarMarkUp.hxx> // SwWrongList
54 #include <mdiexp.hxx> // Statusanzeige
55 #include <statstr.hrc> // StatLine-String
56 #include <cntfrm.hxx>
57 #include <crsskip.hxx>
58 #include <splargs.hxx>
59 #include <redline.hxx> // SwRedline
60 #include <docary.hxx> // SwRedlineTbl
61 #include <docsh.hxx>
62 #include <txatbase.hxx>
63 #include <txtfrm.hxx>
64
65 using namespace ::svx;
66 using namespace ::com::sun::star;
67 using namespace ::com::sun::star::uno;
68 using namespace ::com::sun::star::beans;
69 using namespace ::com::sun::star::linguistic2;
70
71 #define C2U(cChar) rtl::OUString::createFromAscii(cChar)
72
73 /*************************************************************************
74 * class SwLinguIter
75 *************************************************************************/
76
77 class SwLinguIter
78 {
79 SwEditShell *pSh;
80 SwPosition *pStart;
81 SwPosition *pEnd;
82 SwPosition *pCurr;
83 SwPosition *pCurrX;
84 sal_uInt16 nCrsrCnt;
85 public:
86 SwLinguIter();
87
GetSh()88 inline SwEditShell *GetSh() { return pSh; }
GetSh() const89 inline const SwEditShell *GetSh() const { return pSh; }
90
GetEnd() const91 inline const SwPosition *GetEnd() const { return pEnd; }
SetEnd(SwPosition * pNew)92 inline void SetEnd( SwPosition* pNew ){ delete pEnd; pEnd = pNew; }
93
GetStart() const94 inline const SwPosition *GetStart() const { return pStart; }
SetStart(SwPosition * pNew)95 inline void SetStart( SwPosition* pNew ){ delete pStart; pStart = pNew; }
96
GetCurr() const97 inline const SwPosition *GetCurr() const { return pCurr; }
SetCurr(SwPosition * pNew)98 inline void SetCurr( SwPosition* pNew ){ delete pCurr; pCurr = pNew; }
99
GetCurrX() const100 inline const SwPosition *GetCurrX() const { return pCurrX; }
SetCurrX(SwPosition * pNew)101 inline void SetCurrX( SwPosition* pNew ){ delete pCurrX; pCurrX = pNew; }
102
GetCrsrCnt()103 inline sal_uInt16& GetCrsrCnt(){ return nCrsrCnt; }
104
105 // Der UI-Bauchladen:
106 void _Start( SwEditShell *pSh, SwDocPositions eStart,
107 SwDocPositions eEnd );
108 void _End(bool bRestoreSelection = true);
109 };
110
111 /*************************************************************************
112 * class SwSpellIter
113 *************************************************************************/
114
115 // #i18881# to be able to identify the postions of the changed words
116 // the content positions of each portion need to be saved
117 struct SpellContentPosition
118 {
119 sal_uInt16 nLeft;
120 sal_uInt16 nRight;
121 };
122 typedef std::vector<SpellContentPosition> SpellContentPositions;
123 class SwSpellIter : public SwLinguIter
124 {
125 uno::Reference< XSpellChecker1 > xSpeller;
126 ::svx::SpellPortions aLastPortions;
127
128 SpellContentPositions aLastPositions;
129 bool bBackToStartOfSentence;
130 bool bMoveToEndOfSentence;
131
132
133 void CreatePortion(uno::Reference< XSpellAlternatives > xAlt,
134 linguistic2::ProofreadingResult* pGrammarResult,
135 bool bIsField, bool bIsHidden);
136
137 void AddPortion(uno::Reference< XSpellAlternatives > xAlt,
138 linguistic2::ProofreadingResult* pGrammarResult,
139 const SpellContentPositions& rDeletedRedlines);
140 public:
SwSpellIter()141 SwSpellIter() :
142 bBackToStartOfSentence(false), bMoveToEndOfSentence(false) {}
143
144 void Start( SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd );
145
146 uno::Any Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt );
147
148 bool SpellSentence(::svx::SpellPortions& rPortions, bool bIsGrammarCheck);
149 void ToSentenceStart();
GetLastPortions()150 const ::svx::SpellPortions GetLastPortions(){ return aLastPortions;}
GetLastPositions()151 SpellContentPositions GetLastPositions() {return aLastPositions;}
ContinueAfterThisSentence()152 void ContinueAfterThisSentence() { bMoveToEndOfSentence = true; }
153 };
154
155 /*************************************************************************
156 * class SwConvIter
157 * used for text conversion
158 *************************************************************************/
159
160 class SwConvIter : public SwLinguIter
161 {
162 SwConversionArgs &rArgs;
163 public:
SwConvIter(SwConversionArgs & rConvArgs)164 SwConvIter( SwConversionArgs &rConvArgs ) :
165 rArgs( rConvArgs )
166 {}
167
168 void Start( SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd );
169
170 uno::Any Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt );
171 };
172
173 /*************************************************************************
174 * class SwHyphIter
175 *************************************************************************/
176
177 class SwHyphIter : public SwLinguIter
178 {
179 sal_Bool bOldIdle;
180 void DelSoftHyph( SwPaM &rPam );
181
182 public:
SwHyphIter()183 SwHyphIter() : bOldIdle(sal_False) {}
184
185 void Start( SwEditShell *pSh, SwDocPositions eStart, SwDocPositions eEnd );
186 void End();
187
188 void Ignore();
189
190 uno::Any Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt );
191
192 sal_Bool IsAuto();
193 void InsertSoftHyph( const xub_StrLen nHyphPos );
194 void ShowSelection();
195 };
196
197 static SwSpellIter* pSpellIter = 0;
198 static SwConvIter* pConvIter = 0;
199 static SwHyphIter* pHyphIter = 0;
200
201 // Wir ersparen uns in Hyphenate ein GetFrm()
202 // Achtung: in txtedt.cxx stehen extern-Deklarationen auf diese Pointer!
203 const SwTxtNode *pLinguNode;
204 SwTxtFrm *pLinguFrm;
205
206 /*************************************************************************
207 * SwLinguIter::SwLinguIter
208 *************************************************************************/
209
SwLinguIter()210 SwLinguIter::SwLinguIter()
211 : pSh( 0 ), pStart( 0 ), pEnd( 0 ), pCurr( 0 ), pCurrX( 0 )
212 {
213 // @@@ es fehlt: Sicherstellen der Reentrance, ASSERTs etc.
214 }
215
216 /*************************************************************************
217 * SwLinguIter::Start
218 *************************************************************************/
219
220
221
_Start(SwEditShell * pShell,SwDocPositions eStart,SwDocPositions eEnd)222 void SwLinguIter::_Start( SwEditShell *pShell, SwDocPositions eStart,
223 SwDocPositions eEnd )
224 {
225 // es fehlt: Sicherstellen der Reentrance, Locking
226 if( pSh )
227 return;
228
229 sal_Bool bSetCurr;
230
231 pSh = pShell;
232
233 SET_CURR_SHELL( pSh );
234
235 ASSERT( !pEnd, "LinguStart ohne End?");
236
237 SwPaM *pCrsr = pSh->GetCrsr();
238
239 // pStk->SetCurCrsr();
240 // if( pCrsr->HasMark() || pCrsr != pCrsr->GetNext() )
241 if( pShell->HasSelection() || pCrsr != pCrsr->GetNext() )
242 {
243 bSetCurr = 0 != GetCurr();
244 nCrsrCnt = pSh->GetCrsrCnt();
245 if( pSh->IsTableMode() )
246 pSh->TblCrsrToCursor();
247
248 pSh->Push();
249 sal_uInt16 n;
250 for( n = 0; n < nCrsrCnt; ++n )
251 {
252 pSh->Push();
253 pSh->DestroyCrsr();
254 }
255 pSh->Pop( sal_False );
256 }
257 else
258 {
259 bSetCurr = sal_False;
260 nCrsrCnt = 1;
261 pSh->Push();
262 pSh->SetLinguRange( eStart, eEnd );
263 }
264
265 pCrsr = pSh->GetCrsr();
266 if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
267 pCrsr->Exchange();
268
269 pStart = new SwPosition( *pCrsr->GetPoint() );
270 pEnd = new SwPosition( *pCrsr->GetMark() );
271 if( bSetCurr )
272 {
273 SwPosition* pNew = new SwPosition( *GetStart() );
274 SetCurr( pNew );
275 pNew = new SwPosition( *pNew );
276 SetCurrX( pNew );
277 }
278
279 pCrsr->SetMark();
280
281 pLinguFrm = 0;
282 pLinguNode = 0;
283 }
284
285 /*************************************************************************
286 * SwLinguIter::End
287 *************************************************************************/
288
289
290
_End(bool bRestoreSelection)291 void SwLinguIter::_End(bool bRestoreSelection)
292 {
293 if( !pSh )
294 return;
295
296 ASSERT( pEnd, "SwEditShell::SpellEnd() ohne Start?");
297 if(bRestoreSelection)
298 {
299 while( nCrsrCnt-- )
300 pSh->Pop( sal_False );
301
302 pSh->KillPams();
303 pSh->ClearMark();
304 }
305 DELETEZ(pStart);
306 DELETEZ(pEnd);
307 DELETEZ(pCurr);
308 DELETEZ(pCurrX);
309
310 pSh = 0;
311
312 #ifdef LINGU_STATISTIK
313 aSwLinguStat.Flush();
314 #endif
315 }
316
317 /*************************************************************************
318 * virtual SwSpellIter::Start()
319 *************************************************************************/
320
321
322
Start(SwEditShell * pShell,SwDocPositions eStart,SwDocPositions eEnd)323 void SwSpellIter::Start( SwEditShell *pShell, SwDocPositions eStart,
324 SwDocPositions eEnd )
325 {
326 if( GetSh() )
327 return;
328
329 uno::Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
330 xSpeller = ::GetSpellChecker();
331 if ( xSpeller.is() )
332 _Start( pShell, eStart, eEnd );
333 aLastPortions.clear();
334 aLastPositions.clear();
335 }
336
337 /*************************************************************************
338 * SwSpellIter::Continue
339 *************************************************************************/
340
341 // SwSpellIter::Continue ist das alte Original von
342 // SwEditShell::SpellContinue()
343
Continue(sal_uInt16 * pPageCnt,sal_uInt16 * pPageSt)344 uno::Any SwSpellIter::Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
345 {
346 //!!
347 //!! Please check SwConvIter also when modifying this
348 //!!
349
350 uno::Any aSpellRet;
351 SwEditShell *pMySh = GetSh();
352 if( !pMySh )
353 return aSpellRet;
354
355 // const SwPosition *pEnd = GetEnd();
356
357 ASSERT( GetEnd(), "SwEditShell::SpellContinue() ohne Start?");
358
359 uno::Reference< uno::XInterface > xSpellRet;
360 sal_Bool bGoOn = sal_True;
361 do {
362 SwPaM *pCrsr = pMySh->GetCrsr();
363 if ( !pCrsr->HasMark() )
364 pCrsr->SetMark();
365
366 uno::Reference< beans::XPropertySet > xProp( GetLinguPropertySet() );
367 *pMySh->GetCrsr()->GetPoint() = *GetCurr();
368 *pMySh->GetCrsr()->GetMark() = *GetEnd();
369 pMySh->GetDoc()->Spell(*pMySh->GetCrsr(),
370 xSpeller, pPageCnt, pPageSt, false ) >>= xSpellRet;
371 bGoOn = GetCrsrCnt() > 1;
372 if( xSpellRet.is() )
373 {
374 bGoOn = sal_False;
375 SwPosition* pNewPoint = new SwPosition( *pCrsr->GetPoint() );
376 SwPosition* pNewMark = new SwPosition( *pCrsr->GetMark() );
377 SetCurr( pNewPoint );
378 SetCurrX( pNewMark );
379 }
380 if( bGoOn )
381 {
382 pMySh->Pop( sal_False );
383 pCrsr = pMySh->GetCrsr();
384 if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
385 pCrsr->Exchange();
386 SwPosition* pNew = new SwPosition( *pCrsr->GetPoint() );
387 SetStart( pNew );
388 pNew = new SwPosition( *pCrsr->GetMark() );
389 SetEnd( pNew );
390 pNew = new SwPosition( *GetStart() );
391 SetCurr( pNew );
392 pNew = new SwPosition( *pNew );
393 SetCurrX( pNew );
394 pCrsr->SetMark();
395 --GetCrsrCnt();
396 }
397 }while ( bGoOn );
398 aSpellRet <<= xSpellRet;
399 return aSpellRet;
400 }
401
402 /*************************************************************************
403 * virtual SwConvIter::Start()
404 *************************************************************************/
405
406
407
Start(SwEditShell * pShell,SwDocPositions eStart,SwDocPositions eEnd)408 void SwConvIter::Start( SwEditShell *pShell, SwDocPositions eStart,
409 SwDocPositions eEnd )
410 {
411 if( GetSh() )
412 return;
413 _Start( pShell, eStart, eEnd );
414 }
415
416 /*************************************************************************
417 * SwConvIter::Continue
418 *************************************************************************/
419
Continue(sal_uInt16 * pPageCnt,sal_uInt16 * pPageSt)420 uno::Any SwConvIter::Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
421 {
422 //!!
423 //!! Please check SwSpellIter also when modifying this
424 //!!
425
426 uno::Any aConvRet( makeAny( rtl::OUString() ) );
427 SwEditShell *pMySh = GetSh();
428 if( !pMySh )
429 return aConvRet;
430
431 // const SwPosition *pEnd = GetEnd();
432
433 ASSERT( GetEnd(), "SwConvIter::Continue() ohne Start?");
434
435 rtl::OUString aConvText;
436 sal_Bool bGoOn = sal_True;
437 do {
438 SwPaM *pCrsr = pMySh->GetCrsr();
439 if ( !pCrsr->HasMark() )
440 pCrsr->SetMark();
441
442 *pMySh->GetCrsr()->GetPoint() = *GetCurr();
443 *pMySh->GetCrsr()->GetMark() = *GetEnd();
444
445 // call function to find next text portion to be converted
446 uno::Reference< linguistic2::XSpellChecker1 > xEmpty;
447 pMySh->GetDoc()->Spell( *pMySh->GetCrsr(),
448 xEmpty, pPageCnt, pPageSt, false, &rArgs ) >>= aConvText;
449
450 bGoOn = GetCrsrCnt() > 1;
451 if( aConvText.getLength() )
452 {
453 bGoOn = sal_False;
454 SwPosition* pNewPoint = new SwPosition( *pCrsr->GetPoint() );
455 SwPosition* pNewMark = new SwPosition( *pCrsr->GetMark() );
456
457 SetCurr( pNewPoint );
458 SetCurrX( pNewMark );
459 }
460 if( bGoOn )
461 {
462 pMySh->Pop( sal_False );
463 pCrsr = pMySh->GetCrsr();
464 if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
465 pCrsr->Exchange();
466 SwPosition* pNew = new SwPosition( *pCrsr->GetPoint() );
467 SetStart( pNew );
468 pNew = new SwPosition( *pCrsr->GetMark() );
469 SetEnd( pNew );
470 pNew = new SwPosition( *GetStart() );
471 SetCurr( pNew );
472 pNew = new SwPosition( *pNew );
473 SetCurrX( pNew );
474 pCrsr->SetMark();
475 --GetCrsrCnt();
476 }
477 }while ( bGoOn );
478 return makeAny( aConvText );
479 }
480
481
482 /*************************************************************************
483 * SwHyphIter
484 *************************************************************************/
485
486
IsAuto()487 sal_Bool SwHyphIter::IsAuto()
488 {
489 uno::Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
490 return xProp.is() ? *(sal_Bool*)xProp->getPropertyValue(
491 C2U(UPN_IS_HYPH_AUTO) ).getValue()
492 : sal_False;
493 }
494
495
ShowSelection()496 void SwHyphIter::ShowSelection()
497 {
498 SwEditShell *pMySh = GetSh();
499 if( pMySh )
500 {
501 pMySh->StartAction();
502 // Ganz fatal: durch das EndAction() werden Formatierungen
503 // angeregt, die dazu fuehren koennen, dass im Hyphenator
504 // neue Worte eingestellt werden. Deswegen sichern!
505 pMySh->EndAction();
506 }
507 }
508
509 /*************************************************************************
510 * virtual SwHyphIter::Start()
511 *************************************************************************/
512
513
514
Start(SwEditShell * pShell,SwDocPositions eStart,SwDocPositions eEnd)515 void SwHyphIter::Start( SwEditShell *pShell, SwDocPositions eStart, SwDocPositions eEnd )
516 {
517 // robust
518 if( GetSh() || GetEnd() )
519 {
520 ASSERT( !GetSh(), "+SwEditShell::HyphStart: missing HyphEnd()" );
521 return;
522 }
523
524 // nothing to be done (at least not in the way as in the "else" part)
525 bOldIdle = pShell->GetViewOptions()->IsIdle();
526 ((SwViewOption*)pShell->GetViewOptions())->SetIdle( sal_False );
527 _Start( pShell, eStart, eEnd );
528 }
529
530 /*************************************************************************
531 * virtual SwHyphIter::End
532 *************************************************************************/
533
534 // Selektionen wiederherstellen
535
536
537
End()538 void SwHyphIter::End()
539 {
540 if( !GetSh() )
541 return;
542 ((SwViewOption*)GetSh()->GetViewOptions())->SetIdle( bOldIdle );
543 _End();
544 }
545
546 /*************************************************************************
547 * SwHyphIter::Continue
548 *************************************************************************/
549
Continue(sal_uInt16 * pPageCnt,sal_uInt16 * pPageSt)550 uno::Any SwHyphIter::Continue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
551 {
552 uno::Any aHyphRet;
553 SwEditShell *pMySh = GetSh();
554 if( !pMySh )
555 return aHyphRet;
556
557 const sal_Bool bAuto = IsAuto();
558 uno::Reference< XHyphenatedWord > xHyphWord;
559 sal_uInt16 nRet;
560 sal_Bool bGoOn = sal_False;
561 do {
562 SwPaM *pCrsr;
563 do {
564 ASSERT( GetEnd(), "SwEditShell::SpellContinue() ohne Start?" );
565 pCrsr = pMySh->GetCrsr();
566 if ( !pCrsr->HasMark() )
567 pCrsr->SetMark();
568 if ( *pCrsr->GetPoint() < *pCrsr->GetMark() )
569 {
570 pCrsr->Exchange();
571 pCrsr->SetMark();
572 }
573
574 // geraten BUG:
575 if ( *pCrsr->End() > *GetEnd() )
576 nRet = 0;
577 else
578 {
579 *pCrsr->GetMark() = *GetEnd();
580
581 // Muss an der aktuellen Cursorpos das Wort getrennt werden ?
582 const Point aCrsrPos( pMySh->GetCharRect().Pos() );
583 xHyphWord = pMySh->GetDoc()->Hyphenate( pCrsr, aCrsrPos,
584 pPageCnt, pPageSt );
585 }
586
587 if( bAuto && xHyphWord.is() )
588 {
589 pMySh->InsertSoftHyph( xHyphWord->getHyphenationPos() + 1);
590 }
591 } while( bAuto && xHyphWord.is() ); //end of do-while
592 bGoOn = !xHyphWord.is() && GetCrsrCnt() > 1;
593
594 if( bGoOn )
595 {
596 pMySh->Pop( sal_False );
597 pCrsr = pMySh->GetCrsr();
598 if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
599 pCrsr->Exchange();
600 SwPosition* pNew = new SwPosition(*pCrsr->End());
601 SetEnd( pNew );
602 pCrsr->SetMark();
603 --GetCrsrCnt();
604 }
605 } while ( bGoOn );
606 aHyphRet <<= xHyphWord;
607 return aHyphRet;
608 }
609
610 /*************************************************************************
611 * SwHyphIter::HyphIgnore
612 *************************************************************************/
613
614 // Beschreibung: Trennstelle ignorieren
615
Ignore()616 void SwHyphIter::Ignore()
617 {
618 SwEditShell *pMySh = GetSh();
619 SwPaM *pCrsr = pMySh->GetCrsr();
620
621 // Alten SoftHyphen loeschen
622 DelSoftHyph( *pCrsr );
623
624 // und weiter
625 pCrsr->Start()->nContent = pCrsr->End()->nContent;
626 pCrsr->SetMark();
627 }
628
629 /*************************************************************************
630 * SwHyphIter::DelSoftHyph
631 *************************************************************************/
632
DelSoftHyph(SwPaM & rPam)633 void SwHyphIter::DelSoftHyph( SwPaM &rPam )
634 {
635 const SwPosition* pStt = rPam.Start();
636 const xub_StrLen nStart = pStt->nContent.GetIndex();
637 const xub_StrLen nEnd = rPam.End()->nContent.GetIndex();
638 SwTxtNode *pNode = pStt->nNode.GetNode().GetTxtNode();
639 pNode->DelSoftHyph( nStart, nEnd );
640 }
641
642 /*************************************************************************
643 * SwHyphIter::InsertSoftHyph
644 *************************************************************************/
645
646
InsertSoftHyph(const xub_StrLen nHyphPos)647 void SwHyphIter::InsertSoftHyph( const xub_StrLen nHyphPos )
648 {
649 SwEditShell *pMySh = GetSh();
650 ASSERT( pMySh, "+SwEditShell::InsertSoftHyph: missing HyphStart()");
651 if( !pMySh )
652 return;
653
654 SwPaM *pCrsr = pMySh->GetCrsr();
655 SwPosition* pSttPos = pCrsr->Start();
656 SwPosition* pEndPos = pCrsr->End();
657
658 xub_StrLen nLastHyphLen = GetEnd()->nContent.GetIndex() -
659 pSttPos->nContent.GetIndex();
660
661 if( pSttPos->nNode != pEndPos->nNode || !nLastHyphLen )
662 {
663 ASSERT( pSttPos->nNode == pEndPos->nNode,
664 "+SwEditShell::InsertSoftHyph: node warp during hyphenation" );
665 ASSERT(nLastHyphLen, "+SwEditShell::InsertSoftHyph: missing HyphContinue()");
666 *pSttPos = *pEndPos;
667 return;
668 }
669
670 pMySh->StartAction();
671 {
672 SwDoc *pDoc = pMySh->GetDoc();
673 DelSoftHyph( *pCrsr );
674 pSttPos->nContent += nHyphPos;
675 SwPaM aRg( *pSttPos );
676 pDoc->InsertString( aRg, CHAR_SOFTHYPHEN );
677 // Durch das Einfuegen des SoftHyphs ist ein Zeichen hinzugekommen
678 //JP 18.07.95: warum, ist doch ein SwIndex, dieser wird doch mitverschoben !!
679 // pSttPos->nContent++;
680 }
681 // Die Selektion wird wieder aufgehoben
682 pCrsr->DeleteMark();
683 pMySh->EndAction();
684 pCrsr->SetMark();
685 }
686
687 // --------------------- Methoden der SwEditShell ------------------------
688
HasLastSentenceGotGrammarChecked() const689 bool SwEditShell::HasLastSentenceGotGrammarChecked() const
690 {
691 bool bTextWasGrammarChecked = false;
692 if (pSpellIter)
693 {
694 ::svx::SpellPortions aLastPortions( pSpellIter->GetLastPortions() );
695 for (size_t i = 0; i < aLastPortions.size() && !bTextWasGrammarChecked; ++i)
696 {
697 // bIsGrammarError is also true if the text was only checked but no
698 // grammar error was found. (That is if a ProofreadingResult was obtained in
699 // SwDoc::Spell and in turn bIsGrammarError was set in SwSpellIter::CreatePortion)
700 if (aLastPortions[i].bIsGrammarError)
701 bTextWasGrammarChecked = true;
702 }
703 }
704 return bTextWasGrammarChecked;
705 }
706
707 /*************************************************************************
708 * SwEditShell::HasConvIter
709 *************************************************************************/
710
HasConvIter() const711 sal_Bool SwEditShell::HasConvIter() const
712 {
713 return 0 != pConvIter;
714 }
715
716 /*************************************************************************
717 * SwEditShell::HasHyphIter
718 *************************************************************************/
719
HasHyphIter() const720 sal_Bool SwEditShell::HasHyphIter() const
721 {
722 return 0 != pHyphIter;
723 }
724
725 /*************************************************************************
726 * SwEditShell::SetFindRange
727 *************************************************************************/
728
SetLinguRange(SwDocPositions eStart,SwDocPositions eEnd)729 void SwEditShell::SetLinguRange( SwDocPositions eStart, SwDocPositions eEnd )
730 {
731 SwPaM *pCrsr = GetCrsr();
732 MakeFindRange( static_cast<sal_uInt16>(eStart), static_cast<sal_uInt16>(eEnd), pCrsr );
733 if( *pCrsr->GetPoint() > *pCrsr->GetMark() )
734 pCrsr->Exchange();
735 }
736
737 /*************************************************************************
738 * SwEditShell::SpellStart
739 *************************************************************************/
740
SpellStart(SwDocPositions eStart,SwDocPositions eEnd,SwDocPositions eCurr,SwConversionArgs * pConvArgs)741 void SwEditShell::SpellStart(
742 SwDocPositions eStart, SwDocPositions eEnd, SwDocPositions eCurr,
743 SwConversionArgs *pConvArgs )
744 {
745 SwLinguIter *pLinguIter = 0;
746
747 // do not spell if interactive spelling is active elsewhere
748 if (!pConvArgs && !pSpellIter)
749 {
750 ASSERT( !pSpellIter, "wer ist da schon am spellen?" );
751 pSpellIter = new SwSpellIter;
752 pLinguIter = pSpellIter;
753 }
754 // do not do text conversion if it is active elsewhere
755 if (pConvArgs && !pConvIter)
756 {
757 ASSERT( !pConvIter, "text conversion already active!" );
758 pConvIter = new SwConvIter( *pConvArgs );
759 pLinguIter = pConvIter;
760 }
761
762 if (pLinguIter)
763 {
764 SwCursor* pSwCrsr = GetSwCrsr();
765
766 SwPosition *pTmp = new SwPosition( *pSwCrsr->GetPoint() );
767 pSwCrsr->FillFindPos( eCurr, *pTmp );
768 pLinguIter->SetCurr( pTmp );
769
770 pTmp = new SwPosition( *pTmp );
771 pLinguIter->SetCurrX( pTmp );
772 }
773
774 if (!pConvArgs && pSpellIter)
775 pSpellIter->Start( this, eStart, eEnd );
776 if (pConvArgs && pConvIter)
777 pConvIter->Start( this, eStart, eEnd );
778 }
779
780 /*************************************************************************
781 * SwEditShell::SpellEnd
782 *************************************************************************/
783
SpellEnd(SwConversionArgs * pConvArgs,bool bRestoreSelection)784 void SwEditShell::SpellEnd( SwConversionArgs *pConvArgs, bool bRestoreSelection )
785 {
786 if (!pConvArgs && pSpellIter && pSpellIter->GetSh() == this)
787 {
788 ASSERT( pSpellIter, "wo ist mein Iterator?" );
789 pSpellIter->_End(bRestoreSelection);
790 delete pSpellIter, pSpellIter = 0;
791 }
792 if (pConvArgs && pConvIter && pConvIter->GetSh() == this)
793 {
794 ASSERT( pConvIter, "wo ist mein Iterator?" );
795 pConvIter->_End();
796 delete pConvIter, pConvIter = 0;
797 }
798 }
799
800 /*************************************************************************
801 * SwEditShell::SpellContinue
802 *************************************************************************/
803
804 // liefert Rueckgabewerte entsprechend SPL_ in splchk.hxx
805
SpellContinue(sal_uInt16 * pPageCnt,sal_uInt16 * pPageSt,SwConversionArgs * pConvArgs)806 uno::Any SwEditShell::SpellContinue(
807 sal_uInt16* pPageCnt, sal_uInt16* pPageSt,
808 SwConversionArgs *pConvArgs )
809 {
810 uno::Any aRes;
811
812 if ((!pConvArgs && pSpellIter->GetSh() != this) ||
813 ( pConvArgs && pConvIter->GetSh() != this))
814 return aRes;
815
816 if( pPageCnt && !*pPageCnt )
817 {
818 sal_uInt16 nEndPage = GetLayout()->GetPageNum();
819 nEndPage += nEndPage * 10 / 100;
820 *pPageCnt = nEndPage;
821 if( nEndPage )
822 ::StartProgress( STR_STATSTR_SPELL, 0, nEndPage, GetDoc()->GetDocShell() );
823 }
824
825 ASSERT( pConvArgs || pSpellIter, "SpellIter missing" );
826 ASSERT( !pConvArgs || pConvIter, "ConvIter missing" );
827 //JP 18.07.95: verhinder bei Fehlermeldungen die Anzeige der Selektionen
828 // KEIN StartAction, da damit auch die Paints abgeschaltet
829 // werden !!!!!
830 ++nStartAction;
831 rtl::OUString aRet;
832 uno::Reference< uno::XInterface > xRet;
833 if (pConvArgs)
834 {
835 pConvIter->Continue( pPageCnt, pPageSt ) >>= aRet;
836 aRes <<= aRet;
837 }
838 else
839 {
840 pSpellIter->Continue( pPageCnt, pPageSt ) >>= xRet;
841 aRes <<= xRet;
842 }
843 --nStartAction;
844
845 if( aRet.getLength() || xRet.is() )
846 {
847 // dann die awt::Selection sichtbar machen
848 StartAction();
849 EndAction();
850 }
851 return aRes;
852 }
853 /*************************************************************************
854 * SwEditShell::HyphStart
855 *************************************************************************/
856
857 /* Interaktive Trennung, BP 10.03.93
858 *
859 * 1) HyphStart
860 * - Aufheben aller Selektionen
861 * - Sichern des aktuellen Cursors
862 * - falls keine Selektion vorhanden:
863 * - neue Selektion bis zum Dokumentende
864 * 2) HyphContinue
865 * - nLastHyphLen wird auf den Selektionsstart addiert
866 * - iteriert ueber alle selektierten Bereiche
867 * - pDoc->Hyphenate() iteriert ueber alle Nodes der Selektion
868 * - pTxtNode->Hyphenate() ruft das SwTxtFrm::Hyphenate zur EditShell
869 * - SwTxtFrm:Hyphenate() iteriert ueber die Zeilen des Pams
870 * - LineIter::Hyphenate() stellt den Hyphenator
871 * und den Pam auf das zu trennende Wort ein.
872 * - Es gibt nur zwei Returnwerte sal_True, wenn eine Trennstelle anliegt
873 * und sal_False, wenn der Pam abgearbeitet wurde.
874 * - Bei sal_True wird das selektierte Wort zur Anzeige gebracht und
875 * nLastHyphLen gesetzt.
876 * - Bei sal_False wird die aktuelle Selektion geloescht und die naechste
877 * zur aktuellen gewaehlt. Return HYPH_OK, wenn keine mehr vorhanden.
878 * 3) InsertSoftHyph (wird ggf. von der UI gerufen)
879 * - Der aktuelle Cursor wird plaziert und das Attribut eingefuegt.
880 * 4) HyphEnd
881 * - Wiederherstellen des alten Cursors, EndAction
882 */
883
884
885
HyphStart(SwDocPositions eStart,SwDocPositions eEnd)886 void SwEditShell::HyphStart( SwDocPositions eStart, SwDocPositions eEnd )
887 {
888 // do not hyphenate if interactive hyphenationg is active elsewhere
889 if (!pHyphIter)
890 {
891 ASSERT( !pHyphIter, "wer ist da schon am hyphinieren?" );
892 pHyphIter = new SwHyphIter;
893 pHyphIter->Start( this, eStart, eEnd );
894 }
895 }
896
897 /*************************************************************************
898 * SwEditShell::HyphEnd
899 *************************************************************************/
900
901 // Selektionen wiederherstellen
902
903
904
HyphEnd()905 void SwEditShell::HyphEnd()
906 {
907 if (pHyphIter->GetSh() == this)
908 {
909 ASSERT( pHyphIter, "wo ist mein Iterator?" );
910 pHyphIter->End();
911 delete pHyphIter, pHyphIter = 0;
912 }
913 }
914
915 /*************************************************************************
916 * SwEditShell::HyphContinue
917 *************************************************************************/
918
919 // Returnwerte: (BP: ich wuerde es genau umdrehen, aber die UI wuenscht es so)
920 // HYPH_CONTINUE, wenn eine Trennstelle anliegt
921 // HYPH_OK, wenn der selektierte Bereich abgearbeitet wurde.
922
923
924 uno::Reference< uno::XInterface >
HyphContinue(sal_uInt16 * pPageCnt,sal_uInt16 * pPageSt)925 SwEditShell::HyphContinue( sal_uInt16* pPageCnt, sal_uInt16* pPageSt )
926 {
927 if (pHyphIter->GetSh() != this)
928 return 0;
929
930 if( pPageCnt && !*pPageCnt && !*pPageSt )
931 {
932 sal_uInt16 nEndPage = GetLayout()->GetPageNum();
933 nEndPage += nEndPage * 10 / 100;
934 if( nEndPage > 14 )
935 {
936 *pPageCnt = nEndPage;
937 ::StartProgress( STR_STATSTR_HYPHEN, 0, nEndPage, GetDoc()->GetDocShell());
938 }
939 else // Hiermit unterdruecken wir ein fuer allemal
940 *pPageSt = 1; // das StatLineStartPercent
941 }
942
943 ASSERT( pHyphIter, "wo ist mein Iterator?" );
944 //JP 18.07.95: verhinder bei Fehlermeldungen die Anzeige der Selektionen
945 // KEIN StartAction, da damit auch die Paints abgeschaltet
946 // werden !!!!!
947 ++nStartAction;
948 uno::Reference< uno::XInterface > xRet;
949 pHyphIter->Continue( pPageCnt, pPageSt ) >>= xRet;
950 --nStartAction;
951
952 if( xRet.is() )
953 pHyphIter->ShowSelection();
954
955 return xRet;
956 }
957
958
959 /*************************************************************************
960 * SwEditShell::InsertSoftHyph
961 *************************************************************************/
962
963 // Zum Einfuegen des SoftHyphens, Position ist der Offset
964 // innerhalb des getrennten Wortes.
965
966
InsertSoftHyph(const xub_StrLen nHyphPos)967 void SwEditShell::InsertSoftHyph( const xub_StrLen nHyphPos )
968 {
969 ASSERT( pHyphIter, "wo ist mein Iterator?" );
970 pHyphIter->InsertSoftHyph( nHyphPos );
971 }
972
973
974 /*************************************************************************
975 * SwEditShell::HyphIgnore
976 *************************************************************************/
977
978 // Beschreibung: Trennstelle ignorieren
979
HyphIgnore()980 void SwEditShell::HyphIgnore()
981 {
982 ASSERT( pHyphIter, "wo ist mein Iterator?" );
983 //JP 18.07.95: verhinder bei Fehlermeldungen die Anzeige der Selektionen
984 // KEIN StartAction, da damit auch die Paints abgeschaltet
985 // werden !!!!!
986 ++nStartAction;
987 pHyphIter->Ignore();
988 --nStartAction;
989
990 pHyphIter->ShowSelection();
991 }
992
993 /*************************************************************************
994 * SwEditShell::GetCorrection()
995 * liefert eine Liste von Vorschlaegen fuer falsch geschriebene Worte,
996 * ein NULL-Pointer signalisiert, dass das Wort richtig geschrieben ist,
997 * eine leere Liste, dass das Wort zwar unbekannt ist, aber keine Alternativen
998 * geliefert werden koennen.
999 *************************************************************************/
1000
1001
1002 uno::Reference< XSpellAlternatives >
GetCorrection(const Point * pPt,SwRect & rSelectRect)1003 SwEditShell::GetCorrection( const Point* pPt, SwRect& rSelectRect )
1004 {
1005 uno::Reference< XSpellAlternatives > xSpellAlt;
1006
1007 if( IsTableMode() )
1008 return NULL;
1009 SwPaM* pCrsr = GetCrsr();
1010 SwPosition aPos( *pCrsr->GetPoint() );
1011 Point aPt( *pPt );
1012 SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
1013 SwTxtNode *pNode;
1014 SwWrongList *pWrong;
1015 if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
1016 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
1017 0 != (pWrong = pNode->GetWrong()) &&
1018 !pNode->IsInProtectSect() )
1019 {
1020 xub_StrLen nBegin = aPos.nContent.GetIndex();
1021 xub_StrLen nLen = 1;
1022 if( pWrong->InWrongWord(nBegin,nLen) && !pNode->IsSymbol(nBegin) )
1023 {
1024 String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
1025 String aWord( aText );
1026 aWord.EraseAllChars( CH_TXTATR_BREAKWORD ).EraseAllChars( CH_TXTATR_INWORD );
1027
1028 uno::Reference< XSpellChecker1 > xSpell( ::GetSpellChecker() );
1029 if( xSpell.is() )
1030 {
1031 LanguageType eActLang = (LanguageType)pNode->GetLang( nBegin, nLen );
1032 if( xSpell->hasLanguage( eActLang ))
1033 {
1034 // restrict the maximal number of suggestions displayed
1035 // in the context menu.
1036 // Note: That could of course be done by clipping the
1037 // resulting sequence but the current third party
1038 // implementations result differs greatly if the number of
1039 // suggestions to be retuned gets changed. Statistically
1040 // it gets much better if told to return e.g. only 7 strings
1041 // than returning e.g. 16 suggestions and using only the
1042 // first 7. Thus we hand down the value to use to that
1043 // implementation here by providing an additional parameter.
1044 Sequence< PropertyValue > aPropVals(1);
1045 PropertyValue &rVal = aPropVals.getArray()[0];
1046 rVal.Name = C2U( UPN_MAX_NUMBER_OF_SUGGESTIONS );
1047 rVal.Value <<= (sal_Int16) 7;
1048
1049 xSpellAlt = xSpell->spell( aWord, eActLang, aPropVals );
1050 }
1051 }
1052
1053 if ( xSpellAlt.is() ) // error found?
1054 {
1055 //save the start and end positons of the line and the starting point
1056 Push();
1057 LeftMargin();
1058 xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
1059 RightMargin();
1060 xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
1061 Pop(sal_False);
1062
1063 // make sure the selection build later from the
1064 // data below does not include footnotes and other
1065 // "in word" character to the left and right in order
1066 // to preserve those. Therefore count those "in words"
1067 // in order to modify the selection accordingly.
1068 const sal_Unicode* pChar = aText.GetBuffer();
1069 xub_StrLen nLeft = 0;
1070 while (pChar && *pChar++ == CH_TXTATR_INWORD)
1071 ++nLeft;
1072 pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
1073 xub_StrLen nRight = 0;
1074 while (pChar && *pChar-- == CH_TXTATR_INWORD)
1075 ++nRight;
1076
1077 aPos.nContent = nBegin + nLeft;
1078 pCrsr = GetCrsr();
1079 *pCrsr->GetPoint() = aPos;
1080 pCrsr->SetMark();
1081 ExtendSelection( sal_True, nLen - nLeft - nRight );
1082 //no determine the rectangle in the current line
1083 xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
1084 //take one less than the line end - otherwise the next line would be calculated
1085 xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight);
1086 Push();
1087 pCrsr->DeleteMark();
1088 SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
1089 rContent = nWordStart;
1090 SwRect aStartRect;
1091 SwCrsrMoveState aState;
1092 aState.bRealWidth = sal_True;
1093 SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
1094 SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), pPt, pCrsr->GetPoint(), sal_False);
1095
1096 pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
1097 rContent = nWordEnd;
1098 SwRect aEndRect;
1099 pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
1100 rSelectRect = aStartRect.Union( aEndRect );
1101 Pop(sal_False);
1102 }
1103 }
1104 }
1105 return xSpellAlt;
1106 }
1107
1108 /*-------------------------------------------------------------------------
1109
1110 -----------------------------------------------------------------------*/
1111
GetGrammarCorrection(linguistic2::ProofreadingResult & rResult,sal_Int32 & rErrorPosInText,sal_Int32 & rErrorIndexInResult,uno::Sequence<rtl::OUString> & rSuggestions,const Point * pPt,SwRect & rSelectRect)1112 bool SwEditShell::GetGrammarCorrection(
1113 linguistic2::ProofreadingResult /*out*/ &rResult, // the complete result
1114 sal_Int32 /*out*/ &rErrorPosInText, // offset of error position in string that was grammar checked...
1115 sal_Int32 /*out*/ &rErrorIndexInResult, // index of error in rResult.aGrammarErrors
1116 uno::Sequence< rtl::OUString > /*out*/ &rSuggestions, // suggestions to be used for the error found
1117 const Point *pPt, SwRect &rSelectRect )
1118 {
1119 bool bRes = false;
1120
1121 if( IsTableMode() )
1122 return bRes;
1123
1124 SwPaM* pCrsr = GetCrsr();
1125 SwPosition aPos( *pCrsr->GetPoint() );
1126 Point aPt( *pPt );
1127 SwCrsrMoveState eTmpState( MV_SETONLYTEXT );
1128 SwTxtNode *pNode;
1129 SwGrammarMarkUp *pWrong;
1130 if( GetLayout()->GetCrsrOfst( &aPos, aPt, &eTmpState ) &&
1131 0 != (pNode = aPos.nNode.GetNode().GetTxtNode()) &&
1132 0 != (pWrong = pNode->GetGrammarCheck()) &&
1133 !pNode->IsInProtectSect() )
1134 {
1135 xub_StrLen nBegin = aPos.nContent.GetIndex();
1136 xub_StrLen nLen = 1;
1137 if (pWrong->InWrongWord(nBegin, nLen))
1138 {
1139 String aText( pNode->GetTxt().Copy( nBegin, nLen ) );
1140 String aWord( aText );
1141 aWord.EraseAllChars( CH_TXTATR_BREAKWORD ).EraseAllChars( CH_TXTATR_INWORD );
1142
1143 uno::Reference< linguistic2::XProofreadingIterator > xGCIterator( pDoc->GetGCIterator() );
1144 if (xGCIterator.is())
1145 {
1146 // LanguageType eActLang = (LanguageType)pNode->GetLang( nBegin, nLen );
1147 uno::Reference< lang::XComponent > xDoc( pDoc->GetDocShell()->GetBaseModel(), uno::UNO_QUERY );
1148
1149 // Expand the string:
1150 rtl::OUString aExpandText;
1151 const ModelToViewHelper::ConversionMap* pConversionMap =
1152 pNode->BuildConversionMap( aExpandText );
1153 // get XFlatParagraph to use...
1154 uno::Reference< text::XFlatParagraph > xFlatPara = new SwXFlatParagraph( *pNode, aExpandText, pConversionMap );
1155
1156 // get error position of cursor in XFlatParagraph
1157 rErrorPosInText = ModelToViewHelper::ConvertToViewPosition( pConversionMap, nBegin );
1158
1159 sal_Int32 nStartOfSentence = ModelToViewHelper::ConvertToViewPosition( pConversionMap, pWrong->getSentenceStart( nBegin ) );
1160 sal_Int32 nEndOfSentence = ModelToViewHelper::ConvertToViewPosition( pConversionMap, pWrong->getSentenceEnd( nBegin ) );
1161 if( nEndOfSentence == STRING_LEN )
1162 {
1163 /* if( nStartOfSentence == 0 )
1164 {
1165 nStartOfSentence = -1;
1166 nEndOfSentence = -1;
1167 }
1168 else */
1169 nEndOfSentence = aExpandText.getLength();
1170 }
1171
1172 rResult = xGCIterator->checkSentenceAtPosition(
1173 xDoc, xFlatPara, aExpandText, lang::Locale(), nStartOfSentence, nEndOfSentence, rErrorPosInText );
1174 bRes = true;
1175
1176 // get suggestions to use for the specific error position
1177 sal_Int32 nErrors = rResult.aErrors.getLength();
1178 rSuggestions.realloc( 0 );
1179 for (sal_Int32 i = 0; i < nErrors; ++i )
1180 {
1181 // return suggestions for first error that includes the given error position
1182 const linguistic2::SingleProofreadingError &rError = rResult.aErrors[i];
1183 if( (rError.nErrorStart <= rErrorPosInText) &&
1184 (rErrorPosInText + nLen <= rError.nErrorStart + rError.nErrorLength))
1185 {
1186 rSuggestions = rError.aSuggestions;
1187 rErrorIndexInResult = i;
1188 break;
1189 }
1190 }
1191 }
1192
1193 if (rResult.aErrors.getLength() > 0) // error found?
1194 {
1195 //save the start and end positons of the line and the starting point
1196 Push();
1197 LeftMargin();
1198 xub_StrLen nLineStart = GetCrsr()->GetPoint()->nContent.GetIndex();
1199 RightMargin();
1200 xub_StrLen nLineEnd = GetCrsr()->GetPoint()->nContent.GetIndex();
1201 Pop(sal_False);
1202
1203 #if OSL_DEBUG_LEVEL > 1
1204 // pNode->GetGrammarCheck()->Invalidate( 0, STRING_LEN );
1205 // pNode->SetGrammarCheckDirty( true );
1206 #endif
1207 // make sure the selection build later from the
1208 // data below does not include footnotes and other
1209 // "in word" character to the left and right in order
1210 // to preserve those. Therefore count those "in words"
1211 // in order to modify the selection accordingly.
1212 const sal_Unicode* pChar = aText.GetBuffer();
1213 xub_StrLen nLeft = 0;
1214 while (pChar && *pChar++ == CH_TXTATR_INWORD)
1215 ++nLeft;
1216 pChar = aText.Len() ? aText.GetBuffer() + aText.Len() - 1 : 0;
1217 xub_StrLen nRight = 0;
1218 while (pChar && *pChar-- == CH_TXTATR_INWORD)
1219 ++nRight;
1220
1221 aPos.nContent = nBegin + nLeft;
1222 pCrsr = GetCrsr();
1223 *pCrsr->GetPoint() = aPos;
1224 pCrsr->SetMark();
1225 ExtendSelection( sal_True, nLen - nLeft - nRight );
1226 //no determine the rectangle in the current line
1227 xub_StrLen nWordStart = (nBegin + nLeft) < nLineStart ? nLineStart : nBegin + nLeft;
1228 //take one less than the line end - otherwise the next line would be calculated
1229 xub_StrLen nWordEnd = (nBegin + nLen - nLeft - nRight) > nLineEnd ? nLineEnd - 1: (nBegin + nLen - nLeft - nRight);
1230 Push();
1231 pCrsr->DeleteMark();
1232 SwIndex& rContent = GetCrsr()->GetPoint()->nContent;
1233 rContent = nWordStart;
1234 SwRect aStartRect;
1235 SwCrsrMoveState aState;
1236 aState.bRealWidth = sal_True;
1237 SwCntntNode* pCntntNode = pCrsr->GetCntntNode();
1238 SwCntntFrm *pCntntFrame = pCntntNode->getLayoutFrm( GetLayout(), pPt, pCrsr->GetPoint(), sal_False);
1239
1240 pCntntFrame->GetCharRect( aStartRect, *pCrsr->GetPoint(), &aState );
1241 rContent = nWordEnd;
1242 SwRect aEndRect;
1243 pCntntFrame->GetCharRect( aEndRect, *pCrsr->GetPoint(),&aState );
1244 rSelectRect = aStartRect.Union( aEndRect );
1245 Pop(sal_False);
1246 }
1247 }
1248 }
1249
1250 return bRes;
1251 }
1252
1253 /*-- 18.09.2003 15:08:18---------------------------------------------------
1254
1255 -----------------------------------------------------------------------*/
SpellSentence(::svx::SpellPortions & rPortions,bool bIsGrammarCheck)1256 bool SwEditShell::SpellSentence(::svx::SpellPortions& rPortions, bool bIsGrammarCheck)
1257 {
1258 ASSERT( pSpellIter, "SpellIter missing" );
1259 if(!pSpellIter)
1260 return false;
1261 bool bRet = pSpellIter->SpellSentence(rPortions, bIsGrammarCheck);
1262
1263 // make Selection visible - this should simply move the
1264 // cursor to the end of the sentence
1265 StartAction();
1266 EndAction();
1267 return bRet;
1268 }
1269 /*-- 08.09.2008 09:35:19---------------------------------------------------
1270 make SpellIter start with the current sentence when called next time
1271 -----------------------------------------------------------------------*/
PutSpellingToSentenceStart()1272 void SwEditShell::PutSpellingToSentenceStart()
1273 {
1274 ASSERT( pSpellIter, "SpellIter missing" );
1275 if(!pSpellIter)
1276 return;
1277 pSpellIter->ToSentenceStart();
1278 }
1279 /*-- 02.02.2005 14:34:41---------------------------------------------------
1280
1281 -----------------------------------------------------------------------*/
lcl_CountRedlines(const::svx::SpellPortions & rLastPortions)1282 sal_uInt32 lcl_CountRedlines(
1283 const ::svx::SpellPortions& rLastPortions)
1284 {
1285 sal_uInt32 nRet = 0;
1286 SpellPortions::const_iterator aIter = rLastPortions.begin();
1287 for( ; aIter != rLastPortions.end(); ++aIter)
1288 {
1289 if( aIter->bIsHidden )
1290 ++nRet;
1291 }
1292 return nRet;
1293 }
1294 /*-- 18.09.2003 15:08:20---------------------------------------------------
1295
1296 -----------------------------------------------------------------------*/
1297
MoveContinuationPosToEndOfCheckedSentence()1298 void SwEditShell::MoveContinuationPosToEndOfCheckedSentence()
1299 {
1300 // give hint that continuation position for spell/grammar checking is
1301 // at the end of this sentence
1302 if (pSpellIter)
1303 {
1304 pSpellIter->SetCurr( new SwPosition( *pSpellIter->GetCurrX() ) );
1305 pSpellIter->ContinueAfterThisSentence();
1306 }
1307 }
1308
1309
ApplyChangedSentence(const::svx::SpellPortions & rNewPortions,bool bRecheck)1310 void SwEditShell::ApplyChangedSentence(const ::svx::SpellPortions& rNewPortions, bool bRecheck)
1311 {
1312 // Note: rNewPortions.size() == 0 is valid and happens when the whole
1313 // sentence got removed in the dialog
1314
1315 ASSERT( pSpellIter, "SpellIter missing" );
1316 if(pSpellIter &&
1317 pSpellIter->GetLastPortions().size() > 0) // no portions -> no text to be changed
1318 {
1319 const SpellPortions& rLastPortions = pSpellIter->GetLastPortions();
1320 const SpellContentPositions rLastPositions = pSpellIter->GetLastPositions();
1321 ASSERT(rLastPortions.size() > 0 &&
1322 rLastPortions.size() == rLastPositions.size(),
1323 "last vectors of spelling results are not set or not equal")
1324
1325 // iterate over the new portions, beginning at the end to take advantage of the previously
1326 // saved content positions
1327
1328 pDoc->GetIDocumentUndoRedo().StartUndo( UNDO_OVERWRITE, NULL );
1329 StartAction();
1330
1331 SwPaM *pCrsr = GetCrsr();
1332 // save cursor position (which should be at the end of the current sentence)
1333 // for later restoration
1334 Push();
1335
1336 sal_uInt32 nRedlinePortions = lcl_CountRedlines(rLastPortions);
1337 if((rLastPortions.size() - nRedlinePortions) == rNewPortions.size())
1338 {
1339 DBG_ASSERT( rNewPortions.size() > 0, "rNewPortions should not be empty here" );
1340 DBG_ASSERT( rLastPortions.size() > 0, "rLastPortions should not be empty here" );
1341 DBG_ASSERT( rLastPositions.size() > 0, "rLastPositions should not be empty here" );
1342
1343 //the simple case: the same number of elements on both sides
1344 //each changed element has to be applied to the corresponding source element
1345 svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.end();
1346 SpellPortions::const_iterator aCurrentOldPortion = rLastPortions.end();
1347 SpellContentPositions::const_iterator aCurrentOldPosition = rLastPositions.end();
1348 do
1349 {
1350 --aCurrentNewPortion;
1351 --aCurrentOldPortion;
1352 --aCurrentOldPosition;
1353 //jump over redline portions
1354 while(aCurrentOldPortion->bIsHidden)
1355 {
1356 if (aCurrentOldPortion != rLastPortions.begin() &&
1357 aCurrentOldPosition != rLastPositions.begin())
1358 {
1359 --aCurrentOldPortion;
1360 --aCurrentOldPosition;
1361 }
1362 else
1363 {
1364 DBG_ASSERT( 0, "ApplyChangedSentence: iterator positions broken" );
1365 break;
1366 }
1367 }
1368 if ( !pCrsr->HasMark() )
1369 pCrsr->SetMark();
1370 pCrsr->GetPoint()->nContent = aCurrentOldPosition->nLeft;
1371 pCrsr->GetMark()->nContent = aCurrentOldPosition->nRight;
1372 sal_uInt16 nScriptType = GetI18NScriptTypeOfLanguage( aCurrentNewPortion->eLanguage );
1373 sal_uInt16 nLangWhichId = RES_CHRATR_LANGUAGE;
1374 switch(nScriptType)
1375 {
1376 case SCRIPTTYPE_ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
1377 case SCRIPTTYPE_COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
1378 }
1379 if(aCurrentNewPortion->sText != aCurrentOldPortion->sText)
1380 {
1381 //change text ...
1382 pDoc->DeleteAndJoin(*pCrsr);
1383 // ... and apply language if necessary
1384 if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage)
1385 SetAttrItem( SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId), nLangWhichId );
1386 pDoc->InsertString(*pCrsr, aCurrentNewPortion->sText);
1387 }
1388 else if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage)
1389 {
1390 //apply language
1391 SetAttrItem( SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId), nLangWhichId );
1392 }
1393 else if( aCurrentNewPortion->bIgnoreThisError )
1394 {
1395 //add the 'ignore' markup to the TextNode's grammar ignore markup list
1396 IgnoreGrammarErrorAt( *pCrsr );
1397 DBG_ERROR("TODO: add ignore mark to text node");
1398 }
1399 if(aCurrentNewPortion == rNewPortions.begin())
1400 break;
1401 }
1402 while(aCurrentNewPortion != rNewPortions.begin());
1403 }
1404 else
1405 {
1406 DBG_ASSERT( rLastPositions.size() > 0, "rLastPositions should not be empty here" );
1407
1408 //select the complete sentence
1409 SpellContentPositions::const_iterator aCurrentEndPosition = rLastPositions.end();
1410 --aCurrentEndPosition;
1411 SpellContentPositions::const_iterator aCurrentStartPosition = rLastPositions.begin();
1412 pCrsr->GetPoint()->nContent = aCurrentStartPosition->nLeft;
1413 pCrsr->GetMark()->nContent = aCurrentEndPosition->nRight;
1414
1415 //delete the sentence completely
1416 pDoc->DeleteAndJoin(*pCrsr);
1417 svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.begin();
1418 while(aCurrentNewPortion != rNewPortions.end())
1419 {
1420 //set the language attribute
1421 sal_uInt16 nScriptType = GetScriptType();
1422 sal_uInt16 nLangWhichId = RES_CHRATR_LANGUAGE;
1423 switch(nScriptType)
1424 {
1425 case SCRIPTTYPE_ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
1426 case SCRIPTTYPE_COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
1427 }
1428 SfxItemSet aSet(GetAttrPool(), nLangWhichId, nLangWhichId, 0);
1429 GetCurAttr( aSet );
1430 const SvxLanguageItem& rLang = static_cast<const SvxLanguageItem& >(aSet.Get(nLangWhichId));
1431 if(rLang.GetLanguage() != aCurrentNewPortion->eLanguage)
1432 SetAttrItem( SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId) );
1433 //insert the new string
1434 pDoc->InsertString(*pCrsr, aCurrentNewPortion->sText);
1435
1436 //set the cursor to the end of the inserted string
1437 *pCrsr->Start() = *pCrsr->End();
1438 ++aCurrentNewPortion;
1439 }
1440 }
1441
1442 // restore cursor to the end of the sentence
1443 // (will work also if the sentence length has changed,
1444 // since cursors get updated automatically!)
1445 Pop( sal_False );
1446
1447 // collapse cursor to the end of the modified sentence
1448 *pCrsr->Start() = *pCrsr->End();
1449 if (bRecheck)
1450 {
1451 //in grammar check the current sentence has to be checked again
1452 GoStartSentence();
1453 }
1454 // set continuation position for spell/grammar checking to the end of this sentence
1455 pSpellIter->SetCurr( new SwPosition( *pCrsr->Start() ) );
1456
1457 pDoc->GetIDocumentUndoRedo().EndUndo( UNDO_OVERWRITE, NULL );
1458 EndAction();
1459 }
1460 }
1461 /*-- 02.02.2005 10:46:45---------------------------------------------------
1462 collect all deleted redlines of the current text node beginning at the
1463 start of the cursor position
1464 -----------------------------------------------------------------------*/
lcl_CollectDeletedRedlines(SwEditShell * pSh)1465 SpellContentPositions lcl_CollectDeletedRedlines(SwEditShell* pSh)
1466 {
1467 SpellContentPositions aRedlines;
1468 SwDoc* pDoc = pSh->GetDoc();
1469 const bool bShowChg = IDocumentRedlineAccess::IsShowChanges( pDoc->GetRedlineMode() );
1470 if ( bShowChg )
1471 {
1472 SwPaM *pCrsr = pSh->GetCrsr();
1473 const SwPosition* pStartPos = pCrsr->Start();
1474 const SwTxtNode* pTxtNode = pCrsr->GetNode()->GetTxtNode();
1475
1476 sal_uInt16 nAct = pDoc->GetRedlinePos( *pTxtNode, USHRT_MAX );
1477 const xub_StrLen nStartIndex = pStartPos->nContent.GetIndex();
1478 for ( ; nAct < pDoc->GetRedlineTbl().Count(); nAct++ )
1479 {
1480 const SwRedline* pRed = pDoc->GetRedlineTbl()[ nAct ];
1481
1482 if ( pRed->Start()->nNode > pTxtNode->GetIndex() )
1483 break;
1484
1485 if( nsRedlineType_t::REDLINE_DELETE == pRed->GetType() )
1486 {
1487 xub_StrLen nStart, nEnd;
1488 pRed->CalcStartEnd( pTxtNode->GetIndex(), nStart, nEnd );
1489 if(nStart >= nStartIndex || nEnd >= nStartIndex)
1490 {
1491 SpellContentPosition aAdd;
1492 aAdd.nLeft = nStart;
1493 aAdd.nRight = nEnd;
1494 aRedlines.push_back(aAdd);
1495 }
1496 }
1497 }
1498 }
1499 return aRedlines;
1500 }
1501 /*-- 02.02.2005 11:06:12---------------------------------------------------
1502 remove the redline positions after the current selection
1503 -----------------------------------------------------------------------*/
lcl_CutRedlines(SpellContentPositions & aDeletedRedlines,SwEditShell * pSh)1504 void lcl_CutRedlines( SpellContentPositions& aDeletedRedlines, SwEditShell* pSh )
1505 {
1506 if(!aDeletedRedlines.empty())
1507 {
1508 SwPaM *pCrsr = pSh->GetCrsr();
1509 const SwPosition* pEndPos = pCrsr->End();
1510 xub_StrLen nEnd = pEndPos->nContent.GetIndex();
1511 while(!aDeletedRedlines.empty() &&
1512 aDeletedRedlines.back().nLeft > nEnd)
1513 {
1514 aDeletedRedlines.pop_back();
1515 }
1516 }
1517 }
1518 /*-- 02.02.2005 11:43:00---------------------------------------------------
1519
1520 -----------------------------------------------------------------------*/
lcl_FindNextDeletedRedline(const SpellContentPositions & rDeletedRedlines,xub_StrLen nSearchFrom)1521 SpellContentPosition lcl_FindNextDeletedRedline(
1522 const SpellContentPositions& rDeletedRedlines,
1523 xub_StrLen nSearchFrom )
1524 {
1525 SpellContentPosition aRet;
1526 aRet.nLeft = aRet.nRight = STRING_MAXLEN;
1527 if(!rDeletedRedlines.empty())
1528 {
1529 SpellContentPositions::const_iterator aIter = rDeletedRedlines.begin();
1530 for( ; aIter != rDeletedRedlines.end(); ++aIter)
1531 {
1532 if(aIter->nLeft < nSearchFrom)
1533 continue;
1534 aRet = *aIter;
1535 break;
1536 }
1537 }
1538 return aRet;
1539 }
1540 /*-- 18.09.2003 15:08:20---------------------------------------------------
1541
1542 -----------------------------------------------------------------------*/
SpellSentence(::svx::SpellPortions & rPortions,bool bIsGrammarCheck)1543 bool SwSpellIter::SpellSentence(::svx::SpellPortions& rPortions, bool bIsGrammarCheck)
1544 {
1545 bool bRet = false;
1546 aLastPortions.clear();
1547 aLastPositions.clear();
1548
1549 SwEditShell *pMySh = GetSh();
1550 if( !pMySh )
1551 return false;
1552
1553 ASSERT( GetEnd(), "SwEditShell::SpellSentence() ohne Start?");
1554
1555 uno::Reference< XSpellAlternatives > xSpellRet;
1556 linguistic2::ProofreadingResult aGrammarResult;
1557 sal_Bool bGoOn = sal_True;
1558 bool bGrammarErrorFound = false;
1559 do {
1560 SwPaM *pCrsr = pMySh->GetCrsr();
1561 if ( !pCrsr->HasMark() )
1562 pCrsr->SetMark();
1563
1564 *pCrsr->GetPoint() = *GetCurr();
1565 *pCrsr->GetMark() = *GetEnd();
1566
1567 if( bBackToStartOfSentence )
1568 {
1569 pMySh->GoStartSentence();
1570 bBackToStartOfSentence = false;
1571 }
1572 uno::Any aSpellRet =
1573 pMySh->GetDoc()->Spell(*pCrsr,
1574 xSpeller, 0, 0, bIsGrammarCheck );
1575 aSpellRet >>= xSpellRet;
1576 aSpellRet >>= aGrammarResult;
1577 bGoOn = GetCrsrCnt() > 1;
1578 bGrammarErrorFound = aGrammarResult.aErrors.getLength() > 0;
1579 if( xSpellRet.is() || bGrammarErrorFound )
1580 {
1581 bGoOn = sal_False;
1582 SwPosition* pNewPoint = new SwPosition( *pCrsr->GetPoint() );
1583 SwPosition* pNewMark = new SwPosition( *pCrsr->GetMark() );
1584
1585 SetCurr( pNewPoint );
1586 SetCurrX( pNewMark );
1587 }
1588 if( bGoOn )
1589 {
1590 pMySh->Pop( sal_False );
1591 pCrsr = pMySh->GetCrsr();
1592 if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
1593 pCrsr->Exchange();
1594 SwPosition* pNew = new SwPosition( *pCrsr->GetPoint() );
1595 SetStart( pNew );
1596 pNew = new SwPosition( *pCrsr->GetMark() );
1597 SetEnd( pNew );
1598 pNew = new SwPosition( *GetStart() );
1599 SetCurr( pNew );
1600 pNew = new SwPosition( *pNew );
1601 SetCurrX( pNew );
1602 pCrsr->SetMark();
1603 --GetCrsrCnt();
1604 }
1605 }
1606 while ( bGoOn );
1607 if(xSpellRet.is() || bGrammarErrorFound)
1608 {
1609 //an error has been found
1610 //To fill the spell portions the beginning of the sentence has to be found
1611 SwPaM *pCrsr = pMySh->GetCrsr();
1612 //set the mark to the right if necessary
1613 if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
1614 pCrsr->Exchange();
1615 //the cursor has to be collapsed on the left to go to the start of the sentence - if sentence ends inside of the error
1616 pCrsr->DeleteMark();
1617 pCrsr->SetMark();
1618 sal_Bool bStartSent = 0 != pMySh->GoStartSentence();
1619 SpellContentPositions aDeletedRedlines = lcl_CollectDeletedRedlines(pMySh);
1620 if(bStartSent)
1621 {
1622 //create a portion from the start part
1623 AddPortion(0, 0, aDeletedRedlines);
1624 }
1625 //Set the cursor to the error already found
1626 *pCrsr->GetPoint() = *GetCurrX();
1627 *pCrsr->GetMark() = *GetCurr();
1628 AddPortion(xSpellRet, &aGrammarResult, aDeletedRedlines);
1629
1630
1631 //save the end position of the error to continue from here
1632 SwPosition aSaveStartPos = *pCrsr->End();
1633 //determine the end of the current sentence
1634 if ( *pCrsr->GetPoint() < *pCrsr->GetMark() )
1635 pCrsr->Exchange();
1636 //again collapse to start marking after the end of the error
1637 pCrsr->DeleteMark();
1638 pCrsr->SetMark();
1639
1640 pMySh->GoEndSentence();
1641 if( bGrammarErrorFound )
1642 {
1643 rtl::OUString aExpandText;
1644 const ModelToViewHelper::ConversionMap* pConversionMap = ((SwTxtNode*)pCrsr->GetNode())->BuildConversionMap( aExpandText );
1645 xub_StrLen nSentenceEnd = (xub_StrLen)ModelToViewHelper::ConvertToViewPosition( pConversionMap, aGrammarResult.nBehindEndOfSentencePosition );
1646 // remove trailing space
1647 if( aExpandText[nSentenceEnd - 1] == ' ' )
1648 --nSentenceEnd;
1649 if( pCrsr->End()->nContent.GetIndex() < nSentenceEnd )
1650 {
1651 pCrsr->End()->nContent.Assign(
1652 pCrsr->End()->nNode.GetNode().GetCntntNode(), nSentenceEnd);
1653 }
1654 }
1655
1656 lcl_CutRedlines( aDeletedRedlines, pMySh );
1657 //save the 'global' end of the spellchecking
1658 const SwPosition aSaveEndPos = *GetEnd();
1659 //set the sentence end as 'local' end
1660 SetEnd( new SwPosition( *pCrsr->End() ));
1661
1662 *pCrsr->GetPoint() = aSaveStartPos;
1663 *pCrsr->GetMark() = *GetEnd();
1664 //now the rest of the sentence has to be searched for errors
1665 // for each error the non-error text between the current and the last error has
1666 // to be added to the portions - if necessary broken into same-language-portions
1667 if( !bGrammarErrorFound ) //in grammar check there's only one error returned
1668 {
1669 do
1670 {
1671 xSpellRet = 0;
1672 // don't search for grammar errors here anymore!
1673 pMySh->GetDoc()->Spell(*pCrsr,
1674 xSpeller, 0, 0, false ) >>= xSpellRet;
1675 if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
1676 pCrsr->Exchange();
1677 SetCurr( new SwPosition( *pCrsr->GetPoint() ));
1678 SetCurrX( new SwPosition( *pCrsr->GetMark() ));
1679
1680 //if an error has been found go back to the text
1681 //preceeding the error
1682 if(xSpellRet.is())
1683 {
1684 *pCrsr->GetPoint() = aSaveStartPos;
1685 *pCrsr->GetMark() = *GetCurr();
1686 }
1687 //add the portion
1688 AddPortion(0, 0, aDeletedRedlines);
1689
1690 if(xSpellRet.is())
1691 {
1692 *pCrsr->GetPoint() = *GetCurr();
1693 *pCrsr->GetMark() = *GetCurrX();
1694 AddPortion(xSpellRet, 0, aDeletedRedlines);
1695 //move the cursor to the end of the error string
1696 *pCrsr->GetPoint() = *GetCurrX();
1697 //and save the end of the error as new start position
1698 aSaveStartPos = *GetCurrX();
1699 //and the end of the sentence
1700 *pCrsr->GetMark() = *GetEnd();
1701 }
1702 // if the end of the sentence has already been reached then break here
1703 if(*GetCurrX() >= *GetEnd())
1704 break;
1705 }
1706 while(xSpellRet.is());
1707 }
1708 else
1709 {
1710 //go to the end of sentence as the grammar check returned it
1711 // at this time the Point is behind the grammar error
1712 // and the mark points to the sentence end as
1713 if ( *pCrsr->GetPoint() < *pCrsr->GetMark() )
1714 pCrsr->Exchange();
1715 }
1716
1717 // the part between the last error and the end of the sentence has to be added
1718 *pMySh->GetCrsr()->GetPoint() = *GetEnd();
1719 if(*GetCurrX() < *GetEnd())
1720 {
1721 AddPortion(0, 0, aDeletedRedlines);
1722 }
1723 //set the shell cursor to the end of the sentence to prevent a visible selection
1724 *pCrsr->GetMark() = *GetEnd();
1725 if( !bIsGrammarCheck )
1726 {
1727 //set the current position to the end of the sentence
1728 SetCurr( new SwPosition(*GetEnd()) );
1729 }
1730 //restore the 'global' end
1731 SetEnd( new SwPosition(aSaveEndPos) );
1732 rPortions = aLastPortions;
1733 bRet = true;
1734 }
1735 else
1736 {
1737 //if no error could be found the selection has to be corrected - at least if it's not in the body
1738 *pMySh->GetCrsr()->GetPoint() = *GetEnd();
1739 pMySh->GetCrsr()->DeleteMark();
1740 }
1741
1742 return bRet;
1743 }
1744
1745 /*-- 08.09.2008 09:37:15---------------------------------------------------
1746
1747 -----------------------------------------------------------------------*/
ToSentenceStart()1748 void SwSpellIter::ToSentenceStart()
1749 {
1750 bBackToStartOfSentence = true;
1751 }
1752 /*-- 08.10.2003 08:49:56---------------------------------------------------
1753
1754 -----------------------------------------------------------------------*/
lcl_GetLanguage(SwEditShell & rSh)1755 LanguageType lcl_GetLanguage(SwEditShell& rSh)
1756 {
1757 sal_uInt16 nScriptType = rSh.GetScriptType();
1758 sal_uInt16 nLangWhichId = RES_CHRATR_LANGUAGE;
1759
1760 switch(nScriptType)
1761 {
1762 case SCRIPTTYPE_ASIAN : nLangWhichId = RES_CHRATR_CJK_LANGUAGE; break;
1763 case SCRIPTTYPE_COMPLEX : nLangWhichId = RES_CHRATR_CTL_LANGUAGE; break;
1764 }
1765 SfxItemSet aSet(rSh.GetAttrPool(), nLangWhichId, nLangWhichId, 0);
1766 rSh.GetCurAttr( aSet );
1767 const SvxLanguageItem& rLang = static_cast<const SvxLanguageItem& >(aSet.Get(nLangWhichId));
1768 return rLang.GetLanguage();
1769 }
1770 /*-- 08.10.2003 08:53:27---------------------------------------------------
1771 create a text portion at the given position
1772 -----------------------------------------------------------------------*/
CreatePortion(uno::Reference<XSpellAlternatives> xAlt,linguistic2::ProofreadingResult * pGrammarResult,bool bIsField,bool bIsHidden)1773 void SwSpellIter::CreatePortion(uno::Reference< XSpellAlternatives > xAlt,
1774 linguistic2::ProofreadingResult* pGrammarResult,
1775 bool bIsField, bool bIsHidden)
1776 {
1777 svx::SpellPortion aPortion;
1778 String sText;
1779 GetSh()->GetSelectedText( sText );
1780 if(sText.Len())
1781 {
1782 //in case of redlined deletions the selection of an error is not
1783 //the same as the _real_ word
1784 if(xAlt.is())
1785 aPortion.sText = xAlt->getWord();
1786 else if(pGrammarResult)
1787 {
1788 aPortion.bIsGrammarError = true;
1789 if(pGrammarResult->aErrors.getLength())
1790 {
1791 aPortion.aGrammarError = pGrammarResult->aErrors[0];
1792 aPortion.sText = pGrammarResult->aText.copy( aPortion.aGrammarError.nErrorStart, aPortion.aGrammarError.nErrorLength );
1793 aPortion.xGrammarChecker = pGrammarResult->xProofreader;
1794 const beans::PropertyValue* pProperties = pGrammarResult->aProperties.getConstArray();
1795 for( sal_Int32 nProp = 0; nProp < pGrammarResult->aProperties.getLength(); ++nProp )
1796 {
1797 if( pProperties->Name.equalsAscii("DialogTitle") )
1798 {
1799 pProperties->Value >>= aPortion.sDialogTitle;
1800 break;
1801 }
1802 }
1803 }
1804 }
1805 else
1806 aPortion.sText = sText;
1807 aPortion.eLanguage = lcl_GetLanguage(*GetSh());
1808 aPortion.bIsField = bIsField;
1809 aPortion.bIsHidden = bIsHidden;
1810 aPortion.xAlternatives = xAlt;
1811 SpellContentPosition aPosition;
1812 SwPaM *pCrsr = GetSh()->GetCrsr();
1813 aPosition.nLeft = pCrsr->Start()->nContent.GetIndex();
1814 aPosition.nRight = pCrsr->End()->nContent.GetIndex();
1815 aLastPortions.push_back(aPortion);
1816 aLastPositions.push_back(aPosition);
1817 }
1818 }
1819 /*-- 19.09.2003 13:05:43---------------------------------------------------
1820
1821 -----------------------------------------------------------------------*/
AddPortion(uno::Reference<XSpellAlternatives> xAlt,linguistic2::ProofreadingResult * pGrammarResult,const SpellContentPositions & rDeletedRedlines)1822 void SwSpellIter::AddPortion(uno::Reference< XSpellAlternatives > xAlt,
1823 linguistic2::ProofreadingResult* pGrammarResult,
1824 const SpellContentPositions& rDeletedRedlines)
1825 {
1826 SwEditShell *pMySh = GetSh();
1827 String sText;
1828 pMySh->GetSelectedText( sText );
1829 if(sText.Len())
1830 {
1831 if(xAlt.is() || pGrammarResult != 0)
1832 {
1833 CreatePortion(xAlt, pGrammarResult, false, false);
1834 }
1835 else
1836 {
1837 SwPaM *pCrsr = GetSh()->GetCrsr();
1838 if ( *pCrsr->GetPoint() > *pCrsr->GetMark() )
1839 pCrsr->Exchange();
1840 //save the start and end positions
1841 SwPosition aStart(*pCrsr->GetPoint());
1842 SwPosition aEnd(*pCrsr->GetMark());
1843 //iterate over the text to find changes in language
1844 //set the mark equal to the point
1845 *pCrsr->GetMark() = aStart;
1846 SwTxtNode* pTxtNode = pCrsr->GetNode()->GetTxtNode();
1847 LanguageType eStartLanguage = lcl_GetLanguage(*GetSh());
1848 SpellContentPosition aNextRedline = lcl_FindNextDeletedRedline(
1849 rDeletedRedlines, aStart.nContent.GetIndex() );
1850 if( aNextRedline.nLeft == aStart.nContent.GetIndex() )
1851 {
1852 //select until the end of the current redline
1853 xub_StrLen nEnd = aEnd.nContent.GetIndex() < aNextRedline.nRight ?
1854 aEnd.nContent.GetIndex() : aNextRedline.nRight;
1855 pCrsr->GetPoint()->nContent.Assign( pTxtNode, nEnd );
1856 CreatePortion(xAlt, pGrammarResult, false, true);
1857 aStart = *pCrsr->End();
1858 //search for next redline
1859 aNextRedline = lcl_FindNextDeletedRedline(
1860 rDeletedRedlines, aStart.nContent.GetIndex() );
1861 }
1862 while(*pCrsr->GetPoint() < aEnd)
1863 {
1864 //#125786 in table cell with fixed row height the cursor might not move forward
1865 if(!GetSh()->Right(1, CRSR_SKIP_CELLS))
1866 break;
1867
1868 bool bField = false;
1869 //read the character at the current position to check if it's a field
1870 xub_Unicode cChar = pTxtNode->GetTxt().GetChar( pCrsr->GetMark()->nContent.GetIndex() );
1871 if( CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar)
1872 {
1873 const SwTxtAttr* pTxtAttr = pTxtNode->GetTxtAttrForCharAt(
1874 pCrsr->GetMark()->nContent.GetIndex() );
1875 const sal_uInt16 nWhich = pTxtAttr
1876 ? pTxtAttr->Which()
1877 : static_cast<sal_uInt16>(RES_TXTATR_END);
1878 switch (nWhich)
1879 {
1880 case RES_TXTATR_FIELD:
1881 case RES_TXTATR_ANNOTATION:
1882 case RES_TXTATR_FTN:
1883 case RES_TXTATR_FLYCNT:
1884 bField = true;
1885 break;
1886 }
1887 }
1888
1889 LanguageType eCurLanguage = lcl_GetLanguage(*GetSh());
1890 bool bRedline = aNextRedline.nLeft == pCrsr->GetPoint()->nContent.GetIndex();
1891 // create a portion if the next character
1892 // - is a field,
1893 // - is at the beginning of a deleted redline
1894 // - has a different language
1895 if(bField || bRedline || eCurLanguage != eStartLanguage)
1896 {
1897 eStartLanguage = eCurLanguage;
1898 //go one step back - the cursor currently selects the first character
1899 //with a different language
1900 //in the case of redlining it's different
1901 if(eCurLanguage != eStartLanguage || bField)
1902 *pCrsr->GetPoint() = *pCrsr->GetMark();
1903 //set to the last start
1904 *pCrsr->GetMark() = aStart;
1905 //create portion should only be called if a selection exists
1906 //there's no selection if there's a field at the beginning
1907 if(*pCrsr->Start() != *pCrsr->End())
1908 CreatePortion(xAlt, pGrammarResult, false, false);
1909 aStart = *pCrsr->End();
1910 //now export the field - if there is any
1911 if(bField)
1912 {
1913 *pCrsr->GetMark() = *pCrsr->GetPoint();
1914 GetSh()->Right(1, CRSR_SKIP_CELLS);
1915 CreatePortion(xAlt, pGrammarResult, true, false);
1916 aStart = *pCrsr->End();
1917 }
1918 }
1919 // if a redline start then create a portion for it
1920 if(bRedline)
1921 {
1922 *pCrsr->GetMark() = *pCrsr->GetPoint();
1923 //select until the end of the current redline
1924 xub_StrLen nEnd = aEnd.nContent.GetIndex() < aNextRedline.nRight ?
1925 aEnd.nContent.GetIndex() : aNextRedline.nRight;
1926 pCrsr->GetPoint()->nContent.Assign( pTxtNode, nEnd );
1927 CreatePortion(xAlt, pGrammarResult, false, true);
1928 aStart = *pCrsr->End();
1929 //search for next redline
1930 aNextRedline = lcl_FindNextDeletedRedline(
1931 rDeletedRedlines, aStart.nContent.GetIndex() );
1932 }
1933 *pCrsr->GetMark() = *pCrsr->GetPoint();
1934 }
1935 pCrsr->SetMark();
1936 *pCrsr->GetMark() = aStart;
1937 CreatePortion(xAlt, pGrammarResult, false, false);
1938 }
1939 }
1940 }
1941 /*-- 07.08.2008 15:01:25---------------------------------------------------
1942
1943 -----------------------------------------------------------------------*/
IgnoreGrammarErrorAt(SwPaM & rErrorPosition)1944 void SwEditShell::IgnoreGrammarErrorAt( SwPaM& rErrorPosition )
1945 {
1946 SwTxtNode *pNode;
1947 SwWrongList *pWrong;
1948 SwNodeIndex aIdx = rErrorPosition.Start()->nNode;
1949 SwNodeIndex aEndIdx = rErrorPosition.Start()->nNode;
1950 xub_StrLen nStart = rErrorPosition.Start()->nContent.GetIndex();
1951 xub_StrLen nEnd = STRING_LEN;
1952 while( aIdx <= aEndIdx )
1953 {
1954 pNode = aIdx.GetNode().GetTxtNode();
1955 if( pNode ) {
1956 if( aIdx == aEndIdx )
1957 nEnd = rErrorPosition.End()->nContent.GetIndex();
1958 pWrong = pNode->GetGrammarCheck();
1959 if( pWrong )
1960 pWrong->RemoveEntry( nStart, nEnd );
1961 pWrong = pNode->GetWrong();
1962 if( pWrong )
1963 pWrong->RemoveEntry( nStart, nEnd );
1964 SwTxtFrm::repaintTextFrames( *pNode );
1965 }
1966 ++aIdx;
1967 nStart = 0;
1968 }
1969 }
1970
1971
1972