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 <SwSpellDialogChildWindow.hxx>
28 #include <vcl/msgbox.hxx>
29 #include <editeng/svxacorr.hxx>
30 #include <editeng/acorrcfg.hxx>
31 #include <svx/svxids.hrc>
32 #include <sfx2/app.hxx>
33 #include <sfx2/bindings.hxx>
34 #include <sfx2/dispatch.hxx>
35 #include <editeng/unolingu.hxx>
36 #include <editeng/editeng.hxx>
37 #include <editeng/editview.hxx>
38 #include <wrtsh.hxx>
39 #include <sfx2/printer.hxx>
40 #include <svx/svdoutl.hxx>
41 #include <svx/svdview.hxx>
42 #include <svx/svditer.hxx>
43 #include <svx/svdogrp.hxx>
44 #include <unotools/linguprops.hxx>
45 #include <unotools/lingucfg.hxx>
46 #include <doc.hxx>
47 #include <docsh.hxx>
48 #include <docary.hxx>
49 #include <frmfmt.hxx>
50 #include <dcontact.hxx>
51 #include <edtwin.hxx>
52 #include <pam.hxx>
53 #include <drawbase.hxx>
54 #include <unotextrange.hxx>
55 #include <dialog.hrc>
56 #include <cmdid.h>
57 
58 
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::uno;
61 using namespace ::com::sun::star::text;
62 using namespace ::com::sun::star::linguistic2;
63 using namespace ::com::sun::star::beans;
64 
65 SFX_IMPL_CHILDWINDOW(SwSpellDialogChildWindow, FN_SPELL_GRAMMAR_DIALOG)
66 
67 
68 #define SPELL_START_BODY        0   // body text area
69 #define SPELL_START_OTHER       1   // frame, footnote, header, footer
70 #define SPELL_START_DRAWTEXT    2   // started in a draw text object
71 
72 struct SpellState
73 {
74     bool                m_bInitialCall;
75     bool                m_bLockFocus; //lock the focus notification while a modal dialog is active
76     bool                m_bLostFocus;
77 
78     //restart and progress information
79     sal_uInt16              m_SpellStartPosition;
80     bool                m_bBodySpelled;  //body already spelled
81     bool                m_bOtherSpelled; //frames, footnotes, headers and footers spelled
82     bool                m_bStartedInOther; //started the spelling insided of the _other_ area
83     bool                m_bStartedInSelection; // there was an initial text selection
84     SwPaM*              pOtherCursor; // position where the spelling inside the _other_ area started
85     bool                m_bDrawingsSpelled; //all drawings spelled
86     Reference<XTextRange> m_xStartRange; //text range that marks the start of spelling
87     const SdrObject*    m_pStartDrawing; //draw text object spelling started in
88     ESelection          m_aStartDrawingSelection; //draw text start selection
89     bool                m_bRestartDrawing; // the first selected drawing object is found again
90 
91     //lose/get focus information to decide if spelling can be continued
92     ShellModes          m_eSelMode;
93     const SwNode*       m_pPointNode;
94     const SwNode*       m_pMarkNode;
95     xub_StrLen          m_nPointPos;
96     xub_StrLen          m_nMarkPos;
97     const SdrOutliner*  m_pOutliner;
98     ESelection          m_aESelection;
99 
100     //iterating over draw text objects
101     std::list<SdrTextObj*> m_aTextObjects;
102     bool                m_bTextObjectsCollected;
103 
104     SpellState() :
105         m_bInitialCall(true),
106         m_bLockFocus(false),
107         m_bLostFocus(false),
108         m_SpellStartPosition(SPELL_START_BODY),
109         m_bBodySpelled(false),
110         m_bOtherSpelled(false),
111         m_bStartedInOther(false),
112         m_bStartedInSelection(false),
113         pOtherCursor(0),
114         m_bDrawingsSpelled(false),
115         m_pStartDrawing(0),
116         m_bRestartDrawing(false),
117 
118         m_eSelMode(SHELL_MODE_OBJECT), //initially invalid
119         m_pPointNode(0),
120         m_pMarkNode(0),
121         m_nPointPos(0),
122         m_nMarkPos(0),
123         m_pOutliner(0),
124         m_bTextObjectsCollected(false)
125         {}
126 
127     ~SpellState() {delete pOtherCursor;}
128 
129     // reset state in ::InvalidateSpellDialog
130     void    Reset()
131             {   m_bInitialCall = true;
132                 m_bBodySpelled = m_bOtherSpelled = m_bDrawingsSpelled = false;
133                 m_xStartRange = 0;
134                 m_pStartDrawing = 0;
135                 m_bRestartDrawing = false;
136 				m_bTextObjectsCollected = false;
137                 m_aTextObjects.clear();
138                 m_bStartedInOther = false;
139                 delete pOtherCursor;
140                 pOtherCursor = 0;
141             }
142 };
143 /*-- 30.10.2003 14:33:26---------------------------------------------------
144 
145   -----------------------------------------------------------------------*/
146 void lcl_LeaveDrawText(SwWrtShell& rSh)
147 {
148     if(rSh.GetDrawView())
149     {
150         rSh.GetDrawView()->SdrEndTextEdit( sal_True );
151         Point aPt(LONG_MIN, LONG_MIN);
152         //go out of the frame
153         rSh.SelectObj(aPt, SW_LEAVE_FRAME);
154         rSh.EnterStdMode();
155         rSh.GetView().AttrChangedNotify(&rSh);
156     }
157 }
158 /*-- 09.09.2003 10:39:22---------------------------------------------------
159 
160   -----------------------------------------------------------------------*/
161 SwSpellDialogChildWindow::SwSpellDialogChildWindow (
162             Window* _pParent,
163             sal_uInt16 nId,
164             SfxBindings* pBindings,
165             SfxChildWinInfo* pInfo) :
166                 svx::SpellDialogChildWindow (
167                     _pParent, nId, pBindings, pInfo),
168                     m_pSpellState(new SpellState)
169 {
170 
171     String aPropName( String::CreateFromAscii(UPN_IS_GRAMMAR_INTERACTIVE ) );
172     SvtLinguConfig().GetProperty( aPropName ) >>= m_bIsGrammarCheckingOn;
173 }
174 /*-- 09.09.2003 10:39:22---------------------------------------------------
175 
176   -----------------------------------------------------------------------*/
177 SwSpellDialogChildWindow::~SwSpellDialogChildWindow ()
178 {
179     SwWrtShell* pWrtShell = GetWrtShell_Impl();
180     if(!m_pSpellState->m_bInitialCall && pWrtShell)
181         pWrtShell->SpellEnd();
182     delete m_pSpellState;
183 }
184 
185 /*-- 09.09.2003 12:40:07---------------------------------------------------
186 
187   -----------------------------------------------------------------------*/
188 SfxChildWinInfo SwSpellDialogChildWindow::GetInfo (void) const
189 {
190     SfxChildWinInfo aInfo = svx::SpellDialogChildWindow::GetInfo();
191     aInfo.bVisible = sal_False;
192     return aInfo;
193 }
194 
195 /*-- 09.09.2003 10:39:40---------------------------------------------------
196 
197 
198   -----------------------------------------------------------------------*/
199 svx::SpellPortions SwSpellDialogChildWindow::GetNextWrongSentence(bool bRecheck)
200 {
201     svx::SpellPortions aRet;
202     SwWrtShell* pWrtShell = GetWrtShell_Impl();
203     if(pWrtShell)
204     {
205         if (!bRecheck)
206         {
207             // first set continuation point for spell/grammar check to the
208             // end of the current sentence
209             pWrtShell->MoveContinuationPosToEndOfCheckedSentence();
210         }
211 
212         ShellModes  eSelMode = pWrtShell->GetView().GetShellMode();
213         bool bDrawText = SHELL_MODE_DRAWTEXT == eSelMode;
214         bool bNormalText =
215             SHELL_MODE_TABLE_TEXT == eSelMode ||
216             SHELL_MODE_LIST_TEXT == eSelMode ||
217             SHELL_MODE_TABLE_LIST_TEXT == eSelMode ||
218             SHELL_MODE_TEXT == eSelMode;
219         //Writer text outside of the body
220         bool bOtherText = false;
221 
222         if( m_pSpellState->m_bInitialCall )
223         {
224             //if no text selection exists the cursor has to be set into the text
225             if(!bDrawText && !bNormalText)
226             {
227                 if(!MakeTextSelection_Impl(*pWrtShell, eSelMode))
228                     return aRet;
229                 else
230                 {
231                     // the selection type has to be checked again - both text types are possible
232                     if(0 != (pWrtShell->GetSelectionType()& nsSelectionType::SEL_DRW_TXT))
233                         bDrawText = true;
234                     bNormalText = !bDrawText;
235                 }
236             }
237             if(bNormalText)
238             {
239                 //set cursor to the start of the sentence
240                 if(!pWrtShell->HasSelection())
241                     pWrtShell->GoStartSentence();
242                 else
243                 {
244                     pWrtShell->ExpandToSentenceBorders();
245                     m_pSpellState->m_bStartedInSelection = true;
246                 }
247                 //determine if the selection is outside of the body text
248                 bOtherText = !(pWrtShell->GetFrmType(0,sal_True) & FRMTYPE_BODY);
249                 m_pSpellState->m_SpellStartPosition = bOtherText ? SPELL_START_OTHER : SPELL_START_BODY;
250                 if(bOtherText)
251                 {
252                     m_pSpellState->pOtherCursor = new SwPaM(*pWrtShell->GetCrsr()->GetPoint());
253                     m_pSpellState->m_bStartedInOther = true;
254                     pWrtShell->SpellStart( DOCPOS_OTHERSTART, DOCPOS_OTHEREND, DOCPOS_CURR, sal_False );
255                 }
256                 else
257 				{
258 					SwPaM* pCrsr = pWrtShell->GetCrsr();
259 					//mark the start position only if not at start of doc
260 					if(!pWrtShell->IsStartOfDoc())
261 					{
262                         m_pSpellState->m_xStartRange =
263                             SwXTextRange::CreateXTextRange(
264                                 *pWrtShell->GetDoc(),
265                                 *pCrsr->Start(), pCrsr->End());
266 					}
267                     pWrtShell->SpellStart( DOCPOS_START, DOCPOS_END, DOCPOS_CURR, sal_False );
268 				}
269             }
270             else
271             {
272                 SdrView* pSdrView = pWrtShell->GetDrawView();
273                 m_pSpellState->m_SpellStartPosition = SPELL_START_DRAWTEXT;
274                 m_pSpellState->m_pStartDrawing = pSdrView->GetMarkedObjectList().GetMark(0)->GetMarkedSdrObj();
275                 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
276                 // start checking at the top of the drawing object
277                 pOLV->SetSelection( ESelection() );
278                 m_pSpellState->m_aStartDrawingSelection = ESelection();
279 /*
280 Note: spelling in a selection only, or starting in a mid of a drawing object requires
281 further changes elsewhere. (Especially if it should work in sc and sd as well.)
282 The code below would only be part of the solution.
283 (Keeping it a as a comment for the time being)
284                 ESelection aCurSel( pOLV->GetSelection() );
285                 ESelection aSentenceSel( pOLV->GetEditView().GetEditEngine()->SelectSentence( aCurSel ) );
286                 if (!aCurSel.HasRange())
287                 {
288                     aSentenceSel.nEndPara = aSentenceSel.nStartPara;
289                     aSentenceSel.nEndPos  = aSentenceSel.nStartPos;
290                 }
291                 pOLV->SetSelection( aSentenceSel );
292                 m_pSpellState->m_aStartDrawingSelection = aSentenceSel;
293 */
294             }
295 
296             m_pSpellState->m_bInitialCall = false;
297         }
298         if( bDrawText )
299         {
300             // spell inside of the current draw text
301             if(!SpellDrawText_Impl(*pWrtShell, aRet))
302             {
303                 if(!FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet))
304                 {
305                     lcl_LeaveDrawText(*pWrtShell);
306                     //now the drawings have been spelled
307                     m_pSpellState->m_bDrawingsSpelled = true;
308                     //the spelling continues at the other content
309                     //if there's any that has not been spelled yet
310                     if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
311                     {
312                         pWrtShell->SpellStart(DOCPOS_OTHERSTART, DOCPOS_OTHEREND, DOCPOS_OTHERSTART, sal_False );
313                         if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
314 						{
315                             pWrtShell->SpellEnd();
316 							m_pSpellState->m_bOtherSpelled = true;
317 						}
318                     }
319                     else
320                         m_pSpellState->m_bOtherSpelled = true;
321                     //if no result has been found try at the body text - completely
322                     if(!m_pSpellState->m_bBodySpelled && !aRet.size())
323                     {
324                         pWrtShell->SpellStart(DOCPOS_START, DOCPOS_END, DOCPOS_START, sal_False );
325                         if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
326                         {
327                             m_pSpellState->m_bBodySpelled = true;
328                             pWrtShell->SpellEnd();
329                         }
330                     }
331 
332                 }
333             }
334         }
335         else
336         {
337             //spell inside of the Writer text
338             if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
339             {
340                 // if there is a selection (within body or header/footer text)
341                 // then spell/grammar checking should not move outside of it.
342                 if (!m_pSpellState->m_bStartedInSelection)
343                 {
344                     //find out which text has been spelled body or other
345                     bOtherText = !(pWrtShell->GetFrmType(0,sal_True) & FRMTYPE_BODY);
346                     if(bOtherText && m_pSpellState->m_bStartedInOther && m_pSpellState->pOtherCursor)
347                     {
348                         m_pSpellState->m_bStartedInOther = false;
349                         pWrtShell->SetSelection(*m_pSpellState->pOtherCursor);
350                         pWrtShell->SpellEnd();
351                         delete m_pSpellState->pOtherCursor;
352                         m_pSpellState->pOtherCursor = 0;
353                         pWrtShell->SpellStart(DOCPOS_OTHERSTART, DOCPOS_CURR, DOCPOS_OTHERSTART, sal_False );
354                         pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn);
355                     }
356                     if(!aRet.size())
357                     {
358                         //end spelling
359                         pWrtShell->SpellEnd();
360                         if(bOtherText)
361                         {
362                             m_pSpellState->m_bOtherSpelled = true;
363                             //has the body been spelled?
364                             if(!m_pSpellState->m_bBodySpelled)
365                             {
366                                 pWrtShell->SpellStart(DOCPOS_START, DOCPOS_END, DOCPOS_START, sal_False );
367                                 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
368                                 {
369                                     m_pSpellState->m_bBodySpelled = true;
370                                     pWrtShell->SpellEnd();
371                                 }
372                             }
373                         }
374                         else
375                         {
376                              m_pSpellState->m_bBodySpelled = true;
377                              if(!m_pSpellState->m_bOtherSpelled && pWrtShell->HasOtherCnt())
378                              {
379                                 pWrtShell->SpellStart(DOCPOS_OTHERSTART, DOCPOS_OTHEREND, DOCPOS_OTHERSTART, sal_False );
380                                 if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
381                                 {
382                                     pWrtShell->SpellEnd();
383                                     m_pSpellState->m_bOtherSpelled = true;
384                                 }
385                              }
386                              else
387                                  m_pSpellState->m_bOtherSpelled = true;
388                         }
389                     }
390 
391                     //search for a draw text object that contains error and spell it
392                     if(!aRet.size() &&
393                             (m_pSpellState->m_bDrawingsSpelled ||
394                             !FindNextDrawTextError_Impl(*pWrtShell) || !SpellDrawText_Impl(*pWrtShell, aRet)))
395                     {
396                         lcl_LeaveDrawText(*pWrtShell);
397                         m_pSpellState->m_bDrawingsSpelled = true;
398                     }
399                 }
400             }
401         }
402         // now only the rest of the body text can be spelled -
403         // if the spelling started inside of the body
404         //
405         bool bCloseMessage = true;
406         if(!aRet.size() && !m_pSpellState->m_bStartedInSelection)
407         {
408             DBG_ASSERT(m_pSpellState->m_bDrawingsSpelled &&
409                         m_pSpellState->m_bOtherSpelled && m_pSpellState->m_bBodySpelled,
410                         "not all parts of the document are already spelled");
411             if(m_pSpellState->m_xStartRange.is())
412             {
413                 LockFocusNotification( true );
414                 sal_uInt16 nRet = QueryBox( GetWindow(),  SW_RES(RID_QB_SPELL_CONTINUE)).Execute();
415                 if(RET_YES == nRet)
416                 {
417                     SwUnoInternalPaM aPam(*pWrtShell->GetDoc());
418                     if (::sw::XTextRangeToSwPaM(aPam,
419                                 m_pSpellState->m_xStartRange))
420                     {
421                         pWrtShell->SetSelection(aPam);
422                         pWrtShell->SpellStart(DOCPOS_START, DOCPOS_CURR, DOCPOS_START);
423                         if(!pWrtShell->SpellSentence(aRet, m_bIsGrammarCheckingOn))
424                             pWrtShell->SpellEnd();
425                     }
426                     m_pSpellState->m_xStartRange = 0;
427                     LockFocusNotification( false );
428                     //take care that the now valid selection is stored
429                     LoseFocus();
430                 }
431                 else
432                     bCloseMessage = false; //no closing message if a wrap around has been denied
433             }
434         }
435         if(!aRet.size())
436         {
437             if(bCloseMessage)
438 			{
439 				LockFocusNotification( true );
440                 String sInfo(SW_RES(STR_SPELLING_COMPLETED));
441                 //#i84610#
442                 Window* pTemp = GetWindow();    // temporary needed for g++ 3.3.5
443                 InfoBox(pTemp, sInfo ).Execute();
444                 LockFocusNotification( false );
445                 //take care that the now valid selection is stored
446                 LoseFocus();
447 			}
448 
449             //close the spelling dialog
450             GetBindings().GetDispatcher()->Execute(FN_SPELL_GRAMMAR_DIALOG, SFX_CALLMODE_ASYNCHRON);
451         }
452     }
453     return aRet;
454 
455 }
456 /*-- 09.09.2003 10:39:40---------------------------------------------------
457 
458   -----------------------------------------------------------------------*/
459 void SwSpellDialogChildWindow::ApplyChangedSentence(const svx::SpellPortions& rChanged, bool bRecheck)
460 {
461     SwWrtShell* pWrtShell = GetWrtShell_Impl();
462     DBG_ASSERT(!m_pSpellState->m_bInitialCall, "ApplyChangedSentence in initial call or after resume");
463     if(pWrtShell && !m_pSpellState->m_bInitialCall)
464     {
465 		ShellModes  eSelMode = pWrtShell->GetView().GetShellMode();
466 		bool bDrawText = SHELL_MODE_DRAWTEXT == eSelMode;
467 		bool bNormalText =
468 			SHELL_MODE_TABLE_TEXT == eSelMode ||
469 			SHELL_MODE_LIST_TEXT == eSelMode ||
470 			SHELL_MODE_TABLE_LIST_TEXT == eSelMode ||
471 			SHELL_MODE_TEXT == eSelMode;
472 
473         // evaluate if the same sentence should be rechecked or not.
474         // Sentences that got grammar checked should always be rechecked in order
475         // to detect possible errors that get introduced with the changes
476         bRecheck |= pWrtShell->HasLastSentenceGotGrammarChecked();
477 
478 		if(bNormalText)
479 			pWrtShell->ApplyChangedSentence(rChanged, bRecheck);
480         else if(bDrawText )
481         {
482             SdrView* pDrView = pWrtShell->GetDrawView();
483             SdrOutliner *pOutliner = pDrView->GetTextEditOutliner();
484             pOutliner->ApplyChangedSentence(pDrView->GetTextEditOutlinerView()->GetEditView(), rChanged, bRecheck);
485         }
486 	}
487 }
488 /*-- 21.10.2003 09:33:57---------------------------------------------------
489 
490   -----------------------------------------------------------------------*/
491 void SwSpellDialogChildWindow::AddAutoCorrection(
492         const String& rOld, const String& rNew, LanguageType eLanguage)
493 {
494     SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get()->GetAutoCorrect();
495     pACorr->PutText( rOld, rNew, eLanguage );
496 }
497 /*-- 21.10.2003 09:33:59---------------------------------------------------
498 
499   -----------------------------------------------------------------------*/
500 bool SwSpellDialogChildWindow::HasAutoCorrection()
501 {
502     return true;
503 }
504 /*-- 16.06.2008 11:59:17---------------------------------------------------
505 
506   -----------------------------------------------------------------------*/
507 bool SwSpellDialogChildWindow::HasGrammarChecking()
508 {
509     return SvtLinguConfig().HasGrammarChecker();
510 }
511 /*-- 18.06.2008 12:27:11---------------------------------------------------
512 
513   -----------------------------------------------------------------------*/
514 bool SwSpellDialogChildWindow::IsGrammarChecking()
515 {
516     return m_bIsGrammarCheckingOn;
517 }
518 /*-- 18.06.2008 12:27:11---------------------------------------------------
519 
520   -----------------------------------------------------------------------*/
521 void SwSpellDialogChildWindow::SetGrammarChecking(bool bOn)
522 {
523     uno::Any aVal;
524     aVal <<= bOn;
525     m_bIsGrammarCheckingOn = bOn;
526     String aPropName( C2S(UPN_IS_GRAMMAR_INTERACTIVE ) );
527     SvtLinguConfig().SetProperty( aPropName, aVal );
528     // set current spell position to the start of the current sentence to
529     // continue with this sentence after grammar checking state has been changed
530     SwWrtShell* pWrtShell = GetWrtShell_Impl();
531     if(pWrtShell)
532     {
533         ShellModes  eSelMode = pWrtShell->GetView().GetShellMode();
534         bool bDrawText = SHELL_MODE_DRAWTEXT == eSelMode;
535         bool bNormalText =
536             SHELL_MODE_TABLE_TEXT == eSelMode ||
537             SHELL_MODE_LIST_TEXT == eSelMode ||
538             SHELL_MODE_TABLE_LIST_TEXT == eSelMode ||
539             SHELL_MODE_TEXT == eSelMode;
540         if( bNormalText )
541             pWrtShell->PutSpellingToSentenceStart();
542         else if( bDrawText )
543         {
544             SdrView*     pSdrView = pWrtShell->GetDrawView();
545             SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : 0;
546             DBG_ASSERT(pOutliner, "No Outliner in SwSpellDialogChildWindow::SetGrammarChecking");
547             if(pOutliner)
548             {
549                 pOutliner->PutSpellingToSentenceStart( pSdrView->GetTextEditOutlinerView()->GetEditView() );
550             }
551         }
552     }
553 }
554 /*-- 28.10.2003 08:41:09---------------------------------------------------
555 
556   -----------------------------------------------------------------------*/
557 void SwSpellDialogChildWindow::GetFocus()
558 {
559     if(m_pSpellState->m_bLockFocus)
560         return;
561     bool bInvalidate = false;
562     SwWrtShell* pWrtShell = GetWrtShell_Impl();
563     if(pWrtShell && !m_pSpellState->m_bInitialCall)
564     {
565         ShellModes  eSelMode = pWrtShell->GetView().GetShellMode();
566         if(eSelMode != m_pSpellState->m_eSelMode)
567         {
568             //prevent initial invalidation
569             if(m_pSpellState->m_bLostFocus)
570                 bInvalidate = true;
571         }
572         else
573         {
574             switch(m_pSpellState->m_eSelMode)
575             {
576                 case SHELL_MODE_TEXT:
577                 case SHELL_MODE_LIST_TEXT:
578                 case SHELL_MODE_TABLE_TEXT:
579                 case SHELL_MODE_TABLE_LIST_TEXT:
580                 {
581                     SwPaM* pCursor = pWrtShell->GetCrsr();
582                     if(m_pSpellState->m_pPointNode != pCursor->GetNode(sal_True) ||
583                         m_pSpellState->m_pMarkNode != pCursor->GetNode(sal_False)||
584                         m_pSpellState->m_nPointPos != pCursor->GetPoint()->nContent.GetIndex()||
585                         m_pSpellState->m_nMarkPos != pCursor->GetMark()->nContent.GetIndex())
586                             bInvalidate = true;
587                 }
588                 break;
589                 case SHELL_MODE_DRAWTEXT:
590                 {
591                     SdrView*     pSdrView = pWrtShell->GetDrawView();
592                     SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : 0;
593                     if(!pOutliner || m_pSpellState->m_pOutliner != pOutliner)
594                         bInvalidate = true;
595                     else
596                     {
597                         OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
598                         DBG_ASSERT(pOLV, "no OutlinerView in SwSpellDialogChildWindow::GetFocus()");
599                         if(!pOLV || !m_pSpellState->m_aESelection.IsEqual(pOLV->GetSelection()))
600                             bInvalidate = true;
601                     }
602                 }
603                 break;
604                 default: bInvalidate = true;
605             }
606         }
607     }
608     else
609     {
610         bInvalidate = true;
611     }
612     if(bInvalidate)
613         InvalidateSpellDialog();
614 }
615 /*-- 28.10.2003 08:41:09---------------------------------------------------
616 
617   -----------------------------------------------------------------------*/
618 void SwSpellDialogChildWindow::LoseFocus()
619 {
620     //prevent initial invalidation
621     m_pSpellState->m_bLostFocus = true;
622     if(m_pSpellState->m_bLockFocus)
623         return;
624     SwWrtShell* pWrtShell = GetWrtShell_Impl();
625     if(pWrtShell)
626     {
627         m_pSpellState->m_eSelMode = pWrtShell->GetView().GetShellMode();
628         m_pSpellState->m_pPointNode = m_pSpellState->m_pMarkNode = 0;
629         m_pSpellState->m_nPointPos = m_pSpellState->m_nMarkPos = 0;
630         m_pSpellState->m_pOutliner = 0;
631 
632         switch(m_pSpellState->m_eSelMode)
633         {
634             case SHELL_MODE_TEXT:
635             case SHELL_MODE_LIST_TEXT:
636             case SHELL_MODE_TABLE_TEXT:
637             case SHELL_MODE_TABLE_LIST_TEXT:
638             {
639                 //store a node pointer and a pam-position to be able to check on next GetFocus();
640                 SwPaM* pCursor = pWrtShell->GetCrsr();
641                 m_pSpellState->m_pPointNode = pCursor->GetNode(sal_True);
642                 m_pSpellState->m_pMarkNode = pCursor->GetNode(sal_False);
643                 m_pSpellState->m_nPointPos = pCursor->GetPoint()->nContent.GetIndex();
644                 m_pSpellState->m_nMarkPos = pCursor->GetMark()->nContent.GetIndex();
645 
646             }
647             break;
648             case SHELL_MODE_DRAWTEXT:
649             {
650                 SdrView*     pSdrView = pWrtShell->GetDrawView();
651                 SdrOutliner* pOutliner = pSdrView->GetTextEditOutliner();
652                 m_pSpellState->m_pOutliner = pOutliner;
653                 OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
654                 DBG_ASSERT(pOutliner && pOLV, "no Outliner/OutlinerView in SwSpellDialogChildWindow::LoseFocus()");
655                 if(pOLV)
656                 {
657                     m_pSpellState->m_aESelection = pOLV->GetSelection();
658                 }
659             }
660             break;
661             default:;//prevent warning
662         }
663     }
664     else
665         m_pSpellState->m_eSelMode = SHELL_MODE_OBJECT;
666 }
667 /*-- 18.09.2003 12:50:18---------------------------------------------------
668 
669   -----------------------------------------------------------------------*/
670 void SwSpellDialogChildWindow::InvalidateSpellDialog()
671 {
672     SwWrtShell* pWrtShell = GetWrtShell_Impl();
673     if(!m_pSpellState->m_bInitialCall && pWrtShell)
674         pWrtShell->SpellEnd(0, false);
675     m_pSpellState->Reset();
676     svx::SpellDialogChildWindow::InvalidateSpellDialog();
677 }
678 
679 /*-- 18.09.2003 12:54:59---------------------------------------------------
680 
681   -----------------------------------------------------------------------*/
682 SwWrtShell* SwSpellDialogChildWindow::GetWrtShell_Impl()
683 {
684     SfxDispatcher* pDispatch = GetBindings().GetDispatcher();
685     SwView* pView = 0;
686     if(pDispatch)
687     {
688         sal_uInt16 nShellIdx = 0;
689         SfxShell* pShell;
690         while(0 != (pShell = pDispatch->GetShell(nShellIdx++)))
691             if(pShell->ISA(SwView))
692             {
693                 pView = static_cast<SwView* >(pShell);
694                 break;
695             }
696     }
697     return pView ? pView->GetWrtShellPtr(): 0;
698 }
699 
700 /*-- 13.10.2003 15:19:04---------------------------------------------------
701     set the cursor into the body text - necessary if any object is selected
702     on start of the spelling dialog
703   -----------------------------------------------------------------------*/
704 bool SwSpellDialogChildWindow::MakeTextSelection_Impl(SwWrtShell& rShell, ShellModes  eSelMode)
705 {
706     SwView& rView = rShell.GetView();
707     switch(eSelMode)
708     {
709         case SHELL_MODE_TEXT:
710         case SHELL_MODE_LIST_TEXT:
711         case SHELL_MODE_TABLE_TEXT:
712         case SHELL_MODE_TABLE_LIST_TEXT:
713         case SHELL_MODE_DRAWTEXT:
714             DBG_ERROR("text already active in SwSpellDialogChildWindow::MakeTextSelection_Impl()");
715         break;
716 
717         case SHELL_MODE_FRAME:
718         {
719             rShell.UnSelectFrm();
720             rShell.LeaveSelFrmMode();
721             rView.AttrChangedNotify(&rShell);
722         }
723         break;
724 
725         case SHELL_MODE_DRAW:
726         case SHELL_MODE_DRAW_CTRL:
727         case SHELL_MODE_DRAW_FORM:
728         case SHELL_MODE_BEZIER:
729             if(FindNextDrawTextError_Impl(rShell))
730 			{
731                 rView.AttrChangedNotify(&rShell);
732                 break;
733 			}
734         //otherwise no break to deselect the object
735         case SHELL_MODE_GRAPHIC:
736         case SHELL_MODE_OBJECT:
737         {
738             if ( rShell.IsDrawCreate() )
739             {
740                 rView.GetDrawFuncPtr()->BreakCreate();
741                 rView.AttrChangedNotify(&rShell);
742             }
743             else if ( rShell.HasSelection() || rView.IsDrawMode() )
744             {
745                 SdrView *pSdrView = rShell.GetDrawView();
746                 if(pSdrView && pSdrView->AreObjectsMarked() &&
747                     pSdrView->GetHdlList().GetFocusHdl())
748                 {
749                     ((SdrHdlList&)pSdrView->GetHdlList()).ResetFocusHdl();
750                 }
751                 else
752                 {
753                     rView.LeaveDrawCreate();
754                     Point aPt(LONG_MIN, LONG_MIN);
755                     //go out of the frame
756                     rShell.SelectObj(aPt, SW_LEAVE_FRAME);
757                     SfxBindings& rBind = rView.GetViewFrame()->GetBindings();
758                     rBind.Invalidate( SID_ATTR_SIZE );
759                     rShell.EnterStdMode();
760                     rView.AttrChangedNotify(&rShell);
761                 }
762             }
763         }
764         break;
765         default:; //prevent warning
766     }
767     return true;
768 }
769 /*-- 13.10.2003 15:20:09---------------------------------------------------
770     select the next draw text object that has a spelling error
771   -----------------------------------------------------------------------*/
772 bool SwSpellDialogChildWindow::FindNextDrawTextError_Impl(SwWrtShell& rSh)
773 {
774     bool bNextDoc = false;
775     SdrView* pDrView = rSh.GetDrawView();
776     if(!pDrView)
777         return bNextDoc;
778     SwView& rView = rSh.GetView();
779     SwDoc* pDoc = rView.GetDocShell()->GetDoc();
780     const SdrMarkList& rMarkList = pDrView->GetMarkedObjectList();
781     //start at the current draw object - if there is any selected
782     SdrTextObj* pCurrentTextObj = 0;
783     if ( rMarkList.GetMarkCount() == 1 )
784     {
785         SdrObject* pObj = rMarkList.GetMark(0)->GetMarkedSdrObj();
786         if( pObj && pObj->ISA(SdrTextObj) )
787             pCurrentTextObj = static_cast<SdrTextObj*>(pObj);
788     }
789     //at first fill the list of drawing objects
790     if(!m_pSpellState->m_bTextObjectsCollected )
791     {
792         m_pSpellState->m_bTextObjectsCollected = true;
793         std::list<SdrTextObj*> aTextObjs;
794         SwDrawContact::GetTextObjectsFromFmt( aTextObjs, pDoc );
795         if(pCurrentTextObj)
796         {
797             m_pSpellState->m_aTextObjects.remove(pCurrentTextObj);
798             m_pSpellState->m_aTextObjects.push_back(pCurrentTextObj);
799                                 }
800                             }
801     if(m_pSpellState->m_aTextObjects.size())
802     {
803         Reference< XSpellChecker1 >  xSpell( GetSpellChecker() );
804         while(!bNextDoc && m_pSpellState->m_aTextObjects.size())
805         {
806             std::list<SdrTextObj*>::iterator aStart = m_pSpellState->m_aTextObjects.begin();
807             SdrTextObj* pTextObj = *aStart;
808             if(m_pSpellState->m_pStartDrawing == pTextObj)
809                 m_pSpellState->m_bRestartDrawing = true;
810             m_pSpellState->m_aTextObjects.erase(aStart);
811             OutlinerParaObject* pParaObj = pTextObj->GetOutlinerParaObject();
812             if ( pParaObj )
813             {
814                 bool bHasSpellError = false;
815                 {
816                     SdrOutliner aTmpOutliner(pDoc->GetDrawModel()->
817                                              GetDrawOutliner().GetEmptyItemSet().GetPool(),
818                                                 OUTLINERMODE_TEXTOBJECT );
819                     aTmpOutliner.SetRefDevice( pDoc->getPrinter( false ) );
820                     MapMode aMapMode (MAP_TWIP);
821                     aTmpOutliner.SetRefMapMode(aMapMode);
822                     aTmpOutliner.SetPaperSize( pTextObj->GetLogicRect().GetSize() );
823                     aTmpOutliner.SetSpeller( xSpell );
824 
825                     OutlinerView* pOutlView = new OutlinerView( &aTmpOutliner, &(rView.GetEditWin()) );
826                     pOutlView->GetOutliner()->SetRefDevice( rSh.getIDocumentDeviceAccess()->getPrinter( false ) );
827                     aTmpOutliner.InsertView( pOutlView );
828                     Point aPt;
829                     Size aSize(1,1);
830                     Rectangle aRect( aPt, aSize );
831                     pOutlView->SetOutputArea( aRect );
832                     aTmpOutliner.SetText( *pParaObj );
833                     aTmpOutliner.ClearModifyFlag();
834                     bHasSpellError = EE_SPELL_OK != aTmpOutliner.HasSpellErrors();
835                     aTmpOutliner.RemoveView( pOutlView );
836                     delete pOutlView;
837                 }
838                 if(bHasSpellError)
839                 {
840                     //now the current one has to be deselected
841                     if(pCurrentTextObj)
842                         pDrView->SdrEndTextEdit( sal_True );
843                     //and the found one should be activated
844                     rSh.MakeVisible(pTextObj->GetLogicRect());
845                     Point aTmp( 0,0 );
846                     rSh.SelectObj( aTmp, 0, pTextObj );
847                     SdrPageView* pPV = pDrView->GetSdrPageView();
848                     rView.BeginTextEdit( pTextObj, pPV, &rView.GetEditWin(), sal_False, sal_True );
849                     rView.AttrChangedNotify(&rSh);
850                     bNextDoc = true;
851                 }
852             }
853         }
854     }
855     return bNextDoc;
856 }
857 
858 /*-- 13.10.2003 15:24:27---------------------------------------------------
859 
860   -----------------------------------------------------------------------*/
861 bool SwSpellDialogChildWindow::SpellDrawText_Impl(SwWrtShell& rSh, ::svx::SpellPortions& rPortions)
862 {
863     bool bRet = false;
864     SdrView*     pSdrView = rSh.GetDrawView();
865     SdrOutliner* pOutliner = pSdrView ? pSdrView->GetTextEditOutliner() : 0;
866     DBG_ASSERT(pOutliner, "No Outliner in SwSpellDialogChildWindow::SpellDrawText_Impl");
867     if(pOutliner)
868     {
869         bRet = pOutliner->SpellSentence(pSdrView->GetTextEditOutlinerView()->GetEditView(), rPortions, m_bIsGrammarCheckingOn);
870         //find out if the current selection is in the first spelled drawing object
871         //and behind the initial selection
872         if(bRet && m_pSpellState->m_bRestartDrawing)
873         {
874             OutlinerView* pOLV = pSdrView->GetTextEditOutlinerView();
875             ESelection aCurrentSelection = pOLV->GetSelection();
876             if(m_pSpellState->m_aStartDrawingSelection.nEndPara < aCurrentSelection.nEndPara ||
877                (m_pSpellState->m_aStartDrawingSelection.nEndPara ==  aCurrentSelection.nEndPara &&
878                     m_pSpellState->m_aStartDrawingSelection.nEndPos <  aCurrentSelection.nEndPos))
879 			{
880                 bRet = false;
881 				rPortions.clear();
882 			}
883         }
884     }
885     return bRet;
886 }
887 /*-- 30.10.2003 14:54:59---------------------------------------------------
888 
889   -----------------------------------------------------------------------*/
890 void SwSpellDialogChildWindow::LockFocusNotification(bool bLock)
891 {
892     DBG_ASSERT(m_pSpellState->m_bLockFocus != bLock, "invalid locking - no change of state");
893     m_pSpellState->m_bLockFocus = bLock;
894 }
895 
896 
897