namespace svx{ class SpellUndoAction_Impl : public SfxUndoAction
{
sal_uInt16 m_nId; const Link<SpellUndoAction_Impl&,void>& m_rActionLink; //undo of button enabling bool m_bEnableChangePB; bool m_bEnableChangeAllPB; //undo of MarkNextError - used in change and change all, ignore and ignore all
tools::Long m_nOldErrorStart;
tools::Long m_nOldErrorEnd; bool m_bIsErrorLanguageSelected; //undo of AddToDictionary
Reference<XDictionary> m_xDictionary;
OUString m_sAddedWord; //move end of error - ::ChangeMarkedWord()
tools::Long m_nOffset;
// fdo#68794 set initial title for cases where no text has been processed // yet to show its language attributes
OUString sTitle = rParent.HasGrammarChecking() ? m_sTitleSpellingGrammar : m_sTitleSpelling;
m_xDialog->set_title(m_xDialog->strip_mnemonic(sTitle.replaceFirst("$LANGUAGE ($LOCATION)", "")));
// disable controls if service is missing
m_xDialog->set_sensitive(xSpell.is());
//InitHdl wants to use virtual methods, so it //can't be called during the ctor, so init //it on next event cycle post-ctor
m_pInitHdlEvent = Application::PostUserEvent(LINK(this, SpellDialog, InitHdl));
}
SpellDialog::~SpellDialog()
{ if (m_xOptionsDlg)
{
m_xOptionsDlg->response(RET_CANCEL);
m_xOptionsDlg.reset();
}
if (m_pInitHdlEvent)
Application::RemoveUserEvent(m_pInitHdlEvent); if (pImpl)
{ // save possibly modified user-dictionaries
Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() ); if (xDicList.is())
SaveDictionaries( xDicList );
m_xCheckGrammarCB->set_visible(rParent.HasGrammarChecking());
m_xExplainLink->set_visible(!m_xExplainLink->get_uri().isEmpty()); if (m_xExplainFT->get_label().isEmpty())
{
m_xExplainFT->hide();
m_xExplainLink->hide();
}
if (bOldShowExplain != m_xExplainLink->get_visible() || bOldShowGrammar != m_xCheckGrammarCB->get_visible())
m_xDialog->resize_to_request();
}
void SpellDialog::SpellContinue_Impl(std::unique_ptr<UndoChangeGroupGuard>* pGuard, bool bUseSavedSentence, bool bIgnoreCurrentError)
{ //initially or after the last error of a sentence MarkNextError will fail //then GetNextSentence() has to be called followed again by MarkNextError() //MarkNextError is not initially called if the UndoEdit mode is active bool bNextSentence = false; if (!m_xSentenceED)
{ return;
}
IMPL_LINK( SpellDialog, ExtClickHdl, weld::Button&, rBtn, void )
{ if (m_xOptionsPB.get() == &rBtn)
StartSpellOptDlg_Impl(); elseif (m_xAutoCorrPB.get() == &rBtn)
{ //get the currently selected wrong word
OUString sCurrentErrorText = m_xSentenceED->GetErrorText(); //get the wrong word from the XSpellAlternative
SpellErrorDescription aSpellErrorDescription; bool bSpellErrorDescription = m_xSentenceED->GetAlternatives(aSpellErrorDescription); if (bSpellErrorDescription)
{
OUString sWrong(aSpellErrorDescription.sErrorText); //if the word has not been edited in the MultiLineEdit then //the current suggestion should be used //if it's not the 'no suggestions' entry if(sWrong == sCurrentErrorText &&
m_xSuggestionLB->get_sensitive() && m_xSuggestionLB->get_selected_index() != -1 &&
m_sNoSuggestionsST != m_xSuggestionLB->get_selected_text())
{
sCurrentErrorText = m_xSuggestionLB->get_selected_text();
} if(sWrong != sCurrentErrorText)
{
SvxPrepareAutoCorrect( sWrong, sCurrentErrorText );
LanguageType eLang = GetSelectedLang_Impl();
rParent.AddAutoCorrection( sWrong, sCurrentErrorText, eLang ); //correct the word immediately
ChangeHdl(*m_xAutoCorrPB);
}
}
}
}
//dots are sometimes part of the spelled word but they are not necessarily part of the replacement bool bEndsWithDot = aString != "." && aString.endsWith(".");
/* tdf#132822 start an undo group in ctor and close it in the dtor. This can thenbepassedtoSpellContinue_Implwhichcandeleteitinadvanceofits naturalscopetoforceclosingtheundogroupifSpellContinue_Implneedsto fetchanewparagraphanddiscardallundoinformationwhichcanonlybe
done properly if there are no open undo groups */ class UndoChangeGroupGuard
{ private:
SentenceEditWindow_Impl& m_rSentenceED; public:
UndoChangeGroupGuard(SentenceEditWindow_Impl& rSentenceED)
: m_rSentenceED(rSentenceED)
{
m_rSentenceED.UndoActionStart(SPELLUNDO_CHANGE_GROUP);
}
~UndoChangeGroupGuard()
{
m_rSentenceED.UndoActionEnd();
}
};
IMPL_LINK( SpellDialog, DialogUndoHdl, SpellUndoAction_Impl&, rAction, void )
{ switch(rAction.GetId())
{ case SPELLUNDO_CHANGE_TEXTENGINE:
{ if(rAction.IsEnableChangePB())
m_xChangePB->set_sensitive(false); if(rAction.IsEnableChangeAllPB())
m_xChangeAllPB->set_sensitive(false);
} break; case SPELLUNDO_CHANGE_NEXTERROR:
{
m_xSentenceED->MoveErrorMarkTo(static_cast<sal_Int32>(rAction.GetOldErrorStart()), static_cast<sal_Int32>(rAction.GetOldErrorEnd()), false); if(rAction.IsErrorLanguageSelected())
{
UpdateBoxes_Impl();
}
} break; case SPELLUNDO_CHANGE_ADD_TO_DICTIONARY:
{ if(rAction.GetDictionary().is())
rAction.GetDictionary()->remove(rAction.GetAddedWord());
} break; case SPELLUNDO_MOVE_ERROREND :
{ if(rAction.GetOffset() != 0)
m_xSentenceED->MoveErrorEnd(rAction.GetOffset());
} break; case SPELLUNDO_UNDO_EDIT_MODE :
{ //refill the dialog with the currently spelled sentence - throw away all changes
SpellContinue_Impl(nullptr, true);
} break; case SPELLUNDO_ADD_IGNORE_RULE: //undo of ignored rules is not supported break;
}
}
void SpellDialog::Impl_Restore(bool bUseSavedSentence)
{ //clear the "ChangeAllList"
LinguMgr::GetChangeAllList()->clear(); //get a new sentence
m_xSentenceED->SetText(OUString());
m_xSentenceED->ResetModified(); //Resolves: fdo#39348 refill the dialog with the currently spelled sentence
SpellContinue_Impl(nullptr, bUseSavedSentence);
m_xIgnorePB->set_label(m_sIgnoreOnceST);
}
IMPL_LINK_NOARG(SpellDialog, IgnoreHdl, weld::Button&, void)
{ if (m_sResumeST == m_xIgnorePB->get_label())
{
Impl_Restore(false);
} else
{ //in case the error has been changed manually it has to be restored, // since the users choice now was to ignore the error
m_xSentenceED->RestoreCurrentError();
// the word is being ignored
SpellContinue_Impl(nullptr, false, true);
}
}
void SpellDialog::Close()
{ if (IsClosing()) return;
// We have to call ToggleChildWindow directly; calling SfxDispatcher's // Execute() does not work here when we are in a document with protected // section - in that case, the cursor can move from the editable field to // the protected area, and the slots get disabled because of // SfxDisableFlags::SwOnProtectedCursor (see FN_SPELL_GRAMMAR_DIALOG in .sdi). if (SfxViewFrame* pViewFrame = SfxViewFrame::Current())
pViewFrame->ToggleChildWindow(rParent.GetType());
}
IMPL_LINK_NOARG(SpellDialog, LanguageSelectHdl, weld::ComboBox&, void)
{ //If selected language changes, then add->list should be regenerated to //match
InitUserDicts();
//if currently an error is selected then search for alternatives for //this word and fill the alternatives ListBox accordingly
OUString sError = m_xSentenceED->GetErrorText();
m_xSuggestionLB->clear(); if (!sError.isEmpty())
{
LanguageType eLanguage = m_xLanguageLB->get_active_id();
Reference <XSpellAlternatives> xAlt = xSpell->spell( sError, static_cast<sal_uInt16>(eLanguage),
Sequence< PropertyValue >() ); if( xAlt.is() )
m_xSentenceED->SetAlternatives( xAlt ); else
{
m_xSentenceED->ChangeMarkedWord( sError, eLanguage );
SpellContinue_Impl();
}
int SpellDialog::InitUserDicts()
{ const LanguageType nLang = m_xLanguageLB->get_active_id();
// get list of dictionaries
Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() ); if (xDicList.is())
{ // add active, positive dictionary to dic-list (if not already done). // This is to ensure that there is at least on dictionary to which // words could be added.
Reference< XDictionary > xDic( LinguMgr::GetStandardDic() ); if (xDic.is())
xDic->setActive( true );
pImpl->aDics = xDicList->getDictionaries();
}
SvtLinguConfig aCfg;
// list suitable dictionaries bool bEnable = false;
m_xAddToDictMB->clear();
m_aDictIdToName.clear();
sal_uInt16 nItemId = 1; // menu items should be enumerated from 1 and not 0 for (auto& xDicTmp : pImpl->aDics)
{ if (!xDicTmp.is() || LinguMgr::GetIgnoreAllList() == xDicTmp) continue;
IMPL_LINK_NOARG(SpellDialog, CancelHdl, weld::Button&, void)
{ //apply changes and ignored text parts first - if there are any if (m_xSentenceED->IsModified())
{
rParent.ApplyChangedSentence(m_xSentenceED->CreateSpellPortions(), false);
}
Close();
}
if (m_xDialog->has_toplevel_focus())
{ //notify the child window of the focus change
rParent.GetFocus();
} else
{ //notify the child window of the focus change
rParent.LoseFocus();
}
}
bool SpellDialog::GetNextSentence_Impl(std::unique_ptr<UndoChangeGroupGuard>* pGuard, bool bUseSavedSentence, bool bRecheck)
{ bool bRet = false; if(!bUseSavedSentence)
{ //apply changes and ignored text parts
rParent.ApplyChangedSentence(m_xSentenceED->CreateSpellPortions(), bRecheck);
}
m_xSentenceED->ResetIgnoreErrorsAt();
m_xSentenceED->ResetModified();
SpellPortions aSentence = bUseSavedSentence ? m_aSavedSentence : rParent.GetNextWrongSentence( bRecheck ); if(!bUseSavedSentence)
m_aSavedSentence = aSentence; bool bHasReplaced = false; while(!aSentence.empty())
{ //apply all changes that are already part of the "ChangeAllList" //returns true if the list still contains errors after the changes have been applied
if(!aSentence.empty())
{
OUStringBuffer sText; for (autoconst& elem : aSentence)
{ // hidden text has to be ignored if(!elem.bIsHidden)
sText.append(elem.sText);
} // tdf#132822 fire undo-stack UndoActionEnd to close undo stack because we're about to throw away the paragraph entirely if (pGuard)
pGuard->reset();
m_xSentenceED->SetText(sText.makeStringAndClear());
sal_Int32 nStartPosition = 0;
sal_Int32 nEndPosition = 0;
for (autoconst& elem : aSentence)
{ // hidden text has to be ignored if(!elem.bIsHidden)
{
nEndPosition += elem.sText.getLength(); if(elem.xAlternatives.is())
{
SpellErrorDescription aDesc( false, elem.xAlternatives->getWord(),
elem.xAlternatives->getLocale(), elem.xAlternatives->getAlternatives(), nullptr);
SfxGrabBagItem aSpellErrorDescription(EE_CHAR_GRABBAG,
std::map<OUString, css::uno::Any>{{ u"SpellErrorDescription"_ustr, uno::Any(aDesc.toSequence()) }});
m_xSentenceED->SetAttrib(aSpellErrorDescription, nStartPosition, nEndPosition);
} elseif(elem.bIsGrammarError )
{
beans::PropertyValues aProperties = elem.aGrammarError.aProperties;
OUString sFullCommentURL;
sal_Int32 i = 0; while ( sFullCommentURL.isEmpty() && i < aProperties.getLength() )
{ if ( aProperties[i].Name == "FullCommentURL" )
{
uno::Any aValue = aProperties[i].Value;
aValue >>= sFullCommentURL;
}
++i;
}
void SentenceEditWindow_Impl::DoScroll()
{ if (m_xEditView)
{ auto currentDocPos = m_xEditView->GetVisArea().Top(); auto nDiff = currentDocPos - m_xScrolledWindow->vadjustment_get_value(); // we expect SetScrollBarRange callback to be triggered by Scroll // to set where we ended up
m_xEditView->Scroll(0, nDiff);
}
}
void SentenceEditWindow_Impl::EditViewScrollStateChange()
{ // editengine height has changed or editview scroll pos has changed
SetScrollBarRange();
}
void SentenceEditWindow_Impl::SetScrollBarRange()
{
EditEngine *pEditEngine = GetEditEngine(); if (!pEditEngine) return; if (!m_xScrolledWindow) return;
EditView* pEditView = GetEditView(); if (!pEditView) return;
int nVUpper = pEditEngine->GetTextHeight(); int nVCurrentDocPos = pEditView->GetVisArea().Top(); const Size aOut(pEditView->GetOutputArea().GetSize()); int nVStepIncrement = aOut.Height() * 2 / 10; int nVPageIncrement = aOut.Height() * 8 / 10; int nVPageSize = aOut.Height();
/* limit the page size to below nUpper because gtk's gtk_scrolled_window_start_deceleration has effectively...
//check previous position if this exists //that is a redundant in the case the attribute found above already is on the left cursor side //but it's o.k. for two errors/fields side by side if (nCursor)
{
--nCursor;
pBackAttrLeft = FindCharAttrib(nCursor, EE_CHAR_BKGCOLOR, aAttribList);
pErrorAttrLeft = FindCharAttrib(nCursor, EE_CHAR_GRABBAG, aAttribList);
bHasFieldLeft = pBackAttrLeft !=nullptr;
bHasErrorLeft = pErrorAttrLeft != nullptr;
++nCursor;
}
} //Here we have to determine if the error found is the one currently active bool bIsErrorActive = (pErrorAttr && pErrorAttr->nStart == m_nErrorStart) ||
(pErrorAttrLeft && pErrorAttrLeft->nStart == m_nErrorStart);
SAL_WARN_IF(
nSelectionType == INVALID, "cui.dialogs", "selection type not set");
sal_Int8 nAction = ACTION_CONTINUE; switch(nSelectionType)
{ // 1 - backspace delete any other // UE on field FS on error CO on field FS on error CO case LEFT_NO : if(bBackspace)
{
nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_UNDOEDIT; //to force the use of pBackAttrLeft
pBackAttr = nullptr;
} elseif(bDelete)
nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE; else
nAction = bHasError && !nCursor ? ACTION_CONTINUE :
bHasError ? ACTION_EXPAND : bHasErrorLeft ? ACTION_CONTINUE : ACTION_UNDOEDIT; break; // 2 - on field FS on error C case INSIDE_NO :
nAction = bHasField ? ACTION_SELECTFIELD :
bIsErrorActive ? ACTION_CONTINUE : ACTION_UNDOEDIT; break; // 3 - backspace delete any other // on field FS on error CO UE on field UE on error EX case RIGHT_NO : if(bBackspace)
nAction = bHasFieldLeft ? ACTION_SELECTFIELD : ACTION_CONTINUE; elseif(bDelete)
nAction = bHasFieldLeft && bHasError ? ACTION_CONTINUE : ACTION_UNDOEDIT; else
nAction = bHasFieldLeft && bHasError ? ACTION_EXPAND :
bHasError ? ACTION_CONTINUE : bHasErrorLeft ? ACTION_EXPAND :ACTION_UNDOEDIT; break; // 4 - on field UE and on error CO case FULL :
nAction = ACTION_UNDOEDIT; break; // 5 - on field FS and on error CO case INSIDE_YES :
nAction = bHasField ? ACTION_SELECTFIELD : ACTION_CONTINUE; break; // 6 - on field FS and on error UE case BRACE :
nAction = bHasField ? ACTION_SELECTFIELD : ACTION_UNDOEDIT; break; // 7 - UE // 8 - UE case OUTSIDE_NO : case OUTSIDE_YES:
nAction = ACTION_UNDOEDIT; break;
} //save the current paragraph
sal_Int32 nCurrentLen = m_xEditEngine->GetText().getLength(); if (nAction != ACTION_SELECTFIELD)
{
m_xEditView->PostKeyEvent(rKeyEvt);
} else
{ const EECharAttrib* pCharAttr = pBackAttr ? pBackAttr : pBackAttrLeft; if (pCharAttr)
m_xEditView->SetSelection(ESelection(0, pCharAttr->nStart, 0, pCharAttr->nEnd));
} if(nAction == ACTION_EXPAND)
{
DBG_ASSERT(pErrorAttrLeft || pErrorAttr, "where is the error"); //text has been added on the right and only the 'error attribute has to be corrected if (pErrorAttrLeft)
{
SpellErrorDescription aSpellErrorDescription;
ExtractErrorDescription(*pErrorAttrLeft, aSpellErrorDescription);
std::unique_ptr<SfxPoolItem> xNewError(pErrorAttrLeft->pAttr->Clone());
sal_Int32 nStart = pErrorAttrLeft->nStart;
sal_Int32 nEnd = pErrorAttrLeft->nEnd + 1;
m_xEditEngine->RemoveAttribs(ESelection(0, nStart, 0, nEnd), false, EE_CHAR_GRABBAG);
SetAttrib(*xNewError, nStart, nEnd); //only active errors move the mark if (bIsErrorActive)
{ bool bGrammar = aSpellErrorDescription.bIsGrammarError;
MoveErrorMarkTo(nStart, nEnd, bGrammar);
}
} //text has been added on the left then the error attribute has to be expanded and the //field attribute on the right - if any - has to be contracted elseif (pErrorAttr)
{
SpellErrorDescription aSpellErrorDescription;
ExtractErrorDescription(*pErrorAttr, aSpellErrorDescription);
//determine the change
sal_Int32 nAddedChars = m_xEditEngine->GetText().getLength() - nCurrentLen;
std::unique_ptr<SfxPoolItem> xNewError(pErrorAttr->pAttr->Clone());
sal_Int32 nStart = pErrorAttr->nStart + nAddedChars;
sal_Int32 nEnd = pErrorAttr->nEnd + nAddedChars;
m_xEditEngine->RemoveAttribs(ESelection(0, nStart, 0, nEnd), false, EE_CHAR_GRABBAG);
nStart = pErrorAttr->nStart;
SetAttrib(*xNewError, nStart, nEnd); //only if the error is active the mark is moved here if (bIsErrorActive)
{ bool bGrammar = aSpellErrorDescription.bIsGrammarError;
MoveErrorMarkTo(nStart, nEnd, bGrammar);
}
xNewError.reset();
if (pBackAttrLeft)
{
std::unique_ptr<SfxPoolItem> xNewBack(pBackAttrLeft->pAttr->Clone());
sal_Int32 _nStart = pBackAttrLeft->nStart + nAddedChars;
sal_Int32 _nEnd = pBackAttrLeft->nEnd + nAddedChars;
m_xEditEngine->RemoveAttribs(ESelection(0, _nStart, 0, _nEnd), false, EE_CHAR_BKGCOLOR);
_nStart = pBackAttrLeft->nStart;
SetAttrib(*xNewBack, _nStart, _nEnd);
}
}
} elseif(nAction == ACTION_UNDOEDIT)
{
SetUndoEditMode(true);
} //make sure the error positions are correct after text changes //the old attribute may have been deleted //all changes inside of the current error leave the error attribute at the current //start position if (!IsUndoEditMode() && bIsErrorActive)
{
aAttribList.clear();
m_xEditEngine->GetCharAttribs(0, aAttribList); const EECharAttrib* pFontColor = FindCharAttrib(nCursor, EE_CHAR_COLOR, aAttribList); const EECharAttrib* pErrorAttrib = FindCharAttrib(m_nErrorStart, EE_CHAR_GRABBAG, aAttribList); if (pFontColor && pErrorAttrib)
{
m_nErrorStart = pFontColor->nStart;
m_nErrorEnd = pFontColor->nEnd; if (pErrorAttrib->nStart != m_nErrorStart || pErrorAttrib->nEnd != m_nErrorEnd)
{
std::unique_ptr<SfxPoolItem> xNewError(pErrorAttrib->pAttr->Clone());
assert(pErrorAttr);
m_xEditEngine->RemoveAttribs(ESelection(0, pErrorAttr->nStart, 0, pErrorAttr->nEnd), false, EE_CHAR_GRABBAG);
SetAttrib(*xNewError, m_nErrorStart, m_nErrorEnd);
}
}
} //this is not a modification anymore if(nAction != ACTION_SELECTFIELD && !m_bIsUndoEditMode)
CallModifyLink();
} else
bConsumed = m_xEditView->PostKeyEvent(rKeyEvt);
if (m_nErrorEnd >= nTextLen - 1) returnfalse; //if it's not already modified the modified flag has to be reset at the end of the marking bool bModified = IsModified(); bool bRet = false; const sal_Int32 nOldErrorStart = m_nErrorStart; const sal_Int32 nOldErrorEnd = m_nErrorEnd;
//create a cursor behind the end of the last error //- or at 0 at the start of the sentence
sal_Int32 nCursor(m_nErrorEnd ? m_nErrorEnd + 1 : 0);
//search for SpellErrorDescription
SpellErrorDescription aSpellErrorDescription;
//iterate over the text and search for the next error that maybe has //to be replace by a ChangeAllList replacement bool bGrammarError = false; while (nCursor < nTextLen)
{ const SpellErrorDescription* pSpellErrorDescription = nullptr; const EECharAttrib* pEECharAttrib = nullptr;
nCursor = std::max(nCursor, nMinPos); // move forward if possible
// maybe the error found here is already in the ChangeAllList and has to be replaced
Reference<XDictionary> xChangeAll = LinguMgr::GetChangeAllList();
Reference<XDictionaryEntry> xEntry;
int nLenChange = ChangeMarkedWord(sReplacement, LanguageTag::convertToLanguageType(pSpellErrorDescription->aLocale));
nCursor += sReplacement.getLength();
if (nLenChange)
m_xEditEngine->GetCharAttribs(0, aAttribList); // maybe the error found here is already added to the dictionary and has to be ignored
} elseif(pSpellErrorDescription && !bGrammarError &&
xSpell->isValid(GetErrorText(), static_cast<sal_uInt16>(LanguageTag::convertToLanguageType( pSpellErrorDescription->aLocale )),
Sequence< PropertyValue >() ))
{
++nCursor;
} else break;
}
//if an attrib has been found search for the end of the error string if (nCursor < nTextLen)
{
MoveErrorMarkTo(nCursor, m_nErrorEnd, bGrammarError);
bRet = true; //add an undo action
std::unique_ptr<SpellUndoAction_Impl> pAction(new SpellUndoAction_Impl(
SPELLUNDO_CHANGE_NEXTERROR, GetSpellDialog()->aDialogUndoLink));
pAction->SetErrorMove(nOldErrorStart, nOldErrorEnd);
// tdf#116566 Use color defined in the current Color Scheme
Color aSpellErrorCollor = svtools::ColorConfig().GetColorValue(svtools::SPELL).nColor;
Color aGrammarErrorCollor = svtools::ColorConfig().GetColorValue(svtools::GRAMMAR).nColor;
// Set the selection so the editview will autoscroll to make this visible // unless (tdf#133958) the selection already overlaps this range
ESelection aCurrentSelection = m_xEditView->GetSelection();
aCurrentSelection.Adjust(); bool bCurrentSelectionInRange = nStart <= aCurrentSelection.end.nIndex && aCurrentSelection.start.nIndex <= nEnd; if (!bCurrentSelectionInRange)
{
m_xEditView->SetSelection(ESelection(0, nStart)); // tdf#157148 ensure current location is auto-scrolled to be visible
m_xEditView->ShowCursor();
}
if (nDiffLen)
m_xEditEngine->GetCharAttribs(0, aAttribList);
if (!m_nErrorStart)
{ //attributes following an error at the start of the text are not moved but expanded from the //text engine - this is done to keep full-paragraph-attributes //in the current case that handling is not desired const EECharAttrib* pLangAttrib = FindCharAttrib(m_nErrorEnd, EE_CHAR_LANGUAGE, aAttribList);
if (aBreakPositions.empty())
{ //if all content has been overwritten the attributes may have been removed, too
svx::SpellPortion aPortion1;
aPortion1.eLanguage = GetSpellDialog()->GetSelectedLang_Impl();
// quick partly fix of #i71318. Correct fix needs to patch the EditEngine itself... // this one will only prevent text from disappearing. It may to not have the // correct language and will probably not spell checked... const sal_uInt32 nPara = m_xEditEngine->GetParagraphCount(); if (nPara > 1)
{
OUStringBuffer aLeftOverText; for (sal_uInt32 i = 1; i < nPara; ++i)
{
aLeftOverText.append("\x0a"); // the manual line break...
aLeftOverText.append(m_xEditEngine->GetText(i));
} if (pError)
{ // we need to add a new portion containing the left-over text
svx::SpellPortion aPortion2;
aPortion2.eLanguage = eLang;
aPortion2.sText = aLeftOverText.makeStringAndClear();
aRet.push_back( aPortion2 );
} elseif (!aLeftOverText.isEmpty() && !aRet.empty())
{ // we just need to append the left-over text to the last portion (which had no errors)
aRet[ aRet.size() - 1 ].sText += aLeftOverText;
}
}
}
return aRet;
}
void SentenceEditWindow_Impl::Undo()
{
EditUndoManager& rUndoMgr = m_xEditEngine->GetUndoManager();
DBG_ASSERT(GetUndoActionCount(), "no undo actions available" ); if(!GetUndoActionCount()) return; bool bSaveUndoEdit = IsUndoEditMode();
SpellUndoAction_Impl* pUndoAction; //if the undo edit mode is active then undo all changes until the UNDO_EDIT_MODE action has been found do
{
pUndoAction = static_cast<SpellUndoAction_Impl*>(rUndoMgr.GetUndoAction());
rUndoMgr.Undo();
}while(bSaveUndoEdit && SPELLUNDO_UNDO_EDIT_MODE != pUndoAction->GetId() && GetUndoActionCount());
//put the appropriate action on the Undo-stack
AddUndoAction( std::make_unique<SpellUndoAction_Impl>(
SPELLUNDO_UNDO_EDIT_MODE, GetSpellDialog()->aDialogUndoLink) );
pSpellDialog->m_xChangePB->set_sensitive(true);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.