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