xref: /trunk/main/sw/source/ui/uiview/viewling.cxx (revision 8ef2f12b)
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 
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(!this, falscher Dispatcher);
233 			return;
234 	}
235 }
236 
237 /*--------------------------------------------------------------------
238     Description: start language specific text conversion
239  --------------------------------------------------------------------*/
240 
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 
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( !this, "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
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 
416 void SwView::SpellEnd( SwConversionArgs *pConvArgs )
417 {
418     pWrtShell->SpellEnd( pConvArgs );
419 	if( pWrtShell->IsExtMode() )
420 		pWrtShell->SetMark();
421 }
422 
423 
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( !this, "HyphStart with unknown Area" );
442 	}
443 }
444 
445 /*--------------------------------------------------------------------
446 	 Beschreibung: Interaktive Trennung
447  --------------------------------------------------------------------*/
448 
449 
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 
525 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 
536 String SwView::GetThesaurusLookUpText( bool bSelection ) const
537 {
538     return bSelection ? pWrtShell->GetSelTxt() : pWrtShell->GetCurWord();
539 }
540 
541 
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 
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 
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 
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 
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:
868     SwFieldPopup()  {
869 	InsertItem(1, ::rtl::OUString::createFromAscii("Hello"));
870     }
871 };
872 
873 class SwFieldListBox : public ListBox
874 {
875 public:
876     SwFieldListBox(Window* pParent) : ListBox(pParent /*, WB_DROPDOWN*/) {
877     }
878 
879     void *GetImplWin() {
880 	return NULL; //FIXME!!!
881 //	return mpImplWin;
882     }
883 
884 protected:
885     virtual void LoseFocus() {
886 //	printf("ListBox: lose focus!!\n");
887 	ListBox::LoseFocus();
888     }
889 
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:
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 
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 
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 
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 meaningfull returns...
972 	return 1;
973     }
974 }
975 
976 
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