44#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
45#include <com/sun/star/i18n/WordType.hpp>
46#include <com/sun/star/i18n/ScriptType.hpp>
47#include <com/sun/star/lang/Locale.hpp>
48#include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
49#include <com/sun/star/system/SystemShellExecute.hpp>
50#include <com/sun/star/system/SystemShellExecuteFlags.hpp>
51#include <com/sun/star/system/XSystemShellExecute.hpp>
52#include <com/sun/star/i18n/UnicodeType.hpp>
54#include <rtl/character.hxx>
58#include <osl/diagnose.h>
69#include <unicode/ubidi.h>
80 sal_uInt16 nExtra = 0;
90 pSharedVCL(
EditDLL::
Get().GetSharedVclResources()),
91 aPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ),
92 aMinAutoPaperSize( 0x0, 0x0 ),
93 aMaxAutoPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ),
94 aEditDoc( pItemPool ),
98 pTextObjectPool(nullptr),
99 pUndoManager(nullptr),
100 aWordDelimiters(
" .,;:-`'?!_=\"{}()[]"),
104 mfSpacingScaleX(100.0),
105 mfSpacingScaleY(100.0),
106 mbRoundToNearestPt(false),
109 nBigTextObjectStart(20),
112 nCurTextHeightNTP(0),
113 aOnlineSpellTimer(
"editeng::ImpEditEngine aOnlineSpellTimer" ),
114 aStatusTimer(
"editeng::ImpEditEngine aStatusTimer" ),
115 bKernAsianPunctuation(false),
116 bAddExtLeading(false),
117 bIsFormatting(false),
125 bForceAutoColor(false),
126 bCallParaInsertedOrDeleted(false),
127 bFirstWordCapitalization(true),
128 mbLastTryMerge(false),
129 mbReplaceLeadingSingleQuotationMark(true),
130 mbSkipOutsideFormat(false),
131 mbFuzzing(
utl::ConfigManager::IsFuzzing()),
221 pRefDev->SetMapMode( rMapMode );
233 for ( sal_Int32
n = bKeepParaAttribs ? 1 : 0;
n < nParas;
n++ )
239 if ( bKeepParaAttribs )
279 OSL_ENSURE( nStartNode <= nEndNode,
"Selection not sorted ?" );
281 OUStringBuffer aText(256);
285 for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ )
290 const sal_Int32 nStartPos = nNode==nStartNode ? aSel.
Min().
GetIndex() : 0;
291 const sal_Int32 nEndPos = nNode==nEndNode ? aSel.
Max().
GetIndex() : pNode->
Len();
294 if ( nNode < nEndNode )
297 return aText.makeStringAndClear();
343 bool bConsumed =
true;
347 if ( rCEvt.
GetCommand() == CommandEventId::StartExtTextInput )
353 sal_Int32 nMax = aOldTextAfterStartPos.indexOf(
CH_FEATURE );
355 aOldTextAfterStartPos = aOldTextAfterStartPos.copy( 0, nMax );
360 else if ( rCEvt.
GetCommand() == CommandEventId::EndExtTextInput )
362 OSL_ENSURE(
mpIMEInfos,
"CommandEventId::EndExtTextInput => No start ?" );
391 bool bWasCursorOverwrite =
mpIMEInfos->bWasCursorOverwrite;
401 else if ( rCEvt.
GetCommand() == CommandEventId::ExtTextInput )
403 OSL_ENSURE(
mpIMEInfos,
"CommandEventId::ExtTextInput => No Start ?" );
408 if ( !
pData->IsOnlyCursorChanged() )
418 sal_Int32 nNewIMETextLen =
pData->GetText().getLength();
420 if ( ( nOldIMETextLen > nNewIMETextLen ) &&
421 ( nNewIMETextLen < mpIMEInfos->aOldTextAfterStartPos.getLength() ) )
424 sal_Int32 nRestore = nOldIMETextLen - nNewIMETextLen;
429 else if ( ( nOldIMETextLen < nNewIMETextLen ) &&
430 ( nOldIMETextLen < mpIMEInfos->aOldTextAfterStartPos.getLength() ) )
433 sal_Int32 nOverwrite = nNewIMETextLen - nOldIMETextLen;
434 if ( ( nOldIMETextLen + nOverwrite ) >
mpIMEInfos->aOldTextAfterStartPos.getLength() )
435 nOverwrite =
mpIMEInfos->aOldTextAfterStartPos.getLength() - nOldIMETextLen;
436 OSL_ENSURE( nOverwrite && (nOverwrite < 0xFF00),
"IME Overwrite?!" );
444 if (
pData->GetTextAttr() )
463 if (
pData->IsCursorVisible() )
469 else if ( rCEvt.
GetCommand() == CommandEventId::InputContextChange )
472 else if ( rCEvt.
GetCommand() == CommandEventId::CursorPos )
489 if ( nInputEnd > rLine.
GetEnd() )
490 nInputEnd = rLine.
GetEnd();
493 auto nExtTextInputWidth = aR2.
Left() - aR1.
Right();
495 pEditViewCallbacks->EditViewCursorRect(aRect, nExtTextInputWidth);
497 pWindow->SetCursorRect(&aRect, nExtTextInputWidth);
503 pWindow->SetCursorRect();
506 else if ( rCEvt.
GetCommand() == CommandEventId::SelectionChange )
526 else if ( rCEvt.
GetCommand() == CommandEventId::PrepareReconversion )
542 else if ( rCEvt.
GetCommand() == CommandEventId::QueryCharPosition )
554 const sal_Int32 nMinPos =
mpIMEInfos->aPos.GetIndex();
555 const sal_Int32 nMaxPos = nMinPos +
mpIMEInfos->nLen - 1;
556 std::vector<tools::Rectangle> aRects(
mpIMEInfos->nLen);
558 auto CollectCharPositions = [&](
const LineAreaInfo& rInfo) {
561 if (rInfo.nPortion < nPortionPos)
563 if (rInfo.nPortion > nPortionPos)
565 assert(&rInfo.rPortion == pParaPortion);
569 if (rInfo.pLine->GetStart() > nMaxPos)
571 if (rInfo.pLine->GetEnd() < nMinPos)
573 for (sal_Int32
n = nMinPos;
n <= nMaxPos; ++
n)
575 if (rInfo.pLine->IsIn(
n))
589 pWindow->SetCompositionCharRect(aRects.data(), aRects.size());
633 bool bCtrlClickHappened = rMEvt.
IsMod1();
634 bool bCtrlClickSecOption
636 if ((bCtrlClickHappened && bCtrlClickSecOption)
637 || (!bCtrlClickHappened && !bCtrlClickSecOption))
639 css::uno::Reference<css::system::XSystemShellExecute> exec(
640 css::system::SystemShellExecute::create(
642 exec->execute(pUrlField->GetURL(), OUString(),
643 css::system::SystemShellExecuteFlags::DEFAULTS);
680 for (
size_t nView =
aEditViews.size(); nView; )
701 pView->pImpEditView->SetEditSelection( aEmptySel );
718 if (!rText.isEmpty())
723 pView->pImpEditView->SetEditSelection(
EditSelection( aPaM, aPaM ) );
731 pView->InvalidateWindow( aTmpRect );
734 if (rText.isEmpty()) {
782 assert(pNode &&
"ParaAttribsChanged: Which one?");
797 if ( pNextPortion && !pNextPortion->
IsInvalid() )
816 eTextDirection = TextDirectionality::TopToBottom_RightToLeft;
818 eTextDirection = TextDirectionality::BottomToTop_LeftToRight;
820 eTextDirection = TextDirectionality::RightToLeft_TopToBottom;
856 case css::awt::Key::MOVE_TO_BEGIN_OF_LINE:
858 bKeyModifySelection =
false;
860 case css::awt::Key::MOVE_TO_END_OF_LINE:
862 bKeyModifySelection =
false;
864 case css::awt::Key::MOVE_WORD_BACKWARD:
866 bKeyModifySelection =
false;
868 case css::awt::Key::MOVE_WORD_FORWARD:
870 bKeyModifySelection =
false;
872 case css::awt::Key::MOVE_TO_BEGIN_OF_PARAGRAPH:
874 if( aPaM == aOldPaM )
879 bKeyModifySelection =
false;
881 case css::awt::Key::MOVE_TO_END_OF_PARAGRAPH:
883 if( aPaM == aOldPaM )
888 bKeyModifySelection =
false;
890 case css::awt::Key::MOVE_TO_BEGIN_OF_DOCUMENT:
892 bKeyModifySelection =
false;
894 case css::awt::Key::MOVE_TO_END_OF_DOCUMENT:
896 bKeyModifySelection =
false;
898 case css::awt::Key::SELECT_TO_BEGIN_OF_LINE:
900 bKeyModifySelection =
true;
902 case css::awt::Key::SELECT_TO_END_OF_LINE:
904 bKeyModifySelection =
true;
906 case css::awt::Key::SELECT_BACKWARD:
908 bKeyModifySelection =
true;
910 case css::awt::Key::SELECT_FORWARD:
912 bKeyModifySelection =
true;
914 case css::awt::Key::SELECT_WORD_BACKWARD:
916 bKeyModifySelection =
true;
918 case css::awt::Key::SELECT_WORD_FORWARD:
920 bKeyModifySelection =
true;
922 case css::awt::Key::SELECT_TO_BEGIN_OF_PARAGRAPH:
924 if( aPaM == aOldPaM )
929 bKeyModifySelection =
true;
931 case css::awt::Key::SELECT_TO_END_OF_PARAGRAPH:
933 if( aPaM == aOldPaM )
938 bKeyModifySelection =
true;
940 case css::awt::Key::SELECT_TO_BEGIN_OF_DOCUMENT:
942 bKeyModifySelection =
true;
944 case css::awt::Key::SELECT_TO_END_OF_DOCUMENT:
946 bKeyModifySelection =
true;
950 if ( aOldPaM != aPaM )
967 if ( bKeyModifySelection )
971 pEditView->
pImpEditView->DrawSelectionXOR( aTmpNewSel );
1003 UErrorCode nError = U_ZERO_ERROR;
1004 UBiDi* pBidi = ubidi_openSized( aLine.getLength(), 0, &nError );
1006 const UBiDiLevel nBidiLevel =
IsRightToLeft( nPara ) ? 1 : 0 ;
1007 ubidi_setPara( pBidi,
reinterpret_cast<const UChar *
>(aLine.getStr()), aLine.getLength(), nBidiLevel,
nullptr, &nError );
1009 sal_Int32 nVisPos = bStart ? 0 : aLine.getLength()-1;
1010 const sal_Int32 nLogPos = ubidi_getLogicalIndex( pBidi, nVisPos, &nError );
1012 ubidi_close( pBidi );
1023 pEditView->
pImpEditView->SetCursorBidiLevel( bPortionRTL ? 0 : 1 );
1030 pEditView->
pImpEditView->SetCursorBidiLevel( bPortionRTL ? 1 : 0 );
1060 if ( bVisualToLeft )
1062 aPaM =
CursorUp( aPaM, pEditView );
1076 bool bLogicalBackward = bParaRTL ? !bVisualToLeft : bVisualToLeft;
1081 sal_Int32 nPortionStart;
1085 bool bPortionBoundary = ( aPaM.
GetIndex() == nPortionStart ) || ( aPaM.
GetIndex() == (nPortionStart+rTextPortion.
GetLen()) );
1089 sal_Int32 nRTLLevelNextPortion = -1;
1098 if ( !bPortionBoundary || ( nRTLLevel == nRTLLevelNextPortion ) )
1100 if (bVisualToLeft !=
bool(nRTLLevel % 2))
1102 aPaM =
CursorLeft( aPaM, nCharacterIteratorMode );
1107 aPaM =
CursorRight( aPaM, nCharacterIteratorMode );
1116 bool bGotoStartOfNextLine =
false;
1117 bool bGotoEndOfPrevLine =
false;
1122 UErrorCode nError = U_ZERO_ERROR;
1123 UBiDi* pBidi = ubidi_openSized( aLine.getLength(), 0, &nError );
1125 const UBiDiLevel nBidiLevel =
IsRightToLeft( nPara ) ? 1 : 0 ;
1126 ubidi_setPara( pBidi,
reinterpret_cast<const UChar *
>(aLine.getStr()), aLine.getLength(), nBidiLevel,
nullptr, &nError );
1130 bool bEndOfLine = nPosInLine == aLine.getLength();
1131 sal_Int32 nVisPos = ubidi_getVisualIndex( pBidi, !bEndOfLine ? nPosInLine : nPosInLine-1, &nError );
1132 if ( bVisualToLeft )
1134 bGotoEndOfPrevLine = nVisPos == 0;
1140 bGotoStartOfNextLine = nVisPos == (aLine.getLength() - 1);
1145 if ( !bGotoEndOfPrevLine && !bGotoStartOfNextLine )
1147 aPaM.
SetIndex( rLine.
GetStart() + ubidi_getLogicalIndex( pBidi, nVisPos, &nError ) );
1153 bool bWasBehind =
false;
1154 bool bBeforePortion = !nPosInLine || pEditView->
pImpEditView->GetCursorBidiLevel() == 1;
1155 if ( nPosInLine && ( !bBeforePortion ) )
1158 sal_Int32 nPortionStart;
1164 tools::Long nVisPos =
static_cast<tools::Long>(ubidi_getVisualIndex( pBidi, bWasBehind ? nPosInLine-1 : nPosInLine, &nError ));
1165 if ( bVisualToLeft )
1167 if ( !bWasBehind || bRTLPortion )
1172 if ( bWasBehind || bRTLPortion || bBeforePortion )
1176 bGotoEndOfPrevLine = nVisPos < 0;
1177 bGotoStartOfNextLine = nVisPos >= aLine.getLength();
1179 if ( !bGotoEndOfPrevLine && !bGotoStartOfNextLine )
1181 aPaM.
SetIndex( rLine.
GetStart() + ubidi_getLogicalIndex( pBidi, nVisPos, &nError ) );
1184 sal_Int32 _nPortionStart;
1188 if ( bVisualToLeft && !bRTLPortion && _rTextPortion.
IsRightToLeft() )
1190 else if ( !bVisualToLeft && bRTLPortion && ( bWasBehind || !_rTextPortion.
IsRightToLeft() ) )
1193 pEditView->
pImpEditView->SetCursorBidiLevel( _nPortionStart );
1197 ubidi_close( pBidi );
1199 if ( bGotoEndOfPrevLine )
1201 aPaM =
CursorUp( aPaM, pEditView );
1205 else if ( bGotoStartOfNextLine )
1226 _xBI->previousCharacters(
1253 _xBI->nextCharacters(
1272 assert(pView &&
"No View - No Cursor Movement!");
1333 if ( nLine < pPPortion->GetLines().
Count()-1 )
1362 assert(pCurPortion);
1374 assert(pCurPortion);
1424 OSL_ENSURE( pLastNode && pLastPortion,
"CursorEndOfDoc: Node or Portion not found" );
1425 if (!(pLastNode && pLastPortion))
1431 OSL_ENSURE( pLastNode,
"No visible paragraph?" );
1446 if ( aTopLeft.
Y() < 0 )
1450 return GetPaM( aTopLeft );
1460 if ( aBottomRight.
Y() > nHeight )
1462 aBottomRight.
setY( nHeight-2 );
1464 return GetPaM( aBottomRight );
1469 const sal_Int32 nCurrentPos = rPaM.
GetIndex();
1471 if ( nCurrentPos == 0 )
1489 lang::Locale aLocale(
GetLocale( aTmpPaM ) );
1492 i18n::Boundary aBoundary =
1493 _xBI->getWordBoundary(aNewPaM.
GetNode()->
GetString(), nCurrentPos, aLocale, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true);
1494 if ( aBoundary.startPos >= nCurrentPos )
1495 aBoundary = _xBI->previousWord(
1496 aNewPaM.
GetNode()->
GetString(), nCurrentPos, aLocale, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES);
1497 aNewPaM.
SetIndex( ( aBoundary.startPos != -1 ) ? aBoundary.startPos : 0 );
1505 const sal_Int32 nMax = rPaM.
GetNode()->
Len();
1513 lang::Locale aLocale(
GetLocale( aTmpPaM ) );
1516 i18n::Boundary aBoundary = _xBI->nextWord(
1518 aNewPaM.
SetIndex( aBoundary.startPos );
1544 lang::Locale aLocale(
GetLocale( aTmpPaM ) );
1550 i18n::Boundary aBoundary = _xBI->getWordBoundary(
1553 aNewPaM.
SetIndex( aBoundary.startPos );
1566 lang::Locale aLocale(
GetLocale( aTmpPaM ) );
1569 i18n::Boundary aBoundary = _xBI->getWordBoundary(
1572 aNewPaM.
SetIndex( aBoundary.endPos );
1586 lang::Locale aLocale(
GetLocale( aTmpPaM ) );
1589 sal_Int16
nType = _xBI->getWordType(
1592 if (
nType == i18n::WordType::ANY_WORD )
1594 i18n::Boundary aBoundary = _xBI->getWordBoundary(
1598 if ( ( aBoundary.endPos > aPaM.
GetIndex() ) &&
1599 ( ( aBoundary.startPos < aPaM.
GetIndex() ) || ( bAcceptStartOfWord && ( aBoundary.startPos == aPaM.
GetIndex() ) ) ) )
1616 const OUString sParagraph = pNode->
GetString().replaceAll(
"\x01",
"\x0a");
1620 sal_Int32 nEnd = _xBI->endOfSentence(
1624 OSL_ENSURE(pNode->
Len() ? (nStart < pNode->Len()) : (nStart == 0),
"sentence start index out of range");
1625 OSL_ENSURE(nEnd <= pNode->Len(),
"sentence end index out of range");
1638 bool bIsSequenceChecking =
1642 _xBI.is() && i18n::ScriptType::COMPLEX == _xBI->getScriptType( OUString( nChar ), 0 );
1644 return bIsSequenceChecking;
1649 for( sal_Int32 nCharIdx = nStart; nCharIdx < nEnd; ++nCharIdx )
1651 const UCharDirection nCharDir = u_charDirection ( rTxt[ nCharIdx ] );
1652 if ( nCharDir == U_LEFT_TO_RIGHT ||
1653 nCharDir == U_LEFT_TO_RIGHT_EMBEDDING ||
1654 nCharDir == U_LEFT_TO_RIGHT_OVERRIDE )
1671 if ( !pNode->
Len() )
1683 const OUString aFldText =
static_cast<const EditCharAttribField*
>(pField)->GetFieldValue();
1684 if ( !aFldText.isEmpty() )
1686 aText = aText.replaceAt( pField->
GetStart(), 1, aFldText.subView(0,1) );
1687 short nFldScriptType = _xBI->getScriptType( aFldText, 0 );
1689 for ( sal_Int32 nCharInField = 1; nCharInField < aFldText.getLength(); nCharInField++ )
1691 short nTmpType = _xBI->getScriptType( aFldText, nCharInField );
1694 if ( nFldScriptType == i18n::ScriptType::WEAK )
1696 nFldScriptType = nTmpType;
1697 aText = aText.replaceAt( pField->
GetStart(), 1, aFldText.subView(nCharInField,1) );
1702 if ( ( nTmpType == i18n::ScriptType::ASIAN ) || ( nTmpType == i18n::ScriptType::COMPLEX ) )
1704 aText = aText.replaceAt( pField->
GetStart(), 1, aFldText.subView(nCharInField,1) );
1713 sal_Int32 nTextLen = aText.getLength();
1716 short nScriptType = _xBI->getScriptType( aText,
nPos );
1717 rTypes.emplace_back( nScriptType,
nPos, nTextLen );
1718 nPos = _xBI->endOfScript( aText,
nPos, nScriptType );
1719 while ( (
nPos != -1 ) && (
nPos < nTextLen ) )
1721 rTypes.back().nEndPos =
nPos;
1723 nScriptType = _xBI->getScriptType( aText,
nPos );
1726 if ( ( nScriptType == i18n::ScriptType::WEAK ) || ( nScriptType == rTypes.back().nScriptType ) )
1729 rTypes.back().nEndPos = nEndPos;
1733 auto nPrevPos =
nPos;
1734 auto nPrevChar = aText.iterateCodePoints(&nPrevPos, -1);
1735 if (_xBI->getScriptType(aText, nPrevPos) == i18n::ScriptType::WEAK)
1737 auto nChar = aText.iterateCodePoints(&
nPos, 0);
1739 if (
nType == css::i18n::UnicodeType::NON_SPACING_MARK ||
1740 nType == css::i18n::UnicodeType::ENCLOSING_MARK ||
1741 nType == css::i18n::UnicodeType::COMBINING_SPACING_MARK ||
1742 (nPrevChar == 0x202F &&
1743 u_getIntPropertyValue(nChar, UCHAR_SCRIPT) == USCRIPT_MONGOLIAN))
1746 rTypes.back().nEndPos--;
1750 rTypes.emplace_back( nScriptType,
nPos, nTextLen );
1756 if ( rTypes[0].nScriptType == i18n::ScriptType::WEAK )
1767 const sal_Int32 nStart = rDirInfo.nStartPos;
1768 const sal_Int32 nEnd = rDirInfo.nEndPos;
1769 const sal_uInt8 nCurrDirType = rDirInfo.nType;
1771 if ( nCurrDirType % 2 == UBIDI_RTL ||
1777 while ( nIdx < rTypes.size() && rTypes[nIdx].nStartPos < nStart )
1781 while (nIdx < rTypes.size() && rTypes[nIdx].nEndPos <= nEnd)
1784 rTypes.erase(rTypes.begin() + nIdx);
1788 if(nIdx < rTypes.size() && rTypes[nIdx].nStartPos < nStart && rTypes[nIdx].nEndPos > nEnd)
1790 rTypes.insert( rTypes.begin()+nIdx,
ScriptTypePosInfo( rTypes[nIdx].nScriptType, nEnd, rTypes[nIdx].nEndPos ) );
1791 rTypes[nIdx].nEndPos = nStart;
1795 rTypes[nIdx - 1].nEndPos = nStart;
1797 rTypes.insert( rTypes.begin()+nIdx,
ScriptTypePosInfo( i18n::ScriptType::COMPLEX, nStart, nEnd) );
1800 if( nIdx < rTypes.size() )
1801 rTypes[nIdx].nStartPos = nEnd;
1810 explicit FindByPos(sal_Int32 nPos)
1815 bool operator()(
const ScriptTypePosInfos::value_type& rValue)
1817 return rValue.nStartPos <= mnPos && rValue.nEndPos >= mnPos;
1828 sal_uInt16 nScriptType = 0;
1845 ScriptTypePosInfos::const_iterator itr = std::find_if(rTypes.begin(), rTypes.end(), FindByPos(
nPos));
1846 if(itr != rTypes.end())
1848 nScriptType = itr->nScriptType;
1850 *pEndPos = itr->nEndPos;
1867 for ( sal_Int32 nPara = nStartPara; nPara <= nEndPara; nPara++ )
1879 sal_Int32 nS = ( nPara == nStartPara ) ? aSel.
Min().
GetIndex() : 0;
1883 if (nStartPara == nEndPara && nS == nE)
1896 bool bStartInRange = rType.nStartPos <= nS && nS < rType.nEndPos;
1897 bool bEndInRange = rType.nStartPos < nE && nE <= rType.nEndPos;
1899 if (bStartInRange || bEndInRange)
1901 if ( rType.nScriptType != i18n::ScriptType::WEAK )
1911 bool bScriptChange =
false;
1926 if ( rType.nStartPos ==
nPos )
1928 bScriptChange =
true;
1934 return bScriptChange;
1939 bool bTypeFound =
false;
1948 for (
size_t n = rTypes.size();
n && !bTypeFound; )
1950 if ( rTypes[--
n].nScriptType ==
nType )
1972 UErrorCode nError = U_ZERO_ERROR;
1973 UBiDi* pBidi = ubidi_openSized( aText.getLength(), 0, &nError );
1974 nError = U_ZERO_ERROR;
1976 const UBiDiLevel nBidiLevel =
IsRightToLeft(nPara) ? 1 : 0 ;
1977 ubidi_setPara( pBidi,
reinterpret_cast<const UChar *
>(aText.getStr()), aText.getLength(), nBidiLevel,
nullptr, &nError );
1978 nError = U_ZERO_ERROR;
1980 int32_t
nCount = ubidi_countRuns( pBidi, &nError );
1987 UBiDiLevel nCurrDir;
1989 for (int32_t nIdx = 0; nIdx <
nCount; ++nIdx)
1991 ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
1992 rInfos.emplace_back( nCurrDir, nStart, nEnd );
1997 ubidi_close( pBidi );
2001 if ( rInfos.empty() )
2002 rInfos.emplace_back( 0, 0, pParaPortion->
GetNode()->
Len() );
2020 pFrameDirItem =
nullptr;
2030 if ( pFrameDirItem )
2038 bool bHasDifferentRTLLevels =
false;
2050 bHasDifferentRTLLevels =
true;
2055 return bHasDifferentRTLLevels;
2064 if ( pNode && pNode->
Len() )
2075 if ( ( rDirInfo.nStartPos <=
nPos ) && ( rDirInfo.nEndPos >=
nPos ) )
2077 nRightToLeft = rDirInfo.nType;
2079 *pStart = rDirInfo.nStartPos;
2081 *pEnd = rDirInfo.nEndPos;
2087 return nRightToLeft;
2106 return eJustification;
2129 const sal_Int32 nStart = rPaM.
GetIndex();
2130 const sal_Int32 nEnd = nStart + nChars;
2132 for (
const auto & rAttrib : rAttribs)
2152 bool bValidAction = (
static_cast<tools::Long>(nNewPos) < aOldPositions.
Min() ) || (
static_cast<tools::Long>(nNewPos) > aOldPositions.
Max() );
2153 OSL_ENSURE( bValidAction,
"Move in itself?" );
2158 if ( !bValidAction )
2166 if ( nNewPos >= nParaCount )
2167 nNewPos = nParaCount;
2181 else if ( nNewPos == nParaCount )
2187 if ( aOldPositions.
Min() == 0 )
2192 else if ( aOldPositions.
Max() == (nParaCount-1) )
2213 aTmpPortionList.
Append(std::move(pTmpPortion));
2217 assert( nRealNewPos !=
EE_PARA_NOT_FOUND &&
"ImpMoveParagraphs: Invalid Position!" );
2220 while( aTmpPortionList.
Count() > 0 )
2222 std::unique_ptr<ParaPortion> pTmpPortion = aTmpPortionList.
Release(0);
2224 aSelection.
Min().
SetNode( pTmpPortion->GetNode() );
2226 aSelection.
Max().
SetNode( pTmpPortion->GetNode() );
2227 aSelection.
Max().
SetIndex( pTmpPortion->GetNode()->Len() );
2258#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
2267 OSL_ENSURE( pLeft != pRight,
"Join together the same paragraph ?" );
2277 OSL_ENSURE(
false,
"ImpConnectParagraphs with wrong order of pLeft/pRight nodes (!)");
2278 std::swap(pLeft, pRight);
2282 aDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pRight, nParagraphTobeDeleted ));
2298 if ( pRight->
Len() )
2307 assert(pLeftPortion);
2311 sal_Int32 nEnd = pLeft->
Len();
2312 sal_Int32 nInv = nEnd ? nEnd-1 : nEnd;
2317 for (
auto & elem : *pRWrongs)
2319 if (elem.mnStart != 0)
2321 elem.mnStart = elem.mnStart + nEnd;
2322 elem.mnEnd = elem.mnEnd + nEnd;
2357 OSL_ENSURE( !rSel.
DbgIsBuggy(
aEditDoc ),
"Index out of range in DeleteLeftOrRight" );
2369 sal_uInt16 nCharMode = i18n::CharacterIteratorMode::SKIPCHARACTER;
2376 sal_Int32 nCode = rString.iterateCodePoints(&
nIndex, -1);
2378 nCharMode = i18n::CharacterIteratorMode::SKIPCELL;
2391 if ( aDelStart == aCurPos )
2396 aDelStart =
EditPaM( pPrev, 0 );
2411 const sal_Int32 nLen(aCurPos.
GetNode()->
Len());
2417 aDelEnd =
EditPaM( pNext, 0 );
2428 if ( aDelEnd == aCurPos )
2449 return rCurSel.
Min();
2459 OSL_ENSURE( aStartPaM.
GetIndex() <= aStartPaM.
GetNode()->
Len(),
"Index out of range in ImpDeleteSelection" );
2460 OSL_ENSURE( aEndPaM.
GetIndex() <= aEndPaM.
GetNode()->
Len(),
"Index out of range in ImpDeleteSelection" );
2466 OSL_ENSURE( nStartNode <= nEndNode, "Start >
End ?!
" );
2468 // Remove all nodes in between...
2469 for ( sal_Int32 z = nStartNode+1; z < nEndNode; z++ )
2471 // Always nStartNode+1, due to Remove()!
2472 ImpRemoveParagraph( nStartNode+1 );
2475 if ( aStartPaM.GetNode() != aEndPaM.GetNode() )
2477 // The Rest of the StartNodes...
2478 ImpRemoveChars( aStartPaM, aStartPaM.GetNode()->Len() - aStartPaM.GetIndex() );
2479 ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() );
2481 pPortion->MarkSelectionInvalid( aStartPaM.GetIndex() );
2483 // The beginning of the EndNodes...
2484 const sal_Int32 nChars = aEndPaM.GetIndex();
2485 aEndPaM.SetIndex( 0 );
2486 ImpRemoveChars( aEndPaM, nChars );
2487 pPortion = FindParaPortion( aEndPaM.GetNode() );
2489 pPortion->MarkSelectionInvalid( 0 );
2491 aStartPaM = ImpConnectParagraphs( aStartPaM.GetNode(), aEndPaM.GetNode() );
2495 ImpRemoveChars( aStartPaM, aEndPaM.GetIndex() - aStartPaM.GetIndex() );
2496 ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() );
2498 pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() );
2506void ImpEditEngine::ImpRemoveParagraph( sal_Int32 nPara )
2508 ContentNode* pNode = aEditDoc.GetObject( nPara );
2509 ContentNode* pNextNode = aEditDoc.GetObject( nPara+1 );
2513 aDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pNode, nPara ));
2515 // The node is managed by the undo and possibly destroyed!
2516 aEditDoc.Release( nPara );
2517 GetParaPortions().Remove( nPara );
2519 if ( IsCallParaInsertedOrDeleted() )
2521 GetEditEnginePtr()->ParagraphDeleted( nPara );
2524 // Extra-Space may be determined again in the following. For
2525 // ParaAttribsChanged the paragraph is unfortunately formatted again,
2526 // however this method should not be time critical!
2528 ParaAttribsChanged( pNextNode );
2530 if ( IsUndoEnabled() && !IsInUndo() )
2531 InsertUndo(std::make_unique<EditUndoDelContent>(pEditEngine, pNode, nPara));
2534 aEditDoc.RemoveItemsFromPool(*pNode);
2535 if ( pNode->GetStyleSheet() )
2536 EndListening( *pNode->GetStyleSheet() );
2541EditPaM ImpEditEngine::AutoCorrect( const EditSelection& rCurSel, sal_Unicode c,
2542 bool bOverwrite, vcl::Window const * pFrameWin )
2544 // i.e. Calc has special needs regarding a leading single quotation mark
2545 // when starting cell input.
2546 if (c == '\'' && !IsReplaceLeadingSingleQuotationMark() &&
2547 rCurSel.Min() == rCurSel.Max() && rCurSel.Max().GetIndex() == 0)
2549 return InsertTextUserInput( rCurSel, c, bOverwrite );
2552 EditSelection aSel( rCurSel );
2553 SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect();
2556 if ( aSel.HasRange() )
2557 aSel = ImpDeleteSelection( rCurSel );
2559 // #i78661 allow application to turn off capitalization of
2560 // start sentence explicitly.
2561 // (This is done by setting IsFirstWordCapitalization to sal_False.)
2562 bool bOldCapitalStartSentence = pAutoCorrect->IsAutoCorrFlag( ACFlags::CapitalStartSentence );
2563 if (!IsFirstWordCapitalization())
2565 ESelection aESel( CreateESel(aSel) );
2566 EditSelection aFirstWordSel;
2567 EditSelection aSecondWordSel;
2568 if (aESel.nEndPara == 0) // is this the first para?
2570 // select first word...
2571 // start by checking if para starts with word.
2572 aFirstWordSel = SelectWord( CreateSel(ESelection()) );
2573 if (aFirstWordSel.Min().GetIndex() == 0 && aFirstWordSel.Max().GetIndex() == 0)
2575 // para does not start with word -> select next/first word
2576 EditPaM aRightWord( WordRight( aFirstWordSel.Max() ) );
2577 aFirstWordSel = SelectWord( EditSelection( aRightWord ) );
2580 // select second word
2581 // (sometimes aSel might not point to the end of the first word
2582 // but to some following char like '.'. ':', ...
2583 // In those cases we need aSecondWordSel to see if aSel
2584 // will actually effect the first word.)
2585 EditPaM aRight2Word( WordRight( aFirstWordSel.Max() ) );
2586 aSecondWordSel = SelectWord( EditSelection( aRight2Word ) );
2588 bool bIsFirstWordInFirstPara = aESel.nEndPara == 0 &&
2589 aFirstWordSel.Max().GetIndex() <= aSel.Max().GetIndex() &&
2590 aSel.Max().GetIndex() <= aSecondWordSel.Min().GetIndex();
2592 if (bIsFirstWordInFirstPara)
2593 pAutoCorrect->SetAutoCorrFlag( ACFlags::CapitalStartSentence, IsFirstWordCapitalization() );
2596 ContentNode* pNode = aSel.Max().GetNode();
2597 const sal_Int32 nIndex = aSel.Max().GetIndex();
2598 EdtAutoCorrDoc aAuto(pEditEngine, pNode, nIndex, c);
2599 // FIXME: this _must_ be called with reference to the actual node text!
2600 OUString const& rNodeString(pNode->GetString());
2601 pAutoCorrect->DoAutoCorrect(
2602 aAuto, rNodeString, nIndex, c, !bOverwrite, mbNbspRunNext, pFrameWin );
2603 aSel.Max().SetIndex( aAuto.GetCursor() );
2605 // #i78661 since the SvxAutoCorrect object used here is
2606 // shared we need to reset the value to its original state.
2607 pAutoCorrect->SetAutoCorrFlag( ACFlags::CapitalStartSentence, bOldCapitalStartSentence );
2613EditPaM ImpEditEngine::InsertTextUserInput( const EditSelection& rCurSel,
2614 sal_Unicode c, bool bOverwrite )
2617 OSL_ENSURE( c != '\n', "Word wrapping
for InsertText ?
");
2619 EditPaM aPaM( rCurSel.Min() );
2621 bool bDoOverwrite = bOverwrite &&
2622 ( aPaM.GetIndex() < aPaM.GetNode()->Len() );
2624 bool bUndoAction = ( rCurSel.HasRange() || bDoOverwrite );
2627 UndoActionStart( EDITUNDO_INSERT );
2629 if ( rCurSel.HasRange() )
2631 aPaM = ImpDeleteSelection( rCurSel );
2633 else if ( bDoOverwrite )
2635 // If selected, then do not also overwrite a character!
2636 EditSelection aTmpSel( aPaM );
2637 aTmpSel.Max().SetIndex( aTmpSel.Max().GetIndex()+1 );
2638 OSL_ENSURE( !aTmpSel.DbgIsBuggy( aEditDoc ), "Overwrite: Wrong selection!
");
2639 ImpDeleteSelection( aTmpSel );
2642 if ( aPaM.GetNode()->Len() < MAXCHARSINPARA )
2644 if (IsInputSequenceCheckingRequired( c, rCurSel ))
2646 uno::Reference < i18n::XExtendedInputSequenceChecker > _xISC( ImplGetInputSequenceChecker() );
2650 const sal_Int32 nTmpPos = aPaM.GetIndex();
2651 sal_Int16 nCheckMode = SvtCTLOptions::IsCTLSequenceCheckingRestricted() ?
2652 i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
2654 // the text that needs to be checked is only the one
2655 // before the current cursor position
2656 const OUString aOldText( aPaM.GetNode()->Copy(0, nTmpPos) );
2657 OUString aNewText( aOldText );
2658 if (SvtCTLOptions::IsCTLSequenceCheckingTypeAndReplace())
2660 _xISC->correctInputSequence(aNewText, nTmpPos - 1, c, nCheckMode);
2662 // find position of first character that has changed
2663 sal_Int32 nOldLen = aOldText.getLength();
2664 sal_Int32 nNewLen = aNewText.getLength();
2665 const sal_Unicode *pOldTxt = aOldText.getStr();
2666 const sal_Unicode *pNewTxt = aNewText.getStr();
2667 sal_Int32 nChgPos = 0;
2668 while ( nChgPos < nOldLen && nChgPos < nNewLen &&
2669 pOldTxt[nChgPos] == pNewTxt[nChgPos] )
2672 const OUString aChgText( aNewText.copy( nChgPos ) );
2674 // select text from first pos to be changed to current pos
2675 EditSelection aSel( EditPaM( aPaM.GetNode(), nChgPos ), aPaM );
2677 if (!aChgText.isEmpty())
2678 return InsertText( aSel, aChgText ); // implicitly handles undo
2684 // should the character be ignored (i.e. not get inserted) ?
2685 if (!_xISC->checkInputSequence( aOldText, nTmpPos - 1, c, nCheckMode ))
2686 return aPaM; // nothing to be done -> no need for undo
2690 // at this point now we will insert the character 'normally' some lines below...
2693 if ( IsUndoEnabled() && !IsInUndo() )
2695 std::unique_ptr<EditUndoInsertChars> pNewUndo(new EditUndoInsertChars(pEditEngine, CreateEPaM(aPaM), OUString(c)));
2696 bool bTryMerge = !bDoOverwrite && ( c != ' ' );
2697 InsertUndo( std::move(pNewUndo), bTryMerge );
2700 aEditDoc.InsertText( aPaM, OUStringChar(c) );
2701 ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
2703 pPortion->MarkInvalid( aPaM.GetIndex(), 1 );
2704 aPaM.SetIndex( aPaM.GetIndex()+1 ); // does not do EditDoc-Method anymore
2715EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUString& rStr)
2717 UndoActionStart( EDITUNDO_INSERT );
2720 if ( aCurSel.HasRange() )
2721 aPaM = ImpDeleteSelection( aCurSel );
2723 aPaM = aCurSel.Max();
2725 EditPaM aCurPaM( aPaM ); // for the Invalidate
2727 // get word boundaries in order to clear possible WrongList entries
2728 // and invalidate all the necessary text (everything after and including the
2729 // start of the word)
2730 // #i107201# do the expensive SelectWord call only if online spelling is active
2731 EditSelection aCurWord;
2732 if ( GetStatus().DoOnlineSpelling() )
2733 aCurWord = SelectWord( aCurPaM, i18n::WordType::DICTIONARY_WORD );
2735 OUString aText(convertLineEnd(rStr, LINEEND_LF));
2736 if (mbFuzzing) //tab expansion performance in editeng is appalling
2737 aText = aText.replaceAll("\t
","-
");
2738 SfxVoidItem aTabItem( EE_FEATURE_TAB );
2740 // Converts to linesep = \n
2741 // Token LINE_SEP query,
2742 // since the MAC-Compiler makes something else from \n !
2744 sal_Int32 nStart = 0;
2745 while ( nStart < aText.getLength() )
2747 sal_Int32 nEnd = !aStatus.IsSingleLine() ?
2748 aText.indexOf( LINE_SEP, nStart ) : -1;
2750 nEnd = aText.getLength(); // not dereference!
2752 // Start == End => empty line
2753 if ( nEnd > nStart )
2755 OUString aLine = aText.copy( nStart, nEnd-nStart );
2756 sal_Int32 nExistingChars = aPaM.GetNode()->Len();
2757 sal_Int32 nChars = nExistingChars + aLine.getLength();
2758 if (nChars > MAXCHARSINPARA)
2760 sal_Int32 nMaxNewChars = std::max<sal_Int32>(0, MAXCHARSINPARA - nExistingChars);
2761 // Wherever we break, it may be wrong. However, try to find the
2762 // previous non-alnum/non-letter character. Note this is only
2763 // in the to be appended data, otherwise already existing
2764 // characters would have to be moved and PaM to be updated.
2765 // Restrict to 2*42, if not found by then assume other data or
2766 // language-script uses only letters or idiographs.
2767 sal_Int32 nPos = nMaxNewChars;
2768 while (nPos-- > 0 && (nMaxNewChars - nPos) <= 84)
2770 auto nNextPos = nPos;
2771 const auto c = aLine.iterateCodePoints(&nNextPos);
2772 switch (unicode::getUnicodeType(c))
2774 case css::i18n::UnicodeType::UPPERCASE_LETTER:
2775 case css::i18n::UnicodeType::LOWERCASE_LETTER:
2776 case css::i18n::UnicodeType::TITLECASE_LETTER:
2777 case css::i18n::UnicodeType::MODIFIER_LETTER:
2778 case css::i18n::UnicodeType::OTHER_LETTER:
2779 case css::i18n::UnicodeType::DECIMAL_DIGIT_NUMBER:
2780 case css::i18n::UnicodeType::LETTER_NUMBER:
2781 case css::i18n::UnicodeType::OTHER_NUMBER:
2782 case css::i18n::UnicodeType::CURRENCY_SYMBOL:
2786 // Ignore NO-BREAK spaces, NBSP, NNBSP, ZWNBSP.
2787 if (c == 0x00A0 || c == 0x202F || c == 0xFEFF)
2789 const auto n = aLine.iterateCodePoints(&nNextPos, 0);
2790 if (c == '-' && nNextPos < nMaxNewChars)
2792 // Keep HYPHEN-MINUS with a number to the right.
2793 const sal_Int16 t = unicode::getUnicodeType(n);
2794 if ( t == css::i18n::UnicodeType::DECIMAL_DIGIT_NUMBER ||
2795 t == css::i18n::UnicodeType::LETTER_NUMBER ||
2796 t == css::i18n::UnicodeType::OTHER_NUMBER)
2797 nMaxNewChars = nPos; // line break before
2799 nMaxNewChars = nNextPos; // line break after
2803 nMaxNewChars = nNextPos; // line break after
2805 nPos = 0; // will break loop
2809 // Remaining characters end up in the next paragraph. Note that
2810 // new nStart will be nEnd+1 below so decrement by one more.
2811 nEnd -= (aLine.getLength() - nMaxNewChars + 1);
2812 aLine = aLine.copy( 0, nMaxNewChars ); // Delete the Rest...
2814 if ( IsUndoEnabled() && !IsInUndo() )
2815 InsertUndo(std::make_unique<EditUndoInsertChars>(pEditEngine, CreateEPaM(aPaM), aLine));
2817 if ( aLine.indexOf( '\t' ) == -1 )
2818 aPaM = aEditDoc.InsertText( aPaM, aLine );
2821 sal_Int32 nStart2 = 0;
2822 while ( nStart2 < aLine.getLength() )
2824 sal_Int32 nEnd2 = aLine.indexOf( "\t
", nStart2 );
2826 nEnd2 = aLine.getLength(); // not dereference!
2828 if ( nEnd2 > nStart2 )
2829 aPaM = aEditDoc.InsertText( aPaM, aLine.subView( nStart2, nEnd2-nStart2 ) );
2830 if ( nEnd2 < aLine.getLength() )
2832 aPaM = aEditDoc.InsertFeature( aPaM, aTabItem );
2837 ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
2840 if ( GetStatus().DoOnlineSpelling() )
2842 // now remove the Wrongs (red spell check marks) from both words...
2843 WrongList *pWrongs = aCurPaM.GetNode()->GetWrongList();
2844 if (pWrongs && !pWrongs->empty())
2845 pWrongs->ClearWrongs( aCurWord.Min().GetIndex(), aPaM.GetIndex(), aPaM.GetNode() );
2846 // ... and mark both words as 'to be checked again'
2847 pPortion->MarkInvalid( aCurWord.Min().GetIndex(), aLine.getLength() );
2850 pPortion->MarkInvalid( aCurPaM.GetIndex(), aLine.getLength() );
2852 if ( nEnd < aText.getLength() )
2853 aPaM = ImpInsertParaBreak( aPaM );
2864EditPaM ImpEditEngine::ImpFastInsertText( EditPaM aPaM, const OUString& rStr )
2866 OSL_ENSURE( rStr.indexOf( 0x0A ) == -1, "FastInsertText: Newline not allowed!
");
2867 OSL_ENSURE( rStr.indexOf( 0x0D ) == -1, "FastInsertText: Newline not allowed!
");
2868 OSL_ENSURE( rStr.indexOf( '\t' ) == -1, "FastInsertText: Newline not allowed!
");
2870 if ( ( aPaM.GetNode()->Len() + rStr.getLength() ) < MAXCHARSINPARA )
2872 if ( IsUndoEnabled() && !IsInUndo() )
2873 InsertUndo(std::make_unique<EditUndoInsertChars>(pEditEngine, CreateEPaM(aPaM), rStr));
2875 aPaM = aEditDoc.InsertText( aPaM, rStr );
2880 aPaM = ImpInsertText( aPaM, rStr );
2886EditPaM ImpEditEngine::ImpInsertFeature(const EditSelection& rCurSel, const SfxPoolItem& rItem)
2889 if ( rCurSel.HasRange() )
2890 aPaM = ImpDeleteSelection( rCurSel );
2892 aPaM = rCurSel.Max();
2894 if ( aPaM.GetIndex() >= SAL_MAX_INT32-1 )
2897 if ( IsUndoEnabled() && !IsInUndo() )
2898 InsertUndo(std::make_unique<EditUndoInsertFeature>(pEditEngine, CreateEPaM(aPaM), rItem));
2899 aPaM = aEditDoc.InsertFeature( aPaM, rItem );
2902 ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() );
2904 pPortion->MarkInvalid( aPaM.GetIndex()-1, 1 );
2911EditPaM ImpEditEngine::ImpInsertParaBreak( const EditSelection& rCurSel )
2914 if ( rCurSel.HasRange() )
2915 aPaM = ImpDeleteSelection( rCurSel );
2917 aPaM = rCurSel.Max();
2919 return ImpInsertParaBreak( aPaM );
2922EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttribs )
2924 if ( aEditDoc.Count() >= EE_PARA_MAX_COUNT )
2927 << EE_PARA_MAX_COUNT << " paragraphs!");
2931 if ( IsUndoEnabled() && !IsInUndo() )
2932 InsertUndo(std::make_unique<EditUndoSplitPara>(pEditEngine, aEditDoc.GetPos(rPaM.GetNode()), rPaM.GetIndex()));
2934 EditPaM aPaM( aEditDoc.InsertParaBreak( rPaM, bKeepEndingAttribs ) );
2935 if (auto pStyle = aPaM.GetNode()->GetStyleSheet())
2936 StartListening(*pStyle, DuplicateHandling::Allow);
2938 if ( GetStatus().DoOnlineSpelling() )
2940 sal_Int32 nEnd = rPaM.GetNode()->Len();
2941 aPaM.GetNode()->CreateWrongList();
2942 WrongList* pLWrongs = rPaM.GetNode()->GetWrongList();
2943 WrongList* pRWrongs = aPaM.GetNode()->GetWrongList();
2944 // take over misspelled words:
2945 for (auto & elem : *pLWrongs)
2947 // Correct only if really a word gets overlapped in the process of
2949 if (elem.mnStart > o3tl::make_unsigned(nEnd))
2951 pRWrongs->push_back(elem);
2952 editeng::MisspellRange& rRWrong = pRWrongs->back();
2953 rRWrong.mnStart = rRWrong.mnStart - nEnd;
2954 rRWrong.mnEnd = rRWrong.mnEnd - nEnd;
2956 else if (elem.mnStart < o3tl::make_unsigned(nEnd) && elem.mnEnd > o3tl::make_unsigned(nEnd))
2959 sal_Int32 nInv = nEnd ? nEnd-1 : nEnd;
2961 pLWrongs->SetInvalidRange(nInv, nEnd);
2963 pLWrongs->SetValid();
2964 pRWrongs->SetValid();
2965 pRWrongs->SetInvalidRange(0, 1); // Only test the first word
2968 ParaPortion* pPortion = FindParaPortion( rPaM.GetNode() );
2970 pPortion->MarkInvalid( rPaM.GetIndex(), 0 );
2972 // Optimization: Do not place unnecessarily many getPos to Listen!
2973 // Here, as in undo, but also in all other methods.
2974 sal_Int32 nPos = GetParaPortions().GetPos( pPortion );
2975 ParaPortion* pNewPortion = new ParaPortion( aPaM.GetNode() );
2976 GetParaPortions().Insert(nPos+1, std::unique_ptr<ParaPortion>(pNewPortion));
2977 ParaAttribsChanged( pNewPortion->GetNode() );
2978 if ( IsCallParaInsertedOrDeleted() )
2979 GetEditEnginePtr()->ParagraphInserted( nPos+1 );
2981 CursorMoved( rPaM.GetNode() ); // if empty Attributes have emerged.
2986EditPaM ImpEditEngine::ImpFastInsertParagraph( sal_Int32 nPara )
2988 if ( IsUndoEnabled() && !IsInUndo() )
2992 assert(aEditDoc.GetObject(nPara - 1));
2993 InsertUndo(std::make_unique<EditUndoSplitPara>(pEditEngine, nPara-1, aEditDoc.GetObject( nPara-1 )->Len()));
2996 InsertUndo(std::make_unique<EditUndoSplitPara>(pEditEngine, 0, 0));
2999 ContentNode* pNode = new ContentNode( aEditDoc.GetItemPool() );
3000 // If flat mode, then later no Font is set:
3001 pNode->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont();
3003 if ( GetStatus().DoOnlineSpelling() )
3004 pNode->CreateWrongList();
3006 aEditDoc.Insert(nPara, pNode);
3008 GetParaPortions().Insert(nPara, std::make_unique<ParaPortion>( pNode ));
3009 if ( IsCallParaInsertedOrDeleted() )
3010 GetEditEnginePtr()->ParagraphInserted( nPara );
3012 return EditPaM( pNode, 0 );
3015EditPaM ImpEditEngine::InsertParaBreak(const EditSelection& rCurSel)
3017 EditPaM aPaM(ImpInsertParaBreak(rCurSel));
3018 if ( aStatus.DoAutoIndenting() )
3020 sal_Int32 nPara = aEditDoc.GetPos( aPaM.GetNode() );
3021 OSL_ENSURE( nPara > 0, "AutoIndenting: Error!" );
3022 const OUString aPrevParaText( GetEditDoc().GetParaAsString( nPara-1 ) );
3024 while ( ( n < aPrevParaText.getLength() ) &&
3025 ( ( aPrevParaText[n] == ' ' ) || ( aPrevParaText[n] == '\t
' ) ) )
3027 if ( aPrevParaText[n] == '\t
' )
3028 aPaM = ImpInsertFeature( aPaM, SfxVoidItem( EE_FEATURE_TAB ) );
3030 aPaM = ImpInsertText( aPaM, OUString(aPrevParaText[n]) );
3038EditPaM ImpEditEngine::InsertTab(const EditSelection& rCurSel)
3040 EditPaM aPaM( ImpInsertFeature(rCurSel, SfxVoidItem(EE_FEATURE_TAB )));
3044EditPaM ImpEditEngine::InsertField(const EditSelection& rCurSel, const SvxFieldItem& rFld)
3046 return ImpInsertFeature(rCurSel, rFld);
3049bool ImpEditEngine::UpdateFields()
3051 bool bChanges = false;
3052 sal_Int32 nParas = GetEditDoc().Count();
3053 for ( sal_Int32 nPara = 0; nPara < nParas; nPara++ )
3055 bool bChangesInPara = false;
3056 ContentNode* pNode = GetEditDoc().GetObject( nPara );
3058 CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs();
3059 for (std::unique_ptr<EditCharAttrib> & rAttrib : rAttribs)
3061 EditCharAttrib& rAttr = *rAttrib;
3062 if (rAttr.Which() == EE_FEATURE_FIELD)
3064 EditCharAttribField& rField = static_cast<EditCharAttribField&>(rAttr);
3065 EditCharAttribField aCurrent(rField);
3068 if (!aStatus.MarkNonUrlFields() && !aStatus.MarkUrlFields())
3070 else if (aStatus.MarkNonUrlFields() && aStatus.MarkUrlFields())
3071 rField.GetFieldColor() = GetColorConfig().GetColorValue(svtools::WRITERFIELDSHADINGS).nColor;
3075 if (const SvxFieldItem* pFieldItem = dynamic_cast<const SvxFieldItem*>(rField.GetItem()))
3077 if (const SvxFieldData* pFieldData = pFieldItem->GetField())
3078 bURL = (dynamic_cast<const SvxURLField* >(pFieldData) != nullptr);
3080 if ((bURL && aStatus.MarkUrlFields()) || (!bURL && aStatus.MarkNonUrlFields()))
3081 rField.GetFieldColor() = GetColorConfig().GetColorValue( svtools::WRITERFIELDSHADINGS ).nColor;
3084 const OUString aFldValue =
3085 GetEditEnginePtr()->CalcFieldValue(
3086 static_cast<const SvxFieldItem&>(*rField.GetItem()),
3087 nPara, rField.GetStart(), rField.GetTextColor(), rField.GetFieldColor(), rField.GetFldLineStyle() );
3089 rField.SetFieldValue(aFldValue);
3090 if (rField != aCurrent)
3093 bChangesInPara = true;
3097 if ( bChangesInPara )
3099 // If possible be more precise when invalidate.
3100 ParaPortion* pPortion = GetParaPortions()[nPara];
3102 pPortion->MarkSelectionInvalid( 0 );
3108EditPaM ImpEditEngine::InsertLineBreak(const EditSelection& aCurSel)
3110 EditPaM aPaM( ImpInsertFeature( aCurSel, SfxVoidItem( EE_FEATURE_LINEBR ) ) );
3117tools::Rectangle ImpEditEngine::GetEditCursor(const ParaPortion* pPortion, const EditLine* pLine,
3118 sal_Int32 nIndex, GetCursorFlags nFlags)
3120 assert(pPortion && pLine);
3121 // nIndex might be not in the line
3122 // Search within the line...
3125 if ((nIndex == pLine->GetStart()) && (nFlags & GetCursorFlags::StartOfLine))
3127 Range aXRange = GetLineXPosStartEnd(pPortion, pLine);
3128 nX = !IsRightToLeft(GetEditDoc().GetPos(pPortion->GetNode())) ? aXRange.Min()
3131 else if ((nIndex == pLine->GetEnd()) && (nFlags & GetCursorFlags::EndOfLine))
3133 Range aXRange = GetLineXPosStartEnd(pPortion, pLine);
3134 nX = !IsRightToLeft(GetEditDoc().GetPos(pPortion->GetNode())) ? aXRange.Max()
3139 nX = GetXPos(pPortion, pLine, nIndex, bool(nFlags & GetCursorFlags::PreferPortionStart));
3142 tools::Rectangle aEditCursor;
3143 aEditCursor.SetLeft(nX);
3144 aEditCursor.SetRight(nX);
3146 aEditCursor.SetBottom(pLine->GetHeight() - 1);
3147 if (nFlags & GetCursorFlags::TextOnly)
3148 aEditCursor.SetTop(aEditCursor.Bottom() - pLine->GetTxtHeight() + 1);
3150 aEditCursor.SetTop(aEditCursor.Bottom()
3151 - std::min(pLine->GetTxtHeight(), pLine->GetHeight()) + 1);
3155tools::Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, GetCursorFlags nFlags )
3157 assert( IsUpdateLayout() && "Must not be reached when Update=FALSE: PaMtoEditCursor" );
3159 tools::Rectangle aEditCursor;
3160 const sal_Int32 nIndex = aPaM.GetIndex();
3161 const ParaPortion* pPortion = nullptr;
3162 const EditLine* pLastLine = nullptr;
3163 tools::Rectangle aLineArea;
3165 auto FindPortionLineAndArea
3166 = [&, bEOL(bool(nFlags & GetCursorFlags::EndOfLine))](const LineAreaInfo& rInfo) {
3167 if (!rInfo.pLine) // start of ParaPortion
3169 ContentNode* pNode = rInfo.rPortion.GetNode();
3170 OSL_ENSURE(pNode, "Invalid Node in Portion!");
3171 if (pNode != aPaM.GetNode())
3172 return CallbackResult::SkipThisPortion;
3173 pPortion = &rInfo.rPortion;
3175 else // guaranteed that this is the correct ParaPortion
3177 pLastLine = rInfo.pLine;
3178 aLineArea = rInfo.aArea;
3179 if ((rInfo.pLine->GetStart() == nIndex) || (rInfo.pLine->IsIn(nIndex, bEOL)))
3180 return CallbackResult::Stop;
3182 return CallbackResult::Continue;
3184 IterateLineAreas(FindPortionLineAndArea, IterFlag::none);
3188 aEditCursor = GetEditCursor(pPortion, pLastLine, nIndex, nFlags);
3189 aEditCursor.Move(getTopLeftDocOffset(aLineArea));
3192 OSL_FAIL("Line not found!");
3197void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eOptions)
3199 const Point aOrigin(0, 0);
3200 Point aLineStart(aOrigin);
3201 const tools::Long nVertLineSpacing = CalcVertLineSpacing(aLineStart);
3202 const tools::Long nColumnWidth = GetColumnWidth(aPaperSize);
3203 sal_Int16 nColumn = 0;
3204 for (sal_Int32 n = 0, nPortions = GetParaPortions().Count(); n < nPortions; ++n)
3206 ParaPortion* pPortion = GetParaPortions()[n];
3207 bool bSkipThis = true;
3208 if (pPortion->IsVisible())
3210 // when typing idle formatting, asynchronous Paint. Invisible Portions may be invalid.
3211 if (pPortion->IsInvalid())
3215 *pPortion, // pPortion
3217 0, // nHeightNeededToNotWrap
3218 { aLineStart, Size{ nColumnWidth, pPortion->GetFirstLineOffset() } }, // aArea
3223 auto eResult = f(aInfo);
3224 if (eResult == CallbackResult::Stop)
3226 bSkipThis = eResult == CallbackResult::SkipThisPortion;
3228 sal_uInt16 nSBL = 0;
3229 if (!aStatus.IsOutliner())
3231 const SvxLineSpacingItem& rLSItem
3232 = pPortion->GetNode()->GetContentAttribs().GetItem(EE_PARA_SBL);
3233 nSBL = (rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix)
3234 ? scaleYSpacingValue(rLSItem.GetInterLineSpace())
3238 adjustYDirectionAware(aLineStart, pPortion->GetFirstLineOffset());
3239 for (sal_Int32 nLine = 0, nLines = pPortion->GetLines().Count(); nLine < nLines; nLine++)
3241 EditLine& rLine = pPortion->GetLines()[nLine];
3242 tools::Long nLineHeight = rLine.GetHeight();
3243 if (nLine != nLines - 1)
3244 nLineHeight += nVertLineSpacing;
3245 MoveToNextLine(aLineStart, nLineHeight, nColumn, aOrigin,
3246 &aInfo.nHeightNeededToNotWrap);
3247 const bool bInclILS = eOptions & IterFlag::inclILS;
3248 if (bInclILS && (nLine != nLines - 1) && !aStatus.IsOutliner())
3250 adjustYDirectionAware(aLineStart, nSBL);
3251 nLineHeight += nSBL;
3256 Point aOtherCorner(aLineStart);
3257 adjustXDirectionAware(aOtherCorner, nColumnWidth);
3258 adjustYDirectionAware(aOtherCorner, -nLineHeight);
3260 // Calls to f() for each line
3261 aInfo.nColumn = nColumn;
3262 aInfo.pLine = &rLine;
3263 aInfo.nLine = nLine;
3264 aInfo.aArea = tools::Rectangle::Normalize(aLineStart, aOtherCorner);
3266 if (eResult == CallbackResult::Stop)
3268 bSkipThis = eResult == CallbackResult::SkipThisPortion;
3271 if (!bInclILS && (nLine != nLines - 1) && !aStatus.IsOutliner())
3272 adjustYDirectionAware(aLineStart, nSBL);
3274 if (!aStatus.IsOutliner())
3276 const SvxULSpaceItem& rULItem
3277 = pPortion->GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE);
3278 tools::Long nUL = scaleYSpacingValue(rULItem.GetLower());
3279 adjustYDirectionAware(aLineStart, nUL);
3282 // Invisible ParaPortion has no height (see ParaPortion::GetHeight), don't handle it
3286std::tuple<const ParaPortion*, const EditLine*, tools::Long>
3290 sal_Int32 nClickColumn = 0;
3301 const EditLine* pLastLine =
nullptr;
3306 auto FindLastMatchingPortionAndLine = [&](
const LineAreaInfo& rInfo) {
3309 if (rInfo.nColumn > nClickColumn)
3311 pLastPortion = &rInfo.rPortion;
3312 pLastLine = rInfo.pLine;
3321 return { pLastPortion, pLastLine, nLineStartX };
3326 assert(
IsUpdateLayout() &&
"Must not be reached when Update=FALSE: GetPaM" );
3328 if (
const auto& [pPortion, pLine, nLineStartX] =
GetPortionAndLine(aDocPos); pPortion)
3331 =
GetChar(pPortion, pLine, aDocPos.
X() - nLineStartX, bSmart);
3332 EditPaM aPaM(pPortion->GetNode(), nCurIndex);
3334 if (nCurIndex && (nCurIndex == pLine->GetEnd())
3335 && (pLine != &pPortion->GetLines()[pPortion->GetLines().Count() - 1]))
3347 if (
const auto& [pPortion, pLine, nLineStartX] =
GetPortionAndLine(rDocPos); pPortion)
3350 if ((rDocPos.
X() >= nLineStartX + aLineXPosStartEnd.
Min() -
nBorder)
3351 && (rDocPos.
X() <= nLineStartX + aLineXPosStartEnd.
Max() +
nBorder))
3359 assert(
IsUpdateLayout() &&
"Should not be used for Update=FALSE: GetTextHeight" );
3371 sal_uInt32 nMaxWidth = 0;
3376 for ( sal_Int32 nPara = 0; nPara < nParas; nPara++ )
3378 nMaxWidth = std::max(nMaxWidth,
CalcParaWidth(nPara, bIgnoreExtraSpace));
3397 if ( pPortion && pPortion->
IsVisible() )
3406 for ( sal_Int32 nLine = 0; nLine < nLines; nLine++ )
3427 nCurWidth +=
CalcLineWidth( pPortion, &rLine, bIgnoreExtraSpace );
3428 if ( nCurWidth > nMaxWidth )
3430 nMaxWidth = nCurWidth;
3436 return static_cast<sal_uInt32
>(nMaxWidth);
3452 sal_uInt32 nWidth = 0;
3454 for ( sal_Int32 nTP = pLine->
GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ )
3457 switch ( rTextPortion.
GetKind() )
3495 assert(
IsUpdateLayout() &&
"Should not be used for Update=FALSE: GetTextHeight" );
3507 std::numeric_limits<tools::Long>::max());
3514 if (pHeightNTP && !rInfo.rPortion.IsEmpty())
3515 *pHeightNTP = nHeight;
3525 assert(
IsUpdateLayout() &&
"Should not be used when Update=FALSE: CalcTextHeight" );
3581 nTentativeColHeight += nWantedIncrease;
3582 nWantedIncrease = std::numeric_limits<tools::Long>::max();
3583 nCurrentTextHeight = 0;
3586 auto GetHeightAndWantedIncrease = [&, minHeight =
tools::Long(0), lastCol = sal_Int16(0)](
3590 if (lastCol != rInfo.nColumn)
3592 minHeight = std::max(nCurrentTextHeight,
3594 nWantedIncrease = std::min(rInfo.nHeightNeededToNotWrap, nWantedIncrease);
3595 lastCol = rInfo.nColumn;
3601 if (rInfo.rPortion.IsEmpty())
3602 *pHeightNTP = std::max(*pHeightNTP, minHeight);
3604 *pHeightNTP = nCurrentTextHeight;
3611 }
while (nCurrentTextHeight > nTentativeColHeight && nWantedIncrease > 0
3612 && nWantedIncrease != std::numeric_limits<tools::Long>::max());
3613 return nCurrentTextHeight;
3618 OSL_ENSURE( 0 <= nParagraph && nParagraph <
GetParaPortions().
Count(),
"GetLineCount: Out of range" );
3620 OSL_ENSURE( pPPortion,
"Paragraph not found: GetLineCount" );
3629 OSL_ENSURE( 0 <= nParagraph && nParagraph <
GetParaPortions().
Count(),
"GetLineLen: Out of range" );
3631 OSL_ENSURE( pPPortion,
"Paragraph not found: GetLineLen" );
3632 if ( pPPortion && ( nLine < pPPortion->GetLines().
Count() ) )
3643 OSL_ENSURE( 0 <= nParagraph && nParagraph <
GetParaPortions().
Count(),
"GetLineCount: Out of range" );
3645 OSL_ENSURE( pPPortion,
"Paragraph not found: GetLineBoundaries" );
3647 if ( pPPortion && ( nLine < pPPortion->GetLines().
Count() ) )
3657 sal_Int32 nLineNo = -1;
3659 OSL_ENSURE( pNode,
"GetLineNumberAtIndex: invalid paragraph index" );
3663 const bool bValidIndex =
nIndex <= pNode->
Len();
3664 OSL_ENSURE( bValidIndex,
"GetLineNumberAtIndex: invalid index" );
3667 nLineNo = nLineCount > 0 ? nLineCount - 1 : 0;
3668 else if (bValidIndex)
3670 sal_Int32 nStart = -1, nEnd = -1;
3671 for (sal_Int32
i = 0;
i < nLineCount && nLineNo == -1; ++
i)
3674 if (nStart >= 0 && nStart <= nIndex && nEnd >= 0 &&
nIndex < nEnd)
3684 OSL_ENSURE( 0 <= nParagraph && nParagraph <
GetParaPortions().
Count(),
"GetLineCount: Out of range" );
3686 OSL_ENSURE( pPPortion,
"Paragraph not found: GetLineHeight" );
3687 if ( pPPortion && ( nLine < pPPortion->GetLines().
Count() ) )
3698 sal_uInt32 nHeight = 0;
3701 OSL_ENSURE( pPPortion,
"Paragraph not found: GetParaHeight" );
3715 EditSelection aCurSel( pView->pImpEditView->GetEditSelection() );
3716 bool bChanged =
false;
3717 for (
const std::unique_ptr<DeletedNodeInfo> & aDeletedNode :
aDeletedNodes)
3730 assert(
GetParaPortions()[nPara] &&
"Empty Document in UpdateSelections ?");
3732 sal_Int32 nCurPara = nPara;
3734 while ( nPara <= nLastPara && !
GetParaPortions()[nPara]->IsVisible() )
3736 if ( nPara > nLastPara )
3742 OSL_ENSURE(
GetParaPortions()[nPara]->IsVisible(),
"No visible paragraph found: UpdateSelections" );
3746 pView->pImpEditView->SetEditSelection( aTmpSelection );
3757 pView->pImpEditView->SetEditSelection( aCurSel );
3762 pView->pImpEditView->SetEditSelection( aCurSel );
3770 sal_Int32 nStartPara, sal_Int32 nStartPos, sal_Int32 nEndPara, sal_Int32 nEndPos )
3776 sal_Int32
nIndex = nStartPos;
3844 WriteRTF( pDataObj->GetRTFStream(), aSelection );
3845 pDataObj->GetRTFStream().Seek( 0 );
3847 WriteXML( pDataObj->GetODFStream(), aSelection );
3848 pDataObj->GetODFStream().Seek( 0 );
3871 if (
auto pUrlField =
dynamic_cast<const SvxURLField*
>(pFld) )
3874 pDataObj->GetURL() = pUrlField->GetURL();
3886 if ( !rxDataObj.is() )
3889 datatransfer::DataFlavor aFlavor;
3896 if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
3901 uno::Sequence< sal_Int8 >
aSeq;
3909 catch(
const css::uno::Exception&)
3920 datatransfer::DataFlavor aFlavorRichtext;
3922 bool bRtfSupported = rxDataObj->isDataFlavorSupported( aFlavor );
3923 bool bRichtextSupported = rxDataObj->isDataFlavorSupported( aFlavorRichtext );
3924 if ( bRtfSupported || bRichtextSupported )
3926 if(bRichtextSupported)
3928 aFlavor = aFlavorRichtext;
3933 uno::Sequence< sal_Int8 >
aSeq;
3941 catch(
const css::uno::Exception& )
3950 if ( rxDataObj->isDataFlavorSupported( aFlavor ) )
3974 sal_Int32 nChar = -1;
3975 sal_Int32 nCurIndex = pLine->
GetStart();
3979 for ( sal_Int32
i = pLine->
GetStartPortion(); i <= pLine->GetEndPortion();
i++ )
3984 if ( ( nXLeft <= nXPos ) && ( nXRight >= nXPos ) )
3998 if ( nRightDiff < nLeftDiff )
4004 sal_Int32 nMax = rPortion.
GetLen();
4005 sal_Int32 nOffset = -1;
4006 sal_Int32 nTmpCurIndex = nChar - pLine->
GetStart();
4010 nXInPortion = nXRight - nXPos;
4013 for ( sal_Int32
x = 0;
x < nMax;
x++ )
4016 if ( nTmpPosMax > nXInPortion )
4021 tools::Long nDiffRight = nTmpPosMax - nXInPortion;
4022 OSL_ENSURE( nDiffLeft >= 0,
"DiffLeft negative" );
4023 OSL_ENSURE( nDiffRight >= 0,
"DiffRight negative" );
4025 if (bSmart && nDiffRight < nDiffLeft)
4031 while(x < nMax && pLine->GetCharPosArray()[nTmpCurIndex +
x] == nX)
4045 OSL_ENSURE( nOffset <= nMax, "nOffset > nMax
" );
4047 nChar = nChar + nOffset;
4049 // Check if index is within a cell:
4050 if ( nChar && ( nChar < pParaPortion->GetNode()->Len() ) )
4052 EditPaM aPaM( pParaPortion->GetNode(), nChar+1 );
4053 sal_uInt16 nScriptType = GetI18NScriptType( aPaM );
4054 if ( nScriptType == i18n::ScriptType::COMPLEX )
4056 uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() );
4057 sal_Int32 nCount = 1;
4058 lang::Locale aLocale = GetLocale( aPaM );
4059 sal_Int32 nRight = _xBI->nextCharacters(
4060 pParaPortion->GetNode()->GetString(), nChar, aLocale, css::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
4061 sal_Int32 nLeft = _xBI->previousCharacters(
4062 pParaPortion->GetNode()->GetString(), nRight, aLocale, css::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount );
4063 if ( ( nLeft != nChar ) && ( nRight != nChar ) )
4065 nChar = ( std::abs( nRight - nChar ) < std::abs( nLeft - nChar ) ) ? nRight : nLeft;
4070 OUString aStr(pParaPortion->GetNode()->GetString());
4071 // tdf#102625: don't select middle of a pair of surrogates with mouse cursor
4072 if (rtl::isSurrogate(aStr[nChar]))
4079 nCurIndex = nCurIndex + rPortion.GetLen();
4084 nChar = ( nXPos <= pLine->GetStartPosX() ) ? pLine->GetStart() : pLine->GetEnd();
4090Range ImpEditEngine::GetLineXPosStartEnd( const ParaPortion* pParaPortion, const EditLine* pLine ) const
4092 Range aLineXPosStartEnd;
4094 sal_Int32 nPara = GetEditDoc().GetPos( pParaPortion->GetNode() );
4095 if ( !IsRightToLeft( nPara ) )
4097 aLineXPosStartEnd.Min() = pLine->GetStartPosX();
4098 aLineXPosStartEnd.Max() = pLine->GetStartPosX() + pLine->GetTextWidth();
4102 aLineXPosStartEnd.Min() = GetPaperSize().Width() - ( pLine->GetStartPosX() + pLine->GetTextWidth() );
4103 aLineXPosStartEnd.Max() = GetPaperSize().Width() - pLine->GetStartPosX();
4107 return aLineXPosStartEnd;
4110tools::Long ImpEditEngine::GetPortionXOffset(
4111 const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nTextPortion) const
4113 tools::Long nX = pLine->GetStartPosX();
4115 for ( sal_Int32 i = pLine->GetStartPortion(); i < nTextPortion; i++ )
4117 const TextPortion& rPortion = pParaPortion->GetTextPortions()[i];
4118 switch ( rPortion.GetKind() )
4120 case PortionKind::FIELD:
4121 case PortionKind::TEXT:
4122 case PortionKind::HYPHENATOR:
4123 case PortionKind::TAB:
4125 nX += rPortion.GetSize().Width();
4128 case PortionKind::LINEBREAK: break;
4132 sal_Int32 nPara = GetEditDoc().GetPos( pParaPortion->GetNode() );
4133 bool bR2LPara = IsRightToLeft( nPara );
4135 const TextPortion& rDestPortion = pParaPortion->GetTextPortions()[nTextPortion];
4136 if ( rDestPortion.GetKind() != PortionKind::TAB )
4138 if ( !bR2LPara && rDestPortion.GetRightToLeftLevel() )
4140 // Portions behind must be added, visual before this portion
4141 sal_Int32 nTmpPortion = nTextPortion+1;
4142 while ( nTmpPortion <= pLine->GetEndPortion() )
4144 const TextPortion& rNextTextPortion = pParaPortion->GetTextPortions()[nTmpPortion];
4145 if ( rNextTextPortion.GetRightToLeftLevel() && ( rNextTextPortion.GetKind() != PortionKind::TAB ) )
4146 nX += rNextTextPortion.GetSize().Width();
4151 // Portions before must be removed, visual behind this portion
4152 nTmpPortion = nTextPortion;
4153 while ( nTmpPortion > pLine->GetStartPortion() )
4156 const TextPortion& rPrevTextPortion = pParaPortion->GetTextPortions()[nTmpPortion];
4157 if ( rPrevTextPortion.GetRightToLeftLevel() && ( rPrevTextPortion.GetKind() != PortionKind::TAB ) )
4158 nX -= rPrevTextPortion.GetSize().Width();
4163 else if ( bR2LPara && !rDestPortion.IsRightToLeft() )
4165 // Portions behind must be removed, visual behind this portion
4166 sal_Int32 nTmpPortion = nTextPortion+1;
4167 while ( nTmpPortion <= pLine->GetEndPortion() )
4169 const TextPortion& rNextTextPortion = pParaPortion->GetTextPortions()[nTmpPortion];
4170 if ( !rNextTextPortion.IsRightToLeft() && ( rNextTextPortion.GetKind() != PortionKind::TAB ) )
4171 nX += rNextTextPortion.GetSize().Width();
4176 // Portions before must be added, visual before this portion
4177 nTmpPortion = nTextPortion;
4178 while ( nTmpPortion > pLine->GetStartPortion() )
4181 const TextPortion& rPrevTextPortion = pParaPortion->GetTextPortions()[nTmpPortion];
4182 if ( !rPrevTextPortion.IsRightToLeft() && ( rPrevTextPortion.GetKind() != PortionKind::TAB ) )
4183 nX -= rPrevTextPortion.GetSize().Width();
4191 // Switch X positions...
4192 OSL_ENSURE( GetTextRanger() || GetPaperSize().Width(), "GetPortionXOffset - paper size?!
" );
4193 OSL_ENSURE( GetTextRanger() || (nX <= GetPaperSize().Width()), "GetPortionXOffset - position out of paper size!
" );
4194 nX = GetPaperSize().Width() - nX;
4195 nX -= rDestPortion.GetSize().Width();
4201tools::Long ImpEditEngine::GetXPos(
4202 const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nIndex, bool bPreferPortionStart) const
4205 OSL_ENSURE( ( nIndex >= pLine->GetStart() ) && ( nIndex <= pLine->GetEnd() ) , "GetXPos has to be called properly!
" );
4207 bool bDoPreferPortionStart = bPreferPortionStart;
4208 // Assure that the portion belongs to this line:
4209 if ( nIndex == pLine->GetStart() )
4210 bDoPreferPortionStart = true;
4211 else if ( nIndex == pLine->GetEnd() )
4212 bDoPreferPortionStart = false;
4214 sal_Int32 nTextPortionStart = 0;
4215 sal_Int32 nTextPortion = pParaPortion->GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart );
4217 OSL_ENSURE( ( nTextPortion >= pLine->GetStartPortion() ) && ( nTextPortion <= pLine->GetEndPortion() ), "GetXPos: Portion not in current line!
" );
4219 const TextPortion& rPortion = pParaPortion->GetTextPortions()[nTextPortion];
4221 tools::Long nX = GetPortionXOffset( pParaPortion, pLine, nTextPortion );
4223 // calc text width, portion size may include CJK/CTL spacing...
4224 // But the array might not be init yet, if using text ranger this method is called within CreateLines()...
4225 tools::Long nPortionTextWidth = rPortion.GetSize().Width();
4226 if ( ( rPortion.GetKind() == PortionKind::TEXT ) && rPortion.GetLen() && !GetTextRanger() )
4227 nPortionTextWidth = pLine->GetCharPosArray()[nTextPortionStart + rPortion.GetLen() - 1 - pLine->GetStart()];
4229 if ( nTextPortionStart != nIndex )
4231 // Search within portion...
4232 if ( nIndex == ( nTextPortionStart + rPortion.GetLen() ) )
4235 if ( rPortion.GetKind() == PortionKind::TAB )
4237 if ( nTextPortion+1 < pParaPortion->GetTextPortions().Count() )
4239 const TextPortion& rNextPortion = pParaPortion->GetTextPortions()[nTextPortion+1];
4240 if ( rNextPortion.GetKind() != PortionKind::TAB )
4242 if ( !bPreferPortionStart )
4243 nX = GetXPos( pParaPortion, pLine, nIndex, true );
4244 else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) )
4245 nX += nPortionTextWidth;
4248 else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) )
4250 nX += nPortionTextWidth;
4253 else if ( !rPortion.IsRightToLeft() )
4255 nX += nPortionTextWidth;
4258 else if ( rPortion.GetKind() == PortionKind::TEXT )
4260 OSL_ENSURE( nIndex != pLine->GetStart(), "Strange behavior in
new GetXPos()
" );
4261 OSL_ENSURE( !pLine->GetCharPosArray().empty(), "svx::ImpEditEngine::GetXPos(), portion in an empty line?
" );
4263 if( !pLine->GetCharPosArray().empty() )
4265 sal_Int32 nPos = nIndex - 1 - pLine->GetStart();
4266 if (nPos < 0 || o3tl::make_unsigned(nPos) >= pLine->GetCharPosArray().size())
4268 nPos = pLine->GetCharPosArray().size()-1;
4269 OSL_FAIL("svx::ImpEditEngine::GetXPos(), index out of range!
");
4272 // old code restored see #i112788 (which leaves #i74188 unfixed again)
4273 tools::Long nPosInPortion = pLine->GetCharPosArray()[nPos];
4275 if ( !rPortion.IsRightToLeft() )
4277 nX += nPosInPortion;
4281 nX += nPortionTextWidth - nPosInPortion;
4284 if ( rPortion.GetExtraInfos() && rPortion.GetExtraInfos()->bCompressed )
4286 nX += rPortion.GetExtraInfos()->nPortionOffsetX;
4287 if ( rPortion.GetExtraInfos()->nAsianCompressionTypes & AsianCompressionFlags::PunctuationRight )
4289 AsianCompressionFlags nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex ) );
4290 if ( nType == AsianCompressionFlags::PunctuationRight && !pLine->GetCharPosArray().empty() )
4292 sal_Int32 n = nIndex - nTextPortionStart;
4293 const sal_Int32* pDXArray = pLine->GetCharPosArray().data()+( nTextPortionStart-pLine->GetStart() );
4294 sal_Int32 nCharWidth = ( ( (n+1) < rPortion.GetLen() ) ? pDXArray[n] : rPortion.GetSize().Width() )
4295 - ( n ? pDXArray[n-1] : 0 );
4296 if ( (n+1) < rPortion.GetLen() )
4298 // smaller, when char behind is AsianCompressionFlags::PunctuationRight also
4299 nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex+1 ) );
4300 if ( nType == AsianCompressionFlags::PunctuationRight )
4302 sal_Int32 nNextCharWidth = ( ( (n+2) < rPortion.GetLen() ) ? pDXArray[n+1] : rPortion.GetSize().Width() )
4304 sal_Int32 nCompressed = nNextCharWidth/2;
4305 nCompressed *= rPortion.GetExtraInfos()->nMaxCompression100thPercent;
4306 nCompressed /= 10000;
4307 nCharWidth += nCompressed;
4312 nCharWidth *= 2; // last char pos to portion end is only compressed size
4314 nX += nCharWidth/2; // 50% compression
4321 else // if ( nIndex == pLine->GetStart() )
4323 if ( rPortion.IsRightToLeft() )
4325 nX += nPortionTextWidth;
4332void ImpEditEngine::CalcHeight( ParaPortion* pPortion )
4334 pPortion->nHeight = 0;
4335 pPortion->nFirstLineOffset = 0;
4337 if ( !pPortion->IsVisible() )
4340 OSL_ENSURE( pPortion->GetLines().Count(), "Paragraph with no lines in ParaPortion::CalcHeight
" );
4341 for (sal_Int32 nLine = 0; nLine < pPortion->GetLines().Count(); ++nLine)
4342 pPortion->nHeight += pPortion->GetLines()[nLine].GetHeight();
4344 if ( aStatus.IsOutliner() )
4347 const SvxULSpaceItem& rULItem = pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
4348 const SvxLineSpacingItem& rLSItem = pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
4349 sal_Int32 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0;
4353 if ( pPortion->GetLines().Count() > 1 )
4354 pPortion->nHeight += ( pPortion->GetLines().Count() - 1 ) * nSBL;
4355 if ( aStatus.ULSpaceSummation() )
4356 pPortion->nHeight += nSBL;
4359 sal_Int32 nPortion = GetParaPortions().GetPos( pPortion );
4362 sal_uInt16 nUpper = scaleYSpacingValue(rULItem.GetUpper());
4363 pPortion->nHeight += nUpper;
4364 pPortion->nFirstLineOffset = nUpper;
4367 if ( nPortion != (GetParaPortions().Count()-1) )
4369 pPortion->nHeight += scaleYSpacingValue(rULItem.GetLower()); // not in the last
4373 if ( !nPortion || aStatus.ULSpaceSummation() )
4376 ParaPortion* pPrev = GetParaPortions().SafeGetObject( nPortion-1 );
4380 const SvxULSpaceItem& rPrevULItem = pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE );
4381 const SvxLineSpacingItem& rPrevLSItem = pPrev->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL );
4383 // In relation between WinWord6/Writer3:
4384 // With a proportional line spacing the paragraph spacing is
4385 // also manipulated.
4386 // Only Writer3: Do not add up, but minimum distance.
4388 // check if distance by LineSpacing > Upper:
4389 sal_uInt16 nExtraSpace = scaleYSpacingValue(lcl_CalcExtraSpace(rLSItem));
4390 if ( nExtraSpace > pPortion->nFirstLineOffset )
4392 // Paragraph becomes 'bigger':
4393 pPortion->nHeight += ( nExtraSpace - pPortion->nFirstLineOffset );
4394 pPortion->nFirstLineOffset = nExtraSpace;
4397 // Determine nFirstLineOffset now f(pNode) => now f(pNode, pPrev):
4398 sal_uInt16 nPrevLower = scaleYSpacingValue(rPrevULItem.GetLower());
4400 // This PrevLower is still in the height of PrevPortion ...
4401 if ( nPrevLower > pPortion->nFirstLineOffset )
4403 // Paragraph is 'small':
4404 pPortion->nHeight -= pPortion->nFirstLineOffset;
4405 pPortion->nFirstLineOffset = 0;
4407 else if ( nPrevLower )
4409 // Paragraph becomes 'somewhat smaller':
4410 pPortion->nHeight -= nPrevLower;
4411 pPortion->nFirstLineOffset =
4412 pPortion->nFirstLineOffset - nPrevLower;
4414 // I find it not so good, but Writer3 feature:
4415 // Check if distance by LineSpacing > Lower: this value is not
4416 // stuck in the height of PrevPortion.
4417 if ( pPrev->IsInvalid() )
4420 nExtraSpace = scaleYSpacingValue(lcl_CalcExtraSpace(rPrevLSItem));
4421 if ( nExtraSpace > nPrevLower )
4423 sal_uInt16 nMoreLower = nExtraSpace - nPrevLower;
4424 // Paragraph becomes 'bigger', 'grows' downwards:
4425 if ( nMoreLower > pPortion->nFirstLineOffset )
4427 pPortion->nHeight += ( nMoreLower - pPortion->nFirstLineOffset );
4428 pPortion->nFirstLineOffset = nMoreLower;
4433void ImpEditEngine::SetValidPaperSize( const Size& rNewSz )
4435 aPaperSize = rNewSz;
4437 tools::Long nMinWidth = aStatus.AutoPageWidth() ? aMinAutoPaperSize.Width() : 0;
4438 tools::Long nMaxWidth = aStatus.AutoPageWidth() ? aMaxAutoPaperSize.Width() : 0x7FFFFFFF;
4439 tools::Long nMinHeight = aStatus.AutoPageHeight() ? aMinAutoPaperSize.Height() : 0;
4440 tools::Long nMaxHeight = aStatus.AutoPageHeight() ? aMaxAutoPaperSize.Height() : 0x7FFFFFFF;
4442 // Minimum/Maximum width:
4443 if ( aPaperSize.Width() < nMinWidth )
4444 aPaperSize.setWidth( nMinWidth );
4445 else if ( aPaperSize.Width() > nMaxWidth )
4446 aPaperSize.setWidth( nMaxWidth );
4448 // Minimum/Maximum height:
4449 if ( aPaperSize.Height() < nMinHeight )
4450 aPaperSize.setHeight( nMinHeight );
4451 else if ( aPaperSize.Height() > nMaxHeight )
4452 aPaperSize.setHeight( nMaxHeight );
4455std::shared_ptr<SvxForbiddenCharactersTable> const & ImpEditEngine::GetForbiddenCharsTable()
4457 return EditDLL::Get().GetGlobalData()->GetForbiddenCharsTable();
4460void ImpEditEngine::SetForbiddenCharsTable(const std::shared_ptr<SvxForbiddenCharactersTable>& xForbiddenChars)
4462 EditDLL::Get().GetGlobalData()->SetForbiddenCharsTable( xForbiddenChars );
4465bool ImpEditEngine::IsVisualCursorTravelingEnabled()
4467 bool bVisualCursorTravaling = false;
4469 if ( SvtCTLOptions::IsCTLFontEnabled() && ( SvtCTLOptions::GetCTLCursorMovement() == SvtCTLOptions::MOVEMENT_VISUAL ) )
4471 bVisualCursorTravaling = true;
4474 return bVisualCursorTravaling;
4478bool ImpEditEngine::DoVisualCursorTraveling()
4480 // Don't check if it's necessary, because we also need it when leaving the paragraph
4481 return IsVisualCursorTravelingEnabled();
4484IMPL_LINK_NOARG(ImpEditEngine, DocModified, LinkParamNone*, void)
4486 aModifyHdl.Call( nullptr /*GetEditEnginePtr()*/ ); // NULL, because also used for Outliner
4489/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SfxApplication * SfxGetpApp()
bool HasEmptyAttribs() const
AttribsType & GetAttribs()
const EditCharAttrib * FindFeature(sal_Int32 nPos) const
std::vector< std::unique_ptr< EditCharAttrib > > AttribsType
const EditCharAttrib * FindNextAttrib(sal_uInt16 nWhich, sal_Int32 nFromPos) const
CommandEventId GetCommand() const
const CommandSelectionChangeData * GetSelectionChangeData() const
const CommandExtTextInputData * GetExtTextInputData() const
CharAttribList & GetCharAttribs()
sal_Unicode GetChar(sal_Int32 nPos) const
bool IsFeature(sal_Int32 nPos) const
const OUString & GetString() const
ContentAttribs & GetContentAttribs()
WrongList * GetWrongList()
OUString Copy(sal_Int32 nPos) const
SfxStyleSheet * GetStyleSheet()
void SetStyleSheet(SfxStyleSheet *pS, bool bRecalcFont=true)
sal_Int32 GetPosition() const
ContentNode * GetNode() const
const SfxPoolItem * GetItem() const
void Insert(sal_Int32 nPos, ContentNode *p)
sal_Int32 GetPos(const ContentNode *pNode) const
void RemoveChars(EditPaM aPaM, sal_Int32 nChars)
SfxItemPool & GetItemPool()
void SetModifyHdl(const Link< LinkParamNone *, void > &rLink)
OUString GetParaAsString(sal_Int32 nNode) const
const ContentNode * GetObject(sal_Int32 nPos) const
EditPaM ConnectParagraphs(ContentNode *pLeft, ContentNode *pRight)
static OUString GetSepStr(LineEnd eEnd)
void Release(sal_Int32 nPos)
does not delete
EditPaM GetStartPaM() const
virtual void ParagraphDeleted(sal_Int32 nDeletedParagraph)
sal_Int32 GetTextLen() const
virtual void ParaAttribsChanged(sal_Int32 nParagraph)
virtual void ParagraphConnected(sal_Int32 nLeftParagraph, sal_Int32 nRightParagraph)
virtual bool FieldClicked(const SvxFieldItem &rField)
virtual void ParagraphInserted(sal_Int32 nNewParagraph)
sal_Int32 FindLine(sal_Int32 nChar, bool bInclEnd)
CharPosArrayType & GetCharPosArray()
sal_Int32 GetStartPortion() const
sal_uInt16 GetHeight() const
sal_Int32 GetStart() const
void SetIndex(sal_Int32 n)
void SetNode(ContentNode *p)
const ContentNode * GetNode() const
sal_Int32 GetIndex() const
void SetCurView(EditView *pNewView)
bool DbgIsBuggy(EditDoc const &rDoc) const
void Adjust(const EditDoc &rNodes)
EEControlBits & GetControlWord()
virtual OutputDevice & EditViewOutputDevice() const =0
const SvxFieldItem * GetField(const Point &rPos, sal_Int32 *pnPara=nullptr, sal_Int32 *pnPos=nullptr) const
ImpEditView * GetImpEditView() const
void HideCursor(bool bDeactivate=false)
bool IsInsertMode() const
ESelection GetSelection() const
tools::Rectangle GetVisArea() const
bool HasSelection() const
void SetSelection(const ESelection &rNewSel)
EditViewCallbacks * getEditViewCallbacks() const
void ShowCursor(bool bGotoCursor=true, bool bForceVisCursor=true, bool bActivate=false)
vcl::Window * GetWindow() const
void SetInsertMode(bool bInsert)
std::unique_ptr< ImpEditView > pImpEditView
void WriteXML(SvStream &rOutput, const EditSelection &rSel)
void CursorMoved(const ContentNode *pPrevNode)
EditPaM PageDown(const EditPaM &rPaM, EditView const *pView)
tools::Long GetXPos(const ParaPortion *pParaPortion, const EditLine *pLine, sal_Int32 nIndex, bool bPreferPortionStart=false) const
sal_uInt16 GetLineHeight(sal_Int32 nParagraph, sal_Int32 nLine)
EditPaM WordLeft(const EditPaM &rPaM)
void CalcHeight(ParaPortion *pPortion)
tools::Long GetPortionXOffset(const ParaPortion *pParaPortion, const EditLine *pLine, sal_Int32 nTextPortion) const
bool HasDifferentRTLLevels(const ContentNode *pNode)
const ParaPortion * GetNextVisPortion(const ParaPortion *pCurPortion) const
const SfxItemSet & GetEmptyItemSet() const
LanguageType GetDefaultLanguage() const
Link< MoveParagraphsInfo &, void > aBeginMovingParagraphsHdl
EditSelectionEngine aSelEngine
sal_Int32 GetLineLen(sal_Int32 nParagraph, sal_Int32 nLine) const
EditPaM CursorLeft(const EditPaM &rPaM, sal_uInt16 nCharacterIteratorMode=css::i18n::CharacterIteratorMode::SKIPCELL)
ImpEditEngine(EditEngine *pEditEngine, SfxItemPool *pPool)
tools::Long CalcTextHeight(tools::Long *pHeightNTP)
EditPaM CursorStartOfLine(const EditPaM &rPaM)
EditPaM CursorEndOfLine(const EditPaM &rPaM)
css::lang::Locale GetLocale(const EditPaM &rPaM) const
static void ImplInitDigitMode(OutputDevice &rOutDev, LanguageType eLang)
EditPaM StartOfWord(const EditPaM &rPaM)
void IterateLineAreas(const IterateLinesAreasFunc &f, IterFlag eOptions)
void UndoActionStart(sal_uInt16 nId)
OUString GetSelected(const EditSelection &rSel) const
ErrCode WriteRTF(SvStream &rOutput, EditSelection aSel)
void DoOnlineSpelling(ContentNode *pThisNodeOnly=nullptr, bool bSpellAtCursorPos=false, bool bInterruptible=true)
SvtScriptType GetItemScriptType(const EditSelection &rSel) const
void SetAutoCompleteText(const OUString &rStr, bool bUpdateTipWindow)
sal_uInt32 GetTextHeightNTP() const
std::unique_ptr< SfxItemSet > pEmptyItemSet
EditPaM PageUp(const EditPaM &rPaM, EditView const *pView)
EPaM CreateEPaM(const EditPaM &rPaM) const
sal_uInt32 GetParaHeight(sal_Int32 nParagraph)
EditEngine * GetEditEnginePtr() const
ContentNode * GetNextVisNode(ContentNode const *pCurNode)
sal_uInt32 GetTextHeight() const
sal_Int32 GetLineCount(sal_Int32 nParagraph) const
const SfxStyleSheet * GetStyleSheet(sal_Int32 nPara) const
void ImplInitLayoutMode(OutputDevice &rOutDev, sal_Int32 nPara, sal_Int32 nIndex)
EditPaM GetPaM(Point aDocPos, bool bSmart=true)
const ParaPortion * FindParaPortion(const ContentNode *pNode) const
tools::Long getBottomDocOffset(const tools::Rectangle &rect) const
std::vector< std::unique_ptr< DeletedNodeInfo > > aDeletedNodes
bool IsEffectivelyVertical() const
EditPaM CursorRight(const EditPaM &rPaM, sal_uInt16 nCharacterIteratorMode=css::i18n::CharacterIteratorMode::SKIPCELL)
EditUndoManager * pUndoManager
void UpdateViews(EditView *pCurView=nullptr)
void SeekCursor(ContentNode *pNode, sal_Int32 nPos, SvxFont &rFont, OutputDevice *pOut=nullptr)
EditPaM CursorStartOfDoc()
SvxAdjust GetJustification(sal_Int32 nPara) const
bool Command(const CommandEvent &rCEvt, EditView *pView)
EditSelection const & MoveCursor(const KeyEvent &rKeyEvent, EditView *pEditView)
virtual ~ImpEditEngine() override
EditSelFunctionSet aSelFuncSet
bool MouseMove(const MouseEvent &rMouseEvent, EditView *pView)
EEHorizontalTextDirection GetDefaultHorizontalTextDirection() const
sal_uInt8 GetRightToLeft(sal_Int32 nPara, sal_Int32 nChar, sal_Int32 *pStart=nullptr, sal_Int32 *pEnd=nullptr)
std::unique_ptr< ImplIMEInfos > mpIMEInfos
EditSelection ConvertSelection(sal_Int32 nStartPara, sal_Int32 nStartPos, sal_Int32 nEndPara, sal_Int32 nEndPos)
EditPaM ImpInsertParaBreak(EditPaM &rPaM, bool bKeepEndingAttribs=true)
sal_uInt16 GetI18NScriptType(const EditPaM &rPaM, sal_Int32 *pEndPos=nullptr) const
std::unique_ptr< SpellInfo > pSpellInfo
tools::Long nCurTextHeight
EditSelection SelectSentence(const EditSelection &rCurSel) const
bool IsTopToBottom() const
tools::Rectangle GetEditCursor(const ParaPortion *pPortion, const EditLine *pLine, sal_Int32 nIndex, GetCursorFlags nFlags)
std::function< CallbackResult(const LineAreaInfo &)> IterateLinesAreasFunc
bool IsTextPos(const Point &rDocPos, sal_uInt16 nBorder)
void EnableUndo(bool bEnable)
sal_Int32 GetLineNumberAtIndex(sal_Int32 nPara, sal_Int32 nIndex) const
InternalEditStatus aStatus
std::tuple< const ParaPortion *, const EditLine *, tools::Long > GetPortionAndLine(Point aDocPos)
tools::Long mnMinColumnWrapHeight
const SvxLRSpaceItem & GetLRSpaceItem(ContentNode *pNode)
EditPaM WordRight(const EditPaM &rPaM, sal_Int16 nWordType=css::i18n::WordType::ANYWORD_IGNOREWHITESPACES)
tools::Long nCurTextHeightNTP
tools::Long GetColumnWidth(const Size &rPaperSize) const
void FormatAndLayout(EditView *pCurView=nullptr, bool bCalledFromUndo=false)
const OUString & GetAutoCompleteText() const
void GetCharAttribs(sal_Int32 nPara, std::vector< EECharAttrib > &rLst) const
void GetLineBoundaries(sal_Int32 &rStart, sal_Int32 &rEnd, sal_Int32 nParagraph, sal_Int32 nLine) const
EditPaM Read(SvStream &rInput, const OUString &rBaseURL, EETextFormat eFormat, const EditSelection &rSel, SvKeyValueIterator *pHTTPHeaderAttrs=nullptr)
Range GetLineXPosStartEnd(const ParaPortion *pParaPortion, const EditLine *pLine) const
bool IsScriptChange(const EditPaM &rPaM) const
SvxCellJustifyMethod GetJustifyMethod(sal_Int32 nPara) const
EditSelectionEngine & GetSelEngine()
EditPaM DeleteSelected(const EditSelection &rEditSelection)
EditUndoManager & GetUndoManager()
sal_Int32 mnColumnSpacing
void InitScriptTypes(sal_Int32 nPara)
void SetActiveView(EditView *pView)
EditPaM CursorVisualStartEnd(EditView const *pEditView, const EditPaM &rPaM, bool bStart)
bool MouseButtonUp(const MouseEvent &rMouseEvent, EditView *pView)
VclPtr< OutputDevice > pRefDev
tools::Long getYOverflowDirectionAware(const Point &pt, const tools::Rectangle &rectMax) const
sal_Int32 GetChar(const ParaPortion *pParaPortion, const EditLine *pLine, tools::Long nX, bool bSmart=true)
EditPaM CursorDown(const EditPaM &rPaM, EditView const *pEditView)
void InitDoc(bool bKeepParaAttribs)
static EditPaM CursorStartOfParagraph(const EditPaM &rPaM)
EditPaM DeleteLeftOrRight(const EditSelection &rEditSelection, sal_uInt8 nMode, DeleteMode nDelMode)
void adjustYDirectionAware(Point &pt, tools::Long y) const
VclPtr< VirtualDevice > mpOwnDev
void SetRefDevice(OutputDevice *pRefDef)
bool HasUndoManager() const
std::unique_ptr< EditUndoSetAttribs > CreateAttribUndo(EditSelection aSel, const SfxItemSet &rSet)
sal_uInt32 CalcLineWidth(ParaPortion *pPortion, EditLine *pLine, bool bIgnoreExtraSpace)
EditSelection PasteText(css::uno::Reference< css::datatransfer::XTransferable > const &rxDataObj, const OUString &rBaseURL, const EditPaM &rPaM, bool bUseSpecial)
static bool DoVisualCursorTraveling()
sal_uInt16 nOnePixelInRef
OutputDevice * GetRefDevice() const
const ParaPortion * GetPrevVisPortion(const ParaPortion *pCurPortion) const
css::uno::Reference< css::datatransfer::XTransferable > CreateTransferable(const EditSelection &rSelection)
sal_uInt32 CalcTextWidth(bool bIgnoreExtraSpace)
EditPaM AutoCorrect(const EditSelection &rCurEditSelection, sal_Unicode c, bool bOverwrite, vcl::Window const *pFrameWin=nullptr)
Link< MoveParagraphsInfo &, void > aEndMovingParagraphsHdl
double scaleXSpacingValue(tools::Long nXValue) const
EditPaM ImpDeleteSelection(const EditSelection &rCurSel)
VclPtr< VirtualDevice > pVirtDev
TextRanger * GetTextRanger() const
bool IsCallParaInsertedOrDeleted() const
const SfxPoolItem & GetParaAttrib(sal_Int32 nPara, sal_uInt16 nWhich) const
sal_Int32 GetSpaceBeforeAndMinLabelWidth(const ContentNode *pNode, sal_Int32 *pnSpaceBefore=nullptr, sal_Int32 *pnMinLabelWidth=nullptr) const
std::unique_ptr< TextRanger > pTextRanger
ESelection CreateESel(const EditSelection &rSel) const
ContentNode * GetPrevVisNode(ContentNode const *pCurNode)
void InsertUndo(std::unique_ptr< EditUndo > pUndo, bool bTryMerge=false)
EditPaM ImpConnectParagraphs(ContentNode *pLeft, ContentNode *pRight, bool bBackward=false)
bool IsFormatting() const
tools::Rectangle PaMtoEditCursor(EditPaM aPaM, GetCursorFlags nFlags=GetCursorFlags::NONE)
bool HasScriptType(sal_Int32 nPara, sal_uInt16 nType) const
EditPaM CursorVisualLeftRight(EditView const *pEditView, const EditPaM &rPaM, sal_uInt16 nCharacterIteratorMode, bool bToLeft)
void ParaAttribsChanged(ContentNode const *pNode, bool bIgnoreUndoCheck=false)
InternalEditStatus & GetStatus()
const Link< EENotify &, void > & GetNotifyHdl() const
static EditPaM CursorEndOfParagraph(const EditPaM &rPaM)
EditSelection ImpMoveParagraphs(Range aParagraphs, sal_Int32 nNewPos)
void ImpRemoveChars(const EditPaM &rPaM, sal_Int32 nChars)
css::uno::Reference< css::i18n::XBreakIterator > const & ImplGetBreakIterator() const
bool SetUpdateLayout(bool bUpdate, EditView *pCurView=nullptr, bool bForceUpdate=false)
EditSelection SelectWord(const EditSelection &rCurSelection, sal_Int16 nWordType=css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, bool bAcceptStartOfWord=true)
bool IsInputSequenceCheckingRequired(sal_Unicode nChar, const EditSelection &rCurSel) const
void SetRefMapMode(const MapMode &rMapMode)
void SetText(const OUString &rText)
SvxCellVerJustify GetVerJustification(sal_Int32 nPara) const
bool IsUpdateLayout() const
sal_uInt32 CalcParaWidth(sal_Int32 nParagraph, bool bIgnoreExtraSpace)
tools::Long Calc1ColumnTextHeight(tools::Long *pHeightNTP)
bool MouseButtonDown(const MouseEvent &rMouseEvent, EditView *pView)
IdleFormattter aIdleFormatter
EditPaM ImpInsertText(const EditSelection &aCurEditSelection, const OUString &rStr)
bool IsUndoEnabled() const
EditPaM CursorUp(const EditPaM &rPaM, EditView const *pEditView)
void InitWritingDirections(sal_Int32 nPara)
EditPaM InsertText(const EditSelection &aCurEditSelection, const OUString &rStr)
EditPaM EndOfWord(const EditPaM &rPaM)
Size getTopLeftDocOffset(const tools::Rectangle &rect) const
bool IsRightToLeft(sal_Int32 nPara) const
const ParaPortionList & GetParaPortions() const
void CheckIdleFormatter()
std::shared_ptr< editeng::SharedVclResources > pSharedVCL
bool bCallParaInsertedOrDeleted
const EditSelection & GetEditSelection() const
Point GetWindowPos(const Point &rDocPos) const
const vcl::KeyCode & GetKeyCode() const
KeyEvent LogicalTextDirectionality(TextDirectionality eMode) const
sal_uInt16 GetClicks() const
const Point & GetPosPixel() const
SAL_WARN_UNUSED_RESULT Point PixelToLogic(const Point &rDevicePt) const
void Push(vcl::PushFlags nFlags=vcl::PushFlags::ALL)
sal_Int32 GetPos(const ParaPortion *p) const
static void DbgCheck(ParaPortionList const &, EditDoc const &rDoc)
void Insert(sal_Int32 nPos, std::unique_ptr< ParaPortion > p)
void Append(std::unique_ptr< ParaPortion > p)
void Remove(sal_Int32 nPos)
std::unique_ptr< ParaPortion > Release(sal_Int32 nPos)
const ParaPortion * SafeGetObject(sal_Int32 nPos) const
WritingDirectionInfos aWritingDirectionInfos
TextPortionList & GetTextPortions()
tools::Long GetHeight() const
ScriptTypePosInfos aScriptInfos
sal_Int32 GetLineNumber(sal_Int32 nIndex) const
sal_Int32 GetBulletX() const
ContentNode * GetNode() const
EditLineList & GetLines()
void MarkSelectionInvalid(sal_Int32 nStart)
constexpr tools::Long Y() const
void setY(tools::Long nY)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() const
bool Command(const CommandEvent &rCEvt)
bool SelMouseMove(const MouseEvent &rMEvt)
bool SelMouseButtonDown(const MouseEvent &rMEvt)
void CursorPosChanging(bool bShift, bool bMod1)
void SetFunctionSet(FunctionSet *pFuncs)
bool SelMouseButtonUp(const MouseEvent &rMEvt)
static SfxApplication * Get()
virtual sal_uInt16 GetEnumValue() const override
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
bool Set(const SfxItemSet &, bool bDeep=true)
void StartListening(SfxBroadcaster &rBroadcaster, DuplicateHandling eDuplicateHanding=DuplicateHandling::Unexpected)
void EndListening(SfxBroadcaster &rBroadcaster, bool bRemoveAllDuplicates=false)
constexpr tools::Long Width() const
static bool GetFormatDataFlavor(SotClipboardFormatId nFormat, css::datatransfer::DataFlavor &rFlavor)
static bool IsCTLFontEnabled()
static bool IsCTLSequenceChecking()
static bool IsAutoCorrectChar(sal_Unicode cChar)
This item stores a field (SvxFieldData).
const SvxFieldData * GetField() const
void SetPhysFont(OutputDevice &rOut) const
Size QuickGetTextSize(const OutputDevice *pOut, const OUString &rTxt, const sal_Int32 nIdx, const sal_Int32 nLen, KernArray *pDXArray=nullptr) const
short GetTextFirstLineOffset() const
tools::Long GetRight() const
tools::Long GetTextLeft() const
SvxInterLineSpaceRule GetInterLineSpaceRule() const
short GetInterLineSpace() const
void SetPriority(TaskPriority ePriority)
sal_Int32 FindPortion(sal_Int32 nCharPos, sal_Int32 &rPortionStart, bool bPreferStartingPortion=false) const
PortionKind GetKind() const
sal_uInt8 GetRightToLeftLevel() const
bool IsRightToLeft() const
const Size & GetSize() const
void SetTimeout(sal_uInt64 nTimeoutMs)
void SetInvokeHandler(const Link< Timer *, void > &rLink)
static VclPtr< reference_type > Create(Arg &&... arg)
Keeps track of misspelled ranges in paragraph.
void SetInvalidRange(size_t nStart, size_t nEnd)
void push_back(const editeng::MisspellRange &rRange)
void ClearWrongs(size_t nStart, size_t nEnd, const ContentNode *pNode)
static bool isVariationSelector(sal_uInt32 nCode)