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