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