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/util/URL.hpp>
69#include <com/sun/star/beans/PropertyValue.hpp>
70#include <com/sun/star/beans/XPropertySet.hpp>
71#include <com/sun/star/util/URLTransformer.hpp>
72#include <com/sun/star/util/XURLTransformer.hpp>
73
74#include <vcl/svapp.hxx>
75#include <rtl/ustring.hxx>
76
78#include <svtools/langtab.hxx>
79
80#include <editeng/editerr.hxx>
81#include <LibreOfficeKit/LibreOfficeKitEnums.h>
82
83#include <memory>
84
85using namespace sw::mark;
86using namespace ::com::sun::star;
87using namespace ::com::sun::star::beans;
88using namespace ::com::sun::star::uno;
89using namespace ::com::sun::star::linguistic2;
90
91// Lingu-Dispatcher
92
94{
95 switch(rReq.GetSlot())
96 {
97 case SID_THESAURUS:
99 rReq.Ignore();
100 break;
101 case SID_HANGUL_HANJA_CONVERSION:
103 i18n::TextConversionOption::CHARACTER_BY_CHARACTER, true );
104 break;
105 case SID_CHINESE_CONVERSION:
106 {
107 //open ChineseTranslationDialog
108 Reference< XComponentContext > xContext(
109 ::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one
110 if(xContext.is())
111 {
112 Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
113 if(xMCF.is())
114 {
115 Reference< ui::dialogs::XExecutableDialog > xDialog(
116 xMCF->createInstanceWithContext(
117 "com.sun.star.linguistic2.ChineseTranslationDialog", xContext),
118 UNO_QUERY);
119 Reference< lang::XInitialization > xInit( xDialog, UNO_QUERY );
120 if( xInit.is() )
121 {
122 Reference<awt::XWindow> xParentWindow;
123 if (weld::Window* pParentWindow = rReq.GetFrameWeld())
124 xParentWindow = pParentWindow->GetXWindow();
125 // initialize dialog
126 uno::Sequence<uno::Any> aSeq(comphelper::InitAnyPropertySequence(
127 {
128 {"ParentWindow", uno::Any(xParentWindow)}
129 }));
130 xInit->initialize( aSeq );
131
132 //execute dialog
133 sal_Int16 nDialogRet = xDialog->execute();
134 if( RET_OK == nDialogRet )
135 {
136 //get some parameters from the dialog
137 bool bToSimplified = true;
138 bool bUseVariants = true;
139 bool bCommonTerms = true;
140 Reference< beans::XPropertySet > xProp( xDialog, UNO_QUERY );
141 if( xProp.is() )
142 {
143 try
144 {
145 xProp->getPropertyValue( "IsDirectionToSimplified" ) >>= bToSimplified;
146 xProp->getPropertyValue( "IsUseCharacterVariants" ) >>= bUseVariants;
147 xProp->getPropertyValue( "IsTranslateCommonTerms" ) >>= bCommonTerms;
148 }
149 catch (const Exception&)
150 {
151 }
152 }
153
154 //execute translation
157 sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0;
158 if( !bCommonTerms )
159 nOptions = nOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
160
161 vcl::Font aTargetFont = OutputDevice::GetDefaultFont( DefaultFontType::CJK_TEXT,
162 nTargetLang, GetDefaultFontFlags::OnlyOne );
163
164 // disallow formatting, updating the view, ... while
165 // converting the document. (saves time)
166 // Also remember the current view and cursor position for later
167 m_pWrtShell->StartAction();
168
169 // remember cursor position data for later restoration of the cursor
170 const SwPosition *pPoint = m_pWrtShell->GetCursor()->GetPoint();
171 bool bRestoreCursor = pPoint->GetNode().IsTextNode();
172 const SwNodeIndex aPointNodeIndex( pPoint->GetNode() );
173 sal_Int32 nPointIndex = pPoint->GetContentIndex();
174
175 // since this conversion is not interactive the whole converted
176 // document should be undone in a single undo step.
177 m_pWrtShell->StartUndo( SwUndoId::OVERWRITE );
178
179 StartTextConversion( nSourceLang, nTargetLang, &aTargetFont, nOptions, false );
180
182
183 if (bRestoreCursor)
184 {
185 SwTextNode *pTextNode = aPointNodeIndex.GetNode().GetTextNode();
186 // check for unexpected error case
187 OSL_ENSURE(pTextNode && pTextNode->GetText().getLength() >= nPointIndex,
188 "text missing: corrupted node?" );
189 // restore cursor to its original position
190 if (!pTextNode || pTextNode->GetText().getLength() < nPointIndex)
191 m_pWrtShell->GetCursor()->GetPoint()->Assign( aPointNodeIndex );
192 else
193 m_pWrtShell->GetCursor()->GetPoint()->Assign( *pTextNode, nPointIndex );
194 }
195
196 // enable all, restore view and cursor position
197 m_pWrtShell->EndAction();
198 }
199 }
200 Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY );
201 if( xComponent.is() )
202 xComponent->dispose();
203 }
204 }
205 break;
206 }
209 break;
210 default:
211 OSL_ENSURE(false, "wrong Dispatcher");
212 return;
213 }
214}
215
216// start language specific text conversion
217
219 LanguageType nSourceLang,
220 LanguageType nTargetLang,
221 const vcl::Font *pTargetFont,
222 sal_Int32 nOptions,
223 bool bIsInteractive )
224{
225 // do not do text conversion if it is active elsewhere
227 {
228 return;
229 }
230
231 SpellContext();
232
233 const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
234 const bool bOldIdle = pVOpt->IsIdle();
235 pVOpt->SetIdle( false );
236
237 bool bOldIns = m_pWrtShell->IsInsMode();
238 m_pWrtShell->SetInsMode();
239
240 const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection() ||
241 m_pWrtShell->GetCursor() != m_pWrtShell->GetCursor()->GetNext();
242
243 const bool bStart = bSelection || m_pWrtShell->IsStartOfDoc();
244 const bool bOther = !bSelection && !(m_pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY);
245
246 {
247 const uno::Reference< uno::XComponentContext > xContext(
249 SwHHCWrapper aWrap( this, xContext, nSourceLang, nTargetLang, pTargetFont,
250 nOptions, bIsInteractive,
251 bStart, bOther, bSelection );
252 aWrap.Convert();
253 }
254
255 m_pWrtShell->SetInsMode( bOldIns );
256 pVOpt->SetIdle( bOldIdle );
257 SpellContext(false);
258}
259
260// spellcheck and text conversion related stuff
261
263 bool bStartDone, bool bEndDone,
264 SwConversionArgs *pConvArgs )
265{
266 Reference< XLinguProperties > xProp = ::GetLinguPropertySet();
267 bool bIsWrapReverse = !pConvArgs && xProp.is() && xProp->getIsWrapReverse();
268
272 switch ( eWhich )
273 {
274 case SvxSpellArea::Body:
275 if( bIsWrapReverse )
276 eCurr = SwDocPositions::End;
277 else
278 eCurr = SwDocPositions::Start;
279 break;
280 case SvxSpellArea::BodyEnd:
281 if( bIsWrapReverse )
282 {
283 if( bStartDone )
284 eStart = SwDocPositions::Curr;
285 eCurr = SwDocPositions::End;
286 }
287 else if( bStartDone )
288 eCurr = SwDocPositions::Start;
289 break;
290 case SvxSpellArea::BodyStart:
291 if( !bIsWrapReverse )
292 {
293 if( bEndDone )
295 eCurr = SwDocPositions::Start;
296 }
297 else if( bEndDone )
298 eCurr = SwDocPositions::End;
299 break;
300 case SvxSpellArea::Other:
301 if( bIsWrapReverse )
302 {
306 }
307 else
308 {
312 }
313 break;
314 default:
315 OSL_ENSURE( false, "SpellStart with unknown Area" );
316 }
317 m_pWrtShell->SpellStart( eStart, eEnd, eCurr, pConvArgs );
318}
319
320// Error message while Spelling
321
322// The passed pointer nlang is itself the value
324{
325 int nPend = 0;
326
327 if ( m_pWrtShell->ActionPend() )
328 {
329 m_pWrtShell->Push();
330 m_pWrtShell->ClearMark();
331 do
332 {
333 m_pWrtShell->EndAction();
334 ++nPend;
335 }
336 while( m_pWrtShell->ActionPend() );
337 }
338 OUString aErr(SvtLanguageTable::GetLanguageString( eLang ) );
339
340 SwEditWin &rEditWin = GetEditWin();
341 int nWaitCnt = 0;
342 while( rEditWin.IsWait() )
343 {
344 rEditWin.LeaveWait();
345 ++nWaitCnt;
346 }
347 if ( LANGUAGE_NONE == eLang )
349 else
351
352 while( nWaitCnt )
353 {
354 rEditWin.EnterWait();
355 --nWaitCnt;
356 }
357
358 if ( nPend )
359 {
360 while( nPend-- )
361 m_pWrtShell->StartAction();
362 m_pWrtShell->Combine();
363 }
364}
365
366// Finish spelling and restore cursor
367
368void SwView::SpellEnd( SwConversionArgs const *pConvArgs )
369{
370 m_pWrtShell->SpellEnd( pConvArgs );
371 if( m_pWrtShell->IsExtMode() )
372 m_pWrtShell->SetMark();
373}
374
376{
377 switch ( eWhich )
378 {
379 case SvxSpellArea::Body:
381 break;
382 case SvxSpellArea::BodyEnd:
384 break;
385 case SvxSpellArea::BodyStart:
387 break;
388 case SvxSpellArea::Other:
390 break;
391 default:
392 OSL_ENSURE( false, "HyphStart with unknown Area" );
393 }
394}
395
396// Interactive separation
397
399{
400 // do not hyphenate if interactive hyphenation is active elsewhere
402 {
403 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
404 VclMessageType::Warning, VclButtonsType::Ok, SwResId(STR_MULT_INTERACT_HYPH_WARN)));
405 xBox->set_title(SwResId(STR_HYPH_TITLE));
406 xBox->run();
407 return;
408 }
409
410 SfxErrorContext aContext( ERRCTX_SVX_LINGU_HYPHENATION, OUString(), m_pEditWin->GetFrameWeld(),
412
413 Reference< XHyphenator > xHyph( ::GetHyphenator() );
414 if (!xHyph.is())
415 {
417 return;
418 }
419
421 {
422 // Hyphenation in a Draw object
424 }
425 else
426 {
427 SwViewOption* pVOpt = const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions());
428 bool bOldIdle = pVOpt->IsIdle();
429 pVOpt->SetIdle( false );
430
431 Reference< XLinguProperties > xProp( ::GetLinguPropertySet() );
432
433 m_pWrtShell->StartUndo(SwUndoId::INSATTR); // valid later
434
435 bool bHyphSpecial = xProp.is() && xProp->getIsHyphSpecial();
436 bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection() ||
437 m_pWrtShell->GetCursor() != m_pWrtShell->GetCursor()->GetNext();
438 bool bOther = m_pWrtShell->HasOtherCnt() && bHyphSpecial && !bSelection;
439 bool bStart = bSelection || ( !bOther && m_pWrtShell->IsStartOfDoc() );
440 bool bStop = false;
441 if( !bOther && !(m_pWrtShell->GetFrameType(nullptr,true) & FrameTypeFlags::BODY) && !bSelection )
442 // turned on no special area
443 {
444 // I want also in special areas hyphenation
445 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(GetEditWin().GetFrameWeld(),
446 VclMessageType::Question, VclButtonsType::YesNo,
447 SwResId(STR_QUERY_SPECIAL_FORCED)));
448 if (xBox->run() == RET_YES)
449 {
450 bOther = true;
451 if (xProp.is())
452 {
453 xProp->setIsHyphSpecial( true );
454 }
455 }
456 else
457 bStop = true; // No hyphenation
458 }
459
460 if( !bStop )
461 {
462 SwHyphWrapper aWrap( this, xHyph, bStart, bOther, bSelection );
463 aWrap.SpellDocument();
465 }
466 pVOpt->SetIdle( bOldIdle );
467 }
468}
469
471{
472 // must not be a multi-selection, and if it is a selection it needs
473 // to be within a single paragraph
474
475 const bool bMultiSel = m_pWrtShell->GetCursor()->IsMultiSelection();
476 const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection();
477 return !bMultiSel && (!bSelection || m_pWrtShell->IsSelOnePara() );
478}
479
480OUString SwView::GetThesaurusLookUpText( bool bSelection ) const
481{
482 return bSelection ? m_pWrtShell->GetSelText() : m_pWrtShell->GetCurWord();
483}
484
485void SwView::InsertThesaurusSynonym( const OUString &rSynonmText, const OUString &rLookUpText, bool bSelection )
486{
487 bool bOldIns = m_pWrtShell->IsInsMode();
488 m_pWrtShell->SetInsMode();
489
490 m_pWrtShell->StartAllAction();
491 m_pWrtShell->StartUndo(SwUndoId::DELETE);
492
493 if( !bSelection )
494 {
495 if(m_pWrtShell->IsEndWrd())
496 m_pWrtShell->Left(SwCursorSkipMode::Cells, false, 1, false );
497
498 m_pWrtShell->SelWrd();
499
500 // make sure the selection build later from the data below does not
501 // include "in word" character to the left and right in order to
502 // preserve those. Therefore count those "in words" in order to modify
503 // the selection accordingly.
504 const sal_Unicode* pChar = rLookUpText.getStr();
505 sal_Int32 nLeft = 0;
506 while (*pChar++ == CH_TXTATR_INWORD)
507 ++nLeft;
508 pChar = rLookUpText.getLength() ? rLookUpText.getStr() + rLookUpText.getLength() - 1 : nullptr;
509 sal_Int32 nRight = 0;
510 while (pChar && *pChar-- == CH_TXTATR_INWORD)
511 ++nRight;
512
513 // adjust existing selection
514 SwPaM *pCursor = m_pWrtShell->GetCursor();
515 pCursor->GetPoint()->AdjustContent(-nRight);
516 pCursor->GetMark()->AdjustContent(nLeft);
517 }
518
519 m_pWrtShell->Insert( rSynonmText );
520
522 m_pWrtShell->EndAllAction();
523
524 m_pWrtShell->SetInsMode( bOldIns );
525}
526
527// Start thesaurus
528
530{
532 return;
533
534 SfxErrorContext aContext( ERRCTX_SVX_LINGU_THESAURUS, OUString(), m_pEditWin->GetFrameWeld(),
536
537 // Determine language
538 LanguageType eLang = m_pWrtShell->GetCurLang();
539 if( LANGUAGE_SYSTEM == eLang )
540 eLang = GetAppLanguage();
541
542 if( eLang == LANGUAGE_DONTKNOW || eLang == LANGUAGE_NONE )
543 {
545 return;
546 }
547
548 SwViewOption* pVOpt = const_cast<SwViewOption*>(m_pWrtShell->GetViewOptions());
549 const bool bOldIdle = pVOpt->IsIdle();
550 pVOpt->SetIdle( false );
551 comphelper::ScopeGuard guard([&]() { pVOpt->SetIdle(bOldIdle); }); // restore when leaving scope
552
553 // get initial LookUp text
554 const bool bSelection = static_cast<SwCursorShell*>(m_pWrtShell.get())->HasSelection();
555 OUString aTmp = GetThesaurusLookUpText( bSelection );
556
557 Reference< XThesaurus > xThes( ::GetThesaurus() );
558
559 if ( !xThes.is() || !xThes->hasLocale( LanguageTag::convertToLocale( eLang ) ) )
560 SpellError( eLang );
561 else
562 {
564 // create dialog
565 { //Scope for SwWait-Object
566 SwWait aWait( *GetDocShell(), true );
567 // load library with dialog only on demand ...
569 pDlg.reset(pFact->CreateThesaurusDialog(GetEditWin().GetFrameWeld(), xThes, aTmp, eLang));
570 }
571
572 if (pDlg)
573 {
574 guard.dismiss(); // ignore, we'll call SetIdle() explicitly after the dialog ends
575
576 pDlg->StartExecuteAsync([aTmp, bSelection, bOldIdle, pDlg, pVOpt, this](sal_Int32 nResult){
577 if (nResult == RET_OK )
578 InsertThesaurusSynonym(pDlg->GetWord(), aTmp, bSelection);
579
580 pVOpt->SetIdle(bOldIdle);
581 pDlg->disposeOnce();
582 });
583 }
584 }
585}
586
587// Offer online suggestions
588
589namespace {
590
592struct ExecuteInfo
593{
594 uno::Reference< frame::XDispatch > xDispatch;
595 util::URL aTargetURL;
596 uno::Sequence< PropertyValue > aArgs;
597};
598
599class AsyncExecute
600{
601public:
602 DECL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, void*, void );
603};
604
605}
606
607IMPL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, void*, p, void )
608{
609 ExecuteInfo* pExecuteInfo = static_cast<ExecuteInfo*>(p);
610 SolarMutexReleaser aReleaser;
611 try
612 {
613 // Asynchronous execution as this can lead to our own destruction!
614 // Framework can recycle our current frame and the layout manager disposes all user interface
615 // elements if a component gets detached from its frame!
616 pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
617 }
618 catch (const Exception&)
619 {
620 }
621
622 delete pExecuteInfo;
623}
625
626bool SwView::ExecSpellPopup(const Point& rPt)
627{
628 bool bRet = false;
629 const SwViewOption* pVOpt = m_pWrtShell->GetViewOptions();
630 if( pVOpt->IsOnlineSpell() &&
631 !m_pWrtShell->IsSelection())
632 {
633 if (m_pWrtShell->GetSelectionType() & SelectionType::DrawObjectEditMode)
634 bRet = ExecDrwTextSpellPopup(rPt);
635 else if (!m_pWrtShell->IsSelFrameMode())
636 {
637 const bool bOldViewLock = m_pWrtShell->IsViewLocked();
638 m_pWrtShell->LockView( true );
639 m_pWrtShell->Push();
640 SwRect aToFill;
641
642 SwCursorShell *pCursorShell = m_pWrtShell.get();
643 SwPaM *pCursor = pCursorShell->GetCursor();
644 SwPosition aPoint(*pCursor->GetPoint());
645 const SwTextNode *pNode = aPoint.GetNode().GetTextNode();
646
647 // Spell-check in case the idle jobs haven't had a chance to kick in.
648 // This makes it possible to suggest spelling corrections for
649 // wrong words independent of the spell-checking idle job.
650 if (pNode && pNode->IsWrongDirty() &&
651 !pCursorShell->IsTableMode() &&
652 !pCursor->HasMark() && !pCursor->IsMultiSelection())
653 {
654 std::pair<Point, bool> const tmp(rPt, false);
655 SwContentFrame *const pContentFrame = pCursor->GetPointContentNode()->getLayoutFrame(
656 pCursorShell->GetLayout(),
657 &aPoint, &tmp);
658 if (pContentFrame)
659 {
660 SwRect aRepaint(static_cast<SwTextFrame*>(pContentFrame)->AutoSpell_(
661 *pCursor->GetPointContentNode()->GetTextNode(), 0));
662 if (aRepaint.HasArea())
663 m_pWrtShell->InvalidateWindows(aRepaint);
664 }
665 }
666
667 // decide which variant of the context menu to use...
668 // if neither spell checking nor grammar checking provides suggestions use the
669 // default context menu.
670 bool bUseGrammarContext = false;
671 Reference< XSpellAlternatives > xAlt( m_pWrtShell->GetCorrection(&rPt, aToFill) );
672 ProofreadingResult aGrammarCheckRes;
673 sal_Int32 nErrorInResult = -1;
674 uno::Sequence< OUString > aSuggestions;
675 bool bCorrectionRes = false;
676 if (!xAlt.is() || !xAlt->getAlternatives().hasElements())
677 {
678 sal_Int32 nErrorPosInText = -1;
679 bCorrectionRes = m_pWrtShell->GetGrammarCorrection( aGrammarCheckRes, nErrorPosInText, nErrorInResult, aSuggestions, &rPt, aToFill );
680 OUString aMessageText;
681 if (nErrorInResult >= 0)
682 aMessageText = aGrammarCheckRes.aErrors[ nErrorInResult ].aShortComment;
683 // we like to use the grammar checking context menu if we either get
684 // some suggestions or at least a comment about the error found...
685 bUseGrammarContext = bCorrectionRes &&
686 (aSuggestions.hasElements() || !aMessageText.isEmpty());
687 }
688
689 // open respective context menu for spell check or grammar errors with correction suggestions...
690 if ((!bUseGrammarContext && xAlt.is()) ||
691 (bUseGrammarContext && bCorrectionRes && aGrammarCheckRes.aErrors.hasElements()))
692 {
693 // get paragraph text
694 OUString aParaText;
695 if (pNode)
696 {
697 pCursorShell->Push();
698 if (!pCursorShell->IsSttPara())
699 {
700 pCursorShell->MovePara(GoCurrPara, fnParaStart);
701 }
702 pCursorShell->SetMark();
703 if (!pCursorShell->IsEndPara())
704 {
705 pCursorShell->MovePara(GoCurrPara, fnParaEnd);
706 }
707 aParaText = pCursorShell->GetSelText();
709 }
710 else
711 {
712 OSL_FAIL("text node expected but not found" );
713 }
714
715 bRet = true;
716 m_pWrtShell->SttSelect();
717 std::unique_ptr<SwSpellPopup> xPopup(bUseGrammarContext ?
718 new SwSpellPopup(m_pWrtShell.get(), aGrammarCheckRes, nErrorInResult, aSuggestions, aParaText) :
719 new SwSpellPopup(m_pWrtShell.get(), xAlt, aParaText));
720 ui::ContextMenuExecuteEvent aEvent;
721 const Point aPixPos = GetEditWin().LogicToPixel( rPt );
722
724 aEvent.ExecutePosition.X = aPixPos.X();
725 aEvent.ExecutePosition.Y = aPixPos.Y();
726 css::uno::Reference<css::awt::XPopupMenu> xMenu;
727
728 OUString sMenuName = bUseGrammarContext ?
729 OUString("private:resource/GrammarContextMenu") : OUString("private:resource/SpellContextMenu");
730 auto xMenuInterface = xPopup->CreateMenuInterface();
731 if (TryContextMenuInterception(xMenuInterface, sMenuName, xMenu, aEvent))
732 {
735 if (xMenu.is())
736 {
737 css::uno::Reference<css::awt::XWindowPeer> xParent(aEvent.SourceWindow, css::uno::UNO_QUERY);
738 const sal_uInt16 nId = xMenu->execute(xParent, css::awt::Rectangle(aPixPos.X(), aPixPos.Y(), 1, 1),
739 css::awt::PopupMenuDirection::EXECUTE_DOWN);
740 OUString aCommand = xMenu->getCommand(nId);
741 if (aCommand.isEmpty() )
742 {
743 if (!ExecuteMenuCommand(xMenu, *GetViewFrame(), nId))
744 xPopup->Execute(nId);
745 }
746 else
747 {
748 SfxViewFrame *pSfxViewFrame = GetViewFrame();
749 uno::Reference< frame::XFrame > xFrame;
750 if ( pSfxViewFrame )
751 xFrame = pSfxViewFrame->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, aStream.str().c_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
816void SwView::ExecSmartTagPopup( const Point& rPt )
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, bool bMobile=false)
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)
static boost::property_tree::ptree fillPopupMenu(const css::uno::Reference< css::awt::XPopupMenu > &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
bool TryContextMenuInterception(const css::uno::Reference< css::awt::XPopupMenu > &rIn, const OUString &rMenuIdentifier, css::uno::Reference< css::awt::XPopupMenu > &rOut, css::ui::ContextMenuExecuteEvent aEvent)
SfxViewFrame * GetViewFrame() const
static 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:58
SwContentFrame * getLayoutFrame(const SwRootFrame *, const SwPosition *pPos=nullptr, std::pair< Point, bool > const *pViewPosAndCalcFrame=nullptr) const
Definition: node.cxx:1224
bool Pop(PopMode, ::std::optional< SwCallLink > &roLink)
void Push()
store a copy of the current cursor on the cursor stack
Definition: crsrsh.cxx:2246
bool MovePara(SwWhichPara, SwMoveFnCollection const &)
Definition: crsrsh.cxx:695
bool IsEndPara() const
Definition: crsrsh.cxx:1113
SwCursor * GetCursor(bool bMakeTableCursor=true) const
Return pointer to the current shell cursor.
Definition: crsrsh.cxx:193
OUString GetSelText() const
get selected text of a node at current cursor
Definition: crsrsh.cxx:2554
bool IsSttPara() const
Definition: crsrsh.cxx:1094
void SetMark()
Definition: crsrsh.hxx:895
bool IsTableMode() const
Definition: crsrsh.hxx:659
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:136
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:877
bool IsTextNode() const
Definition: node.hxx:665
PaM is Point and Mark: a selection of the document model.
Definition: pam.hxx:187
const SwPosition * GetMark() const
Definition: pam.hxx:263
bool IsMultiSelection() const
Definition: pam.hxx:328
SwContentNode * GetPointContentNode() const
Definition: pam.hxx:287
const SwPosition * GetPoint() const
Definition: pam.hxx:261
bool HasMark() const
A PaM marks a selection if Point and Mark are distinct positions.
Definition: pam.hxx:259
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:165
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:89
bool IsWrongDirty() const
Definition: txtedt.cxx:2320
const OUString & GetText() const
Definition: ndtxt.hxx:227
void SetIdle(bool b) const
Definition: viewopt.hxx:216
bool IsIdle() const
Definition: viewopt.hxx:209
bool IsOnlineSpell() const
Definition: viewopt.hxx:371
SwRootFrame * GetLayout() const
Definition: viewsh.cxx:2172
bool ExecDrwTextSpellPopup(const Point &rPt)
Definition: viewdraw.cxx:717
virtual bool HasSelection(bool bText=true) const override
Definition: view.cxx:1651
SfxDispatcher & GetDispatcher()
Definition: view.cxx:135
std::unique_ptr< SwWrtShell > m_pWrtShell
Definition: view.hxx:194
void ExecLingu(SfxRequest &)
Definition: viewling.cxx:93
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:626
VclPtr< SwEditWin > m_pEditWin
Definition: view.hxx:193
SAL_DLLPRIVATE void StartThesaurus()
Definition: viewling.cxx:529
SAL_DLLPRIVATE void SpellContext(bool bOn=true)
Definition: view.hxx:322
SAL_DLLPRIVATE void HyphenateDocument()
Definition: viewling.cxx:398
OUString GetThesaurusLookUpText(bool bSelection) const
Definition: viewling.cxx:480
SwEditWin & GetEditWin()
Definition: view.hxx:416
SAL_DLLPRIVATE void SpellStart(SvxSpellArea eSpell, bool bStartDone, bool bEndDone, SwConversionArgs *pConvArgs)
Definition: viewling.cxx:262
void ExecSmartTagPopup(const Point &rPt)
Function: ExecSmartTagPopup.
Definition: viewling.cxx:816
SwDocShell * GetDocShell()
Definition: view.cxx:1160
SAL_DLLPRIVATE void HyphStart(SvxSpellArea eSpell)
Definition: viewling.cxx:375
void SpellError(LanguageType eLang)
Definition: viewling.cxx:323
SAL_DLLPRIVATE void StartTextConversion(LanguageType nSourceLang, LanguageType nTargetLang, const vcl::Font *pTargetFont, sal_Int32 nOptions, bool bIsInteractive)
Definition: viewling.cxx:218
SAL_DLLPRIVATE void SpellEnd(SwConversionArgs const *pConvArgs)
Definition: viewling.cxx:368
void InsertThesaurusSynonym(const OUString &rSynonmText, const OUString &rLookUpText, bool bValidSelection)
Definition: viewling.cxx:485
bool IsValidSelectionForThesaurus() const
Definition: viewling.cxx:470
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:501
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:171
LanguageType GetAppLanguage()
Definition: init.cxx:725
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:1218
SwMoveFnCollection const & fnParaStart
Definition: paminit.cxx:48
SwMoveFnCollection const & fnParaEnd
Definition: paminit.cxx:49
Marks a position in the document model.
Definition: pam.hxx:37
SwNode & GetNode() const
Definition: pam.hxx:80
sal_Int32 GetContentIndex() const
Definition: pam.hxx:84
void AdjustContent(sal_Int32 nDelta)
Adjust content index, only valid to call this if the position points to a SwContentNode subclass.
Definition: pam.cxx:261
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:164
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:882
RET_OK
RET_YES
IMPL_STATIC_LINK(AsyncExecute, ExecuteHdl_Impl, void *, p, void)
Definition: viewling.cxx:607
const char * pChar