Line data Source code
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/i18n/TextConversionOption.hpp>
26 : #include <linguistic/lngprops.hxx>
27 : #include <comphelper/processfactory.hxx>
28 : #include <toolkit/helper/vclunohelper.hxx>
29 : #include <vcl/msgbox.hxx>
30 : #include <svtools/ehdl.hxx>
31 : #include <svl/stritem.hxx>
32 : #include <sfx2/viewfrm.hxx>
33 : #include <sfx2/request.hxx>
34 : #include <svx/dlgutil.hxx>
35 : #include <svx/dialmgr.hxx>
36 : #include <editeng/langitem.hxx>
37 : #include <svx/svxerr.hxx>
38 : #include <editeng/unolingu.hxx>
39 : #include <svx/svxdlg.hxx>
40 : #include <editeng/SpellPortions.hxx>
41 : #include <swmodule.hxx>
42 : #include <swwait.hxx>
43 : #include <initui.hxx> // fuer SpellPointer
44 : #include <uitool.hxx>
45 : #include <view.hxx>
46 : #include <wrtsh.hxx>
47 : #include <basesh.hxx>
48 : #include <docsh.hxx> // CheckSpellChanges
49 : #include <viewopt.hxx> // Viewoptions
50 : #include <swundo.hxx> // fuer Undo-Ids
51 : #include <hyp.hxx> // Trennung
52 : #include <olmenu.hxx> // PopupMenu fuer OnlineSpelling
53 : #include <pam.hxx> // Spelling: Multiselektion
54 : #include <edtwin.hxx>
55 : #include <crsskip.hxx>
56 : #include <ndtxt.hxx>
57 : #include <vcl/lstbox.hxx>
58 : #include <cmdid.h>
59 : #include <globals.hrc>
60 : #include <comcore.hrc> // STR_MULT_INTERACT_SPELL_WARN
61 : #include <view.hrc>
62 : #include <hhcwrp.hxx>
63 : #include <com/sun/star/frame/XStorable.hpp>
64 :
65 : #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
66 : #include <com/sun/star/lang/XInitialization.hpp>
67 : #include <com/sun/star/frame/XDispatch.hpp>
68 : #include <com/sun/star/frame/XDispatchProvider.hpp>
69 : #include <com/sun/star/frame/XFrame.hpp>
70 : #include <com/sun/star/util/URL.hpp>
71 : #include <com/sun/star/beans/PropertyValue.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 :
78 : #include <cppuhelper/bootstrap.hxx>
79 : #include "stmenu.hxx" // PopupMenu for smarttags
80 : #include <svx/dialogs.hrc>
81 : #include <svtools/langtab.hxx>
82 : #include <unomid.h>
83 : #include <IMark.hxx>
84 : #include <xmloff/odffields.hxx>
85 :
86 : #include <memory>
87 : #include <editeng/editerr.hxx>
88 :
89 : using namespace sw::mark;
90 : using ::rtl::OUString;
91 : using namespace ::com::sun::star;
92 : using namespace ::com::sun::star::beans;
93 : using namespace ::com::sun::star::uno;
94 : using namespace ::com::sun::star::linguistic2;
95 : using namespace ::com::sun::star::smarttags;
96 :
97 : /*--------------------------------------------------------------------
98 : Beschreibung: Lingu-Dispatcher
99 : --------------------------------------------------------------------*/
100 0 : void SwView::ExecLingu(SfxRequest &rReq)
101 : {
102 0 : switch(rReq.GetSlot())
103 : {
104 : case SID_THESAURUS:
105 0 : StartThesaurus();
106 0 : rReq.Ignore();
107 0 : break;
108 : case SID_HANGUL_HANJA_CONVERSION:
109 : StartTextConversion( LANGUAGE_KOREAN, LANGUAGE_KOREAN, NULL,
110 0 : i18n::TextConversionOption::CHARACTER_BY_CHARACTER, sal_True );
111 0 : break;
112 : case SID_CHINESE_CONVERSION:
113 : {
114 : //open ChineseTranslationDialog
115 : Reference< XComponentContext > xContext(
116 0 : ::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one
117 0 : if(xContext.is())
118 : {
119 0 : Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
120 0 : if(xMCF.is())
121 : {
122 : Reference< ui::dialogs::XExecutableDialog > xDialog(
123 0 : xMCF->createInstanceWithContext(
124 : rtl::OUString("com.sun.star.linguistic2.ChineseTranslationDialog")
125 0 : , xContext), UNO_QUERY);
126 0 : Reference< lang::XInitialization > xInit( xDialog, UNO_QUERY );
127 0 : if( xInit.is() )
128 : {
129 : // initialize dialog
130 0 : Reference< awt::XWindow > xDialogParentWindow(0);
131 0 : Sequence<Any> aSeq(1);
132 0 : Any* pArray = aSeq.getArray();
133 0 : PropertyValue aParam;
134 0 : aParam.Name = rtl::OUString("ParentWindow");
135 0 : aParam.Value <<= makeAny(xDialogParentWindow);
136 0 : pArray[0] <<= makeAny(aParam);
137 0 : xInit->initialize( aSeq );
138 :
139 : //execute dialog
140 0 : sal_Int16 nDialogRet = xDialog->execute();
141 0 : if( RET_OK == nDialogRet )
142 : {
143 : //get some parameters from the dialog
144 0 : sal_Bool bToSimplified = sal_True;
145 0 : sal_Bool bUseVariants = sal_True;
146 0 : sal_Bool bCommonTerms = sal_True;
147 0 : Reference< beans::XPropertySet > xProp( xDialog, UNO_QUERY );
148 0 : if( xProp.is() )
149 : {
150 : try
151 : {
152 0 : xProp->getPropertyValue( "IsDirectionToSimplified" ) >>= bToSimplified;
153 0 : xProp->getPropertyValue( "IsUseCharacterVariants" ) >>= bUseVariants;
154 0 : xProp->getPropertyValue( "IsTranslateCommonTerms" ) >>= bCommonTerms;
155 : }
156 0 : catch (const Exception&)
157 : {
158 : }
159 : }
160 :
161 : //execute translation
162 0 : sal_Int16 nSourceLang = bToSimplified ? LANGUAGE_CHINESE_TRADITIONAL : LANGUAGE_CHINESE_SIMPLIFIED;
163 0 : sal_Int16 nTargetLang = bToSimplified ? LANGUAGE_CHINESE_SIMPLIFIED : LANGUAGE_CHINESE_TRADITIONAL;
164 0 : sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0;
165 0 : if( !bCommonTerms )
166 0 : nOptions = nOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
167 :
168 : Font aTargetFont = GetEditWin().GetDefaultFont( DEFAULTFONT_CJK_TEXT,
169 0 : nTargetLang, DEFAULTFONT_FLAGS_ONLYONE );
170 :
171 : // disallow formatting, updating the view, ... while
172 : // converting the document. (saves time)
173 : // Also remember the current view and cursor position for later
174 0 : pWrtShell->StartAction();
175 :
176 : // remember cursor position data for later restoration of the cursor
177 0 : const SwPosition *pPoint = pWrtShell->GetCrsr()->GetPoint();
178 0 : sal_Bool bRestoreCursor = pPoint->nNode.GetNode().IsTxtNode();
179 0 : const SwNodeIndex aPointNodeIndex( pPoint->nNode );
180 0 : xub_StrLen nPointIndex = pPoint->nContent.GetIndex();
181 :
182 : // since this conversion is not interactive the whole converted
183 : // document should be undone in a single undo step.
184 0 : pWrtShell->StartUndo( UNDO_OVERWRITE );
185 :
186 0 : StartTextConversion( nSourceLang, nTargetLang, &aTargetFont, nOptions, sal_False );
187 :
188 0 : pWrtShell->EndUndo( UNDO_OVERWRITE );
189 :
190 0 : if (bRestoreCursor)
191 : {
192 0 : SwTxtNode *pTxtNode = aPointNodeIndex.GetNode().GetTxtNode();
193 : // check for unexpected error case
194 : OSL_ENSURE( pTxtNode && pTxtNode->GetTxt().Len() >= nPointIndex,
195 : "text missing: corrupted node?" );
196 0 : if (!pTxtNode || pTxtNode->GetTxt().Len() < nPointIndex)
197 0 : nPointIndex = 0;
198 : // restore cursor to its original position
199 0 : pWrtShell->GetCrsr()->GetPoint()->nContent.Assign( pTxtNode, nPointIndex );
200 : }
201 :
202 : // enable all, restore view and cursor position
203 0 : pWrtShell->EndAction();
204 0 : }
205 : }
206 0 : Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY );
207 0 : if( xComponent.is() )
208 0 : xComponent->dispose();
209 0 : }
210 : }
211 0 : break;
212 : }
213 : case FN_HYPHENATE_OPT_DLG:
214 0 : HyphenateDocument();
215 0 : break;
216 : default:
217 : OSL_ENSURE(!this, "wrong Dispatcher");
218 0 : return;
219 : }
220 : }
221 :
222 : /*--------------------------------------------------------------------
223 : Description: start language specific text conversion
224 : --------------------------------------------------------------------*/
225 0 : void SwView::StartTextConversion(
226 : LanguageType nSourceLang,
227 : LanguageType nTargetLang,
228 : const Font *pTargetFont,
229 : sal_Int32 nOptions,
230 : sal_Bool bIsInteractive )
231 : {
232 : // do not do text conversion if it is active elsewhere
233 0 : if (GetWrtShell().HasConvIter())
234 : {
235 0 : return;
236 : }
237 :
238 0 : SpellKontext(sal_True);
239 :
240 0 : const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
241 0 : const sal_Bool bOldIdle = pVOpt->IsIdle();
242 0 : pVOpt->SetIdle( sal_False );
243 :
244 0 : sal_Bool bOldIns = pWrtShell->IsInsMode();
245 0 : pWrtShell->SetInsMode( sal_True );
246 :
247 0 : sal_Bool bSelection = ((SwCrsrShell*)pWrtShell)->HasSelection() ||
248 0 : pWrtShell->GetCrsr() != pWrtShell->GetCrsr()->GetNext();
249 :
250 0 : sal_Bool bStart = bSelection || pWrtShell->IsStartOfDoc();
251 0 : sal_Bool bOther = !bSelection && !(pWrtShell->GetFrmType(0,sal_True) & FRMTYPE_BODY);
252 :
253 : {
254 : const uno::Reference< uno::XComponentContext > xContext(
255 0 : comphelper::getProcessComponentContext() );
256 : SwHHCWrapper aWrap( this, xContext, nSourceLang, nTargetLang, pTargetFont,
257 : nOptions, bIsInteractive,
258 0 : bStart, bOther, bSelection );
259 0 : aWrap.Convert();
260 : }
261 :
262 0 : pWrtShell->SetInsMode( bOldIns );
263 0 : pVOpt->SetIdle( bOldIdle );
264 0 : SpellKontext(sal_False);
265 : }
266 :
267 : /*--------------------------------------------------------------------
268 : spellcheck and text conversion related stuff
269 : --------------------------------------------------------------------*/
270 0 : void SwView::SpellStart( SvxSpellArea eWhich,
271 : sal_Bool bStartDone, sal_Bool bEndDone,
272 : SwConversionArgs *pConvArgs )
273 : {
274 0 : Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
275 0 : sal_Bool bIsWrapReverse = (!pConvArgs && xProp.is()) ?
276 0 : *(sal_Bool*)xProp->getPropertyValue( UPN_IS_WRAP_REVERSE ).getValue() : sal_False;
277 :
278 0 : SwDocPositions eStart = DOCPOS_START;
279 0 : SwDocPositions eEnde = DOCPOS_END;
280 0 : SwDocPositions eCurr = DOCPOS_CURR;
281 0 : switch ( eWhich )
282 : {
283 : case SVX_SPELL_BODY:
284 0 : if( bIsWrapReverse )
285 0 : eCurr = DOCPOS_END;
286 : else
287 0 : eCurr = DOCPOS_START;
288 0 : break;
289 : case SVX_SPELL_BODY_END:
290 0 : if( bIsWrapReverse )
291 : {
292 0 : if( bStartDone )
293 0 : eStart = DOCPOS_CURR;
294 0 : eCurr = DOCPOS_END;
295 : }
296 0 : else if( bStartDone )
297 0 : eCurr = DOCPOS_START;
298 0 : break;
299 : case SVX_SPELL_BODY_START:
300 0 : if( !bIsWrapReverse )
301 : {
302 0 : if( bEndDone )
303 0 : eEnde = DOCPOS_CURR;
304 0 : eCurr = DOCPOS_START;
305 : }
306 0 : else if( bEndDone )
307 0 : eCurr = DOCPOS_END;
308 0 : break;
309 : case SVX_SPELL_OTHER:
310 0 : if( bIsWrapReverse )
311 : {
312 0 : eStart = DOCPOS_OTHERSTART;
313 0 : eEnde = DOCPOS_OTHEREND;
314 0 : eCurr = DOCPOS_OTHEREND;
315 : }
316 : else
317 : {
318 0 : eStart = DOCPOS_OTHERSTART;
319 0 : eEnde = DOCPOS_OTHEREND;
320 0 : eCurr = DOCPOS_OTHERSTART;
321 : }
322 0 : break;
323 : default:
324 : OSL_ENSURE( !this, "SpellStart with unknown Area" );
325 : }
326 0 : pWrtShell->SpellStart( eStart, eEnde, eCurr, pConvArgs );
327 0 : }
328 :
329 : /*--------------------------------------------------------------------
330 : Beschreibung: Fehlermeldung beim Spelling
331 : --------------------------------------------------------------------*/
332 : // Der uebergebene Pointer nLang ist selbst der Wert
333 0 : void SwView::SpellError(LanguageType eLang)
334 : {
335 : #if OSL_DEBUG_LEVEL > 1
336 : sal_Bool bFocus = GetEditWin().HasFocus();
337 : #endif
338 0 : sal_uInt16 nPend = 0;
339 :
340 0 : if ( pWrtShell->ActionPend() )
341 : {
342 0 : pWrtShell->Push();
343 0 : pWrtShell->ClearMark();
344 0 : do
345 : {
346 0 : pWrtShell->EndAction();
347 0 : ++nPend;
348 : }
349 0 : while( pWrtShell->ActionPend() );
350 : }
351 0 : String aErr(SvtLanguageTable::GetLanguageString( eLang ) );
352 :
353 0 : SwEditWin &rEditWin = GetEditWin();
354 : #if OSL_DEBUG_LEVEL > 1
355 : bFocus = rEditWin.HasFocus();
356 : #endif
357 0 : sal_uInt16 nWaitCnt = 0;
358 0 : while( rEditWin.IsWait() )
359 : {
360 0 : rEditWin.LeaveWait();
361 0 : ++nWaitCnt;
362 : }
363 0 : if ( LANGUAGE_NONE == eLang )
364 0 : ErrorHandler::HandleError( ERRCODE_SVX_LINGU_NOLANGUAGE );
365 : else
366 0 : ErrorHandler::HandleError( *new StringErrorInfo( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) );
367 :
368 0 : while( nWaitCnt )
369 : {
370 0 : rEditWin.EnterWait();
371 0 : --nWaitCnt;
372 : }
373 : #if OSL_DEBUG_LEVEL > 1
374 : bFocus = GetEditWin().HasFocus();
375 : #endif
376 :
377 0 : if ( nPend )
378 : {
379 0 : while( nPend-- )
380 0 : pWrtShell->StartAction();
381 0 : pWrtShell->Combine();
382 0 : }
383 : #if OSL_DEBUG_LEVEL > 1
384 : if( !bFocus )
385 : GetEditWin().GrabFocus();
386 : #endif
387 :
388 0 : }
389 :
390 : /*--------------------------------------------------------------------
391 : Beschreibung: Spelling beenden und Cursor wiederherstellen
392 : --------------------------------------------------------------------*/
393 0 : void SwView::SpellEnd( SwConversionArgs *pConvArgs )
394 : {
395 0 : pWrtShell->SpellEnd( pConvArgs );
396 0 : if( pWrtShell->IsExtMode() )
397 0 : pWrtShell->SetMark();
398 0 : }
399 :
400 0 : void SwView::HyphStart( SvxSpellArea eWhich )
401 : {
402 0 : switch ( eWhich )
403 : {
404 : case SVX_SPELL_BODY:
405 0 : pWrtShell->HyphStart( DOCPOS_START, DOCPOS_END );
406 0 : break;
407 : case SVX_SPELL_BODY_END:
408 0 : pWrtShell->HyphStart( DOCPOS_CURR, DOCPOS_END );
409 0 : break;
410 : case SVX_SPELL_BODY_START:
411 0 : pWrtShell->HyphStart( DOCPOS_START, DOCPOS_CURR );
412 0 : break;
413 : case SVX_SPELL_OTHER:
414 0 : pWrtShell->HyphStart( DOCPOS_OTHERSTART, DOCPOS_OTHEREND );
415 0 : break;
416 : default:
417 : OSL_ENSURE( !this, "HyphStart with unknown Area" );
418 : }
419 0 : }
420 :
421 : /*--------------------------------------------------------------------
422 : Beschreibung: Interaktive Trennung
423 : --------------------------------------------------------------------*/
424 0 : void SwView::HyphenateDocument()
425 : {
426 : // do not hyphenate if interactive hyphenationg is active elsewhere
427 0 : if (GetWrtShell().HasHyphIter())
428 : {
429 : MessBox( 0, WB_OK, String( SW_RES( STR_HYPH_TITLE ) ),
430 0 : String( SW_RES( STR_MULT_INTERACT_HYPH_WARN ) ) ).Execute();
431 : return;
432 : }
433 :
434 : SfxErrorContext aContext( ERRCTX_SVX_LINGU_HYPHENATION, aEmptyStr, pEditWin,
435 0 : RID_SVXERRCTX, &DIALOG_MGR() );
436 :
437 0 : Reference< XHyphenator > xHyph( ::GetHyphenator() );
438 0 : if (!xHyph.is())
439 : {
440 0 : ErrorHandler::HandleError( ERRCODE_SVX_LINGU_LINGUNOTEXISTS );
441 : return;
442 : }
443 :
444 0 : if (pWrtShell->GetSelectionType() & (nsSelectionType::SEL_DRW_TXT|nsSelectionType::SEL_DRW))
445 : {
446 : // Silbentrennung in einem Draw-Objekt
447 0 : HyphenateDrawText();
448 : }
449 : else
450 : {
451 0 : SwViewOption* pVOpt = (SwViewOption*)pWrtShell->GetViewOptions();
452 0 : sal_Bool bOldIdle = pVOpt->IsIdle();
453 0 : pVOpt->SetIdle( sal_False );
454 :
455 0 : Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
456 :
457 :
458 0 : pWrtShell->StartUndo(UNDO_INSATTR); // spaeter gueltig
459 :
460 0 : sal_Bool bHyphSpecial = xProp.is() ?
461 0 : *(sal_Bool*)xProp->getPropertyValue( UPN_IS_HYPH_SPECIAL ).getValue() : sal_False;
462 0 : sal_Bool bSelection = ((SwCrsrShell*)pWrtShell)->HasSelection() ||
463 0 : pWrtShell->GetCrsr() != pWrtShell->GetCrsr()->GetNext();
464 0 : sal_Bool bOther = pWrtShell->HasOtherCnt() && bHyphSpecial && !bSelection;
465 0 : sal_Bool bStart = bSelection || ( !bOther && pWrtShell->IsStartOfDoc() );
466 0 : bool bStop = false;
467 0 : if( !bOther && !(pWrtShell->GetFrmType(0,sal_True) & FRMTYPE_BODY) && !bSelection )
468 : // kein Sonderbereich eingeschaltet
469 : {
470 : // Ich will auch in Sonderbereichen trennen
471 0 : QueryBox aBox( &GetEditWin(), SW_RES( DLG_SPECIAL_FORCED ) );
472 0 : if( aBox.Execute() == RET_YES )
473 : {
474 0 : bOther = sal_True;
475 0 : if (xProp.is())
476 : {
477 0 : sal_Bool bTrue = sal_True;
478 0 : Any aTmp(&bTrue, ::getBooleanCppuType());
479 0 : xProp->setPropertyValue( UPN_IS_HYPH_SPECIAL, aTmp );
480 : }
481 : }
482 : else
483 0 : bStop = true; // Nein Es wird nicht getrennt
484 : }
485 :
486 0 : if( !bStop )
487 : {
488 0 : SwHyphWrapper aWrap( this, xHyph, bStart, bOther, bSelection );
489 0 : aWrap.SpellDocument();
490 0 : pWrtShell->EndUndo(UNDO_INSATTR);
491 : }
492 0 : pVOpt->SetIdle( bOldIdle );
493 0 : }
494 : }
495 :
496 0 : bool SwView::IsValidSelectionForThesaurus() const
497 : {
498 : // must not be a multi-selection, and if it is a selection it needs
499 : // to be within a single paragraph
500 :
501 0 : const bool bMultiSel = pWrtShell->GetCrsr() != pWrtShell->GetCrsr()->GetNext();
502 0 : const sal_Bool bSelection = ((SwCrsrShell*)pWrtShell)->HasSelection();
503 0 : return !bMultiSel && (!bSelection || pWrtShell->IsSelOnePara() );
504 : }
505 :
506 0 : String SwView::GetThesaurusLookUpText( bool bSelection ) const
507 : {
508 0 : return bSelection ? pWrtShell->GetSelTxt() : pWrtShell->GetCurWord();
509 : }
510 :
511 0 : void SwView::InsertThesaurusSynonym( const String &rSynonmText, const String &rLookUpText, bool bSelection )
512 : {
513 0 : sal_Bool bOldIns = pWrtShell->IsInsMode();
514 0 : pWrtShell->SetInsMode( sal_True );
515 :
516 0 : pWrtShell->StartAllAction();
517 0 : pWrtShell->StartUndo(UNDO_DELETE);
518 :
519 0 : if( !bSelection )
520 : {
521 0 : if(pWrtShell->IsEndWrd())
522 0 : pWrtShell->Left(CRSR_SKIP_CELLS, sal_False, 1, sal_False );
523 :
524 0 : pWrtShell->SelWrd();
525 :
526 : // make sure the selection build later from the data below does not
527 : // include "in word" character to the left and right in order to
528 : // preserve those. Therefore count those "in words" in order to modify
529 : // the selection accordingly.
530 0 : const sal_Unicode* pChar = rLookUpText.GetBuffer();
531 0 : xub_StrLen nLeft = 0;
532 0 : while (pChar && *pChar++ == CH_TXTATR_INWORD)
533 0 : ++nLeft;
534 0 : pChar = rLookUpText.Len() ? rLookUpText.GetBuffer() + rLookUpText.Len() - 1 : 0;
535 0 : xub_StrLen nRight = 0;
536 0 : while (pChar && *pChar-- == CH_TXTATR_INWORD)
537 0 : ++nRight;
538 :
539 : // adjust existing selection
540 0 : SwPaM *pCrsr = pWrtShell->GetCrsr();
541 0 : pCrsr->GetPoint()->nContent -= nRight;
542 0 : pCrsr->GetMark()->nContent += nLeft;
543 : }
544 :
545 0 : pWrtShell->Insert( rSynonmText );
546 :
547 0 : pWrtShell->EndUndo(UNDO_DELETE);
548 0 : pWrtShell->EndAllAction();
549 :
550 0 : pWrtShell->SetInsMode( bOldIns );
551 0 : }
552 :
553 : /*--------------------------------------------------------------------
554 : Beschreibung: Thesaurus starten
555 : --------------------------------------------------------------------*/
556 0 : void SwView::StartThesaurus()
557 : {
558 0 : if (!IsValidSelectionForThesaurus())
559 : return;
560 :
561 : SfxErrorContext aContext( ERRCTX_SVX_LINGU_THESAURUS, aEmptyStr, pEditWin,
562 0 : RID_SVXERRCTX, &DIALOG_MGR() );
563 :
564 : // Sprache rausholen
565 : //
566 0 : LanguageType eLang = pWrtShell->GetCurLang();
567 0 : if( LANGUAGE_SYSTEM == eLang )
568 0 : eLang = GetAppLanguage();
569 :
570 0 : if( eLang == LANGUAGE_DONTKNOW || eLang == LANGUAGE_NONE )
571 : {
572 0 : SpellError( LANGUAGE_NONE );
573 : return;
574 : }
575 :
576 0 : SwViewOption* pVOpt = (SwViewOption*)pWrtShell->GetViewOptions();
577 0 : sal_Bool bOldIdle = pVOpt->IsIdle();
578 0 : pVOpt->SetIdle( sal_False );
579 :
580 : // get initial LookUp text
581 0 : const sal_Bool bSelection = ((SwCrsrShell*)pWrtShell)->HasSelection();
582 0 : String aTmp = GetThesaurusLookUpText( bSelection );
583 :
584 0 : Reference< XThesaurus > xThes( ::GetThesaurus() );
585 0 : AbstractThesaurusDialog *pDlg = NULL;
586 :
587 0 : if ( !xThes.is() || !xThes->hasLocale( LanguageTag( eLang ).getLocale() ) )
588 0 : SpellError( eLang );
589 : else
590 : {
591 : // create dialog
592 : { //Scope for SwWait-Object
593 0 : SwWait aWait( *GetDocShell(), sal_True );
594 : // load library with dialog only on demand ...
595 0 : SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
596 0 : pDlg = pFact->CreateThesaurusDialog( &GetEditWin(), xThes, aTmp, eLang );
597 : }
598 :
599 0 : if ( pDlg->Execute()== RET_OK )
600 0 : InsertThesaurusSynonym( pDlg->GetWord(), aTmp, bSelection );
601 : }
602 :
603 0 : delete pDlg;
604 :
605 0 : pVOpt->SetIdle( bOldIdle );
606 : }
607 :
608 : /*--------------------------------------------------------------------
609 : Beschreibung: Online-Vorschlaege anbieten
610 : *--------------------------------------------------------------------*/
611 : //!! Start of extra code for context menu modifying extensions
612 0 : struct ExecuteInfo
613 : {
614 : uno::Reference< frame::XDispatch > xDispatch;
615 : util::URL aTargetURL;
616 : uno::Sequence< PropertyValue > aArgs;
617 : };
618 :
619 : class AsyncExecute
620 : {
621 : public:
622 : DECL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, ExecuteInfo* );
623 : };
624 :
625 0 : IMPL_STATIC_LINK_NOINSTANCE( AsyncExecute, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
626 : {
627 0 : const sal_uInt32 nRef = Application::ReleaseSolarMutex();
628 : try
629 : {
630 : // Asynchronous execution as this can lead to our own destruction!
631 : // Framework can recycle our current frame and the layout manager disposes all user interface
632 : // elements if a component gets detached from its frame!
633 0 : pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
634 : }
635 0 : catch (const Exception&)
636 : {
637 : }
638 :
639 0 : Application::AcquireSolarMutex( nRef );
640 0 : delete pExecuteInfo;
641 0 : return 0;
642 : }
643 : //!! End of extra code for context menu modifying extensions
644 :
645 0 : sal_Bool SwView::ExecSpellPopup(const Point& rPt)
646 : {
647 0 : sal_Bool bRet = sal_False;
648 0 : const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
649 0 : if( pVOpt->IsOnlineSpell() &&
650 0 : !pWrtShell->IsSelection())
651 : {
652 0 : if (pWrtShell->GetSelectionType() & nsSelectionType::SEL_DRW_TXT)
653 0 : bRet = ExecDrwTxtSpellPopup(rPt);
654 0 : else if (!pWrtShell->IsSelFrmMode())
655 : {
656 0 : const sal_Bool bOldViewLock = pWrtShell->IsViewLocked();
657 0 : pWrtShell->LockView( sal_True );
658 0 : pWrtShell->Push();
659 0 : SwRect aToFill;
660 :
661 : // decide which variant of the context menu to use...
662 : // if neither spell checking nor grammar checking provides suggestions use the
663 : // default context menu.
664 0 : bool bUseGrammarContext = false;
665 0 : Reference< XSpellAlternatives > xAlt( pWrtShell->GetCorrection(&rPt, aToFill) );
666 0 : ProofreadingResult aGrammarCheckRes;
667 0 : sal_Int32 nErrorInResult = -1;
668 0 : uno::Sequence< rtl::OUString > aSuggestions;
669 0 : bool bCorrectionRes = false;
670 0 : if (!xAlt.is() || xAlt->getAlternatives().getLength() == 0)
671 : {
672 0 : sal_Int32 nErrorPosInText = -1;
673 0 : bCorrectionRes = pWrtShell->GetGrammarCorrection( aGrammarCheckRes, nErrorPosInText, nErrorInResult, aSuggestions, &rPt, aToFill );
674 0 : ::rtl::OUString aMessageText;
675 0 : if (nErrorInResult >= 0)
676 0 : aMessageText = aGrammarCheckRes.aErrors[ nErrorInResult ].aShortComment;
677 : // we like to use the grammar checking context menu if we either get
678 : // some suggestions or at least a comment about the error found...
679 : bUseGrammarContext = bCorrectionRes &&
680 0 : (aSuggestions.getLength() > 0 || !aMessageText.isEmpty());
681 : }
682 :
683 : // open respective context menu for spell check or grammar errors with correction suggestions...
684 0 : if ((!bUseGrammarContext && xAlt.is()) ||
685 0 : (bUseGrammarContext && bCorrectionRes && aGrammarCheckRes.aErrors.getLength() > 0))
686 : {
687 : // get paragraph text
688 0 : String aParaText;
689 0 : SwPosition aPoint( *pWrtShell->GetCrsr()->GetPoint() );
690 : const SwTxtNode *pNode = dynamic_cast< const SwTxtNode * >(
691 0 : &aPoint.nNode.GetNode() );
692 0 : if (pNode)
693 0 : aParaText = pNode->GetTxt(); // this may include hidden text but that should be Ok
694 : else
695 : {
696 : OSL_FAIL("text node expected but not found" );
697 : }
698 :
699 0 : bRet = sal_True;
700 0 : pWrtShell->SttSelect();
701 0 : std::auto_ptr< SwSpellPopup > pPopup;
702 0 : if (bUseGrammarContext)
703 : {
704 0 : sal_Int32 nPos = aPoint.nContent.GetIndex();
705 : (void) nPos;
706 0 : pPopup = std::auto_ptr< SwSpellPopup >(new SwSpellPopup( pWrtShell, aGrammarCheckRes, nErrorInResult, aSuggestions, aParaText ));
707 : }
708 : else
709 0 : pPopup = std::auto_ptr< SwSpellPopup >(new SwSpellPopup( pWrtShell, xAlt, aParaText ));
710 0 : ui::ContextMenuExecuteEvent aEvent;
711 0 : const Point aPixPos = GetEditWin().LogicToPixel( rPt );
712 :
713 0 : aEvent.SourceWindow = VCLUnoHelper::GetInterface( pEditWin );
714 0 : aEvent.ExecutePosition.X = aPixPos.X();
715 0 : aEvent.ExecutePosition.Y = aPixPos.Y();
716 0 : Menu* pMenu = 0;
717 :
718 : ::rtl::OUString sMenuName = bUseGrammarContext ?
719 0 : OUString("private:resource/GrammarContextMenu") : OUString("private:resource/SpellContextMenu");
720 0 : if(TryContextMenuInterception( *pPopup, sMenuName, pMenu, aEvent ))
721 : {
722 :
723 : //! happy hacking for context menu modifying extensions of this
724 : //! 'custom made' menu... *sigh* (code copied from sfx2 and framework)
725 0 : if ( pMenu )
726 : {
727 0 : sal_uInt16 nId = ((PopupMenu*)pMenu)->Execute(pEditWin, aPixPos);
728 0 : OUString aCommand = ((PopupMenu*)pMenu)->GetItemCommand(nId);
729 0 : if (aCommand.isEmpty() )
730 : {
731 0 : if(!ExecuteMenuCommand( *dynamic_cast<PopupMenu*>(pMenu), *GetViewFrame(), nId ))
732 0 : pPopup->Execute(nId);
733 : }
734 : else
735 : {
736 0 : SfxViewFrame *pSfxViewFrame = GetViewFrame();
737 0 : uno::Reference< frame::XFrame > xFrame;
738 0 : if ( pSfxViewFrame )
739 0 : xFrame = pSfxViewFrame->GetFrame().GetFrameInterface();
740 0 : com::sun::star::util::URL aURL;
741 0 : uno::Reference< frame::XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
742 :
743 : try
744 : {
745 0 : uno::Reference< frame::XDispatch > xDispatch;
746 0 : uno::Reference< util::XURLTransformer > xURLTransformer = util::URLTransformer::create(comphelper::getProcessComponentContext());
747 :
748 0 : aURL.Complete = aCommand;
749 0 : xURLTransformer->parseStrict(aURL);
750 0 : uno::Sequence< beans::PropertyValue > aArgs;
751 0 : xDispatch = xDispatchProvider->queryDispatch( aURL, rtl::OUString(), 0 );
752 :
753 :
754 0 : if (xDispatch.is())
755 : {
756 : // Execute dispatch asynchronously
757 0 : ExecuteInfo* pExecuteInfo = new ExecuteInfo;
758 0 : pExecuteInfo->xDispatch = xDispatch;
759 0 : pExecuteInfo->aTargetURL = aURL;
760 0 : pExecuteInfo->aArgs = aArgs;
761 0 : Application::PostUserEvent( STATIC_LINK(0, AsyncExecute , ExecuteHdl_Impl), pExecuteInfo );
762 0 : }
763 : }
764 0 : catch (const Exception&)
765 : {
766 0 : }
767 0 : }
768 : }
769 : else
770 : {
771 0 : pPopup->Execute( aToFill.SVRect(), pEditWin );
772 : }
773 0 : }
774 : }
775 :
776 0 : pWrtShell->Pop( sal_False );
777 0 : pWrtShell->LockView( bOldViewLock );
778 : }
779 : }
780 0 : return bRet;
781 : }
782 :
783 : /** Function: ExecSmartTagPopup
784 :
785 : This function shows the popup menu for smarttag
786 : actions.
787 : */
788 0 : sal_Bool SwView::ExecSmartTagPopup( const Point& rPt )
789 : {
790 0 : sal_Bool bRet = sal_False;
791 0 : const sal_Bool bOldViewLock = pWrtShell->IsViewLocked();
792 0 : pWrtShell->LockView( sal_True );
793 0 : pWrtShell->Push();
794 :
795 :
796 : // get word that was clicked on
797 : // This data structure maps a smart tag type string to the property bag
798 0 : SwRect aToFill;
799 0 : Sequence< rtl::OUString > aSmartTagTypes;
800 0 : Sequence< Reference< container::XStringKeyMap > > aStringKeyMaps;
801 0 : Reference<text::XTextRange> xRange;
802 :
803 0 : pWrtShell->GetSmartTagTerm( rPt, aToFill, aSmartTagTypes, aStringKeyMaps, xRange);
804 0 : if ( xRange.is() && aSmartTagTypes.getLength() )
805 : {
806 0 : bRet = sal_True;
807 0 : pWrtShell->SttSelect();
808 0 : SwSmartTagPopup aPopup( this, aSmartTagTypes, aStringKeyMaps, xRange );
809 0 : aPopup.Execute( aToFill.SVRect(), pEditWin );
810 : }
811 :
812 0 : pWrtShell->Pop( sal_False );
813 0 : pWrtShell->LockView( bOldViewLock );
814 :
815 0 : return bRet;
816 : }
817 :
818 0 : class SwFieldDialog : public FloatingWindow
819 : {
820 : private:
821 : ListBox aListBox;
822 : IFieldmark *pFieldmark;
823 :
824 : DECL_LINK( MyListBoxHandler, ListBox * );
825 :
826 : public:
827 : SwFieldDialog( SwEditWin* parent, IFieldmark *fieldBM );
828 : };
829 :
830 0 : SwFieldDialog::SwFieldDialog( SwEditWin* parent, IFieldmark *fieldBM ) :
831 : FloatingWindow( parent, WB_BORDER | WB_SYSTEMWINDOW ),
832 : aListBox(this),
833 0 : pFieldmark( fieldBM )
834 : {
835 0 : if ( fieldBM != NULL )
836 : {
837 0 : const IFieldmark::parameter_map_t* const pParameters = fieldBM->GetParameters();
838 :
839 0 : rtl::OUString sListKey = rtl::OUString( ODF_FORMDROPDOWN_LISTENTRY );
840 0 : IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find( sListKey );
841 0 : if(pListEntries != pParameters->end())
842 : {
843 0 : Sequence< ::rtl::OUString > vListEntries;
844 0 : pListEntries->second >>= vListEntries;
845 0 : for( ::rtl::OUString* pCurrent = vListEntries.getArray();
846 0 : pCurrent != vListEntries.getArray() + vListEntries.getLength();
847 : ++pCurrent)
848 : {
849 0 : aListBox.InsertEntry(*pCurrent);
850 0 : }
851 : }
852 :
853 : // Select the current one
854 0 : rtl::OUString sResultKey = rtl::OUString( ODF_FORMDROPDOWN_RESULT );
855 0 : IFieldmark::parameter_map_t::const_iterator pResult = pParameters->find( sResultKey );
856 0 : if ( pResult != pParameters->end() )
857 : {
858 0 : sal_Int32 nSelection = -1;
859 0 : pResult->second >>= nSelection;
860 0 : aListBox.SelectEntryPos( nSelection );
861 0 : }
862 : }
863 :
864 0 : Size lbSize=aListBox.GetOptimalSize(WINDOWSIZE_PREFERRED);
865 0 : lbSize.Width()+=50;
866 0 : lbSize.Height()+=20;
867 0 : aListBox.SetSizePixel(lbSize);
868 0 : aListBox.SetSelectHdl( LINK( this, SwFieldDialog, MyListBoxHandler ) );
869 0 : aListBox.Show();
870 :
871 0 : SetSizePixel( lbSize );
872 0 : }
873 :
874 0 : IMPL_LINK( SwFieldDialog, MyListBoxHandler, ListBox *, pBox )
875 : {
876 0 : short res = 0;
877 0 : if ( !pBox->IsTravelSelect() )
878 : {
879 0 : sal_Int32 selection = pBox->GetSelectEntryPos();
880 0 : if ( selection >= 0 )
881 : {
882 0 : rtl::OUString sKey = rtl::OUString( ODF_FORMDROPDOWN_RESULT );
883 0 : (*pFieldmark->GetParameters())[ sKey ] = makeAny(selection);
884 0 : pFieldmark->Invalidate();
885 0 : SwView& rView = ( ( SwEditWin* )GetParent() )->GetView();
886 0 : rView.GetDocShell()->SetModified( sal_True );
887 : }
888 :
889 0 : EndPopupMode();
890 0 : res = 1;
891 : }
892 0 : return res;
893 : }
894 :
895 0 : IMPL_LINK_NOARG(SwView, FieldPopupModeEndHdl)
896 : {
897 0 : if ( mpFieldPopup )
898 : {
899 0 : delete mpFieldPopup;
900 0 : mpFieldPopup = NULL;
901 : }
902 0 : return 0;
903 : }
904 :
905 0 : void SwView::ExecFieldPopup( const Point& rPt, IFieldmark *fieldBM )
906 : {
907 0 : const Point aPixPos = GetEditWin().LogicToPixel( rPt );
908 :
909 0 : mpFieldPopup = new SwFieldDialog( pEditWin, fieldBM );
910 0 : mpFieldPopup->SetPopupModeEndHdl( LINK( this, SwView, FieldPopupModeEndHdl ) );
911 :
912 0 : Rectangle aRect( pEditWin->OutputToScreenPixel( aPixPos ), Size( 0, 0 ) );
913 0 : mpFieldPopup->StartPopupMode( aRect, FLOATWIN_POPUPMODE_DOWN|FLOATWIN_POPUPMODE_GRABFOCUS );
914 30 : }
915 :
916 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|