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