36#include <osl/diagnose.h>
38#include <com/sun/star/i18n/XBreakIterator.hpp>
40#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
42#include <com/sun/star/i18n/WordType.hpp>
44#include <com/sun/star/i18n/InputSequenceChecker.hpp>
45#include <com/sun/star/i18n/InputSequenceCheckMode.hpp>
46#include <com/sun/star/i18n/ScriptType.hpp>
55#include <unicode/ubidi.h>
69 : mpActiveView {nullptr}
78 , mbIsFormatting {false}
82 , mbUndoEnabled {false}
85 , mbRightToLeft {false}
86 , mbHasMultiLineParas {false}
123 mpViews->push_back( pTextView );
132 TextViews::iterator it = std::find(
mpViews->begin(),
mpViews->end(), pTextView );
202 for (
auto nView =
mpViews->size(); nView; )
204 TextView* pView = (*mpViews)[ --nView ];
260 OUStringBuffer aText;
263 for ( sal_uInt32 nP = 0; nP < nParas; ++nP )
267 const size_t nLines = pTEParaPortion->
GetLines().size();
268 for (
size_t nL = 0; nL < nLines; ++nL )
272 if ( pSep && ( ( (nP+1) < nParas ) || ( (nL+1) < nLines ) ) )
276 return aText.makeStringAndClear();
281 return mpDoc->GetText( nPara );
299 return mpDoc->GetNodes()[ nPara ]->GetText().getLength();
318 bool bDoesChange =
false;
373 std::unique_ptr<TextNode> pNode(
new TextNode( OUString() ));
374 mpDoc->GetNodes().insert(
mpDoc->GetNodes().begin(), std::move(pNode) );
393 OUStringBuffer aText;
397 for ( sal_uInt32 nNode = aSel.
GetStart().
GetPara(); nNode <= nEndPara; ++nNode )
401 sal_Int32 nStartPos = 0;
402 sal_Int32 nEndPos = pNode->
GetText().getLength();
403 if ( nNode == nStartPara )
405 if ( nNode == nEndPara )
408 aText.append(pNode->
GetText().subView(nStartPos, nEndPos-nStartPos));
409 if ( nNode < nEndPara )
412 return aText.makeStringAndClear();
422 pView->ImpSetSelection( aEmptySel );
438 if ( !rText.isEmpty() )
443 pView->ImpSetSelection( aEmptySel );
450 if( rText.isEmpty() )
469 SAL_WARN_IF( !nChars,
"vcl",
"ImpRemoveChars: 0 Chars?!" );
477 const sal_Int32 nStart = rPaM.
GetIndex();
478 const sal_Int32 nEnd = nStart + nChars;
482 if ( ( rAttr.
GetEnd() >= nStart ) && ( rAttr.
GetStart() < nEnd ) )
487 InsertUndo( std::make_unique<TextUndoRemoveChars>(
this, rPaM,
aStr ) );
490 mpDoc->RemoveChars( rPaM, nChars );
496 SAL_WARN_IF( nLeft == nRight,
"vcl",
"ImpConnectParagraphs: connect the very same paragraph ?" );
502 InsertUndo( std::make_unique<TextUndoConnectParas>(
this, nLeft, pLeft->
GetText().getLength() ) );
507 SAL_WARN_IF( !pLeft || !pLeftPortion,
"vcl",
"ImpConnectParagraphs(1): Hidden Portion" );
508 SAL_WARN_IF( !pRight || !pRightPortion,
"vcl",
"ImpConnectParagraphs(2): Hidden Portion" );
510 TextPaM aPaM =
mpDoc->ConnectParagraphs( pLeft, pRight );
534 SAL_WARN_IF( !
mpDoc->IsValidPaM( aStartPaM ),
"vcl",
"ImpDeleteText(1): bad Index" );
535 SAL_WARN_IF( !
mpDoc->IsValidPaM( aEndPaM ),
"vcl",
"ImpDeleteText(2): bad Index" );
537 const sal_uInt32 nStartNode = aStartPaM.
GetPara();
538 sal_uInt32 nEndNode = aEndPaM.
GetPara();
541 for ( sal_uInt32
z = nStartNode+1;
z < nEndNode; ++
z )
547 if ( nStartNode != nEndNode )
551 sal_Int32 nChars = pLeft->
GetText().getLength() - aStartPaM.
GetIndex();
556 SAL_WARN_IF( !pPortion,
"vcl",
"ImpDeleteText(3): bad Index" );
561 nEndNode = nStartNode+1;
569 SAL_WARN_IF( !pPortion,
"vcl",
"ImpDeleteText(4): bad Index" );
581 SAL_WARN_IF( !pPortion,
"vcl",
"ImpDeleteText(5): bad Index" );
592 std::unique_ptr<TextNode> pNode = std::move(
mpDoc->GetNodes()[ nPara ]);
595 mpDoc->GetNodes().erase(
mpDoc->GetNodes().begin() + nPara );
597 InsertUndo( std::make_unique<TextUndoDelPara>(
this, pNode.release(), nPara ) );
608 mxISC = i18n::InputSequenceChecker::create( ::comphelper::getProcessComponentContext() );
620 bool bIsSequenceChecking =
625 if (bIsSequenceChecking)
628 bIsSequenceChecking = xBI.is() && i18n::ScriptType::COMPLEX == xBI->getScriptType( OUString( c ), 0 );
631 return bIsSequenceChecking;
641 SAL_WARN_IF( c ==
'\n',
"vcl",
"InsertText: NewLine!" );
642 SAL_WARN_IF( c ==
'\r',
"vcl",
"InsertText: NewLine!" );
647 bool bDoOverwrite = bOverwrite && ( aPaM.
GetIndex() < pNode->
GetText().getLength() );
649 bool bUndoAction = rCurSel.
HasRange() || bDoOverwrite;
658 else if ( bDoOverwrite )
673 sal_Int32 nTmpPos = aPaM.
GetIndex();
675 i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
679 OUString aOldText(
mpDoc->GetText( aPaM.
GetPara() ).copy(0, nTmpPos) );
682 OUString aNewText( aOldText );
683 xISC->correctInputSequence( aNewText, nTmpPos - 1, c, nCheckMode );
686 const sal_Int32 nOldLen = aOldText.getLength();
687 const sal_Int32 nNewLen = aNewText.getLength();
690 sal_Int32 nChgPos = 0;
691 while ( nChgPos < nOldLen && nChgPos < nNewLen &&
692 pOldTxt[nChgPos] == pNewTxt[nChgPos] )
695 OUString aChgText( aNewText.copy( nChgPos ) );
700 if (!aChgText.isEmpty())
709 if (!xISC->checkInputSequence( aOldText, nTmpPos - 1, c, nCheckMode ))
719 std::unique_ptr<TextUndoInsertChars> pNewUndo(
new TextUndoInsertChars(
this, aPaM, OUString(c) ));
720 bool bTryMerge = !bDoOverwrite && ( c !=
' ' );
728 aPaM =
mpDoc->InsertText( aPaM, c );
752 sal_Int32 nStart = 0;
753 while ( nStart < aText.getLength() )
755 sal_Int32 nEnd = aText.indexOf(
LINE_SEP, nStart );
757 nEnd = aText.getLength();
762 OUString aLine(aText.copy(nStart, nEnd-nStart));
764 InsertUndo( std::make_unique<TextUndoInsertChars>(
this, aPaM, aLine ) );
768 if (aLine.indexOf(
'\t' ) != -1)
771 aPaM =
mpDoc->InsertText( aPaM, aLine );
775 if ( nEnd < aText.getLength() )
778 if ( nEnd == aText.getLength() )
807 bool bFirstParaContentChanged = rPaM.
GetIndex() < pNode->
GetText().getLength();
812 SAL_WARN_IF( !pPortion,
"vcl",
"ImpInsertParaBreak: Hidden Portion" );
823 if ( bFirstParaContentChanged )
842 for ( sal_uInt32 nPortion = 0; nPortion < rPaM.
GetPara(); ++nPortion )
872 sal_Int32 nCurIndex = 0;
876 if ( ( rTmpLine.GetStart() == rPaM.
GetIndex() ) || ( rTmpLine.IsIn( rPaM.
GetIndex(), bSpecial ) ) )
882 nCurIndex = nCurIndex + rTmpLine.
GetLen();
890 pLine = & ( pPortion->
GetLines().back() );
909 SAL_WARN_IF( ( nIndex < pLine->GetStart() ) || (
nIndex > pLine->
GetEnd() ) ,
"vcl",
"ImpGetXPos: Bad parameters!" );
911 bool bDoPreferPortionStart = bPreferPortionStart;
914 bDoPreferPortionStart =
true;
916 bDoPreferPortionStart =
false;
920 sal_Int32 nTextPortionStart = 0;
923 SAL_WARN_IF( ( nTextPortion < pLine->GetStartPortion() ) || ( nTextPortion > pLine->
GetEndPortion() ),
"vcl",
"GetXPos: Portion not in current line!" );
931 if ( nTextPortionStart !=
nIndex )
934 if (
nIndex == ( nTextPortionStart + rPortion.
GetLen() ) )
941 nX += nPortionTextWidth;
948 SAL_WARN_IF( bPreferPortionStart,
"vcl",
"ImpGetXPos: How can we get here!" );
967 nX += nPortionTextWidth - nPosInPortion;
975 nX += nPortionTextWidth;
1005 for ( sal_uInt32 nPortion = 0; nPortion <
mpTEParaPortions->Count(); ++nPortion )
1010 if ( nY > rDocPos.Y() )
1013 Point aPosInPara( rDocPos );
1014 aPosInPara.AdjustY( -nY );
1023 const sal_uInt32 nLastNode =
static_cast<sal_uInt32
>(
mpDoc->GetNodes().size() - 1);
1033 sal_Int32 nCurIndex = 0;
1037 std::vector<TextLine>::size_type nLine;
1038 for ( nLine = 0; nLine < pPortion->
GetLines().
size(); nLine++ )
1042 if ( nY > rPosInPara.Y() )
1049 assert(pLine &&
"ImpFindIndex: pLine ?");
1051 nCurIndex =
GetCharPos( nPortion, nLine, rPosInPara.X() );
1053 if ( nCurIndex && ( nCurIndex == pLine->
GetEnd() ) &&
1054 ( pLine != &( pPortion->
GetLines().back() ) ) )
1069 sal_Int32 nCurIndex = rLine.
GetStart();
1072 if ( nXPos <= nTmpX )
1080 if ( nTmpX > nXPos )
1082 if( rTextPortion.
GetLen() > 1 )
1087 SeekCursor( nPortion, nCurIndex+1, aFont,
nullptr );
1091 nPosInPortion = rTextPortion.
GetWidth() - nPosInPortion;
1097 nCurIndex += rTextPortion.
GetLen();
1126 for (
auto nLine = pPortion->
GetLines().size(); nLine; )
1173 sal_Int32 nTabPos =
mpDoc->GetNodes()[ nPara ]->GetText().indexOf(
'\t', nPortionStart );
1174 SAL_WARN_IF( nTabPos != -1 && nTabPos < (nPortionStart+nLen),
"vcl",
"CalcTextWidth: Tab!" );
1178 SeekCursor( nPara, nPortionStart+1, aFont,
nullptr );
1195 nEnd = nStart + rTextPortion.
GetLen();
1200 nStart += rTextPortion.
GetLen();
1211 return pPPortion->
GetLines().size();
1221 if ( pPPortion && ( nLine < pPPortion->GetLines().
size() ) )
1223 return pPPortion->
GetLines()[ nLine ].GetLen();
1234 SAL_WARN_IF( !pPPortion,
"vcl",
"GetParaHeight: paragraph not found" );
1244 sal_uInt16 nLines = pTEParaPortion->
GetLines().size();
1245 sal_uInt16 nLastInvalid, nFirstInvalid = 0;
1247 for ( nLine = 0; nLine < nLines; nLine++ )
1252 nFirstInvalid = nLine;
1257 for ( nLastInvalid = nFirstInvalid; nLastInvalid < nLines; nLastInvalid++ )
1264 if ( nLastInvalid >= nLines )
1265 nLastInvalid = nLines-1;
1272 return static_cast<sal_uInt32
>(
mpDoc->GetNodes().size());
1319 SAL_WARN_IF( !pNode,
"vcl",
"InsertContent: NULL-Pointer!" );
1323 mpDoc->GetNodes().insert(
mpDoc->GetNodes().begin() + nPara, std::move(pNode) );
1331 SAL_WARN_IF( !pNode,
"vcl",
"SplitContent: Invalid Node!" );
1333 SAL_WARN_IF( nSepPos > pNode->
GetText().getLength(),
"vcl",
"SplitContent: Bad index" );
1335 TextPaM aPaM( nNode, nSepPos );
1353 for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
1364 || pNode->
GetText().isEmpty() )
1446 pView->HideCursor();
1449 const Size aOutSz = pView->GetWindow()->GetOutputSizePixel();
1455 Point aNewPos = pView->GetWindowPos( aClipRect.
TopLeft() );
1457 aNewPos.AdjustX( -(aOutSz.
Width() - 1) );
1458 aClipRect.
SetPos( aNewPos );
1460 pView->GetWindow()->Invalidate( aClipRect );
1474 FormatAndUpdate( mpIdleFormatter->GetView() );
1484 for ( sal_uInt32 nPortion = 0; nPortion <
mpTEParaPortions->Count(); ++nPortion )
1523 : std::numeric_limits<tools::Long>::max();
1526 Size( nWidth, aInvRange.
Len() ) );
1597 bool bLineBreak = !pNode->
GetText().isEmpty();
1610 pTEParaPortion->
GetLines().push_back( aTmpLine );
1620 SAL_WARN_IF( nMaxBreakPos >= pNode->
GetText().getLength(),
"vcl",
"ImpBreakLine: Break?!" );
1622 if ( nMaxBreakPos == -1 )
1623 nMaxBreakPos = pNode->
GetText().getLength() - 1;
1626 i18n::LineBreakHyphenationOptions aHyphOptions(
nullptr, uno::Sequence< beans::PropertyValue >(), 1 );
1628 i18n::LineBreakUserOptions aUserOptions;
1631 aUserOptions.applyForbiddenRules =
true;
1632 aUserOptions.allowPunctuationOutsideMargin =
false;
1633 aUserOptions.allowHyphenateEnglish =
false;
1635 static const css::lang::Locale aDefLocale;
1636 i18n::LineBreakResults aLBR = xBI->getLineBreak( pNode->
GetText(), nMaxBreakPos, aDefLocale, pLine->
GetStart(), aHyphOptions, aUserOptions );
1637 sal_Int32 nBreakPos = aLBR.breakIndex;
1638 if ( nBreakPos <= pLine->GetStart() )
1640 nBreakPos = nMaxBreakPos;
1641 if ( nBreakPos <= pLine->GetStart() )
1646 pLine->
SetEnd( nBreakPos );
1649 if ( nBreakPos >= pLine->
GetStart() &&
1651 pNode->
GetText()[ nBreakPos ] ==
' ' )
1656 SAL_WARN_IF( nBreakPos <= pLine->GetStart(),
"vcl",
"ImpBreakLine: SplitTextPortion at beginning of line?" );
1669 std::size_t nSplitPortion;
1670 sal_Int32 nTmpPos = 0;
1674 for ( nSplitPortion = 0; nSplitPortion < nPortions; nSplitPortion++ )
1678 if ( nTmpPos >=
nPos )
1680 if ( nTmpPos ==
nPos )
1681 return nSplitPortion;
1682 pTextPortion = &rTP;
1687 assert(pTextPortion &&
"SplitTextPortion: position outside of region!");
1689 const sal_Int32 nOverlapp = nTmpPos -
nPos;
1690 pTextPortion->
GetLen() -= nOverlapp;
1695 return nSplitPortion;
1702 SAL_WARN_IF( pNode->
GetText().isEmpty(),
"vcl",
"CreateTextPortions: should not be used for empty paragraphs!" );
1709 for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
1719 for (
const auto& rWritingDirection : rWritingDirections )
1720 aPositions.
insert( rWritingDirection.nStartPos );
1735 sal_Int32 nTabPos = pNode->
GetText().indexOf(
'\t' );
1736 while ( nTabPos != -1 )
1738 aPositions.
insert( nTabPos );
1739 aPositions.
insert( nTabPos + 1 );
1740 nTabPos = pNode->
GetText().indexOf(
'\t', nTabPos+1 );
1746 sal_Int32 nPortionStart = 0;
1747 std::size_t nInvPortion = 0;
1752 nPortionStart += rTmpPortion.
GetLen();
1753 if ( nPortionStart >= nStartPos )
1755 nPortionStart -= rTmpPortion.
GetLen();
1760 OSL_ENSURE(nP < pTEParaPortion->GetTextPortions().
size()
1762 "CreateTextPortions: Nothing to delete!");
1763 if ( nInvPortion && ( nPortionStart+pTEParaPortion->
GetTextPortions()[nInvPortion].GetLen() > nStartPos ) )
1769 nPortionStart -= pTEParaPortion->
GetTextPortions()[nInvPortion].GetLen();
1774 aPositions.
insert( nPortionStart );
1776 aPositionsIt = aPositions.
find( nPortionStart );
1777 SAL_WARN_IF( aPositionsIt == aPositions.
end(),
"vcl",
"CreateTextPortions: nPortionStart not found" );
1779 if ( aPositionsIt != aPositions.
end() )
1782 for ( ++nextIt; nextIt != aPositions.
end(); ++aPositionsIt, ++nextIt )
1788 OSL_ENSURE(pTEParaPortion->
GetTextPortions().
size(),
"CreateTextPortions: No Portions?!");
1795 OSL_ENSURE(nNewChars,
"RecalcTextPortion: Diff == 0");
1798 if ( nNewChars > 0 )
1805 ( nStartPos && ( pNode->
GetText()[ nStartPos - 1 ] ==
'\t' ) ) ||
1808 std::size_t nNewPortionPos = 0;
1814 if ( ( nNewPortionPos < pTEParaPortion->GetTextPortions().
size() ) &&
1818 pTEParaPortion->
GetTextPortions()[nNewPortionPos].GetLen() = nNewChars;
1828 sal_Int32 nPortionStart {0};
1831 rTP.
GetLen() += nNewChars;
1842 std::size_t nPortion = 0;
1844 const sal_Int32 nEnd = nStartPos-nNewChars;
1847 for ( nPortion = 0; nPortion < nPortions; nPortion++ )
1852 SAL_WARN_IF(
nPos > nStartPos,
"vcl",
"RecalcTextPortion: Bad Start!" );
1858 SAL_WARN_IF( !pTP,
"vcl",
"RecalcTextPortion: Portion not found!" );
1866 SAL_WARN_IF( pTP->
GetLen() <= (-nNewChars),
"vcl",
"RecalcTextPortion: Portion too small to shrink!" );
1867 pTP->
GetLen() += nNewChars;
1870 "RecalcTextPortion: none are left!" );
1887 TextPaM const* pSelStart =
nullptr;
1888 TextPaM const* pSelEnd =
nullptr;
1889 if ( pSelection && pSelection->
HasRange() )
1891 const bool bInvers = pSelection->
GetEnd() < pSelection->
GetStart();
1892 pSelStart = !bInvers ? &pSelection->
GetStart() : &pSelection->
GetEnd();
1893 pSelEnd = bInvers ? &pSelection->
GetStart() : &pSelection->
GetEnd();
1907 if ( !pPaintArea || ( ( nY + nParaHeight ) > pPaintArea->
Top() ) )
1911 for (
auto & rLine : pPortion->
GetLines() )
1913 Point aTmpPos( rStartPos.X() + rLine.GetStartX(), nY );
1918 nIndex = rLine.GetStart();
1919 for ( std::size_t
y = rLine.GetStartPortion();
y <= rLine.GetEndPortion();
y++ )
1922 "ImpPaint: Line without Textportion!");
1931 if ( ( aTmpPos.X() + nTxtWidth ) >= 0 )
1933 switch ( rTextPortion.
GetKind() )
1941 else if ( pSelection )
1945 sal_Int32 nTmpIndex =
nIndex;
1946 sal_Int32 nEnd = nTmpIndex + rTextPortion.
GetLen();
1947 Point aPos = aTmpPos;
1953 const TextPaM aTextStart( nPara, nTmpIndex );
1954 const TextPaM aTextEnd( nPara, nEnd );
1955 if ( ( aTextStart < *pSelEnd ) && ( aTextEnd > *pSelStart ) )
1958 if ( aTextStart < *pSelStart )
1960 const sal_Int32 nL = pSelStart->
GetIndex() - nTmpIndex;
1963 aPos.setX( rStartPos.X() +
ImpGetOutputOffset( nPara, &rLine, nTmpIndex, nTmpIndex+nL ) );
1965 nTmpIndex = nTmpIndex + nL;
1969 sal_Int32 nL = nEnd - nTmpIndex;
1970 if ( aTextEnd > *pSelEnd )
1971 nL = pSelEnd->
GetIndex() - nTmpIndex;
1977 aPos.setX( rStartPos.X() +
ImpGetOutputOffset( nPara, &rLine, nTmpIndex, nTmpIndex+nL ) );
1981 nTmpIndex = nTmpIndex + nL;
1985 if ( nTmpIndex < nEnd )
1987 nL = nEnd-nTmpIndex;
1989 aPos.setX( rStartPos.X() +
ImpGetOutputOffset( nPara, &rLine, nTmpIndex, nTmpIndex+nL ) );
2011 if ((aTextStart < *pSelEnd) && (aTextEnd > *pSelStart))
2021 pOutDev->
Erase( aTabArea );
2026 OSL_FAIL(
"ImpPaint: Unknown Portion-Type !" );
2036 if ( pPaintArea && ( nY >= pPaintArea->
Bottom() ) )
2045 if ( pPaintArea && ( nY > pPaintArea->
Bottom() ) )
2058 const auto nOldLineCount = pTEParaPortion->
GetLines().size();
2065 pTEParaPortion->
GetLines().clear();
2068 return nOldLineCount != pTEParaPortion->
GetLines().size();
2072 if ( pTEParaPortion->
GetLines().empty() )
2074 pTEParaPortion->
GetLines().emplace_back( );
2079 const sal_Int32 nInvalidEnd = nInvalidStart + std::abs( nInvalidDiff );
2080 bool bQuickFormat =
false;
2087 bQuickFormat = nInvalidDiff != 0;
2088 if ( nInvalidDiff < 0 )
2095 nPos += rTP.GetLen();
2096 if (
nPos > nInvalidStart &&
nPos < nInvalidEnd )
2098 bQuickFormat =
false;
2113 sal_uInt16 nLine = pTEParaPortion->
GetLines().size()-1;
2114 for ( sal_uInt16 nL = 0; nL <= nLine; nL++ )
2117 if ( rLine.
GetEnd() > nInvalidStart )
2140 sal_Int32 nPortionStart = 0;
2141 sal_Int32 nPortionEnd = 0;
2143 sal_Int32 nTmpPos =
nIndex;
2152 bool bBrokenLine =
false;
2154 while ( ( nTmpWidth <= nXWidth ) && !bEOL && ( nTmpPortion < pTEParaPortion->GetTextPortions().
size() ) )
2156 nPortionStart = nTmpPos;
2159 if ( pNode->
GetText()[ nTmpPos ] ==
'\t' )
2163 pPortion->
GetWidth() = nTmpWidth - nCurPos -
mpDoc->GetLeftMargin();
2165 if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->
GetStartPortion() ) )
2185 nTmpPos += pPortion->
GetLen();
2186 nPortionEnd = nTmpPos;
2191 bool bFixedEnd =
false;
2192 if ( nTmpWidth > nXWidth )
2196 nPortionEnd = nTmpPos;
2197 nTmpPos -= pPortion->
GetLen();
2198 nPortionStart = nTmpPos;
2212 pLine->
SetEnd( nPortionEnd );
2214 "CreateLines: No TextPortions?");
2220 pLine->
SetEnd( nPortionStart );
2223 else if ( bBrokenLine )
2225 pLine->
SetEnd( nPortionStart+1 );
2230 SAL_WARN_IF( (nPortionEnd-nPortionStart) != pPortion->
GetLen(),
"vcl",
"CreateLines: There is a Portion after all?!" );
2232 ImpBreakLine( nPara, pLine, nPortionStart, nRemainingWidth );
2239 for ( std::size_t nTP = pLine->
GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ )
2242 nTextWidth += rTextPortion.
GetWidth();
2248 pLine->
SetStartX(
static_cast<sal_uInt16
>(nSpace / 2) );
2250 pLine->
SetStartX(
static_cast<sal_uInt16
>(nSpace) );
2267 if ( pLine->
GetEnd() < nInvalidStart )
2269 if ( *pLine == aSaveLine )
2276 const sal_Int32 nStart = pLine->
GetStart();
2277 const sal_Int32 nEnd = pLine->
GetEnd();
2279 if ( nStart > nInvalidEnd )
2281 if ( ( ( nStart-nInvalidDiff ) == aSaveLine.
GetStart() ) &&
2282 ( ( nEnd-nInvalidDiff ) == aSaveLine.
GetEnd() ) )
2292 else if ( bQuickFormat && ( nEnd > nInvalidEnd) )
2297 if ( nEnd == ( aSaveLine.
GetEnd() + nInvalidDiff ) )
2313 if ( nLine < pTEParaPortion->GetLines().
size()-1 )
2314 pLine = &( pTEParaPortion->
GetLines()[ ++nLine ] );
2317 nDelFromLine = nLine;
2322 if ( nIndex < pNode->
GetText().getLength() )
2326 pLine = &pTEParaPortion->
GetLines()[nLine];
2343 pTEParaPortion->
GetLines().erase( pTEParaPortion->
GetLines().begin() + nDelFromLine,
2344 pTEParaPortion->
GetLines().end() );
2351 return nOldLineCount != pTEParaPortion->
GetLines().size();
2362 i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->
GetText(), rCursorPos.
GetIndex(),
GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true );
2364 if (aBoundary.startPos > 0 && aBoundary.startPos < pNode->
GetText().getLength() && u_charType(pNode->
GetText()[aBoundary.startPos]) == U_CONNECTOR_PUNCTUATION)
2366 aBoundary.startPos = xBI->getWordBoundary(pNode->
GetText(), aBoundary.startPos - 1,
2367 GetLocale(), css::i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true).startPos;
2369 while (aBoundary.startPos > 0 && u_charType(pNode->
GetText()[aBoundary.startPos - 1]) == U_CONNECTOR_PUNCTUATION)
2371 aBoundary.startPos = std::min(aBoundary.startPos,
2372 xBI->getWordBoundary( pNode->
GetText(), aBoundary.startPos - 2,
2373 GetLocale(), css::i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true).startPos);
2376 if (aBoundary.endPos > 0 && aBoundary.endPos < pNode->
GetText().getLength() && u_charType(pNode->
GetText()[aBoundary.endPos - 1]) == U_CONNECTOR_PUNCTUATION)
2378 aBoundary.endPos = xBI->getWordBoundary(pNode->
GetText(), aBoundary.endPos,
2379 GetLocale(), css::i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true).endPos;
2381 while (aBoundary.endPos < pNode->
GetText().getLength() && u_charType(pNode->
GetText()[aBoundary.endPos]) == U_CONNECTOR_PUNCTUATION)
2383 aBoundary.endPos = xBI->getWordBoundary(pNode->
GetText(), aBoundary.endPos + 1,
2384 GetLocale(), css::i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true).endPos;
2392 *pEndOfWord = aSel.
GetEnd();
2408 const sal_uInt32 nParas =
static_cast<sal_uInt32
>(
mpDoc->GetNodes().size());
2416 OStringBuffer aLine;
2417 bool bDone = rInput.
ReadLine( aLine );
2445 const sal_uInt32 nParas =
static_cast<sal_uInt32
>(
mpDoc->GetNodes().size());
2459 const OUString aText = pNode->
GetText().copy( nStartPos, nEndPos-nStartPos );
2466 if ( nPara >=
mpDoc->GetNodes().size() )
2491 if ( nPara >=
mpDoc->GetNodes().size() )
2497 const sal_Int32 nMax = pNode->
GetText().getLength();
2498 if ( nStart > nMax )
2528 const sal_uInt32 nParas =
static_cast<sal_uInt32
>(
mpDoc->GetNodes().size());
2529 if ( rPaM.
GetPara() >= nParas )
2531 rPaM.
GetPara() = nParas ? nParas-1 : 0;
2548 for (
auto nView =
mpViews->size(); nView; )
2550 TextView* pView = (*mpViews)[ --nView ];
2553 for (
int n = 0;
n <= 1;
n++ )
2556 if ( rPaM.
GetPara() >= nPara )
2569 for (
auto nView =
mpViews->size(); nView; )
2571 TextView* pView = (*mpViews)[ --nView ];
2574 const sal_uInt32 nParas =
static_cast<sal_uInt32
>(
mpDoc->GetNodes().size());
2575 for (
int n = 0;
n <= 1;
n++ )
2580 else if ( rPaM.
GetPara() == nPara )
2583 if ( rPaM.
GetPara() >= nParas )
2597 for (
auto nView =
mpViews->size(); nView; )
2599 TextView* pView = (*mpViews)[ --nView ];
2602 const sal_Int32 nEnd =
nPos + nChars;
2603 for (
int n = 0;
n <= 1;
n++ )
2606 if ( rPaM.
GetPara() == nPara )
2624 for (
auto nView =
mpViews->size(); nView; )
2626 TextView* pView = (*mpViews)[ --nView ];
2629 for (
int n = 0;
n <= 1;
n++ )
2632 if ( rPaM.
GetPara() == nPara )
2651 mpDoc->SetLeftMargin(
n );
2709 UErrorCode nError = U_ZERO_ERROR;
2710 UBiDi* pBidi = ubidi_openSized( aText.getLength(), 0, &nError );
2711 nError = U_ZERO_ERROR;
2713 ubidi_setPara( pBidi,
reinterpret_cast<const UChar *
>(aText.getStr()), aText.getLength(), nBidiLevel,
nullptr, &nError );
2714 nError = U_ZERO_ERROR;
2720 UBiDiLevel nCurrDir;
2724 ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
2726 rInfos.emplace_back( nCurrDir % 2 == 0, nStart, nEnd );
2730 ubidi_close( pBidi );
2734 if ( rInfos.empty() )
2735 rInfos.emplace_back( 0, 0, pParaPortion->
GetNode()->
GetText().getLength() );
2741 bool bRightToLeft =
false;
2744 if ( pNode && !pNode->
GetText().isEmpty() )
2751 for (
const auto& rWritingDirectionInfo : rDirInfos )
2753 if ( rWritingDirectionInfo.nStartPos <=
nPos && rWritingDirectionInfo.nEndPos >=
nPos )
2755 bRightToLeft = !rWritingDirectionInfo.bLeftToRight;
2760 return bRightToLeft;
2781 std::size_t nTmpPortion = nTextPortion+1;
2782 while ( nTmpPortion <= pLine->GetEndPortion() )
2792 nTmpPortion = nTextPortion;
2806 std::size_t nTmpPortion = nTextPortion+1;
2807 while ( nTmpPortion <= pLine->GetEndPortion() )
2817 nTmpPortion = nTextPortion;
2859 sal_Int32 nPortionStart {0};
2866 if ( (
nIndex == nPortionStart ) && (
nIndex == nIndex2 ) )
2873 nX = -nX - rTextPortion.
GetWidth();
const LanguageTag & GetUILanguageTag() const
const StyleSettings & GetStyleSettings() const
static const AllSettings & GetSettings()
Gets the application's settings.
void SetAlpha(sal_uInt8 nAlpha)
sal_Unicode GetCharCode() const
const vcl::KeyCode & GetKeyCode() const
const css::lang::Locale & getLocale(bool bResolveSystem=true) const
css::i18n::ForbiddenCharacters getForbiddenCharacters() const
Some things multiple-inherit from VclAbstractDialog and OutputDevice, so we need to use virtual inher...
const vcl::Font & GetFont() const
sal_Int32 GetTextBreak(const OUString &rStr, tools::Long nTextWidth, sal_Int32 nIndex, sal_Int32 nLen=-1, tools::Long nCharExtra=0, vcl::text::TextLayoutCache const *=nullptr, const SalLayoutGlyphs *pGlyphs=nullptr) const
void SetFont(const vcl::Font &rNewFont)
void DrawRect(const tools::Rectangle &rRect)
tools::Long GetTextWidth(const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, vcl::text::TextLayoutCache const *=nullptr, SalLayoutGlyphs const *const pLayoutCache=nullptr) const
Width of the text.
void SetTextColor(const Color &rColor)
vcl::text::ComplexTextLayoutFlags GetLayoutMode() const
const Color & GetTextColor() const
tools::Long GetTextHeight() const
Height where any character of the current font fits; in logic coordinates.
void DrawText(const Point &rStartPt, const OUString &rStr, sal_Int32 nIndex=0, sal_Int32 nLen=-1, std::vector< tools::Rectangle > *pVector=nullptr, OUString *pDisplayText=nullptr, const SalLayoutGlyphs *pLayoutCache=nullptr)
void SetLayoutMode(vcl::text::ComplexTextLayoutFlags nTextLayoutMode)
const AllSettings & GetSettings() const
virtual vcl::Window * GetOwnerWindow() const
Get the vcl::Window that this OutputDevice belongs to, if any.
const Color & GetFillColor() const
void Broadcast(const SfxHint &rHint)
virtual void EnterListAction(const OUString &rComment, const OUString &rRepeatComment, sal_uInt16 nId, ViewShellId nViewShellId)
virtual void AddUndoAction(std::unique_ptr< SfxUndoAction > pAction, bool bTryMerg=false)
constexpr tools::Long Width() const
const Color & GetHighlightColor() const
const Color & GetHighlightTextColor() const
bool WriteLine(std::string_view rStr)
bool ReadLine(OStringBuffer &rStr, sal_Int32 nMaxBytesToRead=0xFFFE)
rtl_TextEncoding GetStreamCharSet() const
bool IsCTLFontEnabled() const
bool IsCTLSequenceCheckingRestricted() const
bool IsCTLSequenceChecking() const
bool IsCTLSequenceCheckingTypeAndReplace() const
void SetNotSimpleInvalid()
void MarkInvalid(sal_Int32 nStart, sal_Int32 nDiff)
sal_Int32 GetInvalidDiff() const
void CorrectValuesBehindLastFormattedLine(sal_uInt16 nLastFormattedLine)
std::vector< TEWritingDirectionInfo > & GetWritingDirectionInfos()
TETextPortionList & GetTextPortions()
bool IsSimpleInvalid() const
void MarkSelectionInvalid(sal_Int32 nStart)
std::vector< TextLine > & GetLines()
sal_Int32 GetInvalidPosStart() const
TextNode * GetNode() const
std::size_t FindPortion(sal_Int32 nCharPos, sal_Int32 &rPortionStart, bool bPreferStartingPortion=false)
std::vector< TETextPortion >::iterator insert(const std::vector< TETextPortion >::iterator &aIter, const TETextPortion &rTP)
std::vector< TETextPortion >::iterator begin()
std::vector< TETextPortion >::iterator erase(const std::vector< TETextPortion >::iterator &aIter)
static constexpr auto npos
void DeleteFromPortion(std::size_t nDelFrom)
void push_back(const TETextPortion &aTP)
bool IsRightToLeft() const
void SetRightToLeft(bool b)
const Color & GetColor() const
virtual void SetFont(vcl::Font &rFont) const =0
TextCharAttrib * FindAttrib(sal_uInt16 nWhich, sal_Int32 nPos)
void InsertAttrib(std::unique_ptr< TextCharAttrib > pAttrib)
bool HasBoundingAttrib(sal_Int32 nBound)
const TextCharAttrib & GetAttrib(sal_uInt16 n) const
void DeleteEmptyAttribs()
const TextAttrib & GetAttr() const
sal_Int32 GetStart() const
SAL_DLLPRIVATE css::uno::Reference< css::i18n::XExtendedInputSequenceChecker > const & GetInputSequenceChecker()
std::unique_ptr< TextDoc > mpDoc
bool GetUpdateMode() const
void RemoveView(TextView *pTextView)
void ImpCharsRemoved(sal_uInt32 nPara, sal_Int32 nPos, sal_Int32 nChars)
bool Read(SvStream &rInput, const TextSelection *pSel=nullptr)
void ImpBreakLine(sal_uInt32 nPara, TextLine *pLine, sal_Int32 nPortionStart, tools::Long nRemainingWidth)
void SetRightToLeft(bool bR2L)
SfxUndoManager & GetUndoManager()
css::lang::Locale maLocale
tools::Long CalcTextWidth()
void CreateTextPortions(sal_uInt32 nPara, sal_Int32 nStartPos)
OUString GetTextLines(LineEnd aSeparator=LINEEND_LF) const
TextView * GetActiveView() const
friend class TextUndoInsertChars
void UpdateViews(TextView *pCurView=nullptr)
sal_Int32 GetTextLen() const
TextPaM GetPaM(const Point &rDocPos)
css::uno::Reference< css::i18n::XExtendedInputSequenceChecker > mxISC
void CreateAndInsertEmptyLine(sal_uInt32 nPara)
SAL_DLLPRIVATE bool IsInputSequenceCheckingRequired(sal_Unicode c, const TextSelection &rCurSel) const
void CheckIdleFormatter()
bool HasUndoManager() const
OUString GetWord(const TextPaM &rCursorPos, TextPaM *pStartOfWord=nullptr, TextPaM *pEndOfWord=nullptr)
static bool IsSimpleCharInput(const KeyEvent &rKeyEvent)
tools::Rectangle PaMtoEditCursor(const TextPaM &rPaM, bool bSpecial=false)
Range GetInvalidYOffsets(sal_uInt32 nPortion)
const TextCharAttrib * FindCharAttrib(const TextPaM &rPaM, sal_uInt16 nWhich) const
std::unique_ptr< TextViews > mpViews
TextPaM SplitContent(sal_uInt32 nNode, sal_Int32 nSepPos)
tools::Rectangle maInvalidRect
tools::Long GetTextHeight() const
void Write(SvStream &rOutput)
std::size_t SplitTextPortion(sal_uInt32 nPara, sal_Int32 nPos)
void ImpParagraphRemoved(sal_uInt32 nPara)
void SetLeftMargin(sal_uInt16 n)
sal_uInt16 GetLineCount(sal_uInt32 nParagraph) const
void SeekCursor(sal_uInt32 nNode, sal_Int32 nPos, vcl::Font &rFont, OutputDevice *pOutDev)
tools::Long mnCurTextWidth
VclPtr< OutputDevice > mpRefDev
tools::Rectangle GetEditCursor(const TextPaM &rPaM, bool bSpecial, bool bPreferPortionStart=false)
LocaleDataWrapper * ImpGetLocaleDataWrapper()
void RemoveAttribs(sal_uInt32 nPara)
void Draw(OutputDevice *pDev, const Point &rPos)
tools::Long mnCurTextHeight
void SetLocale(const css::lang::Locale &rLocale)
void ValidatePaM(TextPaM &rPaM) const
tools::Long ImpGetPortionXOffset(sal_uInt32 nPara, TextLine const *pLine, std::size_t nTextPortion)
void SetActiveView(TextView *pView)
bool ImpGetRightToLeft(sal_uInt32 nPara, sal_Int32 nPos)
sal_Int32 ImpFindIndex(sal_uInt32 nPortion, const Point &rPosInPara)
sal_Int32 GetLineLen(sal_uInt32 nParagraph, sal_uInt16 nLine) const
tools::Long ImpGetOutputOffset(sal_uInt32 nPara, TextLine *pLine, sal_Int32 nIndex, sal_Int32 nIndex2)
virtual ~TextEngine() override
void SetMaxTextLen(sal_Int32 nLen)
TextView * GetView(sal_uInt16 nView) const
void GetTextPortionRange(const TextPaM &rPaM, sal_Int32 &nStart, sal_Int32 &nEnd)
void SetTextAlign(TxtAlign eAlign)
TxtAlign ImpGetAlign() const
TextPaM ConnectContents(sal_uInt32 nLeftNode)
void InsertContent(std::unique_ptr< TextNode > pNode, sal_uInt32 nPara)
TextPaM ImpInsertText(const TextSelection &rSel, sal_Unicode c, bool bOverwrite=false)
void FormatAndUpdate(TextView *pCurView=nullptr)
void ReplaceText(const TextSelection &rSel, const OUString &rText)
TextPaM ImpInsertParaBreak(const TextSelection &rTextSelection)
void ImpParagraphInserted(sal_uInt32 nPara)
void RecalcTextPortion(sal_uInt32 nPara, sal_Int32 nStartPos, sal_Int32 nNewChars)
TextPaM ImpConnectParagraphs(sal_uInt32 nLeft, sal_uInt32 nRight)
void InsertView(TextView *pTextView)
std::unique_ptr< LocaleDataWrapper > mpLocaleDataWrapper
std::unique_ptr< TEParaPortions > mpTEParaPortions
void SetMaxTextWidth(tools::Long nWidth)
void InsertUndo(std::unique_ptr< TextUndo > pUndo, bool bTryMerge=false)
bool IsRightToLeft() const
sal_Int32 GetCharPos(sal_uInt32 nPara, std::vector< TextLine >::size_type nLine, tools::Long nDocPosX)
void ImpCharsInserted(sal_uInt32 nPara, sal_Int32 nPos, sal_Int32 nChars)
OUString GetText(LineEnd aSeparator=LINEEND_LF) const
TextPaM ImpDeleteText(const TextSelection &rSel)
sal_uInt32 GetParagraphCount() const
static bool DoesKeyChangeText(const KeyEvent &rKeyEvent)
friend class TextUndoManager
tools::Long ImpGetXPos(sal_uInt32 nPara, TextLine *pLine, sal_Int32 nIndex, bool bPreferPortionStart=false)
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIterator()
void CursorMoved(sal_uInt32 nNode)
void SetAttrib(const TextAttrib &rAttr, sal_uInt32 nPara, sal_Int32 nStart, sal_Int32 nEnd)
void EnableUndo(bool bEnable)
void ImpRemoveChars(const TextPaM &rPaM, sal_Int32 nChars)
bool IsUndoEnabled() const
std::unique_ptr< TEIMEInfos > mpIMEInfos
bool CreateLines(sal_uInt32 nPara)
void ImpRemoveParagraph(sal_uInt32 nPara)
sal_uInt16 GetViewCount() const
const TextAttrib * FindAttrib(const TextPaM &rPaM, sal_uInt16 nWhich) const
css::lang::Locale const & GetLocale()
void IdleFormatAndUpdate(TextView *pCurView, sal_uInt16 nMaxTimerRestarts=5)
void UndoActionStart(sal_uInt16 nId=0)
void SetUpdateMode(bool bUpdate)
tools::Long CalcParaHeight(sal_uInt32 nParagraph) const
css::uno::Reference< css::i18n::XBreakIterator > mxBreakIterator
tools::Long CalcTextHeight() const
const vcl::Font & GetFont() const
static void ImpInitLayoutMode(OutputDevice *pOutDev)
void ImpInitWritingDirections(sal_uInt32 nPara)
void ImpPaint(OutputDevice *pOut, const Point &rStartPos, tools::Rectangle const *pPaintArea, TextSelection const *pSelection=nullptr)
tools::Long mnMaxTextWidth
void SetText(const OUString &rStr)
std::unique_ptr< TextUndoManager > mpUndoManager
void ValidateSelection(TextSelection &rSel) const
std::unique_ptr< IdleFormatter > mpIdleFormatter
bool IsFormatting() const
void SetFont(const vcl::Font &rFont)
void SetEndPortion(std::size_t n)
void SetStartPortion(std::size_t n)
std::size_t GetEndPortion() const
sal_Int32 GetStart() const
void SetStart(sal_Int32 n)
std::size_t GetStartPortion() const
const TextCharAttribList & GetCharAttribs() const
const OUString & GetText() const
sal_uInt32 GetPara() const
sal_Int32 GetIndex() const
const TextPaM & GetStart() const
const TextPaM & GetEnd() const
void SetSelection(const TextSelection &rNewSel)
void ShowCursor(bool bGotoCursor=true, bool bForceVisCursor=true)
vcl::Window * GetWindow() const
const TextSelection & GetSelection() const
bool IsAutoScroll() const
void ImpSetSelection(const TextSelection &rSelection)
static VclPtr< reference_type > Create(Arg &&... arg)
A construction helper for VclPtr.
std::vector< Value >::const_iterator const_iterator
const_iterator find(const Value &x) const
const_iterator end() const
std::pair< const_iterator, bool > insert(Value &&x)
void SetTransparent(bool bTransparent)
void SetFillColor(const Color &)
void SetColor(const Color &)
const OUString & GetFamilyName() const
void SetUnderline(FontLineStyle)
const Color & GetColor() const
void SetAlignment(TextAlign)
const Color & GetFillColor() const
sal_uInt16 GetCode() const
sal_uInt16 GetModifier() const
KeyFuncType GetFunction() const
void SetInputContext(const InputContext &rInputContext)
bool IsPaintTransparent() const
constexpr ::Color COL_RED(0x80, 0x00, 0x00)
constexpr ::Color COL_LIGHTGRAY(0xC0, 0xC0, 0xC0)
constexpr ::Color COL_BLACK(0x00, 0x00, 0x00)
constexpr ::Color COL_TRANSPARENT(ColorTransparency, 0xFF, 0xFF, 0xFF, 0xFF)
constexpr sal_uInt16 KEY_RETURN
constexpr sal_uInt16 KEY_MOD2
constexpr sal_uInt16 KEY_MOD1
constexpr sal_uInt16 KEY_TAB
constexpr sal_uInt16 KEY_DELETE
constexpr sal_uInt16 KEY_BACKSPACE
TOOLS_DLLPUBLIC OString convertLineEnd(const OString &rIn, LineEnd eLineEnd)
#define LINK(Instance, Class, Member)
#define SAL_WARN_IF(condition, area, stream)
double getLength(const B2DPolygon &rCandidate)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
VCL_DLLPUBLIC css::uno::Reference< css::i18n::XBreakIterator > CreateBreakIterator()
IMPL_LINK_NOARG(TextEngine, IdleFormatHdl, Timer *, void)
static const sal_Unicode * static_getLineEndText(LineEnd aLineEnd)
const sal_Unicode static_aLFText[]
const sal_Unicode static_aCRText[]
const sal_Unicode static_aCRLFText[]
std::vector< TextView * > TextViews
#define TEXTATTR_FONTCOLOR