1429 lines
55 KiB
C++
1429 lines
55 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* 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 .
|
|
*/
|
|
|
|
#include <comphelper/string.hxx>
|
|
#include <comphelper/lok.hxx>
|
|
#include <scitems.hxx>
|
|
#include <editeng/eeitem.hxx>
|
|
#include <i18nutil/unicode.hxx>
|
|
#include <i18nutil/transliteration.hxx>
|
|
|
|
#include <svx/clipfmtitem.hxx>
|
|
#include <svx/svxdlg.hxx>
|
|
#include <editeng/contouritem.hxx>
|
|
#include <editeng/outliner.hxx>
|
|
#include <editeng/crossedoutitem.hxx>
|
|
#include <editeng/editeng.hxx>
|
|
#include <editeng/editview.hxx>
|
|
#include <editeng/escapementitem.hxx>
|
|
#include <editeng/flditem.hxx>
|
|
#include <editeng/flstitem.hxx>
|
|
#include <editeng/fontitem.hxx>
|
|
#include <editeng/urlfieldhelper.hxx>
|
|
#include <editeng/editund2.hxx>
|
|
#include <svx/hlnkitem.hxx>
|
|
#include <vcl/EnumContext.hxx>
|
|
#include <editeng/postitem.hxx>
|
|
#include <editeng/scripttypeitem.hxx>
|
|
#include <editeng/shdditem.hxx>
|
|
#include <editeng/udlnitem.hxx>
|
|
#include <editeng/wghtitem.hxx>
|
|
#include <sfx2/bindings.hxx>
|
|
#include <sfx2/dispatch.hxx>
|
|
#include <sfx2/docfile.hxx>
|
|
#include <sfx2/docfilt.hxx>
|
|
#include <sfx2/namedcolor.hxx>
|
|
#include <sfx2/msg.hxx>
|
|
#include <sfx2/objface.hxx>
|
|
#include <sfx2/objsh.hxx>
|
|
#include <sfx2/request.hxx>
|
|
#include <sfx2/viewfrm.hxx>
|
|
#include <svtools/cliplistener.hxx>
|
|
#include <svl/whiter.hxx>
|
|
#include <sot/formats.hxx>
|
|
#include <vcl/transfer.hxx>
|
|
#include <vcl/unohelp2.hxx>
|
|
#include <svl/stritem.hxx>
|
|
#include <editeng/colritem.hxx>
|
|
|
|
#include <editsh.hxx>
|
|
#include <global.hxx>
|
|
#include <appoptio.hxx>
|
|
#include <scmod.hxx>
|
|
#include <sc.hrc>
|
|
#include <inputhdl.hxx>
|
|
#include <viewutil.hxx>
|
|
#include <viewdata.hxx>
|
|
#include <document.hxx>
|
|
#include <reffind.hxx>
|
|
#include <tabvwsh.hxx>
|
|
#include <editutil.hxx>
|
|
#include <globstr.hrc>
|
|
#include <scresid.hxx>
|
|
#include <gridwin.hxx>
|
|
|
|
#define ShellClass_ScEditShell
|
|
#include <scslots.hxx>
|
|
|
|
#include <scui_def.hxx>
|
|
#include <scabstdlg.hxx>
|
|
#include <memory>
|
|
|
|
using namespace ::com::sun::star;
|
|
|
|
|
|
SFX_IMPL_INTERFACE(ScEditShell, SfxShell)
|
|
|
|
void ScEditShell::InitInterface_Impl()
|
|
{
|
|
GetStaticInterface()->RegisterPopupMenu(u"celledit"_ustr);
|
|
}
|
|
|
|
ScEditShell::ScEditShell(EditView* pView, ScViewData& rData) :
|
|
pEditView (pView),
|
|
rViewData (rData),
|
|
bPastePossible (false),
|
|
bIsInsertMode (true)
|
|
{
|
|
SetPool( pEditView->getEditEngine().GetEmptyItemSet().GetPool() );
|
|
SetUndoManager( &pEditView->getEditEngine().GetUndoManager() );
|
|
SetName(u"EditCell"_ustr);
|
|
SfxShell::SetContextName(vcl::EnumContext::GetContextName(vcl::EnumContext::Context::EditCell));
|
|
}
|
|
|
|
ScEditShell::~ScEditShell()
|
|
{
|
|
if ( mxClipEvtLstnr.is() )
|
|
{
|
|
mxClipEvtLstnr->RemoveListener( rViewData.GetActiveWin() );
|
|
|
|
// The listener may just now be waiting for the SolarMutex and call the link
|
|
// afterwards, in spite of RemoveListener. So the link has to be reset, too.
|
|
mxClipEvtLstnr->ClearCallbackLink();
|
|
}
|
|
}
|
|
|
|
ScInputHandler* ScEditShell::GetMyInputHdl()
|
|
{
|
|
return ScModule::get()->GetInputHdl(rViewData.GetViewShell());
|
|
}
|
|
|
|
void ScEditShell::SetEditView(EditView* pView)
|
|
{
|
|
pEditView = pView;
|
|
pEditView->SetInsertMode( bIsInsertMode );
|
|
SetPool( pEditView->getEditEngine().GetEmptyItemSet().GetPool() );
|
|
SetUndoManager( &pEditView->getEditEngine().GetUndoManager() );
|
|
}
|
|
|
|
static void lcl_RemoveAttribs( EditView& rEditView )
|
|
{
|
|
ScEditEngineDefaulter* pEngine = static_cast<ScEditEngineDefaulter*>(&rEditView.getEditEngine());
|
|
|
|
bool bOld = pEngine->SetUpdateLayout(false);
|
|
|
|
OUString aName = ScResId( STR_UNDO_DELETECONTENTS );
|
|
ViewShellId nViewShellId(-1);
|
|
if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell())
|
|
nViewShellId = pViewSh->GetViewShellId();
|
|
pEngine->GetUndoManager().EnterListAction( aName, aName, 0, nViewShellId );
|
|
|
|
rEditView.RemoveAttribs(true);
|
|
pEngine->RepeatDefaults(); // paragraph attributes from cell formats must be preserved
|
|
|
|
pEngine->GetUndoManager().LeaveListAction();
|
|
|
|
pEngine->SetUpdateLayout(bOld);
|
|
}
|
|
|
|
static void lclInsertCharacter( EditView* pTableView, EditView* pTopView, sal_Unicode cChar )
|
|
{
|
|
OUString aString( cChar );
|
|
if( pTableView )
|
|
pTableView->InsertText( aString );
|
|
if( pTopView )
|
|
pTopView->InsertText( aString );
|
|
}
|
|
|
|
void ScEditShell::Execute( SfxRequest& rReq )
|
|
{
|
|
const SfxItemSet* pReqArgs = rReq.GetArgs();
|
|
sal_uInt16 nSlot = rReq.GetSlot();
|
|
SfxBindings& rBindings = rViewData.GetBindings();
|
|
|
|
ScInputHandler* pHdl = GetMyInputHdl();
|
|
OSL_ENSURE(pHdl,"no ScInputHandler");
|
|
|
|
EditView* pTopView = pHdl->GetTopView(); // Has thee input cell the focus?
|
|
EditView* pTableView = pHdl->GetTableView();
|
|
|
|
OSL_ENSURE(pTableView,"no EditView :-(");
|
|
/* #i91683# No EditView if spell-check dialog is active and positioned on
|
|
* an error and user immediately (without double click or F2) selected a
|
|
* text portion of that cell with the mouse and wanted to modify it. */
|
|
/* FIXME: Bailing out only cures the symptom and prevents a crash, no edit
|
|
* action is possible. A real fix somehow would need to create a valid
|
|
* EditView from the spell-check view. */
|
|
if (!pTableView)
|
|
return;
|
|
|
|
EditEngine& rEngine = pTableView->getEditEngine();
|
|
|
|
pHdl->DataChanging();
|
|
bool bSetSelIsRef = false;
|
|
bool bSetModified = true;
|
|
|
|
switch ( nSlot )
|
|
{
|
|
case SID_ATTR_INSERT:
|
|
case FID_INS_CELL_CONTENTS: // Insert taste, while defined as Acc
|
|
bIsInsertMode = !pTableView->IsInsertMode();
|
|
pTableView->SetInsertMode( bIsInsertMode );
|
|
if (pTopView)
|
|
pTopView->SetInsertMode( bIsInsertMode );
|
|
rBindings.Invalidate( SID_ATTR_INSERT );
|
|
break;
|
|
|
|
case SID_THES:
|
|
{
|
|
OUString aReplaceText;
|
|
const SfxStringItem* pItem2 = rReq.GetArg(FN_PARAM_THES_WORD_REPLACE);
|
|
if (pItem2)
|
|
aReplaceText = pItem2->GetValue();
|
|
if (!aReplaceText.isEmpty())
|
|
ReplaceTextWithSynonym( *pEditView, aReplaceText );
|
|
}
|
|
break;
|
|
|
|
case SID_COPY:
|
|
pTableView->Copy();
|
|
bSetModified = false;
|
|
break;
|
|
|
|
case SID_CUT:
|
|
pTableView->Cut();
|
|
if (pTopView)
|
|
pTopView->DeleteSelected();
|
|
break;
|
|
|
|
case SID_PASTE:
|
|
{
|
|
EVControlBits nControl = pTableView->GetControlWord();
|
|
if (pTopView)
|
|
{
|
|
pTopView->Paste();
|
|
pTableView->SetControlWord(nControl | EVControlBits::SINGLELINEPASTE);
|
|
}
|
|
|
|
pTableView->PasteSpecial();
|
|
pTableView->SetControlWord(nControl);
|
|
}
|
|
break;
|
|
|
|
case SID_DELETE:
|
|
pTableView->DeleteSelected();
|
|
if (pTopView)
|
|
pTopView->DeleteSelected();
|
|
break;
|
|
|
|
case SID_CELL_FORMAT_RESET: // "Standard"
|
|
lcl_RemoveAttribs( *pTableView );
|
|
if ( pTopView )
|
|
lcl_RemoveAttribs( *pTopView );
|
|
break;
|
|
|
|
case SID_CLIPBOARD_FORMAT_ITEMS:
|
|
{
|
|
SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
|
|
const SfxPoolItem* pItem;
|
|
if ( pReqArgs && pReqArgs->GetItemState(nSlot, true, &pItem) == SfxItemState::SET )
|
|
if (auto pIntItem = dynamic_cast<const SfxUInt32Item*>( pItem))
|
|
nFormat = static_cast<SotClipboardFormatId>(pIntItem->GetValue());
|
|
|
|
if ( nFormat != SotClipboardFormatId::NONE )
|
|
{
|
|
if (SotClipboardFormatId::STRING == nFormat)
|
|
pTableView->Paste();
|
|
else
|
|
pTableView->PasteSpecial();
|
|
|
|
if (pTopView)
|
|
pTopView->Paste();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SID_PASTE_SPECIAL:
|
|
{
|
|
SvxAbstractDialogFactory* pFact = SvxAbstractDialogFactory::Create();
|
|
ScopedVclPtr<SfxAbstractPasteDialog> pDlg(pFact->CreatePasteDialog(rViewData.GetDialogParent()));
|
|
SotClipboardFormatId nFormat = SotClipboardFormatId::NONE;
|
|
pDlg->Insert( SotClipboardFormatId::STRING, OUString() );
|
|
pDlg->Insert( SotClipboardFormatId::RTF, OUString() );
|
|
pDlg->Insert( SotClipboardFormatId::RICHTEXT, OUString() );
|
|
// Do not offer SotClipboardFormatId::STRING_TSVC for
|
|
// in-cell paste.
|
|
|
|
TransferableDataHelper aDataHelper(
|
|
TransferableDataHelper::CreateFromSystemClipboard( rViewData.GetActiveWin() ) );
|
|
|
|
nFormat = pDlg->GetFormat( aDataHelper.GetTransferable() );
|
|
pDlg.disposeAndClear();
|
|
|
|
// while the dialog was open, edit mode may have been stopped
|
|
if (!ScModule::get()->IsInputMode())
|
|
return;
|
|
|
|
if (nFormat != SotClipboardFormatId::NONE)
|
|
{
|
|
if (SotClipboardFormatId::STRING == nFormat)
|
|
pTableView->Paste();
|
|
else
|
|
pTableView->PasteSpecial();
|
|
|
|
if (pTopView)
|
|
pTopView->Paste();
|
|
}
|
|
|
|
if (vcl::Window* pViewWindow = pTopView ? pTopView->GetWindow() : nullptr)
|
|
pViewWindow->GrabFocus();
|
|
}
|
|
break;
|
|
|
|
case SID_PASTE_UNFORMATTED:
|
|
{
|
|
pTableView->Paste();
|
|
|
|
if (pTopView)
|
|
{
|
|
pTopView->Paste();
|
|
if (vcl::Window* pViewWindow = pTopView->GetWindow())
|
|
pViewWindow->GrabFocus();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SID_SELECTALL:
|
|
{
|
|
sal_Int32 nPar = rEngine.GetParagraphCount();
|
|
if (nPar)
|
|
{
|
|
sal_Int32 nLen = rEngine.GetTextLen(nPar-1);
|
|
pTableView->SetSelection(ESelection(0,0,nPar-1,nLen));
|
|
if (pTopView)
|
|
pTopView->SetSelection(ESelection(0,0,nPar-1,nLen));
|
|
rBindings.Invalidate( SID_ATTR_CHAR_FONT );
|
|
rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
|
|
rBindings.Invalidate( SID_ATTR_CHAR_WEIGHT );
|
|
rBindings.Invalidate( SID_ATTR_CHAR_POSTURE );
|
|
rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE );
|
|
rBindings.Invalidate( SID_ATTR_CHAR_STRIKEOUT );
|
|
rBindings.Invalidate( SID_ATTR_CHAR_SHADOWED );
|
|
rBindings.Invalidate( SID_ATTR_CHAR_KERNING );
|
|
rBindings.Invalidate( SID_ATTR_CHAR_COLOR );
|
|
rBindings.Invalidate( SID_SET_SUPER_SCRIPT );
|
|
rBindings.Invalidate( SID_SET_SUB_SCRIPT );
|
|
}
|
|
}
|
|
return;
|
|
case SID_UNICODE_NOTATION_TOGGLE:
|
|
{
|
|
EditView* pActiveView = pHdl->GetActiveView();
|
|
if( pActiveView )
|
|
{
|
|
ESelection aSel( pActiveView->GetSelection() );
|
|
OUString sInput(aSel.HasRange() ? pActiveView->GetSelected()
|
|
: rEngine.GetText());
|
|
|
|
if (aSel.start.nIndex > aSel.end.nIndex)
|
|
aSel.end.nIndex = aSel.start.nIndex;
|
|
|
|
//calculate a valid end-position by reading logical characters
|
|
sal_Int32 nUtf16Pos=0;
|
|
while ((nUtf16Pos < sInput.getLength()) && (nUtf16Pos < aSel.end.nIndex))
|
|
{
|
|
sInput.iterateCodePoints(&nUtf16Pos);
|
|
if (nUtf16Pos > aSel.end.nIndex)
|
|
aSel.end.nIndex = nUtf16Pos;
|
|
}
|
|
|
|
ToggleUnicodeCodepoint aToggle;
|
|
while( nUtf16Pos && aToggle.AllowMoreInput( sInput[nUtf16Pos-1]) )
|
|
--nUtf16Pos;
|
|
OUString sReplacement = aToggle.ReplacementString();
|
|
if( !sReplacement.isEmpty() )
|
|
{
|
|
aSel.start.nIndex = aSel.end.nIndex - aToggle.StringToReplace().getLength();
|
|
pTableView->SetSelection( aSel );
|
|
pTableView->InsertText(sReplacement, true);
|
|
if( pTopView )
|
|
{
|
|
pTopView->SetSelection( aSel );
|
|
pTopView->InsertText(sReplacement, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SID_CHARMAP:
|
|
{
|
|
SvtScriptType nScript = pTableView->GetSelectedScriptType();
|
|
sal_uInt16 nFontWhich = ( nScript == SvtScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK :
|
|
( ( nScript == SvtScriptType::COMPLEX ) ? EE_CHAR_FONTINFO_CTL :
|
|
EE_CHAR_FONTINFO );
|
|
auto const attribs = pTableView->GetAttribs();
|
|
const SvxFontItem& rItem = static_cast<const SvxFontItem&>(
|
|
attribs.Get(nFontWhich));
|
|
|
|
OUString aString;
|
|
std::shared_ptr<SvxFontItem> aNewItem(std::make_shared<SvxFontItem>(EE_CHAR_FONTINFO));
|
|
|
|
const SfxItemSet *pArgs = rReq.GetArgs();
|
|
const SfxPoolItem* pItem = nullptr;
|
|
if( pArgs )
|
|
pArgs->GetItemState(SID_CHARMAP, false, &pItem);
|
|
|
|
if ( pItem )
|
|
{
|
|
aString = static_cast<const SfxStringItem*>(pItem)->GetValue();
|
|
const SfxStringItem* pFontItem = pArgs->GetItemIfSet( SID_ATTR_SPECIALCHAR, false);
|
|
if ( pFontItem )
|
|
{
|
|
const OUString& aFontName(pFontItem->GetValue());
|
|
vcl::Font aFont(aFontName, Size(1,1)); // Size just because CTOR
|
|
// tdf#125054 see comment in drtxob.cxx, same ID
|
|
aNewItem = std::make_shared<SvxFontItem>(
|
|
aFont.GetFamilyType(), aFont.GetFamilyName(),
|
|
aFont.GetStyleName(), aFont.GetPitch(),
|
|
aFont.GetCharSet(), ATTR_FONT);
|
|
}
|
|
else
|
|
{
|
|
aNewItem.reset(rItem.Clone());
|
|
}
|
|
|
|
// tdf#125054 force Item to correct intended ID
|
|
aNewItem->SetWhich(EE_CHAR_FONTINFO);
|
|
}
|
|
else
|
|
{
|
|
ScViewUtil::ExecuteCharMap(rItem, *rViewData.GetViewShell());
|
|
|
|
// while the dialog was open, edit mode may have been stopped
|
|
if (!ScModule::get()->IsInputMode())
|
|
return;
|
|
}
|
|
|
|
if ( !aString.isEmpty() )
|
|
{
|
|
// if string contains WEAK characters, set all fonts
|
|
SvtScriptType nSetScript;
|
|
ScDocument& rDoc = rViewData.GetDocument();
|
|
if ( rDoc.HasStringWeakCharacters( aString ) )
|
|
nSetScript = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
|
|
else
|
|
nSetScript = rDoc.GetStringScriptType( aString );
|
|
|
|
SfxItemSet aSet( pTableView->GetEmptyItemSet() );
|
|
SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, GetPool() );
|
|
aSetItem.PutItemForScriptType( nSetScript, *aNewItem );
|
|
aSet.Put( aSetItem.GetItemSet(), false );
|
|
|
|
// SetAttribs on the View selects a word, when nothing is selected
|
|
pTableView->getEditEngine().QuickSetAttribs( aSet, pTableView->GetSelection() );
|
|
pTableView->InsertText(aString);
|
|
if (pTopView)
|
|
pTopView->InsertText(aString);
|
|
|
|
SfxStringItem aStringItem( SID_CHARMAP, aString );
|
|
SfxStringItem aFontItem( SID_ATTR_SPECIALCHAR, aNewItem->GetFamilyName() );
|
|
rReq.AppendItem( aFontItem );
|
|
rReq.AppendItem( aStringItem );
|
|
rReq.Done();
|
|
|
|
}
|
|
|
|
if (vcl::Window* pViewWindow = pTopView ? pTopView->GetWindow() : nullptr)
|
|
pViewWindow->GrabFocus();
|
|
}
|
|
break;
|
|
|
|
case FID_INSERT_NAME:
|
|
{
|
|
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
|
|
|
|
ScopedVclPtr<AbstractScNamePasteDlg> pDlg(pFact->CreateScNamePasteDlg(rViewData.GetDialogParent(), rViewData.GetDocShell()));
|
|
short nRet = pDlg->Execute();
|
|
// pDlg is needed below
|
|
|
|
// while the dialog was open, edit mode may have been stopped
|
|
if (!ScModule::get()->IsInputMode())
|
|
return;
|
|
|
|
if ( nRet == BTN_PASTE_NAME )
|
|
{
|
|
std::vector<OUString> aNames = pDlg->GetSelectedNames();
|
|
if (!aNames.empty())
|
|
{
|
|
OUStringBuffer aBuffer;
|
|
for (const auto& rName : aNames)
|
|
{
|
|
aBuffer.append(rName + " ");
|
|
}
|
|
const OUString s = aBuffer.makeStringAndClear();
|
|
pTableView->InsertText(s);
|
|
if (pTopView)
|
|
pTopView->InsertText(s);
|
|
}
|
|
}
|
|
pDlg.disposeAndClear();
|
|
|
|
if (vcl::Window* pViewWindow = pTopView ? pTopView->GetWindow() : nullptr)
|
|
pViewWindow->GrabFocus();
|
|
}
|
|
break;
|
|
|
|
case SID_CHAR_DLG_EFFECT:
|
|
case SID_CHAR_DLG:
|
|
{
|
|
SfxItemSet aAttrs( pTableView->GetAttribs() );
|
|
|
|
SfxObjectShell* pObjSh = rViewData.GetSfxDocShell();
|
|
|
|
ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
|
|
|
|
ScopedVclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScCharDlg(
|
|
rViewData.GetDialogParent(), &aAttrs, pObjSh, false));
|
|
if (nSlot == SID_CHAR_DLG_EFFECT)
|
|
{
|
|
pDlg->SetCurPageId(u"fonteffects"_ustr);
|
|
}
|
|
short nRet = pDlg->Execute();
|
|
// pDlg is needed below
|
|
|
|
// while the dialog was open, edit mode may have been stopped
|
|
if (!ScModule::get()->IsInputMode())
|
|
return;
|
|
|
|
if ( nRet == RET_OK )
|
|
{
|
|
const SfxItemSet* pOut = pDlg->GetOutputItemSet();
|
|
pTableView->SetAttribs( *pOut );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SID_TOGGLE_REL:
|
|
{
|
|
/* TODO: MLFORMULA: this should work also with multi-line formulas. */
|
|
if (rEngine.GetParagraphCount() == 1)
|
|
{
|
|
OUString aText = rEngine.GetText();
|
|
ESelection aSel = pEditView->GetSelection(); // current View
|
|
|
|
ScDocument& rDoc = rViewData.GetDocument();
|
|
ScRefFinder aFinder(aText, rViewData.GetCurPos(), rDoc, rDoc.GetAddressConvention());
|
|
aFinder.ToggleRel(aSel.start.nIndex, aSel.end.nIndex);
|
|
if (aFinder.GetFound())
|
|
{
|
|
const OUString& aNew = aFinder.GetText();
|
|
ESelection aNewSel( 0,aFinder.GetSelStart(), 0,aFinder.GetSelEnd() );
|
|
rEngine.SetText( aNew );
|
|
pTableView->SetSelection( aNewSel );
|
|
if ( pTopView )
|
|
{
|
|
pTopView->getEditEngine().SetText( aNew );
|
|
pTopView->SetSelection( aNewSel );
|
|
}
|
|
|
|
// reference is being selected -> do not overwrite when typing
|
|
bSetSelIsRef = true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SID_HYPERLINK_SETLINK:
|
|
if( pReqArgs )
|
|
{
|
|
const SfxPoolItem* pItem;
|
|
if ( pReqArgs->GetItemState( SID_HYPERLINK_SETLINK, true, &pItem ) == SfxItemState::SET )
|
|
{
|
|
const SvxHyperlinkItem* pHyper = static_cast<const SvxHyperlinkItem*>(pItem);
|
|
const OUString& rName = pHyper->GetName();
|
|
const OUString& rURL = pHyper->GetURL();
|
|
const OUString& rTarget = pHyper->GetTargetFrame();
|
|
SvxLinkInsertMode eMode = pHyper->GetInsertMode();
|
|
|
|
bool bCellLinksOnly
|
|
= (ScModule::get()->GetAppOptions().GetLinksInsertedLikeMSExcel()
|
|
&& rViewData.GetSfxDocShell()->GetMedium()->GetFilter()->IsMSOFormat())
|
|
|| comphelper::LibreOfficeKit::isActive();
|
|
|
|
bool bDone = false;
|
|
if ( (eMode == HLINK_DEFAULT || eMode == HLINK_FIELD) && !bCellLinksOnly )
|
|
{
|
|
std::unique_ptr<const SvxFieldData> aSvxFieldDataPtr(GetURLField());
|
|
const SvxURLField* pURLField(static_cast<const SvxURLField*>(aSvxFieldDataPtr.get()));
|
|
if ( pURLField )
|
|
{
|
|
// select old field
|
|
|
|
ESelection aSel = pTableView->GetSelection();
|
|
aSel.Adjust();
|
|
aSel.end.nPara = aSel.start.nPara;
|
|
aSel.end.nIndex = aSel.start.nIndex + 1;
|
|
pTableView->SetSelection( aSel );
|
|
|
|
// insert new field
|
|
|
|
SvxURLField aURLField( rURL, rName, SvxURLFormat::Repr );
|
|
aURLField.SetTargetFrame( rTarget );
|
|
SvxFieldItem aURLItem( aURLField, EE_FEATURE_FIELD );
|
|
pTableView->InsertField( aURLItem );
|
|
pTableView->SetSelection( aSel ); // select inserted field
|
|
|
|
// now also fields in the Top-View
|
|
|
|
if ( pTopView )
|
|
{
|
|
aSel = pTopView->GetSelection();
|
|
aSel.end.nPara = aSel.start.nPara;
|
|
aSel.end.nIndex = aSel.start.nIndex + 1;
|
|
pTopView->SetSelection( aSel );
|
|
pTopView->InsertField( aURLItem );
|
|
pTopView->SetSelection( aSel ); // select inserted field
|
|
}
|
|
|
|
bDone = true;
|
|
}
|
|
}
|
|
|
|
if (!bDone)
|
|
{
|
|
if (bCellLinksOnly)
|
|
{
|
|
sal_Int32 nPar = rEngine.GetParagraphCount();
|
|
if (nPar)
|
|
{
|
|
sal_Int32 nLen = rEngine.GetTextLen(nPar - 1);
|
|
pTableView->SetSelection(ESelection(0, 0, nPar - 1, nLen));
|
|
if (pTopView)
|
|
pTopView->SetSelection(ESelection(0, 0, nPar - 1, nLen));
|
|
}
|
|
}
|
|
rViewData.GetViewShell()->
|
|
InsertURL( rName, rURL, rTarget, static_cast<sal_uInt16>(eMode) );
|
|
|
|
// when "Button", the InsertURL in ViewShell turns the EditShell off
|
|
// thus the immediate return statement
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case SID_EDIT_HYPERLINK:
|
|
{
|
|
// Ensure the field is selected first
|
|
pEditView->SelectFieldAtCursor();
|
|
rViewData.GetViewShell()->GetViewFrame().GetDispatcher()->Execute(
|
|
SID_HYPERLINK_DIALOG);
|
|
}
|
|
break;
|
|
case SID_COPY_HYPERLINK_LOCATION:
|
|
{
|
|
const SvxFieldItem* pFieldItem
|
|
= pEditView->GetFieldAtSelection(/*AlsoCheckBeforeCursor=*/true);
|
|
const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr;
|
|
if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
|
|
{
|
|
uno::Reference<datatransfer::clipboard::XClipboard> xClipboard
|
|
= pEditView->GetClipboard();
|
|
vcl::unohelper::TextDataObject::CopyStringTo(pURLField->GetURL(), xClipboard, SfxViewShell::Current());
|
|
}
|
|
}
|
|
break;
|
|
case SID_REMOVE_HYPERLINK:
|
|
{
|
|
URLFieldHelper::RemoveURLField(*pEditView);
|
|
}
|
|
break;
|
|
|
|
case FN_INSERT_SOFT_HYPHEN:
|
|
lclInsertCharacter( pTableView, pTopView, CHAR_SHY );
|
|
break;
|
|
case FN_INSERT_HARDHYPHEN:
|
|
lclInsertCharacter( pTableView, pTopView, CHAR_NBHY );
|
|
break;
|
|
case FN_INSERT_HARD_SPACE:
|
|
lclInsertCharacter( pTableView, pTopView, CHAR_NBSP );
|
|
break;
|
|
case FN_INSERT_NNBSP:
|
|
lclInsertCharacter( pTableView, pTopView, CHAR_NNBSP );
|
|
break;
|
|
case SID_INSERT_RLM:
|
|
lclInsertCharacter( pTableView, pTopView, CHAR_RLM );
|
|
break;
|
|
case SID_INSERT_LRM:
|
|
lclInsertCharacter( pTableView, pTopView, CHAR_LRM );
|
|
break;
|
|
case SID_INSERT_ZWSP:
|
|
lclInsertCharacter( pTableView, pTopView, CHAR_ZWSP );
|
|
break;
|
|
case SID_INSERT_WJ:
|
|
lclInsertCharacter( pTableView, pTopView, CHAR_WJ );
|
|
break;
|
|
case SID_INSERT_FIELD_SHEET:
|
|
{
|
|
SvxTableField aField(rViewData.GetTabNo());
|
|
SvxFieldItem aItem(aField, EE_FEATURE_FIELD);
|
|
pTableView->InsertField(aItem);
|
|
}
|
|
break;
|
|
case SID_INSERT_FIELD_TITLE:
|
|
{
|
|
SvxFileField aField;
|
|
SvxFieldItem aItem(aField, EE_FEATURE_FIELD);
|
|
pTableView->InsertField(aItem);
|
|
}
|
|
break;
|
|
case SID_INSERT_FIELD_DATE_VAR:
|
|
{
|
|
SvxDateField aField;
|
|
SvxFieldItem aItem(aField, EE_FEATURE_FIELD);
|
|
pTableView->InsertField(aItem);
|
|
}
|
|
break;
|
|
}
|
|
|
|
pHdl->DataChanged(false, bSetModified);
|
|
if (bSetSelIsRef)
|
|
pHdl->SetSelIsRef(true);
|
|
}
|
|
|
|
static void lcl_DisableAll( SfxItemSet& rSet ) // disable all slots
|
|
{
|
|
SfxWhichIter aIter( rSet );
|
|
sal_uInt16 nWhich = aIter.FirstWhich();
|
|
while (nWhich)
|
|
{
|
|
rSet.DisableItem( nWhich );
|
|
nWhich = aIter.NextWhich();
|
|
}
|
|
}
|
|
|
|
void ScEditShell::GetState( SfxItemSet& rSet )
|
|
{
|
|
// When deactivating the view, edit mode is stopped, but the EditShell is left active
|
|
// (a shell can't be removed from within Deactivate). In that state, the EditView isn't inserted
|
|
// into the EditEngine, so it can have an invalid selection and must not be used.
|
|
ScInputHandler* pHdl = GetMyInputHdl();
|
|
if ( !rViewData.HasEditView( rViewData.GetActivePart() ) )
|
|
{
|
|
lcl_DisableAll( rSet );
|
|
|
|
// Some items are actually useful and still applicable when in formula building mode: enable
|
|
if (pHdl && pHdl->IsFormulaMode())
|
|
{
|
|
rSet.ClearItem(SID_TOGGLE_REL); // F4 Cycle Cell Reference Types
|
|
rSet.ClearItem(SID_CHARMAP); // Insert Special Characters
|
|
}
|
|
return;
|
|
}
|
|
|
|
EditView* pActiveView = pHdl ? pHdl->GetActiveView() : pEditView;
|
|
|
|
SfxWhichIter aIter( rSet );
|
|
sal_uInt16 nWhich = aIter.FirstWhich();
|
|
while (nWhich)
|
|
{
|
|
switch (nWhich)
|
|
{
|
|
case SID_ATTR_INSERT: // Status row
|
|
{
|
|
if ( pActiveView )
|
|
rSet.Put( SfxBoolItem( nWhich, pActiveView->IsInsertMode() ) );
|
|
else
|
|
{
|
|
// Here the code used to pass the value 42 and it used
|
|
// to "work" without warnings because the SfxBoolItem
|
|
// was based on 'sal_Bool', which is actually 'unsigned
|
|
// char'. But now it uses actual 'bool', and passing 42
|
|
// for a 'bool' parameter causes a warning at least with
|
|
// MSVC. So use 'true'. I really really hope there is
|
|
// not code somewhere that retrieves this "boolean" item
|
|
// and checks it value for the magic value 42...
|
|
rSet.Put( SfxBoolItem( nWhich, true) );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SID_HYPERLINK_GETLINK:
|
|
{
|
|
SvxHyperlinkItem aHLinkItem;
|
|
bool bCellLinksOnly
|
|
= (ScModule::get()->GetAppOptions().GetLinksInsertedLikeMSExcel()
|
|
&& rViewData.GetSfxDocShell()->GetMedium()->GetFilter()->IsMSOFormat())
|
|
|| comphelper::LibreOfficeKit::isActive();
|
|
std::unique_ptr<const SvxFieldData> aSvxFieldDataPtr(GetURLField());
|
|
const SvxURLField* pURLField(static_cast<const SvxURLField*>(aSvxFieldDataPtr.get()));
|
|
if (!bCellLinksOnly)
|
|
{
|
|
if (pURLField)
|
|
{
|
|
aHLinkItem.SetName(pURLField->GetRepresentation());
|
|
aHLinkItem.SetURL(pURLField->GetURL());
|
|
aHLinkItem.SetTargetFrame(pURLField->GetTargetFrame());
|
|
}
|
|
else if (pActiveView)
|
|
{
|
|
// use selected text as name for urls
|
|
OUString sReturn = pActiveView->GetSelected();
|
|
sReturn = sReturn.copy(
|
|
0, std::min(sReturn.getLength(), static_cast<sal_Int32>(255)));
|
|
aHLinkItem.SetName(comphelper::string::stripEnd(sReturn, ' '));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!pURLField)
|
|
{
|
|
aSvxFieldDataPtr = GetFirstURLFieldFromCell();
|
|
pURLField = static_cast<const SvxURLField*>(aSvxFieldDataPtr.get());
|
|
}
|
|
if (pURLField)
|
|
{
|
|
aHLinkItem.SetURL(pURLField->GetURL());
|
|
aHLinkItem.SetTargetFrame(pURLField->GetTargetFrame());
|
|
}
|
|
ScDocument& rDoc = rViewData.GetDocument();
|
|
SCCOL nPosX = rViewData.GetCurX();
|
|
SCROW nPosY = rViewData.GetCurY();
|
|
SCTAB nTab = rViewData.GetTabNo();
|
|
aHLinkItem.SetName(rDoc.GetString(nPosX, nPosY, nTab));
|
|
}
|
|
rSet.Put(aHLinkItem);
|
|
}
|
|
break;
|
|
|
|
case SID_EDIT_HYPERLINK:
|
|
case SID_COPY_HYPERLINK_LOCATION:
|
|
case SID_REMOVE_HYPERLINK:
|
|
{
|
|
if (!URLFieldHelper::IsCursorAtURLField(*pEditView,
|
|
/*AlsoCheckBeforeCursor=*/true))
|
|
rSet.DisableItem (nWhich);
|
|
}
|
|
break;
|
|
|
|
case SID_TRANSLITERATE_HALFWIDTH:
|
|
case SID_TRANSLITERATE_FULLWIDTH:
|
|
case SID_TRANSLITERATE_HIRAGANA:
|
|
case SID_TRANSLITERATE_KATAKANA:
|
|
case SID_INSERT_RLM:
|
|
case SID_INSERT_LRM:
|
|
ScViewUtil::HideDisabledSlot( rSet, rViewData.GetBindings(), nWhich );
|
|
break;
|
|
|
|
case SID_THES:
|
|
{
|
|
OUString aStatusVal;
|
|
LanguageType nLang = LANGUAGE_NONE;
|
|
bool bIsLookUpWord = pActiveView &&
|
|
GetStatusValueForThesaurusFromContext(aStatusVal, nLang, *pActiveView);
|
|
rSet.Put( SfxStringItem( SID_THES, aStatusVal ) );
|
|
|
|
// disable thesaurus context menu entry if there is nothing to look up
|
|
bool bCanDoThesaurus = ScModule::HasThesaurusLanguage( nLang );
|
|
if (!bIsLookUpWord || !bCanDoThesaurus)
|
|
rSet.DisableItem( SID_THES );
|
|
}
|
|
break;
|
|
case SID_INSERT_FIELD_SHEET:
|
|
case SID_INSERT_FIELD_TITLE:
|
|
case SID_INSERT_FIELD_DATE_VAR:
|
|
break;
|
|
case SID_COPY:
|
|
case SID_CUT:
|
|
if (GetObjectShell() && GetObjectShell()->isContentExtractionLocked())
|
|
{
|
|
rSet.DisableItem(SID_COPY);
|
|
rSet.DisableItem(SID_CUT);
|
|
}
|
|
break;
|
|
|
|
}
|
|
nWhich = aIter.NextWhich();
|
|
}
|
|
}
|
|
|
|
std::unique_ptr<const SvxFieldData> ScEditShell::GetURLField()
|
|
{
|
|
ScInputHandler* pHdl = GetMyInputHdl();
|
|
EditView* pActiveView = pHdl ? pHdl->GetActiveView() : pEditView;
|
|
if (!pActiveView)
|
|
return std::unique_ptr<const SvxFieldData>();
|
|
|
|
const SvxFieldData* pField = pActiveView->GetFieldUnderMouseOrInSelectionOrAtCursor();
|
|
if (auto pURLField = dynamic_cast<const SvxURLField*>(pField))
|
|
return pURLField->Clone();
|
|
|
|
return std::unique_ptr<const SvxFieldData>();
|
|
}
|
|
|
|
std::unique_ptr<const SvxFieldData> ScEditShell::GetFirstURLFieldFromCell()
|
|
{
|
|
EditEngine& rEditEngine = GetEditView()->getEditEngine();
|
|
sal_Int32 nParaCount = rEditEngine.GetParagraphCount();
|
|
for (sal_Int32 nPara = 0; nPara < nParaCount; ++nPara)
|
|
{
|
|
ESelection aSel(nPara, 0);
|
|
std::vector<sal_Int32> aPosList;
|
|
rEditEngine.GetPortions(nPara, aPosList);
|
|
for (const auto& rPos : aPosList)
|
|
{
|
|
aSel.end.nIndex = rPos;
|
|
|
|
SfxItemSet aEditSet(rEditEngine.GetAttribs(aSel));
|
|
if (aSel.start.nIndex + 1 == aSel.end.nIndex)
|
|
{
|
|
// test if the character is a text field
|
|
if (const SvxFieldItem* pItem = aEditSet.GetItemIfSet(EE_FEATURE_FIELD, false))
|
|
{
|
|
const SvxFieldData* pField = pItem->GetField();
|
|
if (const SvxURLField* pUrlField = dynamic_cast<const SvxURLField*>(pField))
|
|
{
|
|
return pUrlField->Clone();
|
|
}
|
|
}
|
|
}
|
|
aSel.start.nIndex = aSel.end.nIndex;
|
|
}
|
|
}
|
|
|
|
return std::unique_ptr<const SvxFieldData>();
|
|
}
|
|
|
|
IMPL_LINK( ScEditShell, ClipboardChanged, TransferableDataHelper*, pDataHelper, void )
|
|
{
|
|
bPastePossible = ( pDataHelper->HasFormat( SotClipboardFormatId::STRING )
|
|
|| pDataHelper->HasFormat( SotClipboardFormatId::RTF )
|
|
|| pDataHelper->HasFormat( SotClipboardFormatId::RICHTEXT ));
|
|
|
|
SfxBindings& rBindings = rViewData.GetBindings();
|
|
rBindings.Invalidate( SID_PASTE );
|
|
rBindings.Invalidate( SID_PASTE_SPECIAL );
|
|
rBindings.Invalidate( SID_PASTE_UNFORMATTED );
|
|
rBindings.Invalidate( SID_CLIPBOARD_FORMAT_ITEMS );
|
|
}
|
|
|
|
void ScEditShell::GetClipState( SfxItemSet& rSet )
|
|
{
|
|
// Do not offer SotClipboardFormatId::STRING_TSVC for in-cell paste.
|
|
|
|
if ( !mxClipEvtLstnr.is() )
|
|
{
|
|
// create listener
|
|
mxClipEvtLstnr = new TransferableClipboardListener( LINK( this, ScEditShell, ClipboardChanged ) );
|
|
vcl::Window* pWin = rViewData.GetActiveWin();
|
|
mxClipEvtLstnr->AddListener( pWin );
|
|
|
|
// get initial state
|
|
TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( rViewData.GetActiveWin() ) );
|
|
bPastePossible = ( aDataHelper.HasFormat( SotClipboardFormatId::STRING )
|
|
|| aDataHelper.HasFormat( SotClipboardFormatId::RTF )
|
|
|| aDataHelper.HasFormat( SotClipboardFormatId::RICHTEXT ) );
|
|
}
|
|
|
|
SfxWhichIter aIter( rSet );
|
|
sal_uInt16 nWhich = aIter.FirstWhich();
|
|
while (nWhich)
|
|
{
|
|
switch (nWhich)
|
|
{
|
|
case SID_PASTE:
|
|
case SID_PASTE_SPECIAL:
|
|
case SID_PASTE_UNFORMATTED:
|
|
if( !bPastePossible )
|
|
rSet.DisableItem( nWhich );
|
|
break;
|
|
case SID_CLIPBOARD_FORMAT_ITEMS:
|
|
if( bPastePossible )
|
|
{
|
|
SvxClipboardFormatItem aFormats( SID_CLIPBOARD_FORMAT_ITEMS );
|
|
TransferableDataHelper aDataHelper(
|
|
TransferableDataHelper::CreateFromSystemClipboard( rViewData.GetActiveWin() ) );
|
|
|
|
if ( aDataHelper.HasFormat( SotClipboardFormatId::STRING ) )
|
|
aFormats.AddClipbrdFormat( SotClipboardFormatId::STRING );
|
|
if ( aDataHelper.HasFormat( SotClipboardFormatId::RTF ) )
|
|
aFormats.AddClipbrdFormat( SotClipboardFormatId::RTF );
|
|
|
|
rSet.Put( aFormats );
|
|
}
|
|
else
|
|
rSet.DisableItem( nWhich );
|
|
break;
|
|
}
|
|
nWhich = aIter.NextWhich();
|
|
}
|
|
}
|
|
|
|
static void lcl_InvalidateUnder( SfxBindings& rBindings )
|
|
{
|
|
rBindings.Invalidate( SID_ATTR_CHAR_UNDERLINE );
|
|
rBindings.Invalidate( SID_ULINE_VAL_NONE );
|
|
rBindings.Invalidate( SID_ULINE_VAL_SINGLE );
|
|
rBindings.Invalidate( SID_ULINE_VAL_DOUBLE );
|
|
rBindings.Invalidate( SID_ULINE_VAL_DOTTED );
|
|
}
|
|
|
|
void ScEditShell::ExecuteAttr(SfxRequest& rReq)
|
|
{
|
|
SfxItemSet aSet( pEditView->GetEmptyItemSet() );
|
|
SfxBindings& rBindings = rViewData.GetBindings();
|
|
const SfxItemSet* pArgs = rReq.GetArgs();
|
|
sal_uInt16 nSlot = rReq.GetSlot();
|
|
|
|
switch ( nSlot )
|
|
{
|
|
case SID_ATTR_CHAR_FONTHEIGHT:
|
|
case SID_ATTR_CHAR_FONT:
|
|
{
|
|
if (pArgs)
|
|
{
|
|
// #i78017 establish the same behaviour as in Writer
|
|
SvtScriptType nScript = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
|
|
if (nSlot == SID_ATTR_CHAR_FONT)
|
|
{
|
|
nScript = pEditView->GetSelectedScriptType();
|
|
if (nScript == SvtScriptType::NONE) nScript = ScGlobal::GetDefaultScriptType();
|
|
}
|
|
|
|
SfxItemPool& rPool = GetPool();
|
|
SvxScriptSetItem aSetItem( nSlot, rPool );
|
|
sal_uInt16 nWhich = rPool.GetWhichIDFromSlotID( nSlot );
|
|
aSetItem.PutItemForScriptType( nScript, pArgs->Get( nWhich ) );
|
|
|
|
aSet.Put( aSetItem.GetItemSet(), false );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SID_ATTR_CHAR_COLOR:
|
|
case SID_ATTR_CHAR_BACK_COLOR:
|
|
{
|
|
if (pArgs)
|
|
{
|
|
aSet.Put( pArgs->Get( pArgs->GetPool()->GetWhichIDFromSlotID( nSlot ) ) );
|
|
rBindings.Invalidate( nSlot );
|
|
}
|
|
else
|
|
{
|
|
const sal_uInt16 nEEWhich = GetPool().GetWhichIDFromSlotID(nSlot);
|
|
const std::optional<NamedColor> oColor
|
|
= rViewData.GetDocShell()->GetRecentColor(nSlot);
|
|
if (oColor.has_value())
|
|
{
|
|
const model::ComplexColor aCol = (*oColor).getComplexColor();
|
|
aSet.Put(SvxColorItem(aCol.getFinalColor(), aCol, nEEWhich));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
// Toggles
|
|
|
|
case SID_ATTR_CHAR_WEIGHT:
|
|
{
|
|
// #i78017 establish the same behaviour as in Writer
|
|
SvtScriptType nScript = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
|
|
|
|
SfxItemPool& rPool = GetPool();
|
|
|
|
bool bOld = false;
|
|
SvxScriptSetItem aOldSetItem( nSlot, rPool );
|
|
aOldSetItem.GetItemSet().Put( pEditView->GetAttribs(), false );
|
|
const SfxPoolItem* pCore = aOldSetItem.GetItemOfScript( nScript );
|
|
if ( pCore && static_cast<const SvxWeightItem*>(pCore)->GetWeight() > WEIGHT_NORMAL )
|
|
bOld = true;
|
|
|
|
SvxScriptSetItem aSetItem( nSlot, rPool );
|
|
aSetItem.PutItemForScriptType( nScript,
|
|
SvxWeightItem( bOld ? WEIGHT_NORMAL : WEIGHT_BOLD, EE_CHAR_WEIGHT ) );
|
|
aSet.Put( aSetItem.GetItemSet(), false );
|
|
|
|
rBindings.Invalidate( nSlot );
|
|
}
|
|
break;
|
|
|
|
case SID_ATTR_CHAR_POSTURE:
|
|
{
|
|
// #i78017 establish the same behaviour as in Writer
|
|
SvtScriptType nScript = SvtScriptType::LATIN | SvtScriptType::ASIAN | SvtScriptType::COMPLEX;
|
|
|
|
SfxItemPool& rPool = GetPool();
|
|
|
|
bool bOld = false;
|
|
SvxScriptSetItem aOldSetItem( nSlot, rPool );
|
|
aOldSetItem.GetItemSet().Put( pEditView->GetAttribs(), false );
|
|
const SfxPoolItem* pCore = aOldSetItem.GetItemOfScript( nScript );
|
|
if ( pCore && static_cast<const SvxPostureItem*>(pCore)->GetValue() != ITALIC_NONE )
|
|
bOld = true;
|
|
|
|
SvxScriptSetItem aSetItem( nSlot, rPool );
|
|
aSetItem.PutItemForScriptType( nScript,
|
|
SvxPostureItem( bOld ? ITALIC_NONE : ITALIC_NORMAL, EE_CHAR_ITALIC ) );
|
|
aSet.Put( aSetItem.GetItemSet(), false );
|
|
|
|
rBindings.Invalidate( nSlot );
|
|
}
|
|
break;
|
|
|
|
case SID_ULINE_VAL_NONE:
|
|
aSet.Put( SvxUnderlineItem( LINESTYLE_NONE, EE_CHAR_UNDERLINE ) );
|
|
lcl_InvalidateUnder( rBindings );
|
|
break;
|
|
|
|
case SID_ATTR_CHAR_UNDERLINE:
|
|
case SID_ULINE_VAL_SINGLE:
|
|
case SID_ULINE_VAL_DOUBLE:
|
|
case SID_ULINE_VAL_DOTTED:
|
|
{
|
|
FontLineStyle eOld = pEditView->GetAttribs().Get(EE_CHAR_UNDERLINE).GetLineStyle();
|
|
FontLineStyle eNew = eOld;
|
|
switch (nSlot)
|
|
{
|
|
case SID_ATTR_CHAR_UNDERLINE:
|
|
if ( pArgs )
|
|
{
|
|
const SvxTextLineItem& rTextLineItem = static_cast< const SvxTextLineItem& >( pArgs->Get( pArgs->GetPool()->GetWhichIDFromSlotID(nSlot) ) );
|
|
eNew = rTextLineItem.GetLineStyle();
|
|
}
|
|
else
|
|
{
|
|
eNew = ( eOld != LINESTYLE_NONE ) ? LINESTYLE_NONE : LINESTYLE_SINGLE;
|
|
}
|
|
break;
|
|
case SID_ULINE_VAL_SINGLE:
|
|
eNew = ( eOld == LINESTYLE_SINGLE ) ? LINESTYLE_NONE : LINESTYLE_SINGLE;
|
|
break;
|
|
case SID_ULINE_VAL_DOUBLE:
|
|
eNew = ( eOld == LINESTYLE_DOUBLE ) ? LINESTYLE_NONE : LINESTYLE_DOUBLE;
|
|
break;
|
|
case SID_ULINE_VAL_DOTTED:
|
|
eNew = ( eOld == LINESTYLE_DOTTED ) ? LINESTYLE_NONE : LINESTYLE_DOTTED;
|
|
break;
|
|
}
|
|
aSet.Put( SvxUnderlineItem( eNew, EE_CHAR_UNDERLINE ) );
|
|
lcl_InvalidateUnder( rBindings );
|
|
}
|
|
break;
|
|
|
|
case SID_ATTR_CHAR_OVERLINE:
|
|
{
|
|
FontLineStyle eOld = pEditView->GetAttribs().Get(EE_CHAR_OVERLINE).GetLineStyle();
|
|
FontLineStyle eNew = ( eOld != LINESTYLE_NONE ) ? LINESTYLE_NONE : LINESTYLE_SINGLE;
|
|
aSet.Put( SvxOverlineItem( eNew, EE_CHAR_OVERLINE ) );
|
|
rBindings.Invalidate( nSlot );
|
|
}
|
|
break;
|
|
|
|
case SID_ATTR_CHAR_STRIKEOUT:
|
|
{
|
|
bool bOld = pEditView->GetAttribs().Get(EE_CHAR_STRIKEOUT).GetValue() != STRIKEOUT_NONE;
|
|
aSet.Put( SvxCrossedOutItem( bOld ? STRIKEOUT_NONE : STRIKEOUT_SINGLE, EE_CHAR_STRIKEOUT ) );
|
|
rBindings.Invalidate( nSlot );
|
|
}
|
|
break;
|
|
|
|
case SID_ATTR_CHAR_SHADOWED:
|
|
{
|
|
bool bOld = pEditView->GetAttribs().Get(EE_CHAR_SHADOW).GetValue();
|
|
aSet.Put( SvxShadowedItem( !bOld, EE_CHAR_SHADOW ) );
|
|
rBindings.Invalidate( nSlot );
|
|
}
|
|
break;
|
|
|
|
case SID_ATTR_CHAR_CONTOUR:
|
|
{
|
|
bool bOld = pEditView->GetAttribs().Get(EE_CHAR_OUTLINE).GetValue();
|
|
aSet.Put( SvxContourItem( !bOld, EE_CHAR_OUTLINE ) );
|
|
rBindings.Invalidate( nSlot );
|
|
}
|
|
break;
|
|
|
|
case SID_SET_SUPER_SCRIPT:
|
|
{
|
|
SvxEscapement eOld = static_cast<SvxEscapement>(pEditView->GetAttribs().Get(EE_CHAR_ESCAPEMENT).GetEnumValue());
|
|
SvxEscapement eNew = (eOld == SvxEscapement::Superscript) ?
|
|
SvxEscapement::Off : SvxEscapement::Superscript;
|
|
aSet.Put( SvxEscapementItem( eNew, EE_CHAR_ESCAPEMENT ) );
|
|
rBindings.Invalidate( nSlot );
|
|
}
|
|
break;
|
|
case SID_SET_SUB_SCRIPT:
|
|
{
|
|
SvxEscapement eOld = static_cast<SvxEscapement>(pEditView->GetAttribs().Get(EE_CHAR_ESCAPEMENT).GetEnumValue());
|
|
SvxEscapement eNew = (eOld == SvxEscapement::Subscript) ?
|
|
SvxEscapement::Off : SvxEscapement::Subscript;
|
|
aSet.Put( SvxEscapementItem( eNew, EE_CHAR_ESCAPEMENT ) );
|
|
rBindings.Invalidate( nSlot );
|
|
}
|
|
break;
|
|
case SID_ATTR_CHAR_KERNING:
|
|
{
|
|
if(pArgs)
|
|
{
|
|
aSet.Put ( pArgs->Get(pArgs->GetPool()->GetWhichIDFromSlotID(nSlot)));
|
|
rBindings.Invalidate( nSlot );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case SID_GROW_FONT_SIZE:
|
|
case SID_SHRINK_FONT_SIZE:
|
|
{
|
|
SfxObjectShell* pObjSh = SfxObjectShell::Current();
|
|
const SvxFontListItem* pFontListItem = static_cast<const SvxFontListItem*>
|
|
(pObjSh ? pObjSh->GetItem(SID_ATTR_CHAR_FONTLIST) : nullptr);
|
|
const FontList* pFontList = pFontListItem ? pFontListItem->GetFontList() : nullptr;
|
|
pEditView->ChangeFontSize( nSlot == SID_GROW_FONT_SIZE, pFontList );
|
|
rBindings.Invalidate( SID_ATTR_CHAR_FONTHEIGHT );
|
|
}
|
|
break;
|
|
}
|
|
|
|
// apply
|
|
|
|
EditEngine& rEngine = pEditView->getEditEngine();
|
|
bool bOld = rEngine.SetUpdateLayout(false);
|
|
|
|
pEditView->SetAttribs( aSet );
|
|
|
|
rEngine.SetUpdateLayout(bOld);
|
|
pEditView->Invalidate();
|
|
|
|
ScInputHandler* pHdl = GetMyInputHdl();
|
|
pHdl->SetModified();
|
|
|
|
rReq.Done();
|
|
}
|
|
|
|
void ScEditShell::GetAttrState(SfxItemSet &rSet)
|
|
{
|
|
if ( !rViewData.HasEditView( rViewData.GetActivePart() ) )
|
|
{
|
|
lcl_DisableAll( rSet );
|
|
return;
|
|
}
|
|
|
|
SfxItemSet aAttribs = pEditView->GetAttribs();
|
|
rSet.Put( aAttribs );
|
|
|
|
// choose font info according to selection script type
|
|
|
|
SvtScriptType nScript = pEditView->GetSelectedScriptType();
|
|
if (nScript == SvtScriptType::NONE) nScript = ScGlobal::GetDefaultScriptType();
|
|
|
|
// #i55929# input-language-dependent script type (depends on input language if nothing selected)
|
|
SvtScriptType nInputScript = nScript;
|
|
if ( !pEditView->GetSelection().HasRange() )
|
|
{
|
|
LanguageType nInputLang = rViewData.GetActiveWin()->GetInputLanguage();
|
|
if (nInputLang != LANGUAGE_DONTKNOW && nInputLang != LANGUAGE_SYSTEM)
|
|
nInputScript = SvtLanguageOptions::GetScriptTypeOfLanguage( nInputLang );
|
|
}
|
|
|
|
// #i55929# according to spec, nInputScript is used for font and font height only
|
|
if ( rSet.GetItemState( EE_CHAR_FONTINFO ) != SfxItemState::UNKNOWN )
|
|
ScViewUtil::PutItemScript( rSet, aAttribs, EE_CHAR_FONTINFO, nInputScript );
|
|
if ( rSet.GetItemState( EE_CHAR_FONTHEIGHT ) != SfxItemState::UNKNOWN )
|
|
ScViewUtil::PutItemScript( rSet, aAttribs, EE_CHAR_FONTHEIGHT, nInputScript );
|
|
if ( rSet.GetItemState( EE_CHAR_WEIGHT ) != SfxItemState::UNKNOWN )
|
|
ScViewUtil::PutItemScript( rSet, aAttribs, EE_CHAR_WEIGHT, nScript );
|
|
if ( rSet.GetItemState( EE_CHAR_ITALIC ) != SfxItemState::UNKNOWN )
|
|
ScViewUtil::PutItemScript( rSet, aAttribs, EE_CHAR_ITALIC, nScript );
|
|
|
|
// underline
|
|
SfxItemState eState = aAttribs.GetItemState( EE_CHAR_UNDERLINE );
|
|
if ( eState == SfxItemState::INVALID )
|
|
{
|
|
rSet.InvalidateItem( SID_ULINE_VAL_NONE );
|
|
rSet.InvalidateItem( SID_ULINE_VAL_SINGLE );
|
|
rSet.InvalidateItem( SID_ULINE_VAL_DOUBLE );
|
|
rSet.InvalidateItem( SID_ULINE_VAL_DOTTED );
|
|
}
|
|
else
|
|
{
|
|
FontLineStyle eUnderline = aAttribs.Get(EE_CHAR_UNDERLINE).GetLineStyle();
|
|
rSet.Put(SfxBoolItem(SID_ULINE_VAL_SINGLE, eUnderline == LINESTYLE_SINGLE));
|
|
rSet.Put(SfxBoolItem(SID_ULINE_VAL_DOUBLE, eUnderline == LINESTYLE_DOUBLE));
|
|
rSet.Put(SfxBoolItem(SID_ULINE_VAL_DOTTED, eUnderline == LINESTYLE_DOTTED));
|
|
rSet.Put(SfxBoolItem(SID_ULINE_VAL_NONE, eUnderline == LINESTYLE_NONE));
|
|
}
|
|
|
|
//! Testing whether brace highlighting is active !!!!
|
|
ScInputHandler* pHdl = GetMyInputHdl();
|
|
if ( pHdl && pHdl->IsFormulaMode() )
|
|
rSet.ClearItem( EE_CHAR_WEIGHT ); // Highlighted brace not here
|
|
|
|
SvxEscapement eEsc = static_cast<SvxEscapement>(aAttribs.Get( EE_CHAR_ESCAPEMENT ).GetEnumValue());
|
|
rSet.Put(SfxBoolItem(SID_SET_SUPER_SCRIPT, eEsc == SvxEscapement::Superscript));
|
|
rSet.Put(SfxBoolItem(SID_SET_SUB_SCRIPT, eEsc == SvxEscapement::Subscript));
|
|
rViewData.GetBindings().Invalidate( SID_SET_SUPER_SCRIPT );
|
|
rViewData.GetBindings().Invalidate( SID_SET_SUB_SCRIPT );
|
|
|
|
eState = aAttribs.GetItemState( EE_CHAR_KERNING );
|
|
rViewData.GetBindings().Invalidate( SID_ATTR_CHAR_KERNING );
|
|
if ( eState == SfxItemState::INVALID )
|
|
{
|
|
rSet.InvalidateItem(EE_CHAR_KERNING);
|
|
}
|
|
}
|
|
|
|
OUString ScEditShell::GetSelectionText( bool bWholeWord )
|
|
{
|
|
OUString aStrSelection;
|
|
|
|
if ( rViewData.HasEditView( rViewData.GetActivePart() ) )
|
|
{
|
|
if ( bWholeWord )
|
|
{
|
|
EditEngine& rEngine = pEditView->getEditEngine();
|
|
ESelection aSel = pEditView->GetSelection();
|
|
OUString aStrCurrentDelimiters = rEngine.GetWordDelimiters();
|
|
|
|
rEngine.SetWordDelimiters(u" .,;\"'"_ustr);
|
|
aStrSelection = rEngine.GetWord(aSel.end);
|
|
rEngine.SetWordDelimiters( aStrCurrentDelimiters );
|
|
}
|
|
else
|
|
{
|
|
aStrSelection = pEditView->GetSelected();
|
|
}
|
|
}
|
|
|
|
return aStrSelection;
|
|
}
|
|
|
|
void ScEditShell::ExecuteUndo(const SfxRequest& rReq)
|
|
{
|
|
// Undo must be handled here because it's called for both EditViews
|
|
|
|
ScInputHandler* pHdl = GetMyInputHdl();
|
|
OSL_ENSURE(pHdl,"no ScInputHandler");
|
|
EditView* pTopView = pHdl->GetTopView();
|
|
EditView* pTableView = pHdl->GetTableView();
|
|
OSL_ENSURE(pTableView,"no EditView");
|
|
|
|
pHdl->DataChanging();
|
|
|
|
const SfxItemSet* pReqArgs = rReq.GetArgs();
|
|
sal_uInt16 nSlot = rReq.GetSlot();
|
|
switch ( nSlot )
|
|
{
|
|
case SID_UNDO:
|
|
case SID_REDO:
|
|
{
|
|
bool bIsUndo = ( nSlot == SID_UNDO );
|
|
|
|
sal_uInt16 nCount = 1;
|
|
const SfxPoolItem* pItem;
|
|
if ( pReqArgs && pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
|
|
nCount = static_cast<const SfxUInt16Item*>(pItem)->GetValue();
|
|
|
|
for (sal_uInt16 i=0; i<nCount; i++)
|
|
{
|
|
if ( bIsUndo )
|
|
{
|
|
pTableView->Undo();
|
|
if (pTopView)
|
|
pTopView->Undo();
|
|
}
|
|
else
|
|
{
|
|
pTableView->Redo();
|
|
if (pTopView)
|
|
pTopView->Redo();
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
rViewData.GetBindings().InvalidateAll(false);
|
|
|
|
pHdl->DataChanged();
|
|
}
|
|
|
|
void ScEditShell::GetUndoState(SfxItemSet &rSet)
|
|
{
|
|
// Undo state is taken from normal ViewFrame state function
|
|
|
|
SfxViewFrame& rViewFrm = rViewData.GetViewShell()->GetViewFrame();
|
|
if ( GetUndoManager() )
|
|
{
|
|
SfxWhichIter aIter(rSet);
|
|
sal_uInt16 nWhich = aIter.FirstWhich();
|
|
while( nWhich )
|
|
{
|
|
rViewFrm.GetSlotState( nWhich, nullptr, &rSet );
|
|
nWhich = aIter.NextWhich();
|
|
}
|
|
}
|
|
|
|
// disable if no action in input line EditView
|
|
|
|
ScInputHandler* pHdl = GetMyInputHdl();
|
|
OSL_ENSURE(pHdl,"no ScInputHandler");
|
|
EditView* pTopView = pHdl->GetTopView();
|
|
if (pTopView)
|
|
{
|
|
SfxUndoManager& rTopMgr = pTopView->getEditEngine().GetUndoManager();
|
|
if ( rTopMgr.GetUndoActionCount() == 0 )
|
|
rSet.DisableItem( SID_UNDO );
|
|
if ( rTopMgr.GetRedoActionCount() == 0 )
|
|
rSet.DisableItem( SID_REDO );
|
|
}
|
|
}
|
|
|
|
void ScEditShell::ExecuteTrans( const SfxRequest& rReq )
|
|
{
|
|
TransliterationFlags nType = ScViewUtil::GetTransliterationType( rReq.GetSlot() );
|
|
if ( nType == TransliterationFlags::NONE )
|
|
return;
|
|
|
|
ScInputHandler* pHdl = GetMyInputHdl();
|
|
assert(pHdl && "no ScInputHandler");
|
|
|
|
EditView* pTopView = pHdl->GetTopView();
|
|
EditView* pTableView = pHdl->GetTableView();
|
|
assert(pTableView && "no EditView");
|
|
|
|
pHdl->DataChanging();
|
|
|
|
pTableView->TransliterateText( nType );
|
|
if (pTopView)
|
|
pTopView->TransliterateText( nType );
|
|
|
|
pHdl->DataChanged();
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|