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