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 <osl/diagnose.h>
42#include <swwait.hxx>
43#include <uitool.hxx>
44#include <view.hxx>
45#include <wrtsh.hxx>
46#include <viewopt.hxx>
47#include <swundo.hxx>
48#include <hyp.hxx>
49#include <olmenu.hxx>
50#include <pam.hxx>
51#include <edtwin.hxx>
52#include <ndtxt.hxx>
53#include <txtfrm.hxx>
54#include <cmdid.h>
55#include <strings.hrc>
56#include <hhcwrp.hxx>
57
58#include <boost/property_tree/json_parser.hpp>
59
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>
74
75#include <vcl/svapp.hxx>
76#include <rtl/ustring.hxx>
77
79#include <svtools/langtab.hxx>
80
81#include <editeng/editerr.hxx>
82#include <LibreOfficeKit/LibreOfficeKitEnums.h>
83
84#include <memory>
85
86using namespace sw::mark;
87using namespace ::com::sun::star;
88using namespace ::com::sun::star::beans;
89using namespace ::com::sun::star::uno;
90using namespace ::com::sun::star::linguistic2;
91
92// Lingu-Dispatcher
93
95{
96 switch(rReq.GetSlot())
97 {
98 case SID_THESAURUS:
100 rReq.Ignore();
101 break;
102 case SID_HANGUL_HANJA_CONVERSION:
104 i18n::TextConversionOption::CHARACTER_BY_CHARACTER, true );
105 break;
106 case SID_CHINESE_CONVERSION:
107 {
108 //open ChineseTranslationDialog
109 Reference< XComponentContext > xContext(
110 ::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one
111 if(xContext.is())
112 {
113 Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
114 if(xMCF.is())
115 {
116 Reference< ui::dialogs::XExecutableDialog > xDialog(
117 xMCF->createInstanceWithContext(
118 "com.sun.star.linguistic2.ChineseTranslationDialog", xContext),
119 UNO_QUERY);
120 Reference< lang::XInitialization > xInit( xDialog, UNO_QUERY );
121 if( xInit.is() )
122 {
123 Reference<awt::XWindow> xParentWindow;
124 if (weld::Window* pParentWindow = rReq.GetFrameWeld())
125 xParentWindow = pParentWindow->GetXWindow();
126 // initialize dialog
127 uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence(
128 {
129 {"ParentWindow", uno::Any(xParentWindow)}
130 }));
131 xInit->initialize( aSeq );
132
133 //execute dialog
134 sal_Int16 nDialogRet = xDialog->execute();
135 if( RET_OK == nDialogRet )
136 {
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 );
142 if( xProp.is() )
143 {
144 try
145 {
146 xProp->getPropertyValue( "IsDirectionToSimplified" ) >>= bToSimplified;
147 xProp->getPropertyValue( "IsUseCharacterVariants" ) >>= bUseVariants;
148 xProp->getPropertyValue( "IsTranslateCommonTerms" ) >>= bCommonTerms;
149 }
150 catch (const Exception&)
151 {
152 }
153 }
154
155 //execute translation
158 sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0;
159 if( !bCommonTerms )
160 nOptions = nOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
161
162 vcl::Font aTargetFont = OutputDevice::GetDefaultFont( DefaultFontType::CJK_TEXT,
163 nTargetLang, GetDefaultFontFlags::OnlyOne );
164
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();
169
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();
175
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 );
179
180 StartTextConversion( nSourceLang, nTargetLang, &aTargetFont, nOptions, false );
181
183
184 if (bRestoreCursor)
185 {
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 );
193 else
194 m_pWrtShell->GetCursor()->GetPoint()->Assign( *pTextNode, nPointIndex );
195 }
196
197 // enable all, restore view and cursor position
198 m_pWrtShell->EndAction();
199 }
200 }
201 Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY );
202 if( xComponent.is() )
203 xComponent->dispose();
204 }
205 }
206 break;
207 }
210 break;
211 default:
212 OSL_ENSURE(false, "wrong Dispatcher");
213 return;
214 }
215}
216
217// start language specific text conversion
218
220 LanguageType nSourceLang,
221 LanguageType nTargetLang,
222 const vcl::Font *pTargetFont,
223 sal_Int32 nOptions,
224 bool bIsInteractive )
225{
226 // do not do text conversion if it is active elsewhere
228 {
229 return;
230 }
231
232 SpellContext();
233
234 const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
235 const bool bOldIdle = pVOpt->IsIdle();
236 pVOpt->SetIdle( false );
237
238 bool bOldIns = m_pWrtShell->IsInsMode();
239 m_pWrtShell->SetInsMode();
240
241 const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection() ||
242 m_pWrtShell->GetCursor() != m_pWrtShell->GetCursor()->GetNext();
243
244 const bool bStart = bSelection || m_pWrtShell->IsStartOfDoc();
245 const bool bOther = !bSelection && !(m_pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
246
247 {
248 const uno::Reference< uno::XComponentContext > xContext(
250 SwHHCWrapper aWrap( this, xContext, nSourceLang, nTargetLang, pTargetFont,
251 nOptions, bIsInteractive,
252 bStart, bOther, bSelection );
253 aWrap.Convert();
254 }
255
256 m_pWrtShell->SetInsMode( bOldIns );
257 pVOpt->SetIdle( bOldIdle );
258 SpellContext(false);
259}
260
261// spellcheck and text conversion related stuff
262
264 bool bStartDone, bool bEndDone,
265 SwConversionArgs *pConvArgs )
266{
267 Reference< XLinguProperties > xProp = ::GetLinguPropertySet();
268 bool bIsWrapReverse = !pConvArgs && xProp.is() && xProp->getIsWrapReverse();
269
273 switch ( eWhich )
274 {
275 case SvxSpellArea::Body:
276 if( bIsWrapReverse )
277 eCurr = SwDocPositions::End;
278 else
279 eCurr = SwDocPositions::Start;
280 break;
281 case SvxSpellArea::BodyEnd:
282 if( bIsWrapReverse )
283 {
284 if( bStartDone )
285 eStart = SwDocPositions::Curr;
286 eCurr = SwDocPositions::End;
287 }
288 else if( bStartDone )
289 eCurr = SwDocPositions::Start;
290 break;
291 case SvxSpellArea::BodyStart:
292 if( !bIsWrapReverse )
293 {
294 if( bEndDone )
296 eCurr = SwDocPositions::Start;
297 }
298 else if( bEndDone )
299 eCurr = SwDocPositions::End;
300 break;
301 case SvxSpellArea::Other:
302 if( bIsWrapReverse )
303 {
307 }
308 else
309 {
313 }
314 break;
315 default:
316 OSL_ENSURE( false, "SpellStart with unknown Area" );
317 }
318 m_pWrtShell->SpellStart( eStart, eEnd, eCurr, pConvArgs );
319}
320
321// Error message while Spelling
322
323// The passed pointer nlang is itself the value
325{
326 int nPend = 0;
327
328 if ( m_pWrtShell->ActionPend() )
329 {
330 m_pWrtShell->Push();
331 m_pWrtShell->ClearMark();
332 do
333 {
334 m_pWrtShell->EndAction();
335 ++nPend;
336 }
337 while( m_pWrtShell->ActionPend() );
338 }
339 OUString aErr(SvtLanguageTable::GetLanguageString( eLang ) );
340
341 SwEditWin &rEditWin = GetEditWin();
342 int nWaitCnt = 0;
343 while( rEditWin.IsWait() )
344 {
345 rEditWin.LeaveWait();
346 ++nWaitCnt;
347 }
348 if ( LANGUAGE_NONE == eLang )
350 else
352
353 while( nWaitCnt )
354 {
355 rEditWin.EnterWait();
356 --nWaitCnt;
357 }
358
359 if ( nPend )
360 {
361 while( nPend-- )
362 m_pWrtShell->StartAction();
363 m_pWrtShell->Combine();
364 }
365}
366
367// Finish spelling and restore cursor
368
369void SwView::SpellEnd( SwConversionArgs const *pConvArgs )
370{
371 m_pWrtShell->SpellEnd( pConvArgs );
372 if( m_pWrtShell->IsExtMode() )
373 m_pWrtShell->SetMark();
374}
375
377{
378 switch ( eWhich )
379 {
380 case SvxSpellArea::Body:
382 break;
383 case SvxSpellArea::BodyEnd:
385 break;
386 case SvxSpellArea::BodyStart:
388 break;
389 case SvxSpellArea::Other:
391 break;
392 default:
393 OSL_ENSURE( false, "HyphStart with unknown Area" );
394 }
395}
396
397// Interactive separation
398
400{
401 // do not hyphenate if interactive hyphenation is active elsewhere
403 {
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));
407 xBox->run();
408 return;
409 }
410
411 SfxErrorContext aContext( ERRCTX_SVX_LINGU_HYPHENATION, OUString(), m_pEditWin->GetFrameWeld(),
413
414 Reference< XHyphenator > xHyph( ::GetHyphenator() );
415 if (!xHyph.is())
416 {
418 return;
419 }
420
422 {
423 // Hyphenation in a Draw object
425 }
426 else
427 {
428 SwViewOption* pVOpt = const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions());
429 bool bOldIdle = pVOpt->IsIdle();
430 pVOpt->SetIdle( false );
431
432 Reference< XLinguProperties > xProp( ::GetLinguPropertySet() );
433
434 m_pWrtShell->StartUndo(SwUndoId::INSATTR); // valid later
435
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() );
441 bool bStop = false;
442 if( !bOther && !(m_pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY) && !bSelection )
443 // turned on no special area
444 {
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)
450 {
451 bOther = true;
452 if (xProp.is())
453 {
454 xProp->setIsHyphSpecial( true );
455 }
456 }
457 else
458 bStop = true; // No hyphenation
459 }
460
461 if( !bStop )
462 {
463 SwHyphWrapper aWrap( this, xHyph, bStart, bOther, bSelection );
464 aWrap.SpellDocument();
466 }
467 pVOpt->SetIdle( bOldIdle );
468 }
469}
470
472{
473 // must not be a multi-selection, and if it is a selection it needs
474 // to be within a single paragraph
475
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() );
479}
480
481OUString SwView::GetThesaurusLookUpText( bool bSelection ) const
482{
483 return bSelection ? m_pWrtShell->GetSelText() : m_pWrtShell->GetCurWord();
484}
485
486void SwView::InsertThesaurusSynonym( const OUString &rSynonmText, const OUString &rLookUpText, bool bSelection )
487{
488 bool bOldIns = m_pWrtShell->IsInsMode();
489 m_pWrtShell->SetInsMode();
490
491 m_pWrtShell->StartAllAction();
492 m_pWrtShell->StartUndo(SwUndoId::DELETE);
493
494 if( !bSelection )
495 {
496 if(m_pWrtShell->IsEndWrd())
497 m_pWrtShell->Left(SwCursorSkipMode::Cells, false, 1, false );
498
499 m_pWrtShell->SelWrd();
500
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();
506 sal_Int32 nLeft = 0;
507 while (*pChar++ == CH_TXTATR_INWORD)
508 ++nLeft;
509 pChar = rLookUpText.getLength() ? rLookUpText.getStr() + rLookUpText.getLength() - 1 : nullptr;
510 sal_Int32 nRight = 0;
511 while (pChar && *pChar-- == CH_TXTATR_INWORD)
512 ++nRight;
513
514 // adjust existing selection
515 SwPaM *pCursor = m_pWrtShell->GetCursor();
516 pCursor->GetPoint()->AdjustContent(-nRight);
517 pCursor->GetMark()->AdjustContent(nLeft);
518 }
519
520 m_pWrtShell->Insert( rSynonmText );
521
523 m_pWrtShell->EndAllAction();
524
525 m_pWrtShell->SetInsMode( bOldIns );
526}
527
528// Start thesaurus
529
531{
533 return;
534
535 SfxErrorContext aContext( ERRCTX_SVX_LINGU_THESAURUS, OUString(), m_pEditWin->GetFrameWeld(),
537
538 // Determine language
539 LanguageType eLang = m_pWrtShell->GetCurLang();
540 if( LANGUAGE_SYSTEM == eLang )
541 eLang = GetAppLanguage();
542
543 if( eLang == LANGUAGE_DONTKNOW || eLang == LANGUAGE_NONE )
544 {
546 return;
547 }
548
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
553
554 // get initial LookUp text
555 const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection();
556 OUString aTmp = GetThesaurusLookUpText( bSelection );
557
558 Reference< XThesaurus > xThes( ::GetThesaurus() );
559
560 if ( !xThes.is() || !xThes->hasLocale( LanguageTag::convertToLocale( eLang ) ) )
561 SpellError( eLang );
562 else
563 {
565 // create dialog
566 { //Scope for SwWait-Object
567 SwWait aWait( *GetDocShell(), true );
568 // load library with dialog only on demand ...
570 pDlg.reset(pFact->CreateThesaurusDialog(GetEditWin().GetFrameWeld(), xThes, aTmp, eLang));
571 }
572
573 if (pDlg)
574 {
575 guard.dismiss(); // ignore, we'll call SetIdle() explicitly after the dialog ends
576
577 pDlg->StartExecuteAsync([aTmp, bSelection, bOldIdle, pDlg, pVOpt, this](sal_Int32 nResult){
578 if (nResult == RET_OK )
579 InsertThesaurusSynonym(pDlg->GetWord(), aTmp, bSelection);
580
581 pVOpt->SetIdle(bOldIdle);
582 pDlg->disposeOnce();
583 });
584 }
585 }
586}
587
588// Offer online suggestions
589
590namespace {
591
593struct ExecuteInfo
594{
595 uno::Reference< frame::XDispatch > xDispatch;
596 util::URL aTargetURL;
597 uno::Sequence< PropertyValue > aArgs;
598};
599
600class AsyncExecute
601{
602public:
603 DECL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, void*, void );
604};
605
606}
607
608IMPL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, void*, p, void )
609{
610 ExecuteInfo* pExecuteInfo = static_cast<ExecuteInfo*>(p);
611 SolarMutexReleaser aReleaser;
612 try
613 {
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 );
618 }
619 catch (const Exception&)
620 {
621 }
622
623 delete pExecuteInfo;
624}
626
628{
629 bool bRet = false;
630 const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
631 if( pVOpt->IsOnlineSpell() &&
632 !m_pWrtShell->IsSelection())
633 {
634 if (m_pWrtShell->GetSelectionType() & SelectionType::DrawObjectEditMode)
635 bRet = ExecDrwTextSpellPopup(rPt);
636 else if (!m_pWrtShell->IsSelFrameMode())
637 {
638 const bool bOldViewLock = m_pWrtShell->IsViewLocked();
639 m_pWrtShell->LockView( true );
641 m_pWrtShell->Push();
642 SwRect aToFill;
643
644 SwCursorShell *pCursorShell = m_pWrtShell.get();
645 SwPaM *pCursor = pCursorShell->GetCursor();
646 SwPosition aPoint(*pCursor->GetPoint());
647 const SwTextNode *pNode = aPoint.GetNode().GetTextNode();
648
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())
655 {
656 std::pair<Point, bool> const tmp(rPt, false);
657 SwContentFrame *const pContentFrame = pCursor->GetPointContentNode()->getLayoutFrame(
658 pCursorShell->GetLayout(),
659 &aPoint, &tmp);
660 if (pContentFrame)
661 {
662 SwRect aRepaint(static_cast<SwTextFrame*>(pContentFrame)->AutoSpell_(
663 *pCursor->GetPointContentNode()->GetTextNode(), 0));
664 if (aRepaint.HasArea())
665 m_pWrtShell->InvalidateWindows(aRepaint);
666 }
667 }
668
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())
679 {
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());
689 }
690
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()))
694 {
695 // get paragraph text
696 OUString aParaText;
697 if (pNode)
698 {
699 pCursorShell->Push();
700 if (!pCursorShell->IsSttPara())
701 {
702 pCursorShell->MovePara(GoCurrPara, fnParaStart);
703 }
704 pCursorShell->SetMark();
705 if (!pCursorShell->IsEndPara())
706 {
707 pCursorShell->MovePara(GoCurrPara, fnParaEnd);
708 }
709 aParaText = pCursorShell->GetSelText();
711 }
712 else
713 {
714 OSL_FAIL("text node expected but not found" );
715 }
716
717 bRet = true;
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 );
724
726 aEvent.ExecutePosition.X = aPixPos.X();
727 aEvent.ExecutePosition.Y = aPixPos.Y();
729
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))
734 {
737 if (xMenu.is())
738 {
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() )
744 {
745 if (!ExecuteMenuCommand(xMenu, GetViewFrame(), nId))
746 xPopup->Execute(nId);
747 }
748 else
749 {
750 SfxViewFrame& rSfxViewFrame = GetViewFrame();
751 uno::Reference<frame::XFrame> xFrame = rSfxViewFrame.GetFrame().GetFrameInterface();
752 css::util::URL aURL;
753 uno::Reference< frame::XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
754
755 try
756 {
757 uno::Reference< frame::XDispatch > xDispatch;
758 uno::Reference< util::XURLTransformer > xURLTransformer = util::URLTransformer::create(comphelper::getProcessComponentContext());
759
760 aURL.Complete = aCommand;
761 xURLTransformer->parseStrict(aURL);
762 uno::Sequence< beans::PropertyValue > aArgs;
763 xDispatch = xDispatchProvider->queryDispatch( aURL, OUString(), 0 );
764
765 if (xDispatch.is())
766 {
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 );
773 }
774 }
775 catch (const Exception&)
776 {
777 }
778 }
779 }
780 else
781 {
783 {
784 if (SfxViewShell* pViewShell = SfxViewShell::Current())
785 {
786 boost::property_tree::ptree aMenu = SfxDispatcher::fillPopupMenu(xMenuInterface);
787 boost::property_tree::ptree aRoot;
788 aRoot.add_child("menu", aMenu);
789
790 std::stringstream aStream;
791 boost::property_tree::write_json(aStream, aRoot, true);
792 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU, OString(aStream.str()));
793 }
794 }
795 else
796 {
797 xPopup->Execute(aToFill.SVRect(), m_pEditWin);
798 }
799 }
800 }
801 }
802
805 m_pWrtShell->LockView( bOldViewLock );
806 }
807 }
808 return bRet;
809}
810
817{
818 const bool bOldViewLock = m_pWrtShell->IsViewLocked();
819 m_pWrtShell->LockView( true );
820 m_pWrtShell->Push();
821
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" ) ))
825 };
826
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 );
831
832 css::uno::Reference< css::awt::XPopupMenu > xPopupMenu( xContext->getServiceManager()->createInstanceWithContext(
833 "com.sun.star.awt.PopupMenu", xContext ), css::uno::UNO_QUERY );
834
835 if ( xPopupController.is() && xPopupMenu.is() )
836 {
837 xPopupController->setPopupMenu( xPopupMenu );
838
839 SwRect aToFill;
840 m_pWrtShell->GetSmartTagRect( rPt, aToFill );
841 m_pWrtShell->SttSelect();
842
843 if ( aToFill.HasArea() )
844 xPopupMenu->execute( m_pEditWin->GetComponentInterface(),
845 VCLUnoHelper::ConvertToAWTRect( m_pEditWin->LogicToPixel( aToFill.SVRect() ) ), css::awt::PopupMenuDirection::EXECUTE_DOWN );
846
847 css::uno::Reference< css::lang::XComponent > xComponent( xPopupController, css::uno::UNO_QUERY );
848 if ( xComponent.is() )
849 xComponent->dispose();
850 }
851
853 m_pWrtShell->LockView( bOldViewLock );
854}
855
856/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
AnyEventRef aEvent
static ImplSVEvent * PostUserEvent(const Link< void *, void > &rLink, void *pCaller=nullptr, bool bReferenceLink=false)
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
static DialogMask HandleError(ErrCode nId, weld::Window *pParent=nullptr, DialogMask nMask=DialogMask::MAX)
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
static vcl::Font GetDefaultFont(DefaultFontType nType, LanguageType eLang, GetDefaultFontFlags nFlags, const OutputDevice *pOutDev=nullptr)
constexpr tools::Long Y() const
constexpr tools::Long X() const
static boost::property_tree::ptree fillPopupMenu(const rtl::Reference< VCLXPopupMenu > &rMenu)
const css::uno::Reference< css::frame::XFrame > & GetFrameInterface() const
sal_uInt16 GetSlot() const
void Ignore()
weld::Window * GetFrameWeld() const
SfxViewFrame * GetFrame() const
SfxFrame & GetFrame() const
weld::Window * GetFrameWeld() const
SfxViewFrame & GetViewFrame() const
bool TryContextMenuInterception(const rtl::Reference< VCLXPopupMenu > &rIn, const OUString &rMenuIdentifier, rtl::Reference< VCLXPopupMenu > &rOut, css::ui::ContextMenuExecuteEvent aEvent)
static SAL_WARN_UNUSED_RESULT SfxViewShell * Current()
static OUString GetLanguageString(const LanguageType eType)
static SvxAbstractDialogFactory * Create()
void SpellDocument()
SwContentFrame is the layout for content nodes: a common base class for text (paragraph) and non-text...
Definition: cntfrm.hxx:59
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1223
bool Pop(PopMode, ::std::optional< SwCallLink > &roLink)
void Push()
store a copy of the current cursor on the cursor stack
Definition: crsrsh.cxx:2550
bool MovePara(SwWhichPara, SwMoveFnCollection const &)
Definition: crsrsh.cxx:982
bool IsEndPara() const
Definition: crsrsh.cxx:1400
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:194
OUString GetSelText() const
get selected text of a node at current cursor
Definition: crsrsh.cxx:2862
bool IsSttPara() const
Definition: crsrsh.cxx:1381
void SetMark()
Definition: crsrsh.hxx:906
bool IsTableMode() const
Definition: crsrsh.hxx:668
static bool HasConvIter()
Is text conversion active somewhere else?
Definition: edlingu.cxx:615
static bool HasHyphIter()
Is hyphenation active somewhere else?
Definition: edlingu.cxx:620
Window class for the Writer edit area, this is the one handling mouse and keyboard events and doing t...
Definition: edtwin.hxx:61
void Convert()
Definition: hhcwrp.cxx:503
Marks a node in the document model.
Definition: ndindex.hxx:31
SwNode & GetNode() const
Definition: ndindex.hxx:123
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
bool IsTextNode() const
Definition: node.hxx:190
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:188
const SwPosition * GetMark() const
Definition: pam.hxx:255
bool IsMultiSelection() const
Definition: pam.hxx:322
SwContentNode * GetPointContentNode() const
Definition: pam.hxx:279
const SwPosition * GetPoint() const
Definition: pam.hxx:253
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:251
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
bool HasArea() const
Definition: swrect.hxx:300
tools::Rectangle SVRect() const
Definition: swrect.hxx:292
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:168
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
bool IsWrongDirty() const
Definition: txtedt.cxx:2355
const OUString & GetText() const
Definition: ndtxt.hxx:244
void SetIdle(bool b) const
Definition: viewopt.hxx:339
bool IsIdle() const
Definition: viewopt.hxx:332
bool IsOnlineSpell() const
Definition: viewopt.hxx:537
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2163
bool ExecDrwTextSpellPopup(const Point &rPt)
Definition: viewdraw.cxx:717
virtual bool HasSelection(bool bText=true) const override
Definition: view.cxx:1668
SfxDispatcher & GetDispatcher()
Definition: view.cxx:136
std::unique_ptr< SwWrtShell > m_pWrtShell
Definition: view.hxx:194
void ExecLingu(SfxRequest &)
Definition: viewling.cxx:94
SAL_DLLPRIVATE void HyphenateDrawText()
Definition: viewdraw.cxx:746
bool ExecSpellPopup(const Point &rPt)
! End of extra code for context menu modifying extensions
Definition: viewling.cxx:627
VclPtr< SwEditWin > m_pEditWin
Definition: view.hxx:193
SAL_DLLPRIVATE void StartThesaurus()
Definition: viewling.cxx:530
SAL_DLLPRIVATE void SpellContext(bool bOn=true)
Definition: view.hxx:332
SAL_DLLPRIVATE void HyphenateDocument()
Definition: viewling.cxx:399
OUString GetThesaurusLookUpText(bool bSelection) const
Definition: viewling.cxx:481
SwEditWin & GetEditWin()
Definition: view.hxx:426
SAL_DLLPRIVATE void SpellStart(SvxSpellArea eSpell, bool bStartDone, bool bEndDone, SwConversionArgs *pConvArgs)
Definition: viewling.cxx:263
void ExecSmartTagPopup(const Point &rPt)
Function: ExecSmartTagPopup.
Definition: viewling.cxx:816
SwDocShell * GetDocShell()
Definition: view.cxx:1193
SAL_DLLPRIVATE void HyphStart(SvxSpellArea eSpell)
Definition: viewling.cxx:376
void SpellError(LanguageType eLang)
Definition: viewling.cxx:324
SAL_DLLPRIVATE void StartTextConversion(LanguageType nSourceLang, LanguageType nTargetLang, const vcl::Font *pTargetFont, sal_Int32 nOptions, bool bIsInteractive)
Definition: viewling.cxx:219
SAL_DLLPRIVATE void SpellEnd(SwConversionArgs const *pConvArgs)
Definition: viewling.cxx:369
void InsertThesaurusSynonym(const OUString &rSynonmText, const OUString &rLookUpText, bool bValidSelection)
Definition: viewling.cxx:486
bool IsValidSelectionForThesaurus() const
Definition: viewling.cxx:471
static css::awt::Rectangle ConvertToAWTRect(::tools::Rectangle const &_rRect)
static css::uno::Reference< css::awt::XWindow > GetInterface(vcl::Window *pWindow)
void reset(reference_type *pBody)
Point LogicToPixel(const Point &rLogicPt) const
void LeaveWait()
bool IsWait() const
void EnterWait()
#define FN_HYPHENATE_OPT_DLG
Definition: cmdid.h:520
SwDocPositions
Definition: cshtyp.hxx:104
SVXCORE_DLLPUBLIC std::locale SvxResLocale()
Reference< XDispatch > xDispatch
URL aURL
#define ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS
#define CH_TXTATR_INWORD
Definition: hintids.hxx:175
LanguageType GetAppLanguage()
Definition: init.cxx:741
void * p
#define LANGUAGE_SYSTEM
#define LANGUAGE_CHINESE_TRADITIONAL
#define LANGUAGE_NONE
#define LANGUAGE_CHINESE_SIMPLIFIED
#define LANGUAGE_KOREAN
#define LANGUAGE_DONTKNOW
Sequence< sal_Int8 > aSeq
@ Exception
css::uno::Sequence< css::uno::Any > InitAnyPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
Reference< XComponentContext > getProcessComponentContext()
css::beans::PropertyValue makePropertyValue(const OUString &rName, T &&rValue)
sal_Int16 nId
bool GoCurrPara(SwPaM &rPam, SwMoveFnCollection const &aPosPara)
Definition: pam.cxx:1248
SwMoveFnCollection const & fnParaStart
Definition: paminit.cxx:48
SwMoveFnCollection const & fnParaEnd
Definition: paminit.cxx:49
Marks a position in the document model.
Definition: pam.hxx:38
SwNode & GetNode() const
Definition: pam.hxx:81
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
void AdjustContent(sal_Int32 nDelta)
Adjust content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:262
Reference< XFrame > xFrame
SvxSpellArea
SVX_DLLPUBLIC const ErrMsgCode RID_SVXERRCTX[]
#define ERRCODE_SVX_LINGU_NOLANGUAGE
#define ERRCTX_SVX_LINGU_HYPHENATION
#define ERRCODE_SVX_LINGU_LINGUNOTEXISTS
#define ERRCTX_SVX_LINGU_THESAURUS
OUString SwResId(TranslateId aId)
Definition: swmodule.cxx:168
uno::Reference< linguistic2::XLinguProperties > GetLinguPropertySet()
Definition: swtypes.cxx:61
uno::Reference< linguistic2::XThesaurus > GetThesaurus()
Definition: swtypes.cxx:59
uno::Reference< linguistic2::XHyphenator > GetHyphenator()
Definition: swtypes.cxx:57
OUString aCommand
sal_uInt16 sal_Unicode
OUString aTargetURL
bool ExecuteMenuCommand(const css::uno::Reference< css::awt::XPopupMenu > &rMenu, const SfxViewFrame &rViewFrame, sal_uInt16 nId)
Definition: uitool.cxx:883
RET_OK
RET_YES
IMPL_STATIC_LINK(AsyncExecute, ExecuteHdl_Impl, void *, p, void)
Definition: viewling.cxx:608
const char * pChar