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