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