/* -*- 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 .
*/
// iterate over the paragraphs ... for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ )
{
ContentNode* pNode = maEditDoc.GetObject( nNode );
assert( pNode && "Node not found: GetAttrib" );
const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // Can also be == nStart!
// Problem: Templates... // => Other way: // 1) Hard character attributes, as usual... // 2) Examine Style and paragraph attributes only when OFF...
// First the very hard formatting... if (pNode)
EditDoc::FindAttribs( pNode, nStartPos, nEndPos, aCurSet );
if( nOnlyHardAttrib != EditEngineAttribs::OnlyHard )
{ // and then paragraph formatting and template... for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++)
{ if ( aCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT )
{ const SfxPoolItem* pItem = nullptr; if ( nOnlyHardAttrib == EditEngineAttribs::All )
{ const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich );
aCurSet.Put( rItem );
} elseif ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich, true, &pItem ) == SfxItemState::SET )
{
aCurSet.Put( *pItem );
}
} elseif ( aCurSet.GetItemState( nWhich ) == SfxItemState::SET )
{ const SfxPoolItem* pItem = nullptr; const SfxPoolItem* pTmpItem = nullptr; if ( nOnlyHardAttrib == EditEngineAttribs::All )
{
pItem = &pNode->GetContentAttribs().GetItem( nWhich );
} elseif ( pNode->GetContentAttribs().GetItems().GetItemState( nWhich, true, &pTmpItem ) == SfxItemState::SET )
{
pItem = pTmpItem;
} // pItem can only be NULL when nOnlyHardAttrib... if ( !pItem || ( *pItem != aCurSet.Get( nWhich ) ) )
{ // Problem: When Paragraph style with for example font, // but the Font is hard and completely different, // wrong in selection if invalidated.... // => better not invalidate, instead CHANGE! // It would be better to fill each paragraph with // an itemset and compare this in large. if ( nWhich <= EE_PARA_END )
aCurSet.InvalidateItem( nWhich );
}
}
}
}
}
// fill empty slots with defaults ... if ( nOnlyHardAttrib == EditEngineAttribs::All )
{ for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++ )
{ if ( aCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT )
{
aCurSet.Put( maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( nWhich ) );
}
}
} return aCurSet;
}
SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, GetAttribsFlags nFlags ) const
{ // Optimized function with fewer Puts(), which cause unnecessary cloning from default items. // If this works, change GetAttribs( EditSelection ) to use this for each paragraph and merge the results!
if ( nStart == nEnd )
{
sal_Int32 nCursorPos = nStart; if ( ( rAttr.GetStart() <= nCursorPos ) && ( rAttr.GetEnd() >= nCursorPos ) )
{ // To be used the attribute has to start BEFORE the position, or it must be a // new empty attr AT the position, or we are on position 0. if ( ( rAttr.GetStart() < nCursorPos ) || rAttr.IsEmpty() || !nCursorPos )
{ // maybe this attrib ends here and a new attrib with 0 Len may follow and be valid here, // but that s no problem, the empty item will come later and win.
aAttribs.Put( *rAttr.GetItem() );
}
}
} else
{ // Check every attribute covering the area, partial or full. if ( ( rAttr.GetStart() < nEnd ) && ( rAttr.GetEnd() > nStart ) )
{ if ( ( rAttr.GetStart() <= nStart ) && ( rAttr.GetEnd() >= nEnd ) )
{ // full coverage
aAttribs.Put( *rAttr.GetItem() );
} else
{ // OptimizeRanges() assures that not the same attr can follow for full coverage // only partial, check with current, when using para/style, otherwise invalid. if ( !( nFlags & (GetAttribsFlags::PARAATTRIBS|GetAttribsFlags::STYLESHEET) ) ||
( *rAttr.GetItem() != aAttribs.Get( rAttr.Which() ) ) )
{
aAttribs.InvalidateItem( rAttr.Which() );
}
}
}
}
// When no selection => use the Attribute on the word. // ( the RTF-parser should actually never call the Method without a Range ) if ( nSpecial == SetAttribsMode::WholeWord && !aSel.HasRange() )
aSel = SelectWord( aSel, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, false );
const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart!
// Optimize: If whole paragraph, then RemoveCharAttribs (nPara)? bool bChanged = maEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich ); if ( bRemoveParaAttribs )
{
SetParaAttribs( nNode, *_pEmptyItemSet ); // Invalidated
} elseif (eMode == EERemoveParaAttribsMode::RemoveCharItems)
{ // For 'Format-Standard' also the character attributes should // disappear, which were set as paragraph attributes by the // DrawingEngine. These could not have been set by the user anyway.
// #106871# Not when nWhich // Would have been better to offer a separate method for format/standard... if ( !nWhich )
{
SfxItemSet aAttribs( GetParaAttribs( nNode ) ); for ( sal_uInt16 nW = EE_CHAR_START; nW <= EE_CHAR_END; nW++ )
aAttribs.ClearItem( nW );
SetParaAttribs( nNode, aAttribs );
}
}
void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode )
{
pNode->GetCharAttribs().DeleteEmptyAttribs();
sal_Int32 nEndPos = pNode->Len(); for ( sal_uInt16 nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ )
{ if ( pNode->GetContentAttribs().HasItem( nWhich ) )
{ const SfxPoolItem& rItem = pNode->GetContentAttribs().GetItem( nWhich ); // Fill the gap:
sal_Int32 nLastEnd = 0; const EditCharAttrib* pAttr = pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ); while ( pAttr )
{
nLastEnd = pAttr->GetEnd(); if ( pAttr->GetStart() > nLastEnd )
maEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem ); // #112831# Last Attr might go from 0xffff to 0x0000
pAttr = nLastEnd ? pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ) : nullptr;
}
// And the Rest: if ( nLastEnd < nEndPos )
maEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem );
}
}
mbFormatted = false; // Portion does not need to be invalidated here, happens elsewhere.
}
}
bDone = false;
} break; case KEY_F12:
{ if ( rKeyEvent.GetKeyCode().IsMod1() && rKeyEvent.GetKeyCode().IsMod2() )
DumpData(true);
bDone = false;
} break; #endif case KEY_UP: case KEY_DOWN: case KEY_LEFT: case KEY_RIGHT: case KEY_HOME: case KEY_END: case KEY_PAGEUP: case KEY_PAGEDOWN: case css::awt::Key::MOVE_WORD_FORWARD: case css::awt::Key::SELECT_WORD_FORWARD: case css::awt::Key::MOVE_WORD_BACKWARD: case css::awt::Key::SELECT_WORD_BACKWARD: case css::awt::Key::MOVE_TO_BEGIN_OF_LINE: case css::awt::Key::MOVE_TO_END_OF_LINE: case css::awt::Key::SELECT_TO_BEGIN_OF_LINE: case css::awt::Key::SELECT_TO_END_OF_LINE: case css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH: case css::awt::Key::MOVE_TO_END_OF_PARAGRAPH: case css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH: case css::awt::Key::SELECT_TO_END_OF_PARAGRAPH: case css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT: case css::awt::Key::MOVE_TO_END_OF_DOCUMENT: case css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT: case css::awt::Key::SELECT_TO_END_OF_DOCUMENT:
{ if ( !rKeyEvent.GetKeyCode().IsMod2() || ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) )
{ if ( ImpEditEngine::DoVisualCursorTraveling() && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) /* || ( nCode == KEY_HOME ) || ( nCode == KEY_END ) */ ) )
bSetCursorFlags = false; // Will be manipulated within visual cursor move
bMoved = true;
} #if OSL_DEBUG_LEVEL > 1
GetLanguage(getImpl().GetEditDoc().GetPos( aCurSel.Max().GetNode() ), aCurSel.Max().GetIndex()); #endif
} break; case KEY_BACKSPACE: case KEY_DELETE: case css::awt::Key::DELETE_WORD_BACKWARD: case css::awt::Key::DELETE_WORD_FORWARD: case css::awt::Key::DELETE_TO_BEGIN_OF_PARAGRAPH: case css::awt::Key::DELETE_TO_END_OF_PARAGRAPH:
{ if ( !bReadOnly && !rKeyEvent.GetKeyCode().IsMod2() )
{ // check if we are behind a bullet and using the backspace key
ContentNode *pNode = aCurSel.Min().GetNode(); const SvxNumberFormat *pFmt = GetNumberFormat( pNode ); if (pFmt && nCode == KEY_BACKSPACE &&
!aCurSel.HasRange() && aCurSel.Min().GetIndex() == 0)
{ // if the bullet is still visible, just make it invisible. // Otherwise continue as usual.
// have this and the following paragraphs formatted and repainted. // (not painting a numbering in the list may cause the following // numberings to have different numbers than before and thus the // length may have changed as well )
FormatAndLayout(mpActiveView);
if (bSetCursorFlags)
pEditView->getImpl().maExtraCursorFlags = aNewCursorFlags;
if ( bModified )
{
DBG_ASSERT( !bReadOnly, "ReadOnly but modified???" ); // Idle-Formatter only when AnyInput. if ( bAllowIdle && GetStatus().UseIdleFormatter()
&& Application::AnyInput( VclInputFlags::KEYBOARD) )
IdleFormatAndLayout( pEditView ); else
FormatAndLayout( pEditView );
} elseif ( bMoved )
{ bool bGotoCursor = pEditView->getImpl().DoAutoScroll();
pEditView->getImpl().ShowCursor( bGotoCursor, true );
CallStatusHdl();
}
return bDone;
}
bool ImpEditEngine::IsSimpleCharInput( const KeyEvent& rKeyEvent )
{ // tdf#168375 return false if both KEY_MOD1 and KEY_MOD2 are pressed // Previously this function returned false only if one of these // modifiers is pressed. At least on macOS, pressing Command-Option // with a character is not a simple character so return false if // both modifiers are pressed.
sal_uInt16 nNonShiftModifiers = rKeyEvent.GetKeyCode().GetModifier() & ~KEY_SHIFT;
nNonShiftModifiers &= ( KEY_MOD1 | KEY_MOD2 ); return !nNonShiftModifiers && EditEngine::IsPrintable( rKeyEvent.GetCharCode() );
}
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.