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() );
618 bool bIsSequenceChecking =
623 if (bIsSequenceChecking)
626 bIsSequenceChecking = xBI.is() && i18n::ScriptType::COMPLEX == xBI->getScriptType( OUString( c ), 0 );
629 return bIsSequenceChecking;
639 SAL_WARN_IF( c ==
'\n',
"vcl",
"InsertText: NewLine!" );
640 SAL_WARN_IF( c ==
'\r',
"vcl",
"InsertText: NewLine!" );
645 bool bDoOverwrite = bOverwrite && ( aPaM.
GetIndex() < pNode->
GetText().getLength() );
647 bool bUndoAction = rCurSel.
HasRange() || bDoOverwrite;
656 else if ( bDoOverwrite )
670 sal_Int32 nTmpPos = aPaM.
GetIndex();
672 i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC;
676 OUString aOldText(
mpDoc->GetText( aPaM.
GetPara() ).copy(0, nTmpPos) );
679 OUString aNewText( aOldText );
680 xISC->correctInputSequence( aNewText, nTmpPos - 1, c, nCheckMode );
683 const sal_Int32 nOldLen = aOldText.getLength();
684 const sal_Int32 nNewLen = aNewText.getLength();
687 sal_Int32 nChgPos = 0;
688 while ( nChgPos < nOldLen && nChgPos < nNewLen &&
689 pOldTxt[nChgPos] == pNewTxt[nChgPos] )
692 OUString aChgText( aNewText.copy( nChgPos ) );
697 if (!aChgText.isEmpty())
706 if (!xISC->checkInputSequence( aOldText, nTmpPos - 1, c, nCheckMode ))
716 std::unique_ptr<TextUndoInsertChars> pNewUndo(
new TextUndoInsertChars(
this, aPaM, OUString(c) ));
717 bool bTryMerge = !bDoOverwrite && ( c !=
' ' );
725 aPaM =
mpDoc->InsertText( aPaM, c );
749 sal_Int32 nStart = 0;
750 while ( nStart < aText.getLength() )
752 sal_Int32 nEnd = aText.indexOf(
LINE_SEP, nStart );
754 nEnd = aText.getLength();
759 OUString aLine(aText.copy(nStart, nEnd-nStart));
761 InsertUndo( std::make_unique<TextUndoInsertChars>(
this, aPaM, aLine ) );
765 if (aLine.indexOf(
'\t' ) != -1)
768 aPaM =
mpDoc->InsertText( aPaM, aLine );
772 if ( nEnd < aText.getLength() )
775 if ( nEnd == aText.getLength() )
804 bool bFirstParaContentChanged = rPaM.
GetIndex() < pNode->
GetText().getLength();
809 SAL_WARN_IF( !pPortion,
"vcl",
"ImpInsertParaBreak: Hidden Portion" );
820 if ( bFirstParaContentChanged )
839 for ( sal_uInt32 nPortion = 0; nPortion < rPaM.
GetPara(); ++nPortion )
869 sal_Int32 nCurIndex = 0;
873 if ( ( rTmpLine.GetStart() == rPaM.
GetIndex() ) || ( rTmpLine.IsIn( rPaM.
GetIndex(), bSpecial ) ) )
879 nCurIndex = nCurIndex + rTmpLine.
GetLen();
887 pLine = & ( pPortion->
GetLines().back() );
906 SAL_WARN_IF( ( nIndex < pLine->GetStart() ) || (
nIndex > pLine->
GetEnd() ) ,
"vcl",
"ImpGetXPos: Bad parameters!" );
908 bool bDoPreferPortionStart = bPreferPortionStart;
911 bDoPreferPortionStart =
true;
913 bDoPreferPortionStart =
false;
917 sal_Int32 nTextPortionStart = 0;
920 SAL_WARN_IF( ( nTextPortion < pLine->GetStartPortion() ) || ( nTextPortion > pLine->
GetEndPortion() ),
"vcl",
"GetXPos: Portion not in current line!" );
928 if ( nTextPortionStart !=
nIndex )
931 if (
nIndex == ( nTextPortionStart + rPortion.
GetLen() ) )
938 nX += nPortionTextWidth;
945 SAL_WARN_IF( bPreferPortionStart,
"vcl",
"ImpGetXPos: How can we get here!" );
964 nX += nPortionTextWidth - nPosInPortion;
972 nX += nPortionTextWidth;
1002 for ( sal_uInt32 nPortion = 0; nPortion <
mpTEParaPortions->Count(); ++nPortion )
1007 if ( nY > rDocPos.
Y() )
1010 Point aPosInPara( rDocPos );
1020 const sal_uInt32 nLastNode =
static_cast<sal_uInt32
>(
mpDoc->GetNodes().size() - 1);
1030 sal_Int32 nCurIndex = 0;
1034 std::vector<TextLine>::size_type nLine;
1035 for ( nLine = 0; nLine < pPortion->
GetLines().
size(); nLine++ )
1039 if ( nY > rPosInPara.
Y() )
1046 assert(pLine &&
"ImpFindIndex: pLine ?");
1048 nCurIndex =
GetCharPos( nPortion, nLine, rPosInPara.
X() );
1050 if ( nCurIndex && ( nCurIndex == pLine->
GetEnd() ) &&
1051 ( pLine != &( pPortion->
GetLines().back() ) ) )
1066 sal_Int32 nCurIndex = rLine.
GetStart();
1069 if ( nXPos <= nTmpX )
1077 if ( nTmpX > nXPos )
1079 if( rTextPortion.
GetLen() > 1 )
1084 SeekCursor( nPortion, nCurIndex+1, aFont,
nullptr );
1088 nPosInPortion = rTextPortion.
GetWidth() - nPosInPortion;
1094 nCurIndex += rTextPortion.
GetLen();
1123 for (
auto nLine = pPortion->
GetLines().size(); nLine; )
1170 sal_Int32 nTabPos =
mpDoc->GetNodes()[ nPara ]->GetText().indexOf(
'\t', nPortionStart );
1171 SAL_WARN_IF( nTabPos != -1 && nTabPos < (nPortionStart+nLen),
"vcl",
"CalcTextWidth: Tab!" );
1175 SeekCursor( nPara, nPortionStart+1, aFont,
nullptr );
1192 nEnd = nStart + rTextPortion.
GetLen();
1197 nStart += rTextPortion.
GetLen();
1208 return pPPortion->
GetLines().size();
1218 if ( pPPortion && ( nLine < pPPortion->GetLines().
size() ) )
1220 return pPPortion->
GetLines()[ nLine ].GetLen();
1231 SAL_WARN_IF( !pPPortion,
"vcl",
"GetParaHeight: paragraph not found" );
1241 sal_uInt16 nLines = pTEParaPortion->
GetLines().size();
1242 sal_uInt16 nLastInvalid, nFirstInvalid = 0;
1244 for ( nLine = 0; nLine < nLines; nLine++ )
1249 nFirstInvalid = nLine;
1254 for ( nLastInvalid = nFirstInvalid; nLastInvalid < nLines; nLastInvalid++ )
1261 if ( nLastInvalid >= nLines )
1262 nLastInvalid = nLines-1;
1269 return static_cast<sal_uInt32
>(
mpDoc->GetNodes().size());
1316 SAL_WARN_IF( !pNode,
"vcl",
"InsertContent: NULL-Pointer!" );
1320 mpDoc->GetNodes().insert(
mpDoc->GetNodes().begin() + nPara, std::move(pNode) );
1328 SAL_WARN_IF( !pNode,
"vcl",
"SplitContent: Invalid Node!" );
1330 SAL_WARN_IF( nSepPos > pNode->
GetText().getLength(),
"vcl",
"SplitContent: Bad index" );
1332 TextPaM aPaM( nNode, nSepPos );
1350 for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
1361 || pNode->
GetText().isEmpty() )
1443 pView->HideCursor();
1446 const Size aOutSz = pView->GetWindow()->GetOutputSizePixel();
1452 Point aNewPos = pView->GetWindowPos( aClipRect.
TopLeft() );
1455 aClipRect.
SetPos( aNewPos );
1457 pView->GetWindow()->Invalidate( aClipRect );
1471 FormatAndUpdate( mpIdleFormatter->GetView() );
1481 for ( sal_uInt32 nPortion = 0; nPortion <
mpTEParaPortions->Count(); ++nPortion )
1520 : std::numeric_limits<tools::Long>::max();
1523 Size( nWidth, aInvRange.
Len() ) );
1594 bool bLineBreak = !pNode->
GetText().isEmpty();
1607 pTEParaPortion->
GetLines().push_back( aTmpLine );
1617 SAL_WARN_IF( nMaxBreakPos >= pNode->
GetText().getLength(),
"vcl",
"ImpBreakLine: Break?!" );
1619 if ( nMaxBreakPos == -1 )
1620 nMaxBreakPos = pNode->
GetText().getLength() - 1;
1623 i18n::LineBreakHyphenationOptions aHyphOptions(
nullptr, uno::Sequence< beans::PropertyValue >(), 1 );
1625 i18n::LineBreakUserOptions aUserOptions;
1628 aUserOptions.applyForbiddenRules =
true;
1629 aUserOptions.allowPunctuationOutsideMargin =
false;
1630 aUserOptions.allowHyphenateEnglish =
false;
1632 static const css::lang::Locale aDefLocale;
1633 i18n::LineBreakResults aLBR = xBI->getLineBreak( pNode->
GetText(), nMaxBreakPos, aDefLocale, pLine->
GetStart(), aHyphOptions, aUserOptions );
1634 sal_Int32 nBreakPos = aLBR.breakIndex;
1635 if ( nBreakPos <= pLine->GetStart() )
1637 nBreakPos = nMaxBreakPos;
1638 if ( nBreakPos <= pLine->GetStart() )
1643 pLine->
SetEnd( nBreakPos );
1646 if ( nBreakPos >= pLine->
GetStart() &&
1648 pNode->
GetText()[ nBreakPos ] ==
' ' )
1653 SAL_WARN_IF( nBreakPos <= pLine->GetStart(),
"vcl",
"ImpBreakLine: SplitTextPortion at beginning of line?" );
1666 std::size_t nSplitPortion;
1667 sal_Int32 nTmpPos = 0;
1671 for ( nSplitPortion = 0; nSplitPortion < nPortions; nSplitPortion++ )
1675 if ( nTmpPos >=
nPos )
1677 if ( nTmpPos ==
nPos )
1678 return nSplitPortion;
1679 pTextPortion = &rTP;
1684 assert(pTextPortion &&
"SplitTextPortion: position outside of region!");
1686 const sal_Int32 nOverlapp = nTmpPos -
nPos;
1687 pTextPortion->
GetLen() -= nOverlapp;
1692 return nSplitPortion;
1699 SAL_WARN_IF( pNode->
GetText().isEmpty(),
"vcl",
"CreateTextPortions: should not be used for empty paragraphs!" );
1706 for ( sal_uInt16 nAttr = 0; nAttr < nAttribs; nAttr++ )
1716 for (
const auto& rWritingDirection : rWritingDirections )
1717 aPositions.
insert( rWritingDirection.nStartPos );
1732 sal_Int32 nTabPos = pNode->
GetText().indexOf(
'\t' );
1733 while ( nTabPos != -1 )
1735 aPositions.
insert( nTabPos );
1736 aPositions.
insert( nTabPos + 1 );
1737 nTabPos = pNode->
GetText().indexOf(
'\t', nTabPos+1 );
1743 sal_Int32 nPortionStart = 0;
1744 std::size_t nInvPortion = 0;
1749 nPortionStart += rTmpPortion.
GetLen();
1750 if ( nPortionStart >= nStartPos )
1752 nPortionStart -= rTmpPortion.
GetLen();
1757 OSL_ENSURE(nP < pTEParaPortion->GetTextPortions().
size()
1759 "CreateTextPortions: Nothing to delete!");
1760 if ( nInvPortion && ( nPortionStart+pTEParaPortion->
GetTextPortions()[nInvPortion].GetLen() > nStartPos ) )
1766 nPortionStart -= pTEParaPortion->
GetTextPortions()[nInvPortion].GetLen();
1771 aPositions.
insert( nPortionStart );
1773 aPositionsIt = aPositions.
find( nPortionStart );
1774 SAL_WARN_IF( aPositionsIt == aPositions.
end(),
"vcl",
"CreateTextPortions: nPortionStart not found" );
1776 if ( aPositionsIt != aPositions.
end() )
1779 for ( ++nextIt; nextIt != aPositions.
end(); ++aPositionsIt, ++nextIt )
1785 OSL_ENSURE(pTEParaPortion->
GetTextPortions().
size(),
"CreateTextPortions: No Portions?!");
1792 OSL_ENSURE(nNewChars,
"RecalcTextPortion: Diff == 0");
1795 if ( nNewChars > 0 )
1802 ( nStartPos && ( pNode->
GetText()[ nStartPos - 1 ] ==
'\t' ) ) ||
1805 std::size_t nNewPortionPos = 0;
1811 if ( ( nNewPortionPos < pTEParaPortion->GetTextPortions().
size() ) &&
1815 pTEParaPortion->
GetTextPortions()[nNewPortionPos].GetLen() = nNewChars;
1825 sal_Int32 nPortionStart {0};
1828 rTP.
GetLen() += nNewChars;
1839 std::size_t nPortion = 0;
1841 const sal_Int32 nEnd = nStartPos-nNewChars;
1844 for ( nPortion = 0; nPortion < nPortions; nPortion++ )
1849 SAL_WARN_IF(
nPos > nStartPos,
"vcl",
"RecalcTextPortion: Bad Start!" );
1855 SAL_WARN_IF( !pTP,
"vcl",
"RecalcTextPortion: Portion not found!" );
1863 SAL_WARN_IF( pTP->
GetLen() <= (-nNewChars),
"vcl",
"RecalcTextPortion: Portion too small to shrink!" );
1864 pTP->
GetLen() += nNewChars;
1867 "RecalcTextPortion: none are left!" );
1884 TextPaM const* pSelStart =
nullptr;
1885 TextPaM const* pSelEnd =
nullptr;
1886 if ( pSelection && pSelection->
HasRange() )
1888 const bool bInvers = pSelection->
GetEnd() < pSelection->
GetStart();
1889 pSelStart = !bInvers ? &pSelection->
GetStart() : &pSelection->
GetEnd();
1890 pSelEnd = bInvers ? &pSelection->
GetStart() : &pSelection->
GetEnd();
1904 if ( !pPaintArea || ( ( nY + nParaHeight ) > pPaintArea->
Top() ) )
1908 for (
auto & rLine : pPortion->
GetLines() )
1910 Point aTmpPos( rStartPos.
X() + rLine.GetStartX(), nY );
1915 nIndex = rLine.GetStart();
1916 for ( std::size_t
y = rLine.GetStartPortion();
y <= rLine.GetEndPortion();
y++ )
1919 "ImpPaint: Line without Textportion!");
1928 if ( ( aTmpPos.
X() + nTxtWidth ) >= 0 )
1930 switch ( rTextPortion.
GetKind() )
1938 else if ( pSelection )
1942 sal_Int32 nTmpIndex =
nIndex;
1943 sal_Int32 nEnd = nTmpIndex + rTextPortion.
GetLen();
1944 Point aPos = aTmpPos;
1950 const TextPaM aTextStart( nPara, nTmpIndex );
1951 const TextPaM aTextEnd( nPara, nEnd );
1952 if ( ( aTextStart < *pSelEnd ) && ( aTextEnd > *pSelStart ) )
1955 if ( aTextStart < *pSelStart )
1957 const sal_Int32 nL = pSelStart->
GetIndex() - nTmpIndex;
1962 nTmpIndex = nTmpIndex + nL;
1966 sal_Int32 nL = nEnd - nTmpIndex;
1967 if ( aTextEnd > *pSelEnd )
1968 nL = pSelEnd->
GetIndex() - nTmpIndex;
1978 nTmpIndex = nTmpIndex + nL;
1982 if ( nTmpIndex < nEnd )
1984 nL = nEnd-nTmpIndex;
2008 if ((aTextStart < *pSelEnd) && (aTextEnd > *pSelStart))
2018 pOutDev->
Erase( aTabArea );
2023 OSL_FAIL(
"ImpPaint: Unknown Portion-Type !" );
2033 if ( pPaintArea && ( nY >= pPaintArea->
Bottom() ) )
2042 if ( pPaintArea && ( nY > pPaintArea->
Bottom() ) )
2055 const auto nOldLineCount = pTEParaPortion->
GetLines().size();
2062 pTEParaPortion->
GetLines().clear();
2065 return nOldLineCount != pTEParaPortion->
GetLines().size();
2069 if ( pTEParaPortion->
GetLines().empty() )
2071 pTEParaPortion->
GetLines().emplace_back( );
2076 const sal_Int32 nInvalidEnd = nInvalidStart + std::abs( nInvalidDiff );
2077 bool bQuickFormat =
false;
2084 bQuickFormat = nInvalidDiff != 0;
2085 if ( nInvalidDiff < 0 )
2092 nPos += rTP.GetLen();
2093 if (
nPos > nInvalidStart &&
nPos < nInvalidEnd )
2095 bQuickFormat =
false;
2110 sal_uInt16 nLine = pTEParaPortion->
GetLines().size()-1;
2111 for ( sal_uInt16 nL = 0; nL <= nLine; nL++ )
2114 if ( rLine.
GetEnd() > nInvalidStart )
2137 sal_Int32 nPortionStart = 0;
2138 sal_Int32 nPortionEnd = 0;
2140 sal_Int32 nTmpPos =
nIndex;
2149 bool bBrokenLine =
false;
2151 while ( ( nTmpWidth <= nXWidth ) && !bEOL && ( nTmpPortion < pTEParaPortion->GetTextPortions().
size() ) )
2153 nPortionStart = nTmpPos;
2156 if ( pNode->
GetText()[ nTmpPos ] ==
'\t' )
2160 pPortion->
GetWidth() = nTmpWidth - nCurPos -
mpDoc->GetLeftMargin();
2162 if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->
GetStartPortion() ) )
2182 nTmpPos += pPortion->
GetLen();
2183 nPortionEnd = nTmpPos;
2188 bool bFixedEnd =
false;
2189 if ( nTmpWidth > nXWidth )
2193 nPortionEnd = nTmpPos;
2194 nTmpPos -= pPortion->
GetLen();
2195 nPortionStart = nTmpPos;
2209 pLine->
SetEnd( nPortionEnd );
2211 "CreateLines: No TextPortions?");
2217 pLine->
SetEnd( nPortionStart );
2220 else if ( bBrokenLine )
2222 pLine->
SetEnd( nPortionStart+1 );
2227 SAL_WARN_IF( (nPortionEnd-nPortionStart) != pPortion->
GetLen(),
"vcl",
"CreateLines: There is a Portion after all?!" );
2229 ImpBreakLine( nPara, pLine, nPortionStart, nRemainingWidth );
2236 for ( std::size_t nTP = pLine->
GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ )
2239 nTextWidth += rTextPortion.
GetWidth();
2245 pLine->
SetStartX(
static_cast<sal_uInt16
>(nSpace / 2) );
2247 pLine->
SetStartX(
static_cast<sal_uInt16
>(nSpace) );
2264 if ( pLine->
GetEnd() < nInvalidStart )
2266 if ( *pLine == aSaveLine )
2273 const sal_Int32 nStart = pLine->
GetStart();
2274 const sal_Int32 nEnd = pLine->
GetEnd();
2276 if ( nStart > nInvalidEnd )
2278 if ( ( ( nStart-nInvalidDiff ) == aSaveLine.
GetStart() ) &&
2279 ( ( nEnd-nInvalidDiff ) == aSaveLine.
GetEnd() ) )
2289 else if ( bQuickFormat && ( nEnd > nInvalidEnd) )
2294 if ( nEnd == ( aSaveLine.
GetEnd() + nInvalidDiff ) )
2310 if ( nLine < pTEParaPortion->GetLines().
size()-1 )
2311 pLine = &( pTEParaPortion->
GetLines()[ ++nLine ] );
2314 nDelFromLine = nLine;
2319 if ( nIndex < pNode->
GetText().getLength() )
2323 pLine = &pTEParaPortion->
GetLines()[nLine];
2340 pTEParaPortion->
GetLines().erase( pTEParaPortion->
GetLines().begin() + nDelFromLine,
2341 pTEParaPortion->
GetLines().end() );
2348 return nOldLineCount != pTEParaPortion->
GetLines().size();
2359 i18n::Boundary aBoundary = xBI->getWordBoundary( pNode->
GetText(), rCursorPos.
GetIndex(),
GetLocale(), i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true );
2361 if (aBoundary.startPos > 0 && aBoundary.startPos < pNode->
GetText().getLength() && u_charType(pNode->
GetText()[aBoundary.startPos]) == U_CONNECTOR_PUNCTUATION)
2363 aBoundary.startPos = xBI->getWordBoundary(pNode->
GetText(), aBoundary.startPos - 1,
2364 GetLocale(), css::i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true).startPos;
2366 while (aBoundary.startPos > 0 && u_charType(pNode->
GetText()[aBoundary.startPos - 1]) == U_CONNECTOR_PUNCTUATION)
2368 aBoundary.startPos = std::min(aBoundary.startPos,
2369 xBI->getWordBoundary( pNode->
GetText(), aBoundary.startPos - 2,
2370 GetLocale(), css::i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true).startPos);
2373 if (aBoundary.endPos > 0 && aBoundary.endPos < pNode->
GetText().getLength() && u_charType(pNode->
GetText()[aBoundary.endPos - 1]) == U_CONNECTOR_PUNCTUATION)
2375 aBoundary.endPos = xBI->getWordBoundary(pNode->
GetText(), aBoundary.endPos,
2376 GetLocale(), css::i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true).endPos;
2378 while (aBoundary.endPos < pNode->
GetText().getLength() && u_charType(pNode->
GetText()[aBoundary.endPos]) == U_CONNECTOR_PUNCTUATION)
2380 aBoundary.endPos = xBI->getWordBoundary(pNode->
GetText(), aBoundary.endPos + 1,
2381 GetLocale(), css::i18n::WordType::ANYWORD_IGNOREWHITESPACES,
true).endPos;
2389 *pEndOfWord = aSel.
GetEnd();
2405 const sal_uInt32 nParas =
static_cast<sal_uInt32
>(
mpDoc->GetNodes().size());
2413 OStringBuffer aLine;
2414 bool bDone = rInput.
ReadLine( aLine );
2442 const sal_uInt32 nParas =
static_cast<sal_uInt32
>(
mpDoc->GetNodes().size());
2456 const OUString aText = pNode->
GetText().copy( nStartPos, nEndPos-nStartPos );
2463 if ( nPara >=
mpDoc->GetNodes().size() )
2488 if ( nPara >=
mpDoc->GetNodes().size() )
2494 const sal_Int32 nMax = pNode->
GetText().getLength();
2495 if ( nStart > nMax )
2525 const sal_uInt32 nParas =
static_cast<sal_uInt32
>(
mpDoc->GetNodes().size());
2526 if ( rPaM.
GetPara() >= nParas )
2528 rPaM.
GetPara() = nParas ? nParas-1 : 0;
2545 for (
auto nView =
mpViews->size(); nView; )
2547 TextView* pView = (*mpViews)[ --nView ];
2550 for (
int n = 0;
n <= 1;
n++ )
2553 if ( rPaM.
GetPara() >= nPara )
2566 for (
auto nView =
mpViews->size(); nView; )
2568 TextView* pView = (*mpViews)[ --nView ];
2571 const sal_uInt32 nParas =
static_cast<sal_uInt32
>(
mpDoc->GetNodes().size());
2572 for (
int n = 0;
n <= 1;
n++ )
2577 else if ( rPaM.
GetPara() == nPara )
2580 if ( rPaM.
GetPara() >= nParas )
2594 for (
auto nView =
mpViews->size(); nView; )
2596 TextView* pView = (*mpViews)[ --nView ];
2599 const sal_Int32 nEnd =
nPos + nChars;
2600 for (
int n = 0;
n <= 1;
n++ )
2603 if ( rPaM.
GetPara() == nPara )
2621 for (
auto nView =
mpViews->size(); nView; )
2623 TextView* pView = (*mpViews)[ --nView ];
2626 for (
int n = 0;
n <= 1;
n++ )
2629 if ( rPaM.
GetPara() == nPara )
2648 mpDoc->SetLeftMargin(
n );
2706 UErrorCode nError = U_ZERO_ERROR;
2707 UBiDi* pBidi = ubidi_openSized( aText.getLength(), 0, &nError );
2708 nError = U_ZERO_ERROR;
2710 ubidi_setPara( pBidi,
reinterpret_cast<const UChar *
>(aText.getStr()), aText.getLength(), nBidiLevel,
nullptr, &nError );
2711 nError = U_ZERO_ERROR;
2717 UBiDiLevel nCurrDir;
2721 ubidi_getLogicalRun( pBidi, nStart, &nEnd, &nCurrDir );
2723 rInfos.emplace_back( nCurrDir % 2 == 0, nStart, nEnd );
2727 ubidi_close( pBidi );
2731 if ( rInfos.empty() )
2732 rInfos.emplace_back( 0, 0, pParaPortion->
GetNode()->
GetText().getLength() );
2738 bool bRightToLeft =
false;
2741 if ( pNode && !pNode->
GetText().isEmpty() )
2748 for (
const auto& rWritingDirectionInfo : rDirInfos )
2750 if ( rWritingDirectionInfo.nStartPos <=
nPos && rWritingDirectionInfo.nEndPos >=
nPos )
2752 bRightToLeft = !rWritingDirectionInfo.bLeftToRight;
2757 return bRightToLeft;
2778 std::size_t nTmpPortion = nTextPortion+1;
2779 while ( nTmpPortion <= pLine->GetEndPortion() )
2789 nTmpPortion = nTextPortion;
2803 std::size_t nTmpPortion = nTextPortion+1;
2804 while ( nTmpPortion <= pLine->GetEndPortion() )
2814 nTmpPortion = nTextPortion;
2856 sal_Int32 nPortionStart {0};
2863 if ( (
nIndex == nPortionStart ) && (
nIndex == nIndex2 ) )
2870 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
constexpr tools::Long Y() const
void setX(tools::Long nX)
tools::Long AdjustY(tools::Long nVertMove)
tools::Long AdjustX(tools::Long nHorzMove)
constexpr tools::Long X() 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
static bool IsCTLFontEnabled()
static bool IsCTLSequenceCheckingTypeAndReplace()
static bool IsCTLSequenceChecking()
static bool IsCTLSequenceCheckingRestricted()
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