LibreOffice Module sw (master)  1
viewling.cxx
Go to the documentation of this file.
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 <hintids.hxx>
21 
22 #include <com/sun/star/lang/Locale.hpp>
23 #include <com/sun/star/linguistic2/XThesaurus.hpp>
24 #include <com/sun/star/linguistic2/ProofreadingResult.hpp>
25 #include <com/sun/star/linguistic2/XLinguProperties.hpp>
26 #include <com/sun/star/i18n/TextConversionOption.hpp>
27 #include <linguistic/lngprops.hxx>
28 #include <comphelper/lok.hxx>
34 #include <vcl/weld.hxx>
35 #include <svtools/ehdl.hxx>
36 #include <svl/stritem.hxx>
37 #include <sfx2/dispatch.hxx>
38 #include <sfx2/viewfrm.hxx>
39 #include <sfx2/request.hxx>
40 #include <svx/dlgutil.hxx>
41 #include <svx/dialmgr.hxx>
42 #include <svx/svxids.hrc>
43 #include <editeng/langitem.hxx>
44 #include <svx/svxerr.hxx>
45 #include <editeng/unolingu.hxx>
46 #include <svx/svxdlg.hxx>
48 #include <swmodule.hxx>
49 #include <swwait.hxx>
50 #include <initui.hxx>
51 #include <uitool.hxx>
52 #include <view.hxx>
53 #include <wrtsh.hxx>
54 #include <basesh.hxx>
55 #include <docsh.hxx>
56 #include <viewopt.hxx>
57 #include <swundo.hxx>
58 #include <hyp.hxx>
59 #include <olmenu.hxx>
60 #include <pam.hxx>
61 #include <edtwin.hxx>
62 #include <ndtxt.hxx>
63 #include <txtfrm.hxx>
64 #include <cmdid.h>
65 #include <globals.hrc>
66 #include <strings.hrc>
67 #include <hhcwrp.hxx>
68 
69 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
70 #include <com/sun/star/ui/ContextMenuExecuteEvent.hpp>
71 #include <com/sun/star/lang/XInitialization.hpp>
72 #include <com/sun/star/frame/XDispatch.hpp>
73 #include <com/sun/star/frame/XDispatchProvider.hpp>
74 #include <com/sun/star/frame/XFrame.hpp>
75 #include <com/sun/star/frame/XPopupMenuController.hpp>
76 #include <com/sun/star/awt/PopupMenuDirection.hpp>
77 #include <com/sun/star/util/URL.hpp>
78 #include <com/sun/star/beans/PropertyValue.hpp>
79 #include <com/sun/star/beans/XPropertySet.hpp>
80 #include <com/sun/star/util/URLTransformer.hpp>
81 #include <com/sun/star/util/XURLTransformer.hpp>
82 
83 #include <vcl/svapp.hxx>
84 #include <rtl/ustring.hxx>
85 
86 #include <cppuhelper/bootstrap.hxx>
87 #include <svx/dialogs.hrc>
88 #include <svtools/langtab.hxx>
89 #include <unomid.h>
90 #include <IMark.hxx>
91 #include <xmloff/odffields.hxx>
92 
93 #include <editeng/editerr.hxx>
94 
95 #include <memory>
96 
97 using namespace sw::mark;
98 using namespace ::com::sun::star;
99 using namespace ::com::sun::star::beans;
100 using namespace ::com::sun::star::uno;
101 using namespace ::com::sun::star::linguistic2;
102 
103 // Lingu-Dispatcher
104 
106 {
107  switch(rReq.GetSlot())
108  {
109  case SID_THESAURUS:
110  StartThesaurus();
111  rReq.Ignore();
112  break;
113  case SID_HANGUL_HANJA_CONVERSION:
114  StartTextConversion( LANGUAGE_KOREAN, LANGUAGE_KOREAN, nullptr,
115  i18n::TextConversionOption::CHARACTER_BY_CHARACTER, true );
116  break;
117  case SID_CHINESE_CONVERSION:
118  {
119  //open ChineseTranslationDialog
121  ::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one
122  if(xContext.is())
123  {
124  Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
125  if(xMCF.is())
126  {
127  Reference< ui::dialogs::XExecutableDialog > xDialog(
128  xMCF->createInstanceWithContext(
129  "com.sun.star.linguistic2.ChineseTranslationDialog", xContext),
130  UNO_QUERY);
131  Reference< lang::XInitialization > xInit( xDialog, UNO_QUERY );
132  if( xInit.is() )
133  {
134  Reference<awt::XWindow> xParentWindow;
135  if (weld::Window* pParentWindow = rReq.GetFrameWeld())
136  xParentWindow = pParentWindow->GetXWindow();
137  // initialize dialog
138  uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence(
139  {
140  {"ParentWindow", uno::Any(xParentWindow)}
141  }));
142  xInit->initialize( aSeq );
143 
144  //execute dialog
145  sal_Int16 nDialogRet = xDialog->execute();
146  if( RET_OK == nDialogRet )
147  {
148  //get some parameters from the dialog
149  bool bToSimplified = true;
150  bool bUseVariants = true;
151  bool bCommonTerms = true;
152  Reference< beans::XPropertySet > xProp( xDialog, UNO_QUERY );
153  if( xProp.is() )
154  {
155  try
156  {
157  xProp->getPropertyValue( "IsDirectionToSimplified" ) >>= bToSimplified;
158  xProp->getPropertyValue( "IsUseCharacterVariants" ) >>= bUseVariants;
159  xProp->getPropertyValue( "IsTranslateCommonTerms" ) >>= bCommonTerms;
160  }
161  catch (const Exception&)
162  {
163  }
164  }
165 
166  //execute translation
169  sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0;
170  if( !bCommonTerms )
171  nOptions = nOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
172 
173  vcl::Font aTargetFont = OutputDevice::GetDefaultFont( DefaultFontType::CJK_TEXT,
174  nTargetLang, GetDefaultFontFlags::OnlyOne );
175 
176  // disallow formatting, updating the view, ... while
177  // converting the document. (saves time)
178  // Also remember the current view and cursor position for later
179  m_pWrtShell->StartAction();
180 
181  // remember cursor position data for later restoration of the cursor
182  const SwPosition *pPoint = m_pWrtShell->GetCursor()->GetPoint();
183  bool bRestoreCursor = pPoint->nNode.GetNode().IsTextNode();
184  const SwNodeIndex aPointNodeIndex( pPoint->nNode );
185  sal_Int32 nPointIndex = pPoint->nContent.GetIndex();
186 
187  // since this conversion is not interactive the whole converted
188  // document should be undone in a single undo step.
189  m_pWrtShell->StartUndo( SwUndoId::OVERWRITE );
190 
191  StartTextConversion( nSourceLang, nTargetLang, &aTargetFont, nOptions, false );
192 
193  m_pWrtShell->EndUndo( SwUndoId::OVERWRITE );
194 
195  if (bRestoreCursor)
196  {
197  SwTextNode *pTextNode = aPointNodeIndex.GetNode().GetTextNode();
198  // check for unexpected error case
199  OSL_ENSURE(pTextNode && pTextNode->GetText().getLength() >= nPointIndex,
200  "text missing: corrupted node?" );
201  if (!pTextNode || pTextNode->GetText().getLength() < nPointIndex)
202  nPointIndex = 0;
203  // restore cursor to its original position
204  m_pWrtShell->GetCursor()->GetPoint()->nContent.Assign( pTextNode, nPointIndex );
205  }
206 
207  // enable all, restore view and cursor position
208  m_pWrtShell->EndAction();
209  }
210  }
211  Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY );
212  if( xComponent.is() )
213  xComponent->dispose();
214  }
215  }
216  break;
217  }
219  HyphenateDocument();
220  break;
221  default:
222  OSL_ENSURE(false, "wrong Dispatcher");
223  return;
224  }
225 }
226 
227 // start language specific text conversion
228 
230  LanguageType nSourceLang,
231  LanguageType nTargetLang,
232  const vcl::Font *pTargetFont,
233  sal_Int32 nOptions,
234  bool bIsInteractive )
235 {
236  // do not do text conversion if it is active elsewhere
238  {
239  return;
240  }
241 
242  SpellContext();
243 
244  const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
245  const bool bOldIdle = pVOpt->IsIdle();
246  pVOpt->SetIdle( false );
247 
248  bool bOldIns = m_pWrtShell->IsInsMode();
249  m_pWrtShell->SetInsMode();
250 
251  const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection() ||
252  m_pWrtShell->GetCursor() != m_pWrtShell->GetCursor()->GetNext();
253 
254  const bool bStart = bSelection || m_pWrtShell->IsStartOfDoc();
255  const bool bOther = !bSelection && !(m_pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
256 
257  {
258  const uno::Reference< uno::XComponentContext > xContext(
260  SwHHCWrapper aWrap( this, xContext, nSourceLang, nTargetLang, pTargetFont,
261  nOptions, bIsInteractive,
262  bStart, bOther, bSelection );
263  aWrap.Convert();
264  }
265 
266  m_pWrtShell->SetInsMode( bOldIns );
267  pVOpt->SetIdle( bOldIdle );
268  SpellContext(false);
269 }
270 
271 // spellcheck and text conversion related stuff
272 
274  bool bStartDone, bool bEndDone,
275  SwConversionArgs *pConvArgs )
276 {
277  Reference< XLinguProperties > xProp = ::GetLinguPropertySet();
278  bool bIsWrapReverse = !pConvArgs && xProp.is() && xProp->getIsWrapReverse();
279 
283  switch ( eWhich )
284  {
285  case SvxSpellArea::Body:
286  if( bIsWrapReverse )
287  eCurr = SwDocPositions::End;
288  else
289  eCurr = SwDocPositions::Start;
290  break;
291  case SvxSpellArea::BodyEnd:
292  if( bIsWrapReverse )
293  {
294  if( bStartDone )
295  eStart = SwDocPositions::Curr;
296  eCurr = SwDocPositions::End;
297  }
298  else if( bStartDone )
299  eCurr = SwDocPositions::Start;
300  break;
301  case SvxSpellArea::BodyStart:
302  if( !bIsWrapReverse )
303  {
304  if( bEndDone )
305  eEnd = SwDocPositions::Curr;
306  eCurr = SwDocPositions::Start;
307  }
308  else if( bEndDone )
309  eCurr = SwDocPositions::End;
310  break;
311  case SvxSpellArea::Other:
312  if( bIsWrapReverse )
313  {
316  eCurr = SwDocPositions::OtherEnd;
317  }
318  else
319  {
323  }
324  break;
325  default:
326  OSL_ENSURE( false, "SpellStart with unknown Area" );
327  }
328  m_pWrtShell->SpellStart( eStart, eEnd, eCurr, pConvArgs );
329 }
330 
331 // Error message while Spelling
332 
333 // The passed pointer nlang is itself the value
335 {
336  int nPend = 0;
337 
338  if ( m_pWrtShell->ActionPend() )
339  {
340  m_pWrtShell->Push();
341  m_pWrtShell->ClearMark();
342  do
343  {
344  m_pWrtShell->EndAction();
345  ++nPend;
346  }
347  while( m_pWrtShell->ActionPend() );
348  }
349  OUString aErr(SvtLanguageTable::GetLanguageString( eLang ) );
350 
351  SwEditWin &rEditWin = GetEditWin();
352  int nWaitCnt = 0;
353  while( rEditWin.IsWait() )
354  {
355  rEditWin.LeaveWait();
356  ++nWaitCnt;
357  }
358  if ( LANGUAGE_NONE == eLang )
360  else
362 
363  while( nWaitCnt )
364  {
365  rEditWin.EnterWait();
366  --nWaitCnt;
367  }
368 
369  if ( nPend )
370  {
371  while( nPend-- )
372  m_pWrtShell->StartAction();
373  m_pWrtShell->Combine();
374  }
375 }
376 
377 // Finish spelling and restore cursor
378 
379 void SwView::SpellEnd( SwConversionArgs const *pConvArgs )
380 {
381  m_pWrtShell->SpellEnd( pConvArgs );
382  if( m_pWrtShell->IsExtMode() )
383  m_pWrtShell->SetMark();
384 }
385 
387 {
388  switch ( eWhich )
389  {
390  case SvxSpellArea::Body:
391  m_pWrtShell->HyphStart( SwDocPositions::Start, SwDocPositions::End );
392  break;
393  case SvxSpellArea::BodyEnd:
394  m_pWrtShell->HyphStart( SwDocPositions::Curr, SwDocPositions::End );
395  break;
396  case SvxSpellArea::BodyStart:
397  m_pWrtShell->HyphStart( SwDocPositions::Start, SwDocPositions::Curr );
398  break;
399  case SvxSpellArea::Other:
400  m_pWrtShell->HyphStart( SwDocPositions::OtherStart, SwDocPositions::OtherEnd );
401  break;
402  default:
403  OSL_ENSURE( false, "HyphStart with unknown Area" );
404  }
405 }
406 
407 // Interactive separation
408 
410 {
411  // do not hyphenate if interactive hyphenation is active elsewhere
413  {
414  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
415  VclMessageType::Warning, VclButtonsType::Ok, SwResId(STR_MULT_INTERACT_HYPH_WARN)));
416  xBox->set_title(SwResId(STR_HYPH_TITLE));
417  xBox->run();
418  return;
419  }
420 
421  SfxErrorContext aContext( ERRCTX_SVX_LINGU_HYPHENATION, OUString(), m_pEditWin->GetFrameWeld(),
423 
424  Reference< XHyphenator > xHyph( ::GetHyphenator() );
425  if (!xHyph.is())
426  {
428  return;
429  }
430 
431  if (m_pWrtShell->GetSelectionType() & (SelectionType::DrawObjectEditMode|SelectionType::DrawObject))
432  {
433  // Hyphenation in a Draw object
434  HyphenateDrawText();
435  }
436  else
437  {
438  SwViewOption* pVOpt = const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions());
439  bool bOldIdle = pVOpt->IsIdle();
440  pVOpt->SetIdle( false );
441 
442  Reference< XLinguProperties > xProp( ::GetLinguPropertySet() );
443 
444  m_pWrtShell->StartUndo(SwUndoId::INSATTR); // valid later
445 
446  bool bHyphSpecial = xProp.is() && xProp->getIsHyphSpecial();
447  bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection() ||
448  m_pWrtShell->GetCursor() != m_pWrtShell->GetCursor()->GetNext();
449  bool bOther = m_pWrtShell->HasOtherCnt() && bHyphSpecial && !bSelection;
450  bool bStart = bSelection || ( !bOther && m_pWrtShell->IsStartOfDoc() );
451  bool bStop = false;
452  if( !bOther && !(m_pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY) && !bSelection )
453  // turned on no special area
454  {
455  // I want also in special areas hyphenation
456  std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
457  VclMessageType::Question, VclButtonsType::YesNo,
458  SwResId(STR_QUERY_SPECIAL_FORCED)));
459  if (xBox->run() == RET_YES)
460  {
461  bOther = true;
462  if (xProp.is())
463  {
464  xProp->setIsHyphSpecial( true );
465  }
466  }
467  else
468  bStop = true; // No hyphenation
469  }
470 
471  if( !bStop )
472  {
473  SwHyphWrapper aWrap( this, xHyph, bStart, bOther, bSelection );
474  aWrap.SpellDocument();
475  m_pWrtShell->EndUndo(SwUndoId::INSATTR);
476  }
477  pVOpt->SetIdle( bOldIdle );
478  }
479 }
480 
482 {
483  // must not be a multi-selection, and if it is a selection it needs
484  // to be within a single paragraph
485 
486  const bool bMultiSel = m_pWrtShell->GetCursor()->IsMultiSelection();
487  const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection();
488  return !bMultiSel && (!bSelection || m_pWrtShell->IsSelOnePara() );
489 }
490 
491 OUString SwView::GetThesaurusLookUpText( bool bSelection ) const
492 {
493  return bSelection ? m_pWrtShell->GetSelText() : m_pWrtShell->GetCurWord();
494 }
495 
496 void SwView::InsertThesaurusSynonym( const OUString &rSynonmText, const OUString &rLookUpText, bool bSelection )
497 {
498  bool bOldIns = m_pWrtShell->IsInsMode();
499  m_pWrtShell->SetInsMode();
500 
501  m_pWrtShell->StartAllAction();
502  m_pWrtShell->StartUndo(SwUndoId::DELETE);
503 
504  if( !bSelection )
505  {
506  if(m_pWrtShell->IsEndWrd())
507  m_pWrtShell->Left(CRSR_SKIP_CELLS, false, 1, false );
508 
509  m_pWrtShell->SelWrd();
510 
511  // make sure the selection build later from the data below does not
512  // include "in word" character to the left and right in order to
513  // preserve those. Therefore count those "in words" in order to modify
514  // the selection accordingly.
515  const sal_Unicode* pChar = rLookUpText.getStr();
516  sal_Int32 nLeft = 0;
517  while (*pChar++ == CH_TXTATR_INWORD)
518  ++nLeft;
519  pChar = rLookUpText.getLength() ? rLookUpText.getStr() + rLookUpText.getLength() - 1 : nullptr;
520  sal_Int32 nRight = 0;
521  while (pChar && *pChar-- == CH_TXTATR_INWORD)
522  ++nRight;
523 
524  // adjust existing selection
525  SwPaM *pCursor = m_pWrtShell->GetCursor();
526  pCursor->GetPoint()->nContent -= nRight;
527  pCursor->GetMark()->nContent += nLeft;
528  }
529 
530  m_pWrtShell->Insert( rSynonmText );
531 
532  m_pWrtShell->EndUndo(SwUndoId::DELETE);
533  m_pWrtShell->EndAllAction();
534 
535  m_pWrtShell->SetInsMode( bOldIns );
536 }
537 
538 // Start thesaurus
539 
541 {
542  if (!IsValidSelectionForThesaurus())
543  return;
544 
545  SfxErrorContext aContext( ERRCTX_SVX_LINGU_THESAURUS, OUString(), m_pEditWin->GetFrameWeld(),
547 
548  // Determine language
549  LanguageType eLang = m_pWrtShell->GetCurLang();
550  if( LANGUAGE_SYSTEM == eLang )
551  eLang = GetAppLanguage();
552 
553  if( eLang == LANGUAGE_DONTKNOW || eLang == LANGUAGE_NONE )
554  {
555  SpellError( LANGUAGE_NONE );
556  return;
557  }
558 
559  SwViewOption* pVOpt = const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions());
560  const bool bOldIdle = pVOpt->IsIdle();
561  pVOpt->SetIdle( false );
562  comphelper::ScopeGuard guard([&]() { pVOpt->SetIdle(bOldIdle); }); // restore when leaving scope
563 
564  // get initial LookUp text
565  const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection();
566  OUString aTmp = GetThesaurusLookUpText( bSelection );
567 
568  Reference< XThesaurus > xThes( ::GetThesaurus() );
569 
570  if ( !xThes.is() || !xThes->hasLocale( LanguageTag::convertToLocale( eLang ) ) )
571  SpellError( eLang );
572  else
573  {
575  // create dialog
576  { //Scope for SwWait-Object
577  SwWait aWait( *GetDocShell(), true );
578  // load library with dialog only on demand ...
580  pDlg.reset(pFact->CreateThesaurusDialog(GetEditWin().GetFrameWeld(), xThes, aTmp, eLang));
581  }
582 
583  if (pDlg)
584  {
585  guard.dismiss(); // ignore, we'll call SetIdle() explicitly after the dialog ends
586 
587  pDlg->StartExecuteAsync([aTmp, bSelection, bOldIdle, pDlg, pVOpt, this](sal_Int32 nResult){
588  if (nResult == RET_OK )
589  InsertThesaurusSynonym(pDlg->GetWord(), aTmp, bSelection);
590 
591  pVOpt->SetIdle(bOldIdle);
592  pDlg->disposeOnce();
593  });
594  }
595  }
596 }
597 
598 // Offer online suggestions
599 
602 {
603  uno::Reference< frame::XDispatch > xDispatch;
604  util::URL aTargetURL;
605  uno::Sequence< PropertyValue > aArgs;
606 };
607 
609 {
610 public:
611  DECL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, void*, void );
612 };
613 
614 IMPL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, void*, p, void )
615 {
616  ExecuteInfo* pExecuteInfo = static_cast<ExecuteInfo*>(p);
617  SolarMutexReleaser aReleaser;
618  try
619  {
620  // Asynchronous execution as this can lead to our own destruction!
621  // Framework can recycle our current frame and the layout manager disposes all user interface
622  // elements if a component gets detached from its frame!
623  pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
624  }
625  catch (const Exception&)
626  {
627  }
628 
629  delete pExecuteInfo;
630 }
632 
634 {
635  bool bRet = false;
636  const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
637  if( pVOpt->IsOnlineSpell() &&
638  !m_pWrtShell->IsSelection())
639  {
640  if (m_pWrtShell->GetSelectionType() & SelectionType::DrawObjectEditMode)
641  bRet = ExecDrwTextSpellPopup(rPt);
642  else if (!m_pWrtShell->IsSelFrameMode())
643  {
644  const bool bOldViewLock = m_pWrtShell->IsViewLocked();
645  m_pWrtShell->LockView( true );
646  m_pWrtShell->Push();
647  SwRect aToFill;
648 
649  SwCursorShell *pCursorShell = m_pWrtShell.get();
650  SwPaM *pCursor = pCursorShell->GetCursor();
651  SwPosition aPoint(*pCursor->GetPoint());
652  const SwTextNode *pNode = aPoint.nNode.GetNode().GetTextNode();
653 
654  // Spell-check in case the idle jobs haven't had a chance to kick in.
655  // This makes it possible to suggest spelling corrections for
656  // wrong words independent of the spell-checking idle job.
657  if (pNode && pNode->IsWrongDirty() &&
658  !pCursorShell->IsTableMode() &&
659  !pCursor->HasMark() && !pCursor->IsMultiSelection())
660  {
661  std::pair<Point, bool> const tmp(rPt, false);
662  SwContentFrame *const pContentFrame = pCursor->GetContentNode()->getLayoutFrame(
663  pCursorShell->GetLayout(),
664  &aPoint, &tmp);
665  if (pContentFrame)
666  {
667  SwRect aRepaint(static_cast<SwTextFrame*>(pContentFrame)->AutoSpell_(
668  *pCursor->GetContentNode()->GetTextNode(), 0));
669  if (aRepaint.HasArea())
670  m_pWrtShell->InvalidateWindows(aRepaint);
671  }
672  }
673 
674  // decide which variant of the context menu to use...
675  // if neither spell checking nor grammar checking provides suggestions use the
676  // default context menu.
677  bool bUseGrammarContext = false;
678  Reference< XSpellAlternatives > xAlt( m_pWrtShell->GetCorrection(&rPt, aToFill) );
679  ProofreadingResult aGrammarCheckRes;
680  sal_Int32 nErrorInResult = -1;
681  uno::Sequence< OUString > aSuggestions;
682  bool bCorrectionRes = false;
683  if (!xAlt.is() || !xAlt->getAlternatives().hasElements())
684  {
685  sal_Int32 nErrorPosInText = -1;
686  bCorrectionRes = m_pWrtShell->GetGrammarCorrection( aGrammarCheckRes, nErrorPosInText, nErrorInResult, aSuggestions, &rPt, aToFill );
687  OUString aMessageText;
688  if (nErrorInResult >= 0)
689  aMessageText = aGrammarCheckRes.aErrors[ nErrorInResult ].aShortComment;
690  // we like to use the grammar checking context menu if we either get
691  // some suggestions or at least a comment about the error found...
692  bUseGrammarContext = bCorrectionRes &&
693  (aSuggestions.hasElements() || !aMessageText.isEmpty());
694  }
695 
696  // open respective context menu for spell check or grammar errors with correction suggestions...
697  if ((!bUseGrammarContext && xAlt.is()) ||
698  (bUseGrammarContext && bCorrectionRes && aGrammarCheckRes.aErrors.hasElements()))
699  {
700  // get paragraph text
701  OUString aParaText;
702  if (pNode)
703  aParaText = pNode->GetText(); // this may include hidden text but that should be Ok
704  else
705  {
706  OSL_FAIL("text node expected but not found" );
707  }
708 
709  bRet = true;
710  m_pWrtShell->SttSelect();
711  std::unique_ptr<SwSpellPopup> xPopup(bUseGrammarContext ?
712  new SwSpellPopup(m_pWrtShell.get(), aGrammarCheckRes, nErrorInResult, aSuggestions, aParaText) :
713  new SwSpellPopup(m_pWrtShell.get(), xAlt, aParaText));
714  ui::ContextMenuExecuteEvent aEvent;
715  const Point aPixPos = GetEditWin().LogicToPixel( rPt );
716 
717  aEvent.SourceWindow = VCLUnoHelper::GetInterface( m_pEditWin );
718  aEvent.ExecutePosition.X = aPixPos.X();
719  aEvent.ExecutePosition.Y = aPixPos.Y();
720  ScopedVclPtr<Menu> pMenu;
721 
722  OUString sMenuName = bUseGrammarContext ?
723  OUString("private:resource/GrammarContextMenu") : OUString("private:resource/SpellContextMenu");
724  if (TryContextMenuInterception(xPopup->GetMenu(), sMenuName, pMenu, aEvent))
725  {
728  if ( pMenu )
729  {
730  const sal_uInt16 nId = static_cast<PopupMenu*>(pMenu.get())->Execute(m_pEditWin, aPixPos);
731  OUString aCommand = static_cast<PopupMenu*>(pMenu.get())->GetItemCommand(nId);
732  if (aCommand.isEmpty() )
733  {
734  if (!ExecuteMenuCommand(dynamic_cast<PopupMenu&>(*pMenu), *GetViewFrame(), nId))
735  xPopup->Execute(nId);
736  }
737  else
738  {
739  SfxViewFrame *pSfxViewFrame = GetViewFrame();
740  uno::Reference< frame::XFrame > xFrame;
741  if ( pSfxViewFrame )
742  xFrame = pSfxViewFrame->GetFrame().GetFrameInterface();
743  css::util::URL aURL;
744  uno::Reference< frame::XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
745 
746  try
747  {
748  uno::Reference< frame::XDispatch > xDispatch;
749  uno::Reference< util::XURLTransformer > xURLTransformer = util::URLTransformer::create(comphelper::getProcessComponentContext());
750 
751  aURL.Complete = aCommand;
752  xURLTransformer->parseStrict(aURL);
753  uno::Sequence< beans::PropertyValue > aArgs;
754  xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 );
755 
756  if (xDispatch.is())
757  {
758  // Execute dispatch asynchronously
759  ExecuteInfo* pExecuteInfo = new ExecuteInfo;
760  pExecuteInfo->xDispatch = xDispatch;
761  pExecuteInfo->aTargetURL = aURL;
762  pExecuteInfo->aArgs = aArgs;
763  Application::PostUserEvent( LINK(nullptr, AsyncExecute , ExecuteHdl_Impl), pExecuteInfo );
764  }
765  }
766  catch (const Exception&)
767  {
768  }
769  }
770  }
771  else
772  {
774  xPopup->GetMenu().SetLOKNotifier(SfxViewShell::Current());
775 
776  xPopup->Execute(aToFill.SVRect(), m_pEditWin);
777  }
778  }
779  }
780 
781  m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
782  m_pWrtShell->LockView( bOldViewLock );
783  }
784  }
785  return bRet;
786 }
787 
794 {
795  const bool bOldViewLock = m_pWrtShell->IsViewLocked();
796  m_pWrtShell->LockView( true );
797  m_pWrtShell->Push();
798 
799  css::uno::Sequence< css::uno::Any > aArgs( 2 );
800  aArgs[0] <<= comphelper::makePropertyValue( "Frame", GetDispatcher().GetFrame()->GetFrame().GetFrameInterface() );
801  aArgs[1] <<= comphelper::makePropertyValue( "CommandURL", OUString( ".uno:OpenSmartTagMenuOnCursor" ) );
802 
803  css::uno::Reference< css::uno::XComponentContext > xContext = comphelper::getProcessComponentContext();
804  css::uno::Reference< css::frame::XPopupMenuController > xPopupController(
805  xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
806  "com.sun.star.comp.svx.SmartTagMenuController", aArgs, xContext ), css::uno::UNO_QUERY );
807 
808  css::uno::Reference< css::awt::XPopupMenu > xPopupMenu( xContext->getServiceManager()->createInstanceWithContext(
809  "com.sun.star.awt.PopupMenu", xContext ), css::uno::UNO_QUERY );
810 
811  if ( xPopupController.is() && xPopupMenu.is() )
812  {
813  xPopupController->setPopupMenu( xPopupMenu );
814 
815  SwRect aToFill;
816  m_pWrtShell->GetSmartTagRect( rPt, aToFill );
817  m_pWrtShell->SttSelect();
818 
819  if ( aToFill.HasArea() )
820  xPopupMenu->execute( m_pEditWin->GetComponentInterface(),
821  VCLUnoHelper::ConvertToAWTRect( m_pEditWin->LogicToPixel( aToFill.SVRect() ) ), css::awt::PopupMenuDirection::EXECUTE_DOWN );
822 
823  css::uno::Reference< css::lang::XComponent > xComponent( xPopupController, css::uno::UNO_QUERY );
824  if ( xComponent.is() )
825  xComponent->dispose();
826  }
827 
828  m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent);
829  m_pWrtShell->LockView( bOldViewLock );
830 }
831 
832 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
uno::Reference< linguistic2::XHyphenator > GetHyphenator()
Definition: swtypes.cxx:50
const sal_Char * pChar
bool IsWait() const
#define LANGUAGE_NONE
static vcl::Font GetDefaultFont(DefaultFontType nType, LanguageType eLang, GetDefaultFontFlags nFlags, const OutputDevice *pOutDev=nullptr)
void SpellDocument()
SAL_DLLPRIVATE void HyphenateDocument()
Definition: viewling.cxx:409
void ExecLingu(SfxRequest &)
Definition: viewling.cxx:105
Marks a position in the document model.
Definition: pam.hxx:35
bool IsMultiSelection() const
Definition: pam.hxx:272
SwPaM * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:184
uno::Sequence< PropertyValue > aArgs
Definition: viewling.cxx:605
! Start of extra code for context menu modifying extensions
Definition: viewling.cxx:601
const OUString & GetText() const
Definition: ndtxt.hxx:210
static bool HasConvIter()
Is text conversion active somewhere else?
Definition: edlingu.cxx:600
#define FN_HYPHENATE_OPT_DLG
Definition: cmdid.h:472
SwNodeIndex nNode
Definition: pam.hxx:37
bool IsTableMode() const
Definition: crsrsh.hxx:647
SAL_DLLPRIVATE void SpellStart(SvxSpellArea eSpell, bool bStartDone, bool bEndDone, SwConversionArgs *pConvArgs)
Definition: viewling.cxx:273
static SvxAbstractDialogFactory * Create()
void EnterWait()
Reference< XFrame > xFrame
const SwPosition * GetMark() const
Definition: pam.hxx:209
#define LANGUAGE_KOREAN
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1147
sal_Int16 nId
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
SwNode & GetNode() const
Definition: ndindex.hxx:119
sal_uInt16 Execute(vcl::Window *pWindow, const Point &rPopupPos)
Of course Writer needs its own rectangles.
Definition: swrect.hxx:34
static bool HasHyphIter()
Is hyphenation active somewhere else?
Definition: edlingu.cxx:605
virtual OUString GetWord()=0
uno::Reference< linguistic2::XLinguProperties > GetLinguPropertySet()
Definition: swtypes.cxx:60
SwDocPositions
Definition: cshtyp.hxx:103
SwContentNode * GetContentNode(bool bPoint=true) const
Definition: pam.hxx:229
sal_uInt16 sal_Unicode
#define CH_TXTATR_INWORD
Definition: hintids.hxx:44
RET_YES
SwIndex nContent
Definition: pam.hxx:38
SfxFrame & GetFrame() const
static SfxViewShell * Current()
SwPaM * GetNext()
Definition: pam.hxx:264
css::uno::Reference< css::lang::XComponent > xComponent
bool ExecSpellPopup(const Point &rPt)
! End of extra code for context menu modifying extensions
Definition: viewling.cxx:633
weld::Window * GetFrameWeld(const SfxFrame *pFrame)
Definition: dialoghelp.cxx:20
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:136
uno::Reference< frame::XDispatch > xDispatch
Definition: viewling.cxx:603
const SwPosition * GetPoint() const
Definition: pam.hxx:207
css::uno::Sequence< css::uno::Any > InitAnyPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
Window class for the Writer edit area, this is the one handling mouse and keyboard events and doing t...
Definition: edtwin.hxx:58
SVX_DLLPUBLIC const ErrMsgCode RID_SVXERRCTX[]
#define LANGUAGE_SYSTEM
static DialogMask HandleError(ErrCode nId, weld::Window *pParent=nullptr, DialogMask nMask=DialogMask::MAX)
void ExecSmartTagPopup(const Point &rPt)
Function: ExecSmartTagPopup.
Definition: viewling.cxx:793
bool IsIdle() const
Definition: viewopt.hxx:202
void SpellError(LanguageType eLang)
Definition: viewling.cxx:334
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:205
bool HasArea() const
Definition: swrect.hxx:290
#define ERRCTX_SVX_LINGU_THESAURUS
#define LANGUAGE_DONTKNOW
#define LANGUAGE_CHINESE_SIMPLIFIED
void InsertThesaurusSynonym(const OUString &rSynonmText, const OUString &rLookUpText, bool bValidSelection)
Definition: viewling.cxx:496
CPPUHELPER_DLLPUBLIC css::uno::Reference< css::uno::XComponentContext > SAL_CALL defaultBootstrap_InitialComponentContext()
Marks a node in the document model.
Definition: ndindex.hxx:31
IMPL_STATIC_LINK(AsyncExecute, ExecuteHdl_Impl, void *, p, void)
Definition: viewling.cxx:614
OUString SwResId(const char *pId)
Definition: swmodule.cxx:190
bool IsOnlineSpell() const
Definition: viewopt.hxx:332
OUString GetThesaurusLookUpText(bool bSelection) const
Definition: viewling.cxx:491
#define ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS
static css::awt::Rectangle ConvertToAWTRect(::tools::Rectangle const &_rRect)
long X() const
const css::uno::Reference< css::frame::XFrame > & GetFrameInterface() const
#define ERRCODE_SVX_LINGU_LINGUNOTEXISTS
void reset(reference_type *pBody)
weld::Window * GetFrameWeld() const
SAL_DLLPRIVATE void StartTextConversion(LanguageType nSourceLang, LanguageType nTargetLang, const vcl::Font *pTargetFont, sal_Int32 nOptions, bool bIsInteractive)
Definition: viewling.cxx:229
void Convert()
Definition: hhcwrp.cxx:513
const sal_uInt16 CRSR_SKIP_CELLS
Definition: swcrsr.hxx:64
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:79
sal_uInt16 GetSlot() const
SfxDispatcher * GetDispatcher()
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
tools::Rectangle SVRect() const
Definition: swrect.hxx:282
SAL_DLLPRIVATE void HyphStart(SvxSpellArea eSpell)
Definition: viewling.cxx:386
bool IsValidSelectionForThesaurus() const
Definition: viewling.cxx:481
SvxSpellArea
void SetIdle(bool b) const
Definition: viewopt.hxx:209
SAL_DLLPRIVATE void StartThesaurus()
Definition: viewling.cxx:540
sal_Int32 GetIndex() const
Definition: index.hxx:95
uno::Reference< linguistic2::XThesaurus > GetThesaurus()
Definition: swtypes.cxx:55
LanguageType GetAppLanguage()
Definition: init.cxx:729
RET_OK
bool ExecuteMenuCommand(PopupMenu const &rMenu, SfxViewFrame const &rViewFrame, sal_uInt16 nId)
Definition: uitool.cxx:838
Reference< XComponentContext > getProcessComponentContext()
util::URL aTargetURL
Definition: viewling.cxx:604
#define ERRCTX_SVX_LINGU_HYPHENATION
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage)
static OUString GetLanguageString(const LanguageType eType)
#define LANGUAGE_CHINESE_TRADITIONAL
SAL_DLLPRIVATE void SpellEnd(SwConversionArgs const *pConvArgs)
Definition: viewling.cxx:379
void LeaveWait()
static css::uno::Reference< css::awt::XWindow > GetInterface(vcl::Window *pWindow)
#define ERRCODE_SVX_LINGU_NOLANGUAGE
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2075
void Ignore()
bool IsTextNode() const
Definition: node.hxx:636
std::locale SvxResLocale()
long Y() const
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:842
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)