1
0
Fork 0
libreoffice/sc/source/ui/view/spelldialog.cxx
Daniel Baumann 8e63e14cf6
Adding upstream version 4:25.2.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-22 16:20:04 +02:00

281 lines
8.8 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 <spelldialog.hxx>
#include <sfx2/bindings.hxx>
#include <svx/svxids.hrc>
#include <editeng/editstat.hxx>
#include <editeng/editview.hxx>
#include <editeng/unolingu.hxx>
#include <selectionstate.hxx>
#include <osl/diagnose.h>
#include <spelleng.hxx>
#include <tabvwsh.hxx>
#include <docsh.hxx>
#include <scmod.hxx>
#include <editable.hxx>
#include <undoblk.hxx>
#include <gridwin.hxx>
#include <refupdatecontext.hxx>
#include <vcl/svapp.hxx>
SFX_IMPL_CHILDWINDOW_WITHID( ScSpellDialogChildWindow, SID_SPELL_DIALOG )
ScSpellDialogChildWindow::ScSpellDialogChildWindow( vcl::Window* pParentP, sal_uInt16 nId,
SfxBindings* pBindings, SAL_UNUSED_PARAMETER SfxChildWinInfo* /*pInfo*/ ) :
svx::SpellDialogChildWindow( pParentP, nId, pBindings ),
mpViewShell( nullptr ),
mpViewData( nullptr ),
mpDocShell( nullptr ),
mpDoc( nullptr ),
mbNeedNextObj( false ),
mbOldIdleEnabled(true)
{
Init();
}
ScSpellDialogChildWindow::~ScSpellDialogChildWindow()
{
Reset();
}
SfxChildWinInfo ScSpellDialogChildWindow::GetInfo() const
{
return svx::SpellDialogChildWindow::GetInfo();
}
void ScSpellDialogChildWindow::InvalidateSpellDialog()
{
svx::SpellDialogChildWindow::InvalidateSpellDialog();
}
// protected ------------------------------------------------------------------
svx::SpellPortions ScSpellDialogChildWindow::GetNextWrongSentence( bool /*bRecheck*/ )
{
svx::SpellPortions aPortions;
if( mxEngine && mpViewData )
{
if( EditView* pEditView = mpViewData->GetSpellingView() )
{
// edit engine handles cell iteration internally
do
{
if( mbNeedNextObj )
mxEngine->SpellNextDocument();
mbNeedNextObj = !mxEngine->IsFinished() && !mxEngine->SpellSentence( *pEditView, aPortions );
}
while( mbNeedNextObj );
}
}
return aPortions;
}
void ScSpellDialogChildWindow::ApplyChangedSentence( const svx::SpellPortions& rChanged, bool bRecheck )
{
if( mxEngine && mpViewData )
if( EditView* pEditView = mpViewData->GetSpellingView() )
{
mxEngine->ApplyChangedSentence( *pEditView, rChanged, bRecheck );
// Reset the spell checking results to clear the markers.
mpViewData->GetActiveWin()->ResetAutoSpell();
}
}
void ScSpellDialogChildWindow::GetFocus()
{
SolarMutexGuard aGuard;
if( IsSelectionChanged() )
{
Reset();
InvalidateSpellDialog();
Init();
}
}
void ScSpellDialogChildWindow::LoseFocus()
{
}
// private --------------------------------------------------------------------
void ScSpellDialogChildWindow::Reset()
{
if( mpViewShell && (mpViewShell == dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() )) )
{
if( mxEngine && mxEngine->IsAnyModified() )
{
const ScAddress& rCursor = mxOldSel->GetCellCursor();
SCTAB nTab = rCursor.Tab();
SCCOL nOldCol = rCursor.Col();
SCROW nOldRow = rCursor.Row();
SCCOL nNewCol = mpViewData->GetCurX();
SCROW nNewRow = mpViewData->GetCurY();
mpDocShell->GetUndoManager()->AddUndoAction( std::make_unique<ScUndoConversion>(
mpDocShell, mpViewData->GetMarkData(),
nOldCol, nOldRow, nTab, std::move(mxUndoDoc),
nNewCol, nNewRow, nTab, std::move(mxRedoDoc),
ScConversionParam( SC_CONVERSION_SPELLCHECK ) ) );
sc::SetFormulaDirtyContext aCxt;
mpDoc->SetAllFormulasDirty(aCxt);
mpDocShell->SetDocumentModified();
}
mpViewData->SetSpellingView( nullptr );
mpViewShell->KillEditView( true );
mpDocShell->PostPaintGridAll();
mpViewShell->UpdateInputHandler();
mpDoc->EnableIdle(mbOldIdleEnabled);
}
mxEngine.reset();
mxUndoDoc.reset();
mxRedoDoc.reset();
mxOldSel.reset();
mxOldRangeList.clear();
mpViewShell = nullptr;
mpViewData = nullptr;
mpDocShell = nullptr;
mpDoc = nullptr;
mbNeedNextObj = false;
mbOldIdleEnabled = true;
}
void ScSpellDialogChildWindow::Init()
{
if( mpViewShell )
return;
if( (mpViewShell = dynamic_cast<ScTabViewShell*>( SfxViewShell::Current() )) == nullptr )
return;
mpViewData = &mpViewShell->GetViewData();
// exit edit mode - TODO support spelling in edit mode
if( mpViewData->HasEditView( mpViewData->GetActivePart() ) )
ScModule::get()->InputEnterHandler();
mxOldSel.reset( new ScSelectionState( *mpViewData ) );
mpDocShell = mpViewData->GetDocShell();
mpDoc = &mpDocShell->GetDocument();
const ScAddress& rCursor = mxOldSel->GetCellCursor();
SCCOL nCol = rCursor.Col();
SCROW nRow = rCursor.Row();
SCTAB nTab = rCursor.Tab();
ScMarkData& rMarkData = mpViewData->GetMarkData();
mxOldRangeList = new ScRangeList;
rMarkData.FillRangeListWithMarks(mxOldRangeList.get(), true);
rMarkData.MarkToMulti();
switch( mxOldSel->GetSelectionType() )
{
case SC_SELECTTYPE_NONE:
case SC_SELECTTYPE_SHEET:
{
// test if there is something editable
ScEditableTester aTester( *mpDoc, rMarkData );
if( !aTester.IsEditable() )
{
// #i85751# Don't show an ErrorMessage here, because the vcl
// parent of the InfoBox is not fully initialized yet.
// This leads to problems in the modality behaviour of the
// ScSpellDialogChildWindow.
//mpViewShell->ErrorMessage( aTester.GetMessageId() );
return;
}
}
break;
// edit mode exited, see TODO above
// case SC_SELECTTYPE_EDITCELL:
// break;
default:
OSL_FAIL( "ScSpellDialogChildWindow::Init - unknown selection type" );
}
mbOldIdleEnabled = mpDoc->IsIdleEnabled();
mpDoc->EnableIdle(false); // stop online spelling
// *** create Undo/Redo documents *** -------------------------------------
mxUndoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
mxUndoDoc->InitUndo( *mpDoc, nTab, nTab );
mxRedoDoc.reset( new ScDocument( SCDOCMODE_UNDO ) );
mxRedoDoc->InitUndo( *mpDoc, nTab, nTab );
if ( rMarkData.GetSelectCount() > 1 )
{
for (const auto& rTab : rMarkData)
{
if( rTab != nTab )
{
mxUndoDoc->AddUndoTab( rTab, rTab );
mxRedoDoc->AddUndoTab( rTab, rTab );
}
}
}
// *** create and init the edit engine *** --------------------------------
mxEngine.reset( new ScSpellingEngine(
mpDoc->GetEnginePool(), *mpViewData, mxUndoDoc.get(), mxRedoDoc.get(), LinguMgr::GetSpellChecker() ) );
mxEngine->SetRefDevice( mpViewData->GetActiveWin()->GetOutDev() );
mpViewShell->MakeEditView( mxEngine.get(), nCol, nRow );
EditView* pEditView = mpViewData->GetEditView( mpViewData->GetActivePart() );
mpViewData->SetSpellingView( pEditView );
tools::Rectangle aRect( Point( 0, 0 ), Point( 0, 0 ) );
pEditView->SetOutputArea( aRect );
mxEngine->SetControlWord( EEControlBits::USECHARATTRIBS );
mxEngine->EnableUndo( false );
mxEngine->SetPaperSize( aRect.GetSize() );
mxEngine->SetTextCurrentDefaults( OUString() );
mxEngine->ClearModifyFlag();
mbNeedNextObj = true;
}
bool ScSpellDialogChildWindow::IsSelectionChanged()
{
if (!mxOldRangeList || !mpViewShell
|| (mpViewShell != dynamic_cast<ScTabViewShell*>(SfxViewShell::Current())))
return true;
if( EditView* pEditView = mpViewData->GetSpellingView() )
if (&pEditView->getEditEngine() != mxEngine.get())
return true;
ScRangeList aCurrentRangeList;
mpViewData->GetMarkData().FillRangeListWithMarks(&aCurrentRangeList, true);
return (*mxOldRangeList != aCurrentRangeList);
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */