xref: /trunk/main/sw/source/ui/uiview/viewling.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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