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