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