1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <hintids.hxx>
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>
28 #include <comphelper/processfactory.hxx>
29 #include <comphelper/propertyvalue.hxx>
30 #include <comphelper/propertysequence.hxx>
31 #include <comphelper/scopeguard.hxx>
32 #include <toolkit/helper/vclunohelper.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 <osl/diagnose.h>
46 #include <viewopt.hxx>
55 #include <strings.hrc>
58 #include <boost/property_tree/json_parser.hpp>
60 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
61 #include <com/sun/star/ui/ContextMenuExecuteEvent.hpp>
62 #include <com/sun/star/lang/XInitialization.hpp>
63 #include <com/sun/star/frame/XDispatch.hpp>
64 #include <com/sun/star/frame/XDispatchProvider.hpp>
65 #include <com/sun/star/frame/XFrame.hpp>
66 #include <com/sun/star/frame/XPopupMenuController.hpp>
67 #include <com/sun/star/awt/PopupMenuDirection.hpp>
68 #include <com/sun/star/awt/XVclWindowPeer.hpp>
69 #include <com/sun/star/util/URL.hpp>
70 #include <com/sun/star/beans/PropertyValue.hpp>
71 #include <com/sun/star/beans/XPropertySet.hpp>
72 #include <com/sun/star/util/URLTransformer.hpp>
73 #include <com/sun/star/util/XURLTransformer.hpp>
75 #include <vcl/svapp.hxx>
76 #include <rtl/ustring.hxx>
78 #include <cppuhelper/bootstrap.hxx>
79 #include <svtools/langtab.hxx>
81 #include <editeng/editerr.hxx>
82 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
86 using namespace sw::mark
;
87 using namespace ::com::sun::star
;
88 using namespace ::com::sun::star::beans
;
89 using namespace ::com::sun::star::uno
;
90 using namespace ::com::sun::star::linguistic2
;
94 void SwView::ExecLingu(SfxRequest
&rReq
)
96 switch(rReq
.GetSlot())
102 case SID_HANGUL_HANJA_CONVERSION
:
103 StartTextConversion( LANGUAGE_KOREAN
, LANGUAGE_KOREAN
, nullptr,
104 i18n::TextConversionOption::CHARACTER_BY_CHARACTER
, true );
106 case SID_CHINESE_CONVERSION
:
108 //open ChineseTranslationDialog
109 Reference
< XComponentContext
> xContext(
110 ::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one
113 Reference
< lang::XMultiComponentFactory
> xMCF( xContext
->getServiceManager() );
116 Reference
< ui::dialogs::XExecutableDialog
> xDialog(
117 xMCF
->createInstanceWithContext(
118 "com.sun.star.linguistic2.ChineseTranslationDialog", xContext
),
120 Reference
< lang::XInitialization
> xInit( xDialog
, UNO_QUERY
);
123 Reference
<awt::XWindow
> xParentWindow
;
124 if (weld::Window
* pParentWindow
= rReq
.GetFrameWeld())
125 xParentWindow
= pParentWindow
->GetXWindow();
127 uno::Sequence
<uno::Any
> aSeq(comphelper::InitAnyPropertySequence(
129 {"ParentWindow", uno::Any(xParentWindow
)}
131 xInit
->initialize( aSeq
);
134 sal_Int16 nDialogRet
= xDialog
->execute();
135 if( RET_OK
== nDialogRet
)
137 //get some parameters from the dialog
138 bool bToSimplified
= true;
139 bool bUseVariants
= true;
140 bool bCommonTerms
= true;
141 Reference
< beans::XPropertySet
> xProp( xDialog
, UNO_QUERY
);
146 xProp
->getPropertyValue( "IsDirectionToSimplified" ) >>= bToSimplified
;
147 xProp
->getPropertyValue( "IsUseCharacterVariants" ) >>= bUseVariants
;
148 xProp
->getPropertyValue( "IsTranslateCommonTerms" ) >>= bCommonTerms
;
150 catch (const Exception
&)
155 //execute translation
156 LanguageType nSourceLang
= bToSimplified
? LANGUAGE_CHINESE_TRADITIONAL
: LANGUAGE_CHINESE_SIMPLIFIED
;
157 LanguageType nTargetLang
= bToSimplified
? LANGUAGE_CHINESE_SIMPLIFIED
: LANGUAGE_CHINESE_TRADITIONAL
;
158 sal_Int32 nOptions
= bUseVariants
? i18n::TextConversionOption::USE_CHARACTER_VARIANTS
: 0;
160 nOptions
= nOptions
| i18n::TextConversionOption::CHARACTER_BY_CHARACTER
;
162 vcl::Font aTargetFont
= OutputDevice::GetDefaultFont( DefaultFontType::CJK_TEXT
,
163 nTargetLang
, GetDefaultFontFlags::OnlyOne
);
165 // disallow formatting, updating the view, ... while
166 // converting the document. (saves time)
167 // Also remember the current view and cursor position for later
168 m_pWrtShell
->StartAction();
170 // remember cursor position data for later restoration of the cursor
171 const SwPosition
*pPoint
= m_pWrtShell
->GetCursor()->GetPoint();
172 bool bRestoreCursor
= pPoint
->GetNode().IsTextNode();
173 const SwNodeIndex
aPointNodeIndex( pPoint
->GetNode() );
174 sal_Int32 nPointIndex
= pPoint
->GetContentIndex();
176 // since this conversion is not interactive the whole converted
177 // document should be undone in a single undo step.
178 m_pWrtShell
->StartUndo( SwUndoId::OVERWRITE
);
180 StartTextConversion( nSourceLang
, nTargetLang
, &aTargetFont
, nOptions
, false );
182 m_pWrtShell
->EndUndo( SwUndoId::OVERWRITE
);
186 SwTextNode
*pTextNode
= aPointNodeIndex
.GetNode().GetTextNode();
187 // check for unexpected error case
188 OSL_ENSURE(pTextNode
&& pTextNode
->GetText().getLength() >= nPointIndex
,
189 "text missing: corrupted node?" );
190 // restore cursor to its original position
191 if (!pTextNode
|| pTextNode
->GetText().getLength() < nPointIndex
)
192 m_pWrtShell
->GetCursor()->GetPoint()->Assign( aPointNodeIndex
);
194 m_pWrtShell
->GetCursor()->GetPoint()->Assign( *pTextNode
, nPointIndex
);
197 // enable all, restore view and cursor position
198 m_pWrtShell
->EndAction();
201 Reference
< lang::XComponent
> xComponent( xDialog
, UNO_QUERY
);
202 if( xComponent
.is() )
203 xComponent
->dispose();
208 case FN_HYPHENATE_OPT_DLG
:
212 OSL_ENSURE(false, "wrong Dispatcher");
217 // start language specific text conversion
219 void SwView::StartTextConversion(
220 LanguageType nSourceLang
,
221 LanguageType nTargetLang
,
222 const vcl::Font
*pTargetFont
,
224 bool bIsInteractive
)
226 // do not do text conversion if it is active elsewhere
227 if (SwEditShell::HasConvIter())
234 const SwViewOption
* pVOpt
= m_pWrtShell
->GetViewOptions();
235 const bool bOldIdle
= pVOpt
->IsIdle();
236 pVOpt
->SetIdle( false );
238 bool bOldIns
= m_pWrtShell
->IsInsMode();
239 m_pWrtShell
->SetInsMode();
241 const bool bSelection
= static_cast<SwCursorShell
*>(m_pWrtShell
.get())->HasSelection() ||
242 m_pWrtShell
->GetCursor() != m_pWrtShell
->GetCursor()->GetNext();
244 const bool bStart
= bSelection
|| m_pWrtShell
->IsStartOfDoc();
245 const bool bOther
= !bSelection
&& !(m_pWrtShell
->GetFrameType(nullptr,true) & FrameTypeFlags::BODY
);
248 const uno::Reference
< uno::XComponentContext
> xContext(
249 comphelper::getProcessComponentContext() );
250 SwHHCWrapper
aWrap( this, xContext
, nSourceLang
, nTargetLang
, pTargetFont
,
251 nOptions
, bIsInteractive
,
252 bStart
, bOther
, bSelection
);
256 m_pWrtShell
->SetInsMode( bOldIns
);
257 pVOpt
->SetIdle( bOldIdle
);
261 // spellcheck and text conversion related stuff
263 void SwView::SpellStart( SvxSpellArea eWhich
,
264 bool bStartDone
, bool bEndDone
,
265 SwConversionArgs
*pConvArgs
)
267 Reference
< XLinguProperties
> xProp
= ::GetLinguPropertySet();
268 bool bIsWrapReverse
= !pConvArgs
&& xProp
.is() && xProp
->getIsWrapReverse();
270 SwDocPositions eStart
= SwDocPositions::Start
;
271 SwDocPositions eEnd
= SwDocPositions::End
;
272 SwDocPositions eCurr
= SwDocPositions::Curr
;
275 case SvxSpellArea::Body
:
277 eCurr
= SwDocPositions::End
;
279 eCurr
= SwDocPositions::Start
;
281 case SvxSpellArea::BodyEnd
:
285 eStart
= SwDocPositions::Curr
;
286 eCurr
= SwDocPositions::End
;
288 else if( bStartDone
)
289 eCurr
= SwDocPositions::Start
;
291 case SvxSpellArea::BodyStart
:
292 if( !bIsWrapReverse
)
295 eEnd
= SwDocPositions::Curr
;
296 eCurr
= SwDocPositions::Start
;
299 eCurr
= SwDocPositions::End
;
301 case SvxSpellArea::Other
:
304 eStart
= SwDocPositions::OtherStart
;
305 eEnd
= SwDocPositions::OtherEnd
;
306 eCurr
= SwDocPositions::OtherEnd
;
310 eStart
= SwDocPositions::OtherStart
;
311 eEnd
= SwDocPositions::OtherEnd
;
312 eCurr
= SwDocPositions::OtherStart
;
316 OSL_ENSURE( false, "SpellStart with unknown Area" );
318 m_pWrtShell
->SpellStart( eStart
, eEnd
, eCurr
, pConvArgs
);
321 // Error message while Spelling
323 // The passed pointer nlang is itself the value
324 void SwView::SpellError(LanguageType eLang
)
328 if ( m_pWrtShell
->ActionPend() )
331 m_pWrtShell
->ClearMark();
334 m_pWrtShell
->EndAction();
337 while( m_pWrtShell
->ActionPend() );
339 OUString
aErr(SvtLanguageTable::GetLanguageString( eLang
) );
341 SwEditWin
&rEditWin
= GetEditWin();
343 while( rEditWin
.IsWait() )
345 rEditWin
.LeaveWait();
348 if ( LANGUAGE_NONE
== eLang
)
349 ErrorHandler::HandleError( ERRCODE_SVX_LINGU_NOLANGUAGE
);
351 ErrorHandler::HandleError( *new StringErrorInfo( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS
, aErr
) );
355 rEditWin
.EnterWait();
362 m_pWrtShell
->StartAction();
363 m_pWrtShell
->Combine();
367 // Finish spelling and restore cursor
369 void SwView::SpellEnd( SwConversionArgs
const *pConvArgs
)
371 m_pWrtShell
->SpellEnd( pConvArgs
);
372 if( m_pWrtShell
->IsExtMode() )
373 m_pWrtShell
->SetMark();
376 void SwView::HyphStart( SvxSpellArea eWhich
)
380 case SvxSpellArea::Body
:
381 m_pWrtShell
->HyphStart( SwDocPositions::Start
, SwDocPositions::End
);
383 case SvxSpellArea::BodyEnd
:
384 m_pWrtShell
->HyphStart( SwDocPositions::Curr
, SwDocPositions::End
);
386 case SvxSpellArea::BodyStart
:
387 m_pWrtShell
->HyphStart( SwDocPositions::Start
, SwDocPositions::Curr
);
389 case SvxSpellArea::Other
:
390 m_pWrtShell
->HyphStart( SwDocPositions::OtherStart
, SwDocPositions::OtherEnd
);
393 OSL_ENSURE( false, "HyphStart with unknown Area" );
397 // Interactive separation
399 void SwView::HyphenateDocument()
401 // do not hyphenate if interactive hyphenation is active elsewhere
402 if (SwEditShell::HasHyphIter())
404 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
405 VclMessageType::Warning
, VclButtonsType::Ok
, SwResId(STR_MULT_INTERACT_HYPH_WARN
)));
406 xBox
->set_title(SwResId(STR_HYPH_TITLE
));
411 SfxErrorContext
aContext( ERRCTX_SVX_LINGU_HYPHENATION
, OUString(), m_pEditWin
->GetFrameWeld(),
412 RID_SVXERRCTX
, SvxResLocale() );
414 Reference
< XHyphenator
> xHyph( ::GetHyphenator() );
417 ErrorHandler::HandleError( ERRCODE_SVX_LINGU_LINGUNOTEXISTS
);
421 if (m_pWrtShell
->GetSelectionType() & (SelectionType::DrawObjectEditMode
|SelectionType::DrawObject
))
423 // Hyphenation in a Draw object
428 SwViewOption
* pVOpt
= const_cast<SwViewOption
*>(m_pWrtShell
->GetViewOptions());
429 bool bOldIdle
= pVOpt
->IsIdle();
430 pVOpt
->SetIdle( false );
432 Reference
< XLinguProperties
> xProp( ::GetLinguPropertySet() );
434 m_pWrtShell
->StartUndo(SwUndoId::INSATTR
); // valid later
436 bool bHyphSpecial
= xProp
.is() && xProp
->getIsHyphSpecial();
437 bool bSelection
= static_cast<SwCursorShell
*>(m_pWrtShell
.get())->HasSelection() ||
438 m_pWrtShell
->GetCursor() != m_pWrtShell
->GetCursor()->GetNext();
439 bool bOther
= m_pWrtShell
->HasOtherCnt() && bHyphSpecial
&& !bSelection
;
440 bool bStart
= bSelection
|| ( !bOther
&& m_pWrtShell
->IsStartOfDoc() );
442 if( !bOther
&& !(m_pWrtShell
->GetFrameType(nullptr,true) & FrameTypeFlags::BODY
) && !bSelection
)
443 // turned on no special area
445 // I want also in special areas hyphenation
446 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
447 VclMessageType::Question
, VclButtonsType::YesNo
,
448 SwResId(STR_QUERY_SPECIAL_FORCED
)));
449 if (xBox
->run() == RET_YES
)
454 xProp
->setIsHyphSpecial( true );
458 bStop
= true; // No hyphenation
463 SwHyphWrapper
aWrap( this, xHyph
, bStart
, bOther
, bSelection
);
464 aWrap
.SpellDocument();
465 m_pWrtShell
->EndUndo(SwUndoId::INSATTR
);
467 pVOpt
->SetIdle( bOldIdle
);
471 bool SwView::IsValidSelectionForThesaurus() const
473 // must not be a multi-selection, and if it is a selection it needs
474 // to be within a single paragraph
476 const bool bMultiSel
= m_pWrtShell
->GetCursor()->IsMultiSelection();
477 const bool bSelection
= static_cast<SwCursorShell
*>(m_pWrtShell
.get())->HasSelection();
478 return !bMultiSel
&& (!bSelection
|| m_pWrtShell
->IsSelOnePara() );
481 OUString
SwView::GetThesaurusLookUpText( bool bSelection
) const
483 return bSelection
? m_pWrtShell
->GetSelText() : m_pWrtShell
->GetCurWord();
486 void SwView::InsertThesaurusSynonym( const OUString
&rSynonmText
, const OUString
&rLookUpText
, bool bSelection
)
488 bool bOldIns
= m_pWrtShell
->IsInsMode();
489 m_pWrtShell
->SetInsMode();
491 m_pWrtShell
->StartAllAction();
492 m_pWrtShell
->StartUndo(SwUndoId::DELETE
);
496 if(m_pWrtShell
->IsEndWrd())
497 m_pWrtShell
->Left(SwCursorSkipMode::Cells
, false, 1, false );
499 m_pWrtShell
->SelWrd();
501 // make sure the selection build later from the data below does not
502 // include "in word" character to the left and right in order to
503 // preserve those. Therefore count those "in words" in order to modify
504 // the selection accordingly.
505 const sal_Unicode
* pChar
= rLookUpText
.getStr();
507 while (*pChar
++ == CH_TXTATR_INWORD
)
509 pChar
= rLookUpText
.getLength() ? rLookUpText
.getStr() + rLookUpText
.getLength() - 1 : nullptr;
510 sal_Int32 nRight
= 0;
511 while (pChar
&& *pChar
-- == CH_TXTATR_INWORD
)
514 // adjust existing selection
515 SwPaM
*pCursor
= m_pWrtShell
->GetCursor();
516 pCursor
->GetPoint()->AdjustContent(-nRight
);
517 pCursor
->GetMark()->AdjustContent(nLeft
);
520 m_pWrtShell
->Insert( rSynonmText
);
522 m_pWrtShell
->EndUndo(SwUndoId::DELETE
);
523 m_pWrtShell
->EndAllAction();
525 m_pWrtShell
->SetInsMode( bOldIns
);
530 void SwView::StartThesaurus()
532 if (!IsValidSelectionForThesaurus())
535 SfxErrorContext
aContext( ERRCTX_SVX_LINGU_THESAURUS
, OUString(), m_pEditWin
->GetFrameWeld(),
536 RID_SVXERRCTX
, SvxResLocale() );
538 // Determine language
539 LanguageType eLang
= m_pWrtShell
->GetCurLang();
540 if( LANGUAGE_SYSTEM
== eLang
)
541 eLang
= GetAppLanguage();
543 if( eLang
== LANGUAGE_DONTKNOW
|| eLang
== LANGUAGE_NONE
)
545 SpellError( LANGUAGE_NONE
);
549 SwViewOption
* pVOpt
= const_cast<SwViewOption
*>(m_pWrtShell
->GetViewOptions());
550 const bool bOldIdle
= pVOpt
->IsIdle();
551 pVOpt
->SetIdle( false );
552 comphelper::ScopeGuard
guard([&]() { pVOpt
->SetIdle(bOldIdle
); }); // restore when leaving scope
554 // get initial LookUp text
555 const bool bSelection
= static_cast<SwCursorShell
*>(m_pWrtShell
.get())->HasSelection();
556 OUString aTmp
= GetThesaurusLookUpText( bSelection
);
558 Reference
< XThesaurus
> xThes( ::GetThesaurus() );
560 if ( !xThes
.is() || !xThes
->hasLocale( LanguageTag::convertToLocale( eLang
) ) )
564 VclPtr
<AbstractThesaurusDialog
> pDlg
;
566 { //Scope for SwWait-Object
567 SwWait
aWait( *GetDocShell(), true );
568 // load library with dialog only on demand ...
569 SvxAbstractDialogFactory
* pFact
= SvxAbstractDialogFactory::Create();
570 pDlg
.reset(pFact
->CreateThesaurusDialog(GetEditWin().GetFrameWeld(), xThes
, aTmp
, eLang
));
575 guard
.dismiss(); // ignore, we'll call SetIdle() explicitly after the dialog ends
577 pDlg
->StartExecuteAsync([aTmp
, bSelection
, bOldIdle
, pDlg
, pVOpt
, this](sal_Int32 nResult
){
578 if (nResult
== RET_OK
)
579 InsertThesaurusSynonym(pDlg
->GetWord(), aTmp
, bSelection
);
581 pVOpt
->SetIdle(bOldIdle
);
588 // Offer online suggestions
592 //!! Start of extra code for context menu modifying extensions
595 uno::Reference
< frame::XDispatch
> xDispatch
;
596 util::URL aTargetURL
;
597 uno::Sequence
< PropertyValue
> aArgs
;
603 DECL_STATIC_LINK( AsyncExecute
, ExecuteHdl_Impl
, void*, void );
608 IMPL_STATIC_LINK( AsyncExecute
, ExecuteHdl_Impl
, void*, p
, void )
610 ExecuteInfo
* pExecuteInfo
= static_cast<ExecuteInfo
*>(p
);
611 SolarMutexReleaser aReleaser
;
614 // Asynchronous execution as this can lead to our own destruction!
615 // Framework can recycle our current frame and the layout manager disposes all user interface
616 // elements if a component gets detached from its frame!
617 pExecuteInfo
->xDispatch
->dispatch( pExecuteInfo
->aTargetURL
, pExecuteInfo
->aArgs
);
619 catch (const Exception
&)
625 //!! End of extra code for context menu modifying extensions
627 bool SwView::ExecSpellPopup(const Point
& rPt
)
630 const SwViewOption
* pVOpt
= m_pWrtShell
->GetViewOptions();
631 if( pVOpt
->IsOnlineSpell() &&
632 !m_pWrtShell
->IsSelection())
634 if (m_pWrtShell
->GetSelectionType() & SelectionType::DrawObjectEditMode
)
635 bRet
= ExecDrwTextSpellPopup(rPt
);
636 else if (!m_pWrtShell
->IsSelFrameMode())
638 const bool bOldViewLock
= m_pWrtShell
->IsViewLocked();
639 m_pWrtShell
->LockView( true );
640 if (!comphelper::LibreOfficeKit::isActive())
644 SwCursorShell
*pCursorShell
= m_pWrtShell
.get();
645 SwPaM
*pCursor
= pCursorShell
->GetCursor();
646 SwPosition
aPoint(*pCursor
->GetPoint());
647 const SwTextNode
*pNode
= aPoint
.GetNode().GetTextNode();
649 // Spell-check in case the idle jobs haven't had a chance to kick in.
650 // This makes it possible to suggest spelling corrections for
651 // wrong words independent of the spell-checking idle job.
652 if (pNode
&& pNode
->IsWrongDirty() &&
653 !pCursorShell
->IsTableMode() &&
654 !pCursor
->HasMark() && !pCursor
->IsMultiSelection())
656 std::pair
<Point
, bool> const tmp(rPt
, false);
657 SwContentFrame
*const pContentFrame
= pCursor
->GetPointContentNode()->getLayoutFrame(
658 pCursorShell
->GetLayout(),
662 SwRect
aRepaint(static_cast<SwTextFrame
*>(pContentFrame
)->AutoSpell_(
663 *pCursor
->GetPointContentNode()->GetTextNode(), 0));
664 if (aRepaint
.HasArea())
665 m_pWrtShell
->InvalidateWindows(aRepaint
);
669 // decide which variant of the context menu to use...
670 // if neither spell checking nor grammar checking provides suggestions use the
671 // default context menu.
672 bool bUseGrammarContext
= false;
673 Reference
< XSpellAlternatives
> xAlt( m_pWrtShell
->GetCorrection(&rPt
, aToFill
) );
674 ProofreadingResult aGrammarCheckRes
;
675 sal_Int32 nErrorInResult
= -1;
676 uno::Sequence
< OUString
> aSuggestions
;
677 bool bCorrectionRes
= false;
678 if (!xAlt
.is() || !xAlt
->getAlternatives().hasElements())
680 sal_Int32 nErrorPosInText
= -1;
681 bCorrectionRes
= m_pWrtShell
->GetGrammarCorrection( aGrammarCheckRes
, nErrorPosInText
, nErrorInResult
, aSuggestions
, &rPt
, aToFill
);
682 OUString aMessageText
;
683 if (nErrorInResult
>= 0)
684 aMessageText
= aGrammarCheckRes
.aErrors
[ nErrorInResult
].aShortComment
;
685 // we like to use the grammar checking context menu if we either get
686 // some suggestions or at least a comment about the error found...
687 bUseGrammarContext
= bCorrectionRes
&&
688 (aSuggestions
.hasElements() || !aMessageText
.isEmpty());
691 // open respective context menu for spell check or grammar errors with correction suggestions...
692 if ((!bUseGrammarContext
&& xAlt
.is()) ||
693 (bUseGrammarContext
&& bCorrectionRes
&& aGrammarCheckRes
.aErrors
.hasElements()))
695 // get paragraph text
699 pCursorShell
->Push();
700 if (!pCursorShell
->IsSttPara())
702 pCursorShell
->MovePara(GoCurrPara
, fnParaStart
);
704 pCursorShell
->SetMark();
705 if (!pCursorShell
->IsEndPara())
707 pCursorShell
->MovePara(GoCurrPara
, fnParaEnd
);
709 aParaText
= pCursorShell
->GetSelText();
710 pCursorShell
->Pop(SwCursorShell::PopMode::DeleteCurrent
);
714 OSL_FAIL("text node expected but not found" );
718 m_pWrtShell
->SttSelect();
719 std::unique_ptr
<SwSpellPopup
> xPopup(bUseGrammarContext
?
720 new SwSpellPopup(m_pWrtShell
.get(), aGrammarCheckRes
, nErrorInResult
, aSuggestions
, aParaText
) :
721 new SwSpellPopup(m_pWrtShell
.get(), xAlt
, aParaText
));
722 ui::ContextMenuExecuteEvent aEvent
;
723 const Point aPixPos
= GetEditWin().LogicToPixel( rPt
);
725 aEvent
.SourceWindow
= VCLUnoHelper::GetInterface( m_pEditWin
);
726 aEvent
.ExecutePosition
.X
= aPixPos
.X();
727 aEvent
.ExecutePosition
.Y
= aPixPos
.Y();
728 rtl::Reference
<VCLXPopupMenu
> xMenu
;
730 OUString sMenuName
= bUseGrammarContext
?
731 OUString("private:resource/GrammarContextMenu") : OUString("private:resource/SpellContextMenu");
732 rtl::Reference
<VCLXPopupMenu
> xMenuInterface
= xPopup
->CreateMenuInterface();
733 if (TryContextMenuInterception(xMenuInterface
, sMenuName
, xMenu
, aEvent
))
735 //! happy hacking for context menu modifying extensions of this
736 //! 'custom made' menu... *sigh* (code copied from sfx2 and framework)
739 css::uno::Reference
<css::awt::XWindowPeer
> xParent(aEvent
.SourceWindow
, css::uno::UNO_QUERY
);
740 const sal_uInt16 nId
= xMenu
->execute(xParent
, css::awt::Rectangle(aPixPos
.X(), aPixPos
.Y(), 1, 1),
741 css::awt::PopupMenuDirection::EXECUTE_DOWN
);
742 OUString aCommand
= xMenu
->getCommand(nId
);
743 if (aCommand
.isEmpty() )
745 if (!ExecuteMenuCommand(xMenu
, GetViewFrame(), nId
))
746 xPopup
->Execute(nId
);
750 SfxViewFrame
& rSfxViewFrame
= GetViewFrame();
751 uno::Reference
<frame::XFrame
> xFrame
= rSfxViewFrame
.GetFrame().GetFrameInterface();
753 uno::Reference
< frame::XDispatchProvider
> xDispatchProvider( xFrame
, UNO_QUERY
);
757 uno::Reference
< frame::XDispatch
> xDispatch
;
758 uno::Reference
< util::XURLTransformer
> xURLTransformer
= util::URLTransformer::create(comphelper::getProcessComponentContext());
760 aURL
.Complete
= aCommand
;
761 xURLTransformer
->parseStrict(aURL
);
762 uno::Sequence
< beans::PropertyValue
> aArgs
;
763 xDispatch
= xDispatchProvider
->queryDispatch( aURL
, OUString(), 0 );
767 // Execute dispatch asynchronously
768 ExecuteInfo
* pExecuteInfo
= new ExecuteInfo
;
769 pExecuteInfo
->xDispatch
= xDispatch
;
770 pExecuteInfo
->aTargetURL
= aURL
;
771 pExecuteInfo
->aArgs
= aArgs
;
772 Application::PostUserEvent( LINK(nullptr, AsyncExecute
, ExecuteHdl_Impl
), pExecuteInfo
);
775 catch (const Exception
&)
782 if (comphelper::LibreOfficeKit::isActive())
784 if (SfxViewShell
* pViewShell
= SfxViewShell::Current())
786 boost::property_tree::ptree aMenu
= SfxDispatcher::fillPopupMenu(xMenuInterface
);
787 boost::property_tree::ptree aRoot
;
788 aRoot
.add_child("menu", aMenu
);
790 std::stringstream aStream
;
791 boost::property_tree::write_json(aStream
, aRoot
, true);
792 pViewShell
->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU
, OString(aStream
.str()));
797 xPopup
->Execute(aToFill
.SVRect(), m_pEditWin
);
803 if (!comphelper::LibreOfficeKit::isActive())
804 m_pWrtShell
->Pop(SwCursorShell::PopMode::DeleteCurrent
);
805 m_pWrtShell
->LockView( bOldViewLock
);
811 /** Function: ExecSmartTagPopup
813 This function shows the popup menu for smarttag
816 void SwView::ExecSmartTagPopup( const Point
& rPt
)
818 const bool bOldViewLock
= m_pWrtShell
->IsViewLocked();
819 m_pWrtShell
->LockView( true );
822 css::uno::Sequence
< css::uno::Any
> aArgs
{
823 css::uno::Any(comphelper::makePropertyValue( "Frame", GetDispatcher().GetFrame()->GetFrame().GetFrameInterface() )),
824 css::uno::Any(comphelper::makePropertyValue( "CommandURL", OUString( ".uno:OpenSmartTagMenuOnCursor" ) ))
827 css::uno::Reference
< css::uno::XComponentContext
> xContext
= comphelper::getProcessComponentContext();
828 css::uno::Reference
< css::frame::XPopupMenuController
> xPopupController(
829 xContext
->getServiceManager()->createInstanceWithArgumentsAndContext(
830 "com.sun.star.comp.svx.SmartTagMenuController", aArgs
, xContext
), css::uno::UNO_QUERY
);
832 css::uno::Reference
< css::awt::XPopupMenu
> xPopupMenu( xContext
->getServiceManager()->createInstanceWithContext(
833 "com.sun.star.awt.PopupMenu", xContext
), css::uno::UNO_QUERY
);
835 if ( xPopupController
.is() && xPopupMenu
.is() )
837 xPopupController
->setPopupMenu( xPopupMenu
);
840 m_pWrtShell
->GetSmartTagRect( rPt
, aToFill
);
841 m_pWrtShell
->SttSelect();
843 if ( aToFill
.HasArea() )
844 xPopupMenu
->execute( m_pEditWin
->GetComponentInterface(),
845 VCLUnoHelper::ConvertToAWTRect( m_pEditWin
->LogicToPixel( aToFill
.SVRect() ) ), css::awt::PopupMenuDirection::EXECUTE_DOWN
);
847 css::uno::Reference
< css::lang::XComponent
> xComponent( xPopupController
, css::uno::UNO_QUERY
);
848 if ( xComponent
.is() )
849 xComponent
->dispose();
852 m_pWrtShell
->Pop(SwCursorShell::PopMode::DeleteCurrent
);
853 m_pWrtShell
->LockView( bOldViewLock
);
856 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */