blob: e763981fc83ffa734b61a2f154208dd0acafc647 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <hintids.hxx>
#ifndef _SVSTDARR_HXX
#define _SVSTDARR_STRINGSDTOR
#include <svl/svstdarr.hxx>
#endif
#include <com/sun/star/lang/Locale.hpp>
#include <com/sun/star/linguistic2/XThesaurus.hpp>
#include <com/sun/star/linguistic2/ProofreadingResult.hpp>
#include <com/sun/star/i18n/TextConversionOption.hpp>
#include <linguistic/lngprops.hxx>
#include <comphelper/processfactory.hxx>
#include <toolkit/helper/vclunohelper.hxx>
#include <vcl/msgbox.hxx>
#include <svtools/ehdl.hxx>
#include <svl/stritem.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/request.hxx>
#include <svx/dlgutil.hxx>
#include <svx/dialmgr.hxx>
#include <editeng/langitem.hxx>
#include <svx/svxerr.hxx>
#include <editeng/unolingu.hxx>
#include <svx/svxdlg.hxx>
#include <editeng/SpellPortions.hxx>
#include <swmodule.hxx>
#include <swwait.hxx>
#include <initui.hxx> // fuer SpellPointer
#include <uitool.hxx>
#include <view.hxx>
#include <wrtsh.hxx>
#include <basesh.hxx>
#include <docsh.hxx> // CheckSpellChanges
#include <viewopt.hxx> // Viewoptions
#include <swundo.hxx> // fuer Undo-Ids
#include <hyp.hxx> // Trennung
#include <olmenu.hxx> // PopupMenu fuer OnlineSpelling
#include <pam.hxx> // Spelling: Multiselektion
#include <edtwin.hxx>
#include <crsskip.hxx>
#include <ndtxt.hxx>
#include <vcl/lstbox.hxx>
#include <cmdid.h>
#include <globals.hrc>
#include <comcore.hrc> // STR_MULT_INTERACT_SPELL_WARN
#include <view.hrc>
#include <hhcwrp.hxx>
#include <com/sun/star/frame/XStorable.hpp>
#include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <com/sun/star/frame/XDispatch.hpp>
#include <com/sun/star/frame/XDispatchProvider.hpp>
#include <com/sun/star/frame/XFrame.hpp>
#include <com/sun/star/util/URL.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/util/XURLTransformer.hpp>
#include <unotools/processfactory.hxx>
#include <vcl/svapp.hxx>
#include <rtl/ustring.hxx>
#include <cppuhelper/bootstrap.hxx>
#include "stmenu.hxx" // PopupMenu for smarttags
#include <svx/dialogs.hrc>
#include <svtools/langtab.hxx>
#include <unomid.h>
#include <IMark.hxx>
#include <xmloff/odffields.hxx>
#include <memory>
#include <editeng/editerr.hxx>
using namespace sw::mark;
using ::rtl::OUString;
using namespace ::com::sun::star;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::linguistic2;
using namespace ::com::sun::star::smarttags;
/*--------------------------------------------------------------------
Beschreibung: Lingu-Dispatcher
--------------------------------------------------------------------*/
void SwView::ExecLingu(SfxRequest &rReq)
{
switch(rReq.GetSlot())
{
case SID_THESAURUS:
StartThesaurus();
rReq.Ignore();
break;
case SID_HANGUL_HANJA_CONVERSION:
StartTextConversion( LANGUAGE_KOREAN, LANGUAGE_KOREAN, NULL,
i18n::TextConversionOption::CHARACTER_BY_CHARACTER, sal_True );
break;
case SID_CHINESE_CONVERSION:
{
//open ChineseTranslationDialog
Reference< XComponentContext > xContext(
::cppu::defaultBootstrap_InitialComponentContext() ); //@todo get context from calc if that has one
if(xContext.is())
{
Reference< lang::XMultiComponentFactory > xMCF( xContext->getServiceManager() );
if(xMCF.is())
{
Reference< ui::dialogs::XExecutableDialog > xDialog(
xMCF->createInstanceWithContext(
rtl::OUString::createFromAscii("com.sun.star.linguistic2.ChineseTranslationDialog")
, xContext), UNO_QUERY);
Reference< lang::XInitialization > xInit( xDialog, UNO_QUERY );
if( xInit.is() )
{
// initialize dialog
Reference< awt::XWindow > xDialogParentWindow(0);
Sequence<Any> aSeq(1);
Any* pArray = aSeq.getArray();
PropertyValue aParam;
aParam.Name = rtl::OUString::createFromAscii("ParentWindow");
aParam.Value <<= makeAny(xDialogParentWindow);
pArray[0] <<= makeAny(aParam);
xInit->initialize( aSeq );
//execute dialog
sal_Int16 nDialogRet = xDialog->execute();
if( RET_OK == nDialogRet )
{
//get some parameters from the dialog
sal_Bool bToSimplified = sal_True;
sal_Bool bUseVariants = sal_True;
sal_Bool bCommonTerms = sal_True;
Reference< beans::XPropertySet > xProp( xDialog, UNO_QUERY );
if( xProp.is() )
{
try
{
xProp->getPropertyValue( C2U("IsDirectionToSimplified") ) >>= bToSimplified;
xProp->getPropertyValue( C2U("IsUseCharacterVariants") ) >>= bUseVariants;
xProp->getPropertyValue( C2U("IsTranslateCommonTerms") ) >>= bCommonTerms;
}
catch( Exception& )
{
}
}
//execute translation
sal_Int16 nSourceLang = bToSimplified ? LANGUAGE_CHINESE_TRADITIONAL : LANGUAGE_CHINESE_SIMPLIFIED;
sal_Int16 nTargetLang = bToSimplified ? LANGUAGE_CHINESE_SIMPLIFIED : LANGUAGE_CHINESE_TRADITIONAL;
sal_Int32 nOptions = bUseVariants ? i18n::TextConversionOption::USE_CHARACTER_VARIANTS : 0;
if( !bCommonTerms )
nOptions = nOptions | i18n::TextConversionOption::CHARACTER_BY_CHARACTER;
Font aTargetFont = GetEditWin().GetDefaultFont( DEFAULTFONT_CJK_TEXT,
nTargetLang, DEFAULTFONT_FLAGS_ONLYONE );
// disallow formatting, updating the view, ... while
// converting the document. (saves time)
// Also remember the current view and cursor position for later
pWrtShell->StartAction();
// remember cursor position data for later restoration of the cursor
const SwPosition *pPoint = pWrtShell->GetCrsr()->GetPoint();
sal_Bool bRestoreCursor = pPoint->nNode.GetNode().IsTxtNode();
const SwNodeIndex aPointNodeIndex( pPoint->nNode );
xub_StrLen nPointIndex = pPoint->nContent.GetIndex();;
// since this conversion is not interactive the whole converted
// document should be undone in a single undo step.
pWrtShell->StartUndo( UNDO_OVERWRITE );
StartTextConversion( nSourceLang, nTargetLang, &aTargetFont, nOptions, sal_False );
pWrtShell->EndUndo( UNDO_OVERWRITE );
if (bRestoreCursor)
{
SwTxtNode *pTxtNode = aPointNodeIndex.GetNode().GetTxtNode();
// check for unexpected error case
DBG_ASSERT( pTxtNode && pTxtNode->GetTxt().Len() >= nPointIndex,
"text missing: corrupted node?" );
if (!pTxtNode || pTxtNode->GetTxt().Len() < nPointIndex)
nPointIndex = 0;
// restore cursor to its original position
pWrtShell->GetCrsr()->GetPoint()->nContent.Assign( pTxtNode, nPointIndex );
}
// enable all, restore view and cursor position
pWrtShell->EndAction();
}
}
Reference< lang::XComponent > xComponent( xDialog, UNO_QUERY );
if( xComponent.is() )
xComponent->dispose();
}
}
break;
}
case FN_HYPHENATE_OPT_DLG:
HyphenateDocument();
break;
default:
ASSERT(!this, falscher Dispatcher);
return;
}
}
/*--------------------------------------------------------------------
Description: start language specific text conversion
--------------------------------------------------------------------*/
void SwView::StartTextConversion(
LanguageType nSourceLang,
LanguageType nTargetLang,
const Font *pTargetFont,
sal_Int32 nOptions,
sal_Bool bIsInteractive )
{
// do not do text conversion if it is active elsewhere
if (GetWrtShell().HasConvIter())
{
return;
}
SpellKontext(sal_True);
const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
const sal_Bool bOldIdle = pVOpt->IsIdle();
pVOpt->SetIdle( sal_False );
sal_Bool bOldIns = pWrtShell->IsInsMode();
pWrtShell->SetInsMode( sal_True );
sal_Bool bSelection = ((SwCrsrShell*)pWrtShell)->HasSelection() ||
pWrtShell->GetCrsr() != pWrtShell->GetCrsr()->GetNext();
sal_Bool bStart = bSelection || pWrtShell->IsStartOfDoc();
sal_Bool bOther = !bSelection && !(pWrtShell->GetFrmType(0,sal_True) & FRMTYPE_BODY);
{
const uno::Reference< lang::XMultiServiceFactory > xMgr(
comphelper::getProcessServiceFactory() );
SwHHCWrapper aWrap( this, xMgr, nSourceLang, nTargetLang, pTargetFont,
nOptions, bIsInteractive,
bStart, bOther, bSelection );
aWrap.Convert();
}
pWrtShell->SetInsMode( bOldIns );
pVOpt->SetIdle( bOldIdle );
SpellKontext(sal_False);
}
/*--------------------------------------------------------------------
spellcheck and text conversion related stuff
--------------------------------------------------------------------*/
void SwView::SpellStart( SvxSpellArea eWhich,
sal_Bool bStartDone, sal_Bool bEndDone,
SwConversionArgs *pConvArgs )
{
Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
sal_Bool bIsWrapReverse = (!pConvArgs && xProp.is()) ?
*(sal_Bool*)xProp->getPropertyValue( C2U(UPN_IS_WRAP_REVERSE) ).getValue() : sal_False;
SwDocPositions eStart = DOCPOS_START;
SwDocPositions eEnde = DOCPOS_END;
SwDocPositions eCurr = DOCPOS_CURR;
switch ( eWhich )
{
case SVX_SPELL_BODY:
if( bIsWrapReverse )
eCurr = DOCPOS_END;
else
eCurr = DOCPOS_START;
break;
case SVX_SPELL_BODY_END:
if( bIsWrapReverse )
{
if( bStartDone )
eStart = DOCPOS_CURR;
eCurr = DOCPOS_END;
}
else if( bStartDone )
eCurr = DOCPOS_START;
break;
case SVX_SPELL_BODY_START:
if( !bIsWrapReverse )
{
if( bEndDone )
eEnde = DOCPOS_CURR;
eCurr = DOCPOS_START;
}
else if( bEndDone )
eCurr = DOCPOS_END;
break;
case SVX_SPELL_OTHER:
if( bIsWrapReverse )
{
eStart = DOCPOS_OTHERSTART;
eEnde = DOCPOS_OTHEREND;
eCurr = DOCPOS_OTHEREND;
}
else
{
eStart = DOCPOS_OTHERSTART;
eEnde = DOCPOS_OTHEREND;
eCurr = DOCPOS_OTHERSTART;
}
break;
default:
ASSERT( !this, "SpellStart with unknown Area" );
}
pWrtShell->SpellStart( eStart, eEnde, eCurr, pConvArgs );
}
/*--------------------------------------------------------------------
Beschreibung: Fehlermeldung beim Spelling
--------------------------------------------------------------------*/
// Der uebergebene Pointer nLang ist selbst der Wert
IMPL_LINK( SwView, SpellError, LanguageType *, pLang )
{
#if OSL_DEBUG_LEVEL > 1
sal_Bool bFocus = GetEditWin().HasFocus();
#endif
sal_uInt16 nPend = 0;
if ( pWrtShell->ActionPend() )
{
pWrtShell->Push();
pWrtShell->ClearMark();
do
{
pWrtShell->EndAction();
++nPend;
}
while( pWrtShell->ActionPend() );
}
LanguageType eLang = pLang ? *pLang : LANGUAGE_NONE;
String aErr(SvtLanguageTable::GetLanguageString( eLang ) );
SwEditWin &rEditWin = GetEditWin();
#if OSL_DEBUG_LEVEL > 1
bFocus = rEditWin.HasFocus();
#endif
sal_uInt16 nWaitCnt = 0;
while( rEditWin.IsWait() )
{
rEditWin.LeaveWait();
++nWaitCnt;
}
if ( LANGUAGE_NONE == eLang )
ErrorHandler::HandleError( ERRCODE_SVX_LINGU_NOLANGUAGE );
else
ErrorHandler::HandleError( *new StringErrorInfo( ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS, aErr ) );
while( nWaitCnt )
{
rEditWin.EnterWait();
--nWaitCnt;
}
#if OSL_DEBUG_LEVEL > 1
bFocus = GetEditWin().HasFocus();
#endif
if ( nPend )
{
while( nPend-- )
pWrtShell->StartAction();
pWrtShell->Combine();
}
#if OSL_DEBUG_LEVEL > 1
if( !bFocus )
GetEditWin().GrabFocus();
#endif
return 0;
}
/*--------------------------------------------------------------------
Beschreibung: Spelling beenden und Cursor wiederherstellen
--------------------------------------------------------------------*/
void SwView::SpellEnd( SwConversionArgs *pConvArgs )
{
pWrtShell->SpellEnd( pConvArgs );
if( pWrtShell->IsExtMode() )
pWrtShell->SetMark();
}
void SwView::HyphStart( SvxSpellArea eWhich )
{
switch ( eWhich )
{
case SVX_SPELL_BODY:
pWrtShell->HyphStart( DOCPOS_START, DOCPOS_END );
break;
case SVX_SPELL_BODY_END:
pWrtShell->HyphStart( DOCPOS_CURR, DOCPOS_END );
break;
case SVX_SPELL_BODY_START:
pWrtShell->HyphStart( DOCPOS_START, DOCPOS_CURR );
break;
case SVX_SPELL_OTHER:
pWrtShell->HyphStart( DOCPOS_OTHERSTART, DOCPOS_OTHEREND );
break;
default:
ASSERT( !this, "HyphStart with unknown Area" );
}
}
/*--------------------------------------------------------------------
Beschreibung: Interaktive Trennung
--------------------------------------------------------------------*/
void SwView::HyphenateDocument()
{
// do not hyphenate if interactive hyphenationg is active elsewhere
if (GetWrtShell().HasHyphIter())
{
MessBox( 0, WB_OK, String( SW_RES( STR_HYPH_TITLE ) ),
String( SW_RES( STR_MULT_INTERACT_HYPH_WARN ) ) ).Execute();
return;
}
SfxErrorContext aContext( ERRCTX_SVX_LINGU_HYPHENATION, aEmptyStr, pEditWin,
RID_SVXERRCTX, &DIALOG_MGR() );
Reference< XHyphenator > xHyph( ::GetHyphenator() );
if (!xHyph.is())
{
ErrorHandler::HandleError( ERRCODE_SVX_LINGU_LINGUNOTEXISTS );
return;
}
if (pWrtShell->GetSelectionType() & (nsSelectionType::SEL_DRW_TXT|nsSelectionType::SEL_DRW))
{
// Silbentrennung in einem Draw-Objekt
HyphenateDrawText();
}
else
{
SwViewOption* pVOpt = (SwViewOption*)pWrtShell->GetViewOptions();
sal_Bool bOldIdle = pVOpt->IsIdle();
pVOpt->SetIdle( sal_False );
Reference< beans::XPropertySet > xProp( ::GetLinguPropertySet() );
pWrtShell->StartUndo(UNDO_INSATTR); // spaeter gueltig
sal_Bool bHyphSpecial = xProp.is() ?
*(sal_Bool*)xProp->getPropertyValue( C2U(UPN_IS_HYPH_SPECIAL) ).getValue() : sal_False;
sal_Bool bSelection = ((SwCrsrShell*)pWrtShell)->HasSelection() ||
pWrtShell->GetCrsr() != pWrtShell->GetCrsr()->GetNext();
sal_Bool bOther = pWrtShell->HasOtherCnt() && bHyphSpecial && !bSelection;
sal_Bool bStart = bSelection || ( !bOther && pWrtShell->IsStartOfDoc() );
sal_Bool bStop = sal_False;
if( !bOther && !(pWrtShell->GetFrmType(0,sal_True) & FRMTYPE_BODY) && !bSelection )
// kein Sonderbereich eingeschaltet
{
// Ich will auch in Sonderbereichen trennen
QueryBox aBox( &GetEditWin(), SW_RES( DLG_SPECIAL_FORCED ) );
if( aBox.Execute() == RET_YES )
{
bOther = sal_True;
if (xProp.is())
{
sal_Bool bTrue = sal_True;
Any aTmp(&bTrue, ::getBooleanCppuType());
xProp->setPropertyValue( C2U(UPN_IS_HYPH_SPECIAL), aTmp );
}
}
else
bStop = sal_True; // Nein Es wird nicht getrennt
}
if( !bStop )
{
SwHyphWrapper aWrap( this, xHyph, bStart, bOther, bSelection );
aWrap.SpellDocument();
pWrtShell->EndUndo(UNDO_INSATTR);
}
pVOpt->SetIdle( bOldIdle );
}
}
/*--------------------------------------------------------------------
--------------------------------------------------------------------*/
bool SwView::IsValidSelectionForThesaurus() const
{
// must not be a multi-selection, and if it is a selection it needs
// to be within a single paragraph
const bool bMultiSel = pWrtShell->GetCrsr() != pWrtShell->GetCrsr()->GetNext();
const sal_Bool bSelection = ((SwCrsrShell*)pWrtShell)->HasSelection();
return !bMultiSel && (!bSelection || pWrtShell->IsSelOnePara() );
}
String SwView::GetThesaurusLookUpText( bool bSelection ) const
{
return bSelection ? pWrtShell->GetSelTxt() : pWrtShell->GetCurWord();
}
void SwView::InsertThesaurusSynonym( const String &rSynonmText, const String &rLookUpText, bool bSelection )
{
sal_Bool bOldIns = pWrtShell->IsInsMode();
pWrtShell->SetInsMode( sal_True );
pWrtShell->StartAllAction();
pWrtShell->StartUndo(UNDO_DELETE);
if( !bSelection )
{
if(pWrtShell->IsEndWrd())
pWrtShell->Left(CRSR_SKIP_CELLS, sal_False, 1, sal_False );
pWrtShell->SelWrd();
// make sure the selection build later from the
// data below does not include footnotes and other
// "in word" character to the left and right in order
// to preserve those. Therefore count those "in words"
// in order to modify the selection accordingly.
const sal_Unicode* pChar = rLookUpText.GetBuffer();
xub_StrLen nLeft = 0;
while (pChar && *pChar++ == CH_TXTATR_INWORD)
++nLeft;
pChar = rLookUpText.Len() ? rLookUpText.GetBuffer() + rLookUpText.Len() - 1 : 0;
xub_StrLen nRight = 0;
while (pChar && *pChar-- == CH_TXTATR_INWORD)
++nRight;
// adjust existing selection
SwPaM *pCrsr = pWrtShell->GetCrsr();
pCrsr->GetPoint()->nContent/*.nIndex*/ -= nRight;
pCrsr->GetMark()->nContent/*.nIndex*/ += nLeft;
}
pWrtShell->Insert( rSynonmText );
pWrtShell->EndUndo(UNDO_DELETE);
pWrtShell->EndAllAction();
pWrtShell->SetInsMode( bOldIns );
}
/*--------------------------------------------------------------------
Beschreibung: Thesaurus starten
--------------------------------------------------------------------*/
void SwView::StartThesaurus()
{
if (!IsValidSelectionForThesaurus())
return;
SfxErrorContext aContext( ERRCTX_SVX_LINGU_THESAURUS, aEmptyStr, pEditWin,
RID_SVXERRCTX, &DIALOG_MGR() );
// Sprache rausholen
//
LanguageType eLang = pWrtShell->GetCurLang();
if( LANGUAGE_SYSTEM == eLang )
eLang = GetAppLanguage();
if( eLang == LANGUAGE_DONTKNOW || eLang == LANGUAGE_NONE )
{
LanguageType nLanguage = LANGUAGE_NONE;
SpellError( &nLanguage );
return;
}
SwViewOption* pVOpt = (SwViewOption*)pWrtShell->GetViewOptions();
sal_Bool bOldIdle = pVOpt->IsIdle();
pVOpt->SetIdle( sal_False );
// get initial LookUp text
const sal_Bool bSelection = ((SwCrsrShell*)pWrtShell)->HasSelection();
String aTmp = GetThesaurusLookUpText( bSelection );
Reference< XThesaurus > xThes( ::GetThesaurus() );
AbstractThesaurusDialog *pDlg = NULL;
if ( !xThes.is() || !xThes->hasLocale( SvxCreateLocale( eLang ) ) )
SpellError( &eLang );
else
{
// create dialog
{ //Scope for SwWait-Object
SwWait aWait( *GetDocShell(), true );
// load library with dialog only on demand ...
SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
pDlg = pFact->CreateThesaurusDialog( &GetEditWin(), xThes, aTmp, eLang );
}
if ( pDlg->Execute()== RET_OK )
InsertThesaurusSynonym( pDlg->GetWord(), aTmp, bSelection );
}
delete pDlg;
pVOpt->SetIdle( bOldIdle );
}
/*--------------------------------------------------------------------
Beschreibung: Online-Vorschlaege anbieten
*--------------------------------------------------------------------*/
//!! Start of extra code for context menu modifying extensions
struct ExecuteInfo
{
uno::Reference< frame::XDispatch > xDispatch;
util::URL aTargetURL;
uno::Sequence< PropertyValue > aArgs;
};
class AsyncExecute
{
public:
DECL_STATIC_LINK( AsyncExecute, ExecuteHdl_Impl, ExecuteInfo* );
};
IMPL_STATIC_LINK_NOINSTANCE( AsyncExecute, ExecuteHdl_Impl, ExecuteInfo*, pExecuteInfo )
{
const sal_uInt32 nRef = Application::ReleaseSolarMutex();
try
{
// Asynchronous execution as this can lead to our own destruction!
// Framework can recycle our current frame and the layout manager disposes all user interface
// elements if a component gets detached from its frame!
pExecuteInfo->xDispatch->dispatch( pExecuteInfo->aTargetURL, pExecuteInfo->aArgs );
}
catch ( Exception& )
{
}
Application::AcquireSolarMutex( nRef );
delete pExecuteInfo;
return 0;
}
//!! End of extra code for context menu modifying extensions
sal_Bool SwView::ExecSpellPopup(const Point& rPt)
{
sal_Bool bRet = sal_False;
const SwViewOption* pVOpt = pWrtShell->GetViewOptions();
if( pVOpt->IsOnlineSpell() &&
!pWrtShell->IsSelection())
{
if (pWrtShell->GetSelectionType() & nsSelectionType::SEL_DRW_TXT)
bRet = ExecDrwTxtSpellPopup(rPt);
else if (!pWrtShell->IsSelFrmMode())
{
const sal_Bool bOldViewLock = pWrtShell->IsViewLocked();
pWrtShell->LockView( sal_True );
pWrtShell->Push();
SwRect aToFill;
// decide which variant of the context menu to use...
// if neither spell checking nor grammar checking provides suggestions use the
// default context menu.
bool bUseGrammarContext = false;
Reference< XSpellAlternatives > xAlt( pWrtShell->GetCorrection(&rPt, aToFill) );
/*linguistic2::*/ProofreadingResult aGrammarCheckRes;
sal_Int32 nErrorPosInText = -1;
sal_Int32 nErrorInResult = -1;
uno::Sequence< rtl::OUString > aSuggestions;
bool bCorrectionRes = false;
if (!xAlt.is() || xAlt->getAlternatives().getLength() == 0)
{
bCorrectionRes = pWrtShell->GetGrammarCorrection( aGrammarCheckRes, nErrorPosInText, nErrorInResult, aSuggestions, &rPt, aToFill );
::rtl::OUString aMessageText;
if (nErrorInResult >= 0)
aMessageText = aGrammarCheckRes.aErrors[ nErrorInResult ].aShortComment;
// we like to use the grammar checking context menu if we either get
// some suggestions or at least a comment about the error found...
bUseGrammarContext = bCorrectionRes &&
(aSuggestions.getLength() > 0 || aMessageText.getLength() > 0);
}
// open respective context menu for spell check or grammar errors with correction suggestions...
if ((!bUseGrammarContext && xAlt.is()) ||
(bUseGrammarContext && bCorrectionRes && aGrammarCheckRes.aErrors.getLength() > 0))
{
// get paragraph text
String aParaText;
SwPosition aPoint( *pWrtShell->GetCrsr()->GetPoint() );
const SwTxtNode *pNode = dynamic_cast< const SwTxtNode * >(
&aPoint.nNode.GetNode() );
if (pNode)
aParaText = pNode->GetTxt(); // this may include hidden text but that should be Ok
else
{
DBG_ERROR( "text node expected but not found" );
}
bRet = sal_True;
pWrtShell->SttSelect();
std::auto_ptr< SwSpellPopup > pPopup;
if (bUseGrammarContext)
{
sal_Int32 nPos = aPoint.nContent.GetIndex();
(void) nPos;
pPopup = std::auto_ptr< SwSpellPopup >(new SwSpellPopup( pWrtShell, aGrammarCheckRes, nErrorInResult, aSuggestions, aParaText ));
}
else
pPopup = std::auto_ptr< SwSpellPopup >(new SwSpellPopup( pWrtShell, xAlt, aParaText ));
ui::ContextMenuExecuteEvent aEvent;
const Point aPixPos = GetEditWin().LogicToPixel( rPt );
aEvent.SourceWindow = VCLUnoHelper::GetInterface( pEditWin );
aEvent.ExecutePosition.X = aPixPos.X();
aEvent.ExecutePosition.Y = aPixPos.Y();
Menu* pMenu = 0;
::rtl::OUString sMenuName = ::rtl::OUString::createFromAscii(
bUseGrammarContext ? "private:resource/GrammarContextMenu" : "private:resource/SpellContextMenu");
if(TryContextMenuInterception( *pPopup, sMenuName, pMenu, aEvent ))
{
//! happy hacking for context menu modifying extensions of this
//! 'custom made' menu... *sigh* (code copied from sfx2 and framework)
if ( pMenu )
{
OUString aSlotURL( RTL_CONSTASCII_USTRINGPARAM( "slot:" ));
sal_uInt16 nId = ((PopupMenu*)pMenu)->Execute(pEditWin, aPixPos);
OUString aCommand = ((PopupMenu*)pMenu)->GetItemCommand(nId);
if (aCommand.getLength() == 0 )
{
if(!ExecuteMenuCommand( *dynamic_cast<PopupMenu*>(pMenu), *GetViewFrame(), nId ))
pPopup->Execute(nId);
}
else
{
SfxViewFrame *pSfxViewFrame = GetViewFrame();
uno::Reference< frame::XFrame > xFrame;
if ( pSfxViewFrame )
xFrame = pSfxViewFrame->GetFrame().GetFrameInterface();
com::sun::star::util::URL aURL;
uno::Reference< frame::XDispatchProvider > xDispatchProvider( xFrame, UNO_QUERY );
uno::Reference< lang::XMultiServiceFactory > xMgr( utl::getProcessServiceFactory(), uno::UNO_QUERY );
try
{
uno::Reference< frame::XDispatch > xDispatch;
uno::Reference< util::XURLTransformer > xURLTransformer;
if (xMgr.is())
{
xURLTransformer = uno::Reference< util::XURLTransformer >( xMgr->createInstance(
C2U("com.sun.star.util.URLTransformer")), UNO_QUERY);
}
aURL.Complete = aCommand;
xURLTransformer->parseStrict(aURL);
uno::Sequence< beans::PropertyValue > aArgs;
xDispatch = xDispatchProvider->queryDispatch( aURL, rtl::OUString(), 0 );
if (xDispatch.is())
{
// Execute dispatch asynchronously
ExecuteInfo* pExecuteInfo = new ExecuteInfo;
pExecuteInfo->xDispatch = xDispatch;
pExecuteInfo->aTargetURL = aURL;
pExecuteInfo->aArgs = aArgs;
Application::PostUserEvent( STATIC_LINK(0, AsyncExecute , ExecuteHdl_Impl), pExecuteInfo );
}
}
catch (Exception &)
{
}
}
}
else
{
pPopup->Execute( aToFill.SVRect(), pEditWin );
}
}
}
pWrtShell->Pop( sal_False );
pWrtShell->LockView( bOldViewLock );
}
}
return bRet;
}
/** Function: ExecSmartTagPopup
This function shows the popup menu for smarttag
actions.
*/
sal_Bool SwView::ExecSmartTagPopup( const Point& rPt )
{
sal_Bool bRet = sal_False;
const sal_Bool bOldViewLock = pWrtShell->IsViewLocked();
pWrtShell->LockView( sal_True );
pWrtShell->Push();
// get word that was clicked on
// This data structure maps a smart tag type string to the property bag
SwRect aToFill;
Sequence< rtl::OUString > aSmartTagTypes;
Sequence< Reference< container::XStringKeyMap > > aStringKeyMaps;
Reference<text::XTextRange> xRange;
pWrtShell->GetSmartTagTerm( rPt, aToFill, aSmartTagTypes, aStringKeyMaps, xRange);
if ( xRange.is() && aSmartTagTypes.getLength() )
{
bRet = sal_True;
pWrtShell->SttSelect();
SwSmartTagPopup aPopup( this, aSmartTagTypes, aStringKeyMaps, xRange );
aPopup.Execute( aToFill.SVRect(), pEditWin );
}
pWrtShell->Pop( sal_False );
pWrtShell->LockView( bOldViewLock );
return bRet;
}
class SwFieldPopup : public PopupMenu
{
public:
SwFieldPopup() {
InsertItem(1, ::rtl::OUString::createFromAscii("Hello"));
}
};
class SwFieldListBox : public ListBox
{
public:
SwFieldListBox(Window* pParent) : ListBox(pParent /*, WB_DROPDOWN*/) {
}
void *GetImplWin() {
return NULL; //FIXME!!!
// return mpImplWin;
}
protected:
virtual void LoseFocus() {
// printf("ListBox: lose focus!!\n");
ListBox::LoseFocus();
}
virtual void Select() {
// printf("SELECT!!! IsTravelSelect=%i\n", IsTravelSelect());
ListBox::Select();
}
};
class SwFieldDialog : public Dialog
{
private:
SwFieldListBox aListBox;
Edit aText;
int selection;
DECL_LINK( MyListBoxHandler, ListBox * );
public:
SwFieldDialog(Window* parent, IFieldmark *fieldBM) : Dialog(parent, WB_BORDER | WB_SYSTEMWINDOW | WB_NOSHADOW ), aListBox(this), aText(this, WB_RIGHT | WB_READONLY), selection(-1) {
assert(fieldBM!=NULL);
if (fieldBM!=NULL) {
const IFieldmark::parameter_map_t* const pParameters = fieldBM->GetParameters();
IFieldmark::parameter_map_t::const_iterator pListEntries = pParameters->find(::rtl::OUString::createFromAscii(ODF_FORMDROPDOWN_LISTENTRY));
if(pListEntries != pParameters->end())
{
Sequence< ::rtl::OUString> vListEntries;
pListEntries->second >>= vListEntries;
for( ::rtl::OUString* pCurrent = vListEntries.getArray();
pCurrent != vListEntries.getArray() + vListEntries.getLength();
++pCurrent)
{
aListBox.InsertEntry(*pCurrent);
}
}
}
Size lbSize=aListBox.GetOptimalSize(WINDOWSIZE_PREFERRED);
lbSize.Width()+=50;
lbSize.Height()+=20;
aListBox.SetSizePixel(lbSize);
aListBox.SetSelectHdl( LINK( this, SwFieldDialog, MyListBoxHandler ) );
aListBox.Show();
aText.SetText(rtl::OUString::createFromAscii("Cancel"));
Size tSize=aText.GetOptimalSize(WINDOWSIZE_PREFERRED);
aText.SetSizePixel(Size(lbSize.Width(), tSize.Height()));
aText.SetPosPixel(Point(0, lbSize.Height()));
aText.Show();
SetSizePixel(Size(lbSize.Width(), lbSize.Height()+tSize.Height()));
// SetSizePixel(Size(200, 200));
}
int getSelection() {
return selection;
}
protected:
/*
virtual void LoseFocus() {
printf("lose focus!!\n");
Dialog::LoseFocus();
printf("close:\n");
EndDialog(8);
}
*/
virtual long PreNotify( NotifyEvent& rNEvt ) {
if (rNEvt.GetType() == EVENT_LOSEFOCUS && aListBox.GetImplWin()==rNEvt.GetWindow()) {
EndDialog(8);
return 1;
}
if (rNEvt.GetType() == EVENT_KEYINPUT) {
// printf("PreNotify::KEYINPUT\n");
}
return Dialog::PreNotify(rNEvt);
}
};
IMPL_LINK( SwFieldDialog, MyListBoxHandler, ListBox *, pBox )
{
// printf("### DROP DOWN SELECT... IsTravelSelect=%i\n", pBox->IsTravelSelect());
if (pBox->IsTravelSelect()) {
return 0;
} else {
this->selection=pBox->GetSelectEntryPos();
EndDialog(9); //@TODO have meaningfull returns...
return 1;
}
}
sal_Bool SwView::ExecFieldPopup( const Point& rPt, IFieldmark *fieldBM )
{
sal_Bool bRet = sal_False;
const sal_Bool bOldViewLock = pWrtShell->IsViewLocked();
pWrtShell->LockView( sal_True );
pWrtShell->Push();
bRet=sal_True;
const Point aPixPos = GetEditWin().LogicToPixel( rPt );
SwFieldDialog aFldDlg(pEditWin, fieldBM);
aFldDlg.SetPosPixel(pEditWin->OutputToScreenPixel(aPixPos));
/*short ret=*/aFldDlg.Execute();
sal_Int32 selection=aFldDlg.getSelection();
if (selection>=0) {
(*fieldBM->GetParameters())[::rtl::OUString::createFromAscii(ODF_FORMDROPDOWN_RESULT)] = makeAny(selection);
}
pWrtShell->Pop( sal_False );
pWrtShell->LockView( bOldViewLock );
return bRet;
}