64#include <com/sun/star/i18n/BreakIterator.hpp>
65#include <com/sun/star/i18n/ScriptType.hpp>
66#include <com/sun/star/i18n/InputSequenceChecker.hpp>
72#include <rtl/ustrbuf.hxx>
76#include <osl/diagnose.h>
84#include <unicode/uchar.h>
102 sal_Int32 nTabPortion;
121 case 0x3008:
case 0x300A:
case 0x300C:
case 0x300E:
122 case 0x3010:
case 0x3014:
case 0x3016:
case 0x3018:
123 case 0x301A:
case 0x301D:
case 0xFF09:
case 0xFF3D:
128 case 0x3001:
case 0x3002:
case 0x3009:
case 0x300B:
129 case 0x300D:
case 0x300F:
case 0x3011:
case 0x3015:
130 case 0x3017:
case 0x3019:
case 0x301B:
case 0x301E:
131 case 0x301F:
case 0xFF08:
case 0xFF0C:
case 0xFF0E:
132 case 0xFF1A:
case 0xFF1B:
case 0xFF3B:
case 0xFF5B:
151 const Point& rOrigin,
153 bool bIsRightToLeft )
160 size_t nEnd, nStart =
nIndex;
161 bool bWrong = pWrongs->
NextWrong(nStart, nEnd);
165 if (nStart >= nMaxEnd)
174 Point aPoint1(rPoint);
191 aPoint1.
AdjustX((bIsRightToLeft ? -1 : 1) * pDXArray[nStart -
nIndex - 1]);
196 Point aPoint2(rPoint);
197 assert(nEnd >
nIndex &&
"RedLine: aPnt2?");
203 aPoint2.
AdjustX((bIsRightToLeft ? -1 : 1) * pDXArray[nEnd -
nIndex - 1]);
223 bWrong = pWrongs->
NextWrong(nStart, nEnd);
231#define IS_JOINING_GROUP(c, g) ( u_getIntPropertyValue( (c), UCHAR_JOINING_GROUP ) == U_JG_##g )
232#define isAinChar(c) IS_JOINING_GROUP((c), AIN)
233#define isAlefChar(c) IS_JOINING_GROUP((c), ALEF)
234#define isDalChar(c) IS_JOINING_GROUP((c), DAL)
235#define isFehChar(c) (IS_JOINING_GROUP((c), FEH) || IS_JOINING_GROUP((c), AFRICAN_FEH))
236#define isGafChar(c) IS_JOINING_GROUP((c), GAF)
237#define isHehChar(c) IS_JOINING_GROUP((c), HEH)
238#define isKafChar(c) IS_JOINING_GROUP((c), KAF)
239#define isLamChar(c) IS_JOINING_GROUP((c), LAM)
240#define isQafChar(c) (IS_JOINING_GROUP((c), QAF) || IS_JOINING_GROUP((c), AFRICAN_QAF))
241#define isRehChar(c) IS_JOINING_GROUP((c), REH)
242#define isTahChar(c) IS_JOINING_GROUP((c), TAH)
243#define isTehMarbutaChar(c) IS_JOINING_GROUP((c), TEH_MARBUTA)
244#define isWawChar(c) IS_JOINING_GROUP((c), WAW)
245#define isSeenOrSadChar(c) (IS_JOINING_GROUP((c), SAD) || IS_JOINING_GROUP((c), SEEN))
251 switch (u_getIntPropertyValue(cCh, UCHAR_JOINING_GROUP))
255 case U_JG_AFRICAN_NOON:
259 case U_JG_BURUSHASKI_YEH_BARREE:
274 switch (u_getIntPropertyValue(cCh, UCHAR_JOINING_GROUP))
278 case U_JG_YEH_BARREE:
279 case U_JG_BURUSHASKI_YEH_BARREE:
280 case U_JG_YEH_WITH_TAIL:
293 return u_getIntPropertyValue( cCh, UCHAR_JOINING_TYPE ) == U_JT_TRANSPARENT;
304 const int32_t nJoiningType = u_getIntPropertyValue( cPrevCh, UCHAR_JOINING_TYPE );
305 bool bRet = nJoiningType != U_JT_RIGHT_JOINING && nJoiningType != U_JT_NON_JOINING;
334 aClipRect = pView->pImpEditView->GetWindowPos( aClipRect );
337 pView->InvalidateWindow(aClipRect);
339 pView->InvalidateOtherViewWindows( aClipRect );
345 bool bGotoCursor = pCurView->
pImpEditView->DoAutoScroll();
358 aOnlineSpellTimer.Start();
363 aIdleFormatter.ResetRestarts();
368 EditView* pView = aIdleFormatter.GetView();
369 for (
EditView* aEditView : aEditViews)
371 if( aEditView == pView )
373 FormatAndLayout( pView );
418 aRepaintParas.
reserve(nParaCount);
420 for ( sal_Int32 nPara = 0; nPara < nParaCount; nPara++ )
453 aRepaintParas.
insert(nPara);
496 if (!aRepaintParas.
empty())
498 auto CombineRepaintParasAreas = [&](
const LineAreaInfo& rInfo) {
499 if (aRepaintParas.
count(rInfo.nPortion))
518 bool bChange =
false;
579 Size aSz( aInvSize );
590 pView->pImpEditView->RecalcOutputArea();
599 SAL_INFO(
"editeng.chaining",
"[OVERFLOW-CHECK] Current MaxAutoPaperHeight is " << nBoxHeight);
602 SAL_INFO(
"editeng.chaining",
"[OVERFLOW-CHECK] Current Text Height is " << nTxtHeight);
606 bool bOnlyOneEmptyPara = (nParaCount == 1) &&
607 (nFirstLineCount == 1) &&
610 if (nTxtHeight > nBoxHeight && !bOnlyOneEmptyPara)
627 constexpr const double f120Percent = 12.0 / 10.0;
643 assert( pParaPortion->
GetNode() &&
"Portion without Node in CreateLines" );
647 bool bProcessingEmptyLine = ( pParaPortion->
GetNode()->
Len() == 0 );
664 sal_Int64 nCurrentPosY = nStartPosY;
694 sal_Int32 nSpaceBefore = 0;
695 sal_Int32 nMinLabelWidth = 0;
703 const sal_Int32 nInvalidEnd = nInvalidStart + std::abs( nInvalidDiff );
705 bool bQuickFormat =
false;
706 if ( !bEmptyNodeWithPolygon && !
HasScriptType( nPara, i18n::ScriptType::COMPLEX ) )
713 else if ( ( pParaPortion->
IsSimpleInvalid() ) && ( nInvalidDiff < 0 ) )
716 sal_Int32 nStart = nInvalidStart;
717 sal_Int32 nEnd = nStart - nInvalidDiff;
721 for ( sal_Int32 nTP = 0; nTP < nPortions; nTP++ )
726 if ( (
nPos > nStart ) && (
nPos < nEnd ) )
728 bQuickFormat =
false;
740 sal_Int32 nRealInvalidStart = nInvalidStart;
742 if ( bEmptyNodeWithPolygon )
748 else if ( bQuickFormat )
764 for ( sal_Int32 nL = 0; nL <= nLine; nL++ )
767 if ( rLine.
GetEnd() > nRealInvalidStart )
776 if ( nLine && ( !pParaPortion->
IsSimpleInvalid() || ( nInvalidEnd < pNode->Len() ) || ( nInvalidDiff <= 0 ) ) )
795 sal_Int32 nDelFromLine = -1;
796 bool bLineBreak =
false;
804 bool bSameLineAgain =
false;
807 bool bForceOneRun = bEmptyNodeWithPolygon;
808 bool bCompressedChars =
false;
810 while ( ( nIndex < pNode->Len() ) || bForceOneRun )
814 bForceOneRun =
false;
818 sal_Int32 nPortionStart = 0;
819 sal_Int32 nPortionEnd = 0;
827 if ( !nLine && ( pParaPortion->
GetBulletX() > nStartX ) )
837 nMaxLineWidth -= nStartX;
841 if ( ( nMaxLineWidth < 0 ) && ( nStartX < 0 ) )
845 if ( nMaxLineWidth <= 0 )
856 sal_Int32 nTmpPos =
nIndex;
861 std::deque<tools::Long>* pTextRanges =
nullptr;
870 if ( !bSameLineAgain )
883 sal_uInt16 nLineHeight = aTempFormatterMetrics.
GetHeight();
884 if ( nLineHeight > nTextLineHeight )
885 nTextLineHeight = nLineHeight;
898 nYOff = nMaxPolygonX-nYOff;
899 nYDiff = -nTextLineHeight;
902 assert( pTextRanges &&
"GetTextRanges?!" );
907 assert(pTextRanges->size() % 2 == 0 &&
"textranges are always in pairs");
908 if (!pTextRanges->empty())
912 DBG_ASSERT( nA <= nB,
"TextRange distorted?" );
914 if ( nW > nMaxRangeWidth )
920 nXWidth = nMaxRangeWidth;
932 nXWidth = 0x7FFFFFFF;
940 sal_Int32 nPortionLen = 0;
941 bool bContinueLastPortion =
false;
942 bool bBrokenLine =
false;
945 while ( ( nTmpWidth < nXWidth ) && !bEOL )
948 assert(nTextPortions > 0);
949 bContinueLastPortion = (nTmpPortion >= nTextPortions);
950 if (bContinueLastPortion)
952 if (nTmpPos >= pNode->
Len())
960 nTmpPortion = nTextPortions - 1;
961 SAL_WARN(
"editeng",
"ImpEditEngine::CreateLines - continuation of a broken portion");
964 nPortionStart = nTmpPos;
970 sal_Int32 nTmpLen = pPortion->
GetLen();
972 if (nTmpPortion && nTmpLen)
978 nTmpPos = nTmpPos - rPrev.
GetLen();
983 assert( nTmpPortion < pParaPortion->GetTextPortions().
Count() &&
"No more Portions left!" );
987 if (bContinueLastPortion)
991 nPortionLen = pNode->
Len() - nPortionStart;
995 nPortionLen = pPortion->
GetLen();
999 DBG_ASSERT( nPortionLen || bProcessingEmptyLine,
"Empty Portion in CreateLines ?!" );
1000 if ( pNextFeature && ( pNextFeature->
GetStart() == nTmpPos ) )
1003 "editeng",
"ImpEditEngine::CreateLines - feature in continued portion will be wrong");
1017 short nAllSpaceBeforeText =
static_cast< short >(rLRItem.
GetTextLeft() + nSpaceBeforeAndMinLabelWidth);
1020 aCurrentTab.bValid =
false;
1023 if ( bRightToLeftPara )
1036 aCurrentTab.bValid =
true;
1037 aCurrentTab.nStartPosX = nTmpWidth;
1038 aCurrentTab.nTabPortion = nTmpPortion;
1043 pPortion->
setWidth( aCurrentTab.nTabPos - (nTmpWidth+nStartX) );
1051 nTmpWidth = aCurrentTab.nTabPos-nStartX;
1055 if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->
GetStartPortion() ) )
1059 pPortion->
setWidth( nXWidth-nOldTmpWidth );
1060 nTmpWidth = nXWidth-1;
1067 bCompressedChars =
false;
1077 bCompressedChars =
false;
1089 OUString aFieldValue =
static_cast<const EditCharAttribField*
>(pNextFeature)->GetFieldValue();
1093 aFieldValue, 0, aFieldValue.getLength(), &aTmpDXArray));
1101 if(
nullptr == pExtraInfo)
1115 const sal_Int32 nTextLength(aFieldValue.getLength());
1118 sal_Int32 nNextCellBreak(
1119 xBreakIterator->nextCharacters(
1123 css::i18n::CharacterIteratorMode::SKIPCELL,
1126 sal_Int32 nLastCellBreak(0);
1127 sal_Int32 nLineStartX(0);
1132 for(sal_Int32
a(0);
a < nTextLength;
a++)
1134 if(
a == nNextCellBreak)
1137 if(aTmpDXArray[
a] - nLineStartX > nXWidth)
1148 nLineStartX = aTmpDXArray[nLastCellBreak];
1153 nNextCellBreak = xBreakIterator->nextCharacters(
1157 css::i18n::CharacterIteratorMode::SKIPCELL,
1170 if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->
GetStartPortion() ) )
1172 nTmpWidth = nXWidth-1;
1178 bCompressedChars =
false;
1181 default: OSL_FAIL(
"What feature?" );
1187 DBG_ASSERT( nPortionLen || bProcessingEmptyLine,
"Empty Portion - Extra Space?!" );
1192 if (!bContinueLastPortion)
1195 if (bContinueLastPortion)
1198 pParaPortion->
GetNode()->
GetString(), nTmpPos, nPortionLen, &aCharPositionArray ));
1210 if ( ( aTmpFont.
GetFixKerning() > 0 ) && ( ( nTmpPos + nPortionLen ) < pNode->
Len() ) )
1220 assert(aCharPositionArray.
get_factor() == 1);
1222 rArray.insert( rArray.begin() +
nPos, rKernArray.data(), rKernArray.data() + nPortionLen);
1227 sal_Int32* pDXArray = rArray.data() + nTmpPos - pLine->
GetStart();
1229 pNode, pPortion, nTmpPos, pDXArray, 10000,
false);
1234 sal_Int32 _nPortionEnd = nTmpPos + nPortionLen;
1235 if( bScriptSpace && ( _nPortionEnd < pNode->Len() ) && ( nTmpWidth < nXWidth ) &&
IsScriptChange(
EditPaM( pNode, _nPortionEnd ) ) )
1237 bool bAllow =
false;
1240 if ( ( nScriptTypeLeft == i18n::ScriptType::ASIAN ) || ( nScriptTypeRight == i18n::ScriptType::ASIAN ) )
1249 nTmpWidth += nExtraSpace;
1254 if ( aCurrentTab.bValid && ( nTmpPortion != aCurrentTab.nTabPortion ) )
1257 for ( sal_Int32
n = aCurrentTab.nTabPortion+1;
n <= nTmpPortion;
n++ )
1268 nW = nWidthAfterTab/2;
1274 sal_Int32 nDecPos = aText.indexOf( aCurrentTab.aTabStop.GetDecimal() );
1275 if ( nDecPos != -1 )
1279 nTmpPos, nDecPos,
nullptr ).
Width();
1280 aCurrentTab.bValid =
false;
1285 OSL_FAIL(
"CreateLines: Tab not handled!" );
1287 tools::Long nMaxW = aCurrentTab.nTabPos - aCurrentTab.nStartPosX - nStartX;
1291 aCurrentTab.bValid =
false;
1294 rTabPortion.
setWidth( aCurrentTab.nTabPos - aCurrentTab.nStartPosX - nW - nStartX );
1295 nTmpWidth = aCurrentTab.nStartPosX + rTabPortion.
GetSize().
Width() + nWidthAfterTab;
1298 nTmpPos = nTmpPos + nPortionLen;
1299 nPortionEnd = nTmpPos;
1307 aCurrentTab.bValid =
false;
1312 bool bFixedEnd =
false;
1316 nTmpPos -= pPortion ? nPortionLen : 0;
1317 nPortionStart = nTmpPos;
1326 nPortionEnd = nTmpPortion;
1328 if ( pPortion && nPortionLen > 1 )
1336 else if ( nTmpWidth >= nXWidth )
1338 nPortionEnd = nTmpPos;
1339 nTmpPos -= pPortion ? nPortionLen : 0;
1340 nPortionStart = nTmpPos;
1344 if( pPortion )
switch ( pPortion->
GetKind() )
1372 pLine->
SetEnd( nPortionEnd );
1379 pLine->
SetEnd( nPortionEnd );
1382 else if ( bFixedEnd )
1384 pLine->
SetEnd( nPortionStart );
1387 else if ( bLineBreak || bBrokenLine )
1389 pLine->
SetEnd( nPortionStart+1 );
1393 else if ( !bEOL && !bContinueLastPortion )
1395 DBG_ASSERT( pPortion && ((nPortionEnd-nPortionStart) == pPortion->
GetLen()),
"However, another portion?!" );
1398 bool bCanHyphenate = ( aTmpFont.
GetCharSet() != RTL_TEXTENCODING_SYMBOL );
1404 pNode, pPortion, nPortionStart, pDXArray, 10000,
true);
1407 ImpBreakLine( pParaPortion, pLine, pPortion, nPortionStart,
1408 nRemainingWidth, bCanHyphenate && bHyphenatePara );
1418 if ( aTextSize.
Height() == 0 )
1435 sal_Int32 nTPos = pLine->
GetStart();
1436 for ( sal_Int32 nP = pLine->
GetStartPortion(); nP <= pLine->GetEndPortion(); nP++ )
1447 nTPos = nTPos + rTP.
GetLen();
1449 sal_uInt16 nLineHeight = aFormatterMetrics.
GetHeight();
1454 bSameLineAgain =
false;
1458 bSameLineAgain =
true;
1468 sal_uInt16 nTxtHeight = pLine->
GetHeight();
1469 if ( nTxtHeight < nMinHeight )
1474 pLine->
SetHeight( nMinHeight, nTxtHeight );
1482 sal_uInt16 nTxtHeight = pLine->
GetHeight();
1484 pLine->
SetHeight( nFixHeight, nTxtHeight );
1491 double fProportionalScale = double(nPropLineSpace) / 100.0;
1492 constexpr const double f80Percent = 8.0 / 10.0;
1494 if (nPropLineSpace && nPropLineSpace < 100)
1499 if (!nAscent || nAscent > nNewAscent)
1505 else if (nPropLineSpace && nPropLineSpace != 100)
1507 sal_uInt16 nTxtHeight = pLine->
GetHeight();
1508 sal_Int32 nPropTextHeight = nTxtHeight * fProportionalScale * fSpacingFactor;
1512 pLine->
SetHeight(
static_cast<sal_uInt16
>( nPropTextHeight ), nTxtHeight );
1521 if (nPropLineSpace && nPropLineSpace < 100)
1526 if (!nAscent || nAscent > nNewAscent)
1545 if ( aTextSize.
Width() < nMaxLineWidthFix )
1546 nMaxLineWidth = nMaxLineWidthFix;
1549 if ( bCompressedChars )
1552 if ( nRemainingWidth > 0 )
1575 switch ( eJustification )
1598 if ( nRemainingSpace > 0 && (!bEOC || bDistLastLine) )
1617 size_t nLen = pLine->
GetLen();
1618 if (rArray.size() > nLen)
1619 rArray.erase(rArray.begin()+nLen, rArray.end());
1625 if ( nTextExtraYOffset )
1627 pLine->
SetHeight(
static_cast<sal_uInt16
>( pLine->
GetHeight() + nTextExtraYOffset ), 0 );
1639 if ( pLine->
GetEnd() < nInvalidStart )
1641 if ( *pLine == aSaveLine )
1648 sal_Int32 nStart = pLine->
GetStart();
1649 sal_Int32 nEnd = pLine->
GetEnd();
1651 if ( nStart > nInvalidEnd )
1653 if ( ( ( nStart-nInvalidDiff ) == aSaveLine.
GetStart() ) &&
1654 ( ( nEnd-nInvalidDiff ) == aSaveLine.
GetEnd() ) )
1665 else if (bQuickFormat && (nEnd > nInvalidEnd))
1670 if ( nEnd == ( aSaveLine.
GetEnd() + nInvalidDiff ) )
1680 if ( !bSameLineAgain )
1690 if ( nLine < pParaPortion->GetLines().Count()-1 )
1691 pLine = &pParaPortion->
GetLines()[++nLine];
1692 if ( pLine && (
nIndex >= pNode->
Len() ) )
1694 nDelFromLine = nLine;
1703 if ( pLine && (
nIndex >= pNode->
Len()) )
1704 nDelFromLine = nLine;
1709 if ( nIndex < pNode->Len() )
1722 bForceOneRun =
true;
1723 bProcessingEmptyLine =
true;
1737 if ( nDelFromLine >= 0 )
1752 return bHeightChanged;
1764 bool bLineBreak = pParaPortion->
GetNode()->
Len() > 0;
1765 sal_Int32 nSpaceBefore = 0;
1779 if ( !aBulletArea.IsEmpty() && aBulletArea.Right() > 0 )
1804 sal_uInt16 nLineHeight = aFormatterMetrics.
GetHeight();
1805 if ( nLineHeight > pTmpLine->
GetHeight() )
1814 if ( nMaxLineWidth < 0 )
1817 nStartX = nMaxLineWidth / 2;
1819 nStartX = nMaxLineWidth;
1829 sal_uInt16 nTxtHeight = pTmpLine->
GetHeight();
1830 if ( nTxtHeight < nMinHeight )
1835 pTmpLine->
SetHeight( nMinHeight, nTxtHeight );
1841 sal_uInt16 nTxtHeight = pTmpLine->
GetHeight();
1844 pTmpLine->
SetHeight( nFixHeight, nTxtHeight );
1855 sal_uInt16 nTxtHeight = pTmpLine->
GetHeight();
1856 sal_Int32 nH = nTxtHeight;
1864 pTmpLine->
SetHeight(
static_cast<sal_uInt16
>(nH), nTxtHeight );
1878 pTmpLine->
SetHeight(
static_cast<sal_uInt16
>(nMinHeight) );
1902 bool bRet = ( pParaPortion->
GetHeight() != nOldHeight );
1910 sal_Int32 nBreakInLine = nPortionStart - pLine->
GetStart();
1911 sal_Int32 nMax = nBreakInLine + pPortion->
GetLen();
1912 while ( ( nBreakInLine < nMax ) && ( pLine->
GetCharPosArray()[nBreakInLine] < nRemainingWidth ) )
1915 sal_Int32 nMaxBreakPos = nBreakInLine + pLine->
GetStart();
1918 bool bCompressBlank =
false;
1919 bool bHyphenated =
false;
1920 bool bHangingPunctuation =
false;
1923 bool bAltFullLeft =
false;
1924 bool bAltFullRight =
false;
1925 sal_uInt32 nAltDelChar = 0;
1927 if ( ( nMaxBreakPos < ( nMax + pLine->
GetStart() ) ) && ( pNode->
GetChar( nMaxBreakPos ) ==
' ' ) )
1930 nBreakPos = nMaxBreakPos + 1;
1931 bCompressBlank =
true;
1935 sal_Int32 nMinBreakPos = pLine->
GetStart();
1937 for (
size_t nAttr = rAttrs.size(); nAttr; )
1942 nMinBreakPos = rAttr.
GetEnd();
1946 assert(nMinBreakPos <= nMaxBreakPos);
1951 const bool bAllowPunctuationOutsideMargin =
static_cast<const SfxBoolItem&
>(
1954 if (nMinBreakPos == nMaxBreakPos)
1956 nBreakPos = nMinBreakPos;
1960 Reference< XHyphenator > xHyph;
1961 if ( bCanHyphenate )
1963 i18n::LineBreakHyphenationOptions aHyphOptions( xHyph, Sequence< PropertyValue >(), 1 );
1964 i18n::LineBreakUserOptions aUserOptions;
1967 aUserOptions.forbiddenBeginCharacters = pForbidden->beginLine;
1968 aUserOptions.forbiddenEndCharacters = pForbidden->endLine;
1970 aUserOptions.allowPunctuationOutsideMargin = bAllowPunctuationOutsideMargin;
1971 aUserOptions.allowHyphenateEnglish =
false;
1975 i18n::LineBreakResults aLBR = _xBI->getLineBreak(
1976 pNode->
GetString(), nMaxBreakPos, aLocale, nMinBreakPos, aHyphOptions, aUserOptions );
1977 nBreakPos = aLBR.breakIndex;
1981 nBreakPos = nMaxBreakPos;
1985 if ( nBreakPos < nMinBreakPos )
1987 nBreakPos = nMinBreakPos;
1989 else if ( ( nBreakPos > nMaxBreakPos ) && !aUserOptions.allowPunctuationOutsideMargin )
1991 OSL_FAIL(
"I18N: XBreakIterator::getLineBreak returns position > Max" );
1992 nBreakPos = nMaxBreakPos;
2001 if ( (nBreakPos + ( bAllowPunctuationOutsideMargin ? 0 : 1 ) ) <= nMaxBreakPos )
2004 if ( cFirstInNextLine == 12290 )
2008 bHangingPunctuation = nBreakPos > nMaxBreakPos;
2016 if ( !bHangingPunctuation && bCanHyphenate &&
GetHyphenator().is() )
2018 i18n::Boundary aBoundary = _xBI->getWordBoundary(
2020 sal_Int32 nWordStart = nBreakPos;
2021 sal_Int32 nWordEnd = aBoundary.endPos;
2022 DBG_ASSERT( nWordEnd >= nWordStart,
"Start >= End?" );
2024 sal_Int32 nWordLen = nWordEnd - nWordStart;
2025 if ( ( nWordEnd >= nMaxBreakPos ) && ( nWordLen > 3 ) )
2028 const OUString aWord = pNode->
GetString().copy(nWordStart, nWordLen);
2029 sal_Int32 nMinTrail = nWordEnd-nMaxBreakPos+1;
2030 Reference< XHyphenatedWord > xHyphWord;
2032 xHyphWord =
xHyphenator->hyphenate( aWord, aLocale, aWord.getLength() - nMinTrail, Sequence< PropertyValue >() );
2035 bool bAlternate = xHyphWord->isAlternativeSpelling();
2036 sal_Int32 _nWordLen = 1 + xHyphWord->getHyphenPos();
2038 if ( ( _nWordLen >= 2 ) && ( (nWordStart+_nWordLen) >= (pLine->
GetStart() + 2 ) ) )
2043 nBreakPos = nWordStart + _nWordLen;
2048 OUString aAlt( xHyphWord->getHyphenatedWord() );
2049 std::u16string_view aAltLeft(aAlt.subView(0, _nWordLen));
2050 std::u16string_view aAltRight(aAlt.subView(_nWordLen));
2051 bAltFullLeft = aWord.startsWith(aAltLeft);
2052 bAltFullRight = aWord.endsWith(aAltRight);
2053 nAltDelChar = aWord.getLength() - aAlt.getLength() +
static_cast<int>(!bAltFullLeft) +
static_cast<int>(!bAltFullRight);
2069 sal_Int32 nAltStart = _nWordLen - 1;
2070 sal_Int32 nTxtStart = nAltStart - (aAlt.getLength() - aWord.getLength());
2071 sal_Int32 nTxtEnd = nTxtStart;
2072 sal_Int32 nAltEnd = nAltStart;
2076 while( nTxtEnd < aWord.getLength() && nAltEnd < aAlt.getLength() &&
2077 aWord[nTxtEnd] != aAlt[nAltEnd] )
2084 if( nAltEnd > nTxtEnd && nAltStart == nAltEnd &&
2085 aWord[ nTxtEnd ] == aAlt[nAltEnd] )
2092 DBG_ASSERT( ( nAltEnd - nAltStart ) == 1,
"Alternate: Wrong assumption!" );
2094 if ( nTxtEnd > nTxtStart )
2095 cAlternateReplChar = aAlt[nAltStart];
2097 cAlternateExtraChar = aAlt[nAltStart];
2100 nBreakPos = nWordStart + nTxtStart;
2101 if ( cAlternateReplChar || aAlt.getLength() < aWord.getLength() || !bAltFullRight)
2109 if ( nBreakPos <= pLine->GetStart() )
2112 nBreakPos = nMaxBreakPos;
2114 if ( nBreakPos <= pLine->GetStart() )
2120 pLine->
SetEnd( nBreakPos );
2122 sal_Int32 nEndPortion =
SplitTextPortion( pParaPortion, nBreakPos, pLine );
2124 if ( !bCompressBlank && !bHangingPunctuation )
2129 assert( nBreakPos > pLine->
GetStart() &&
"ImpBreakLines - BreakPos not expected!" );
2130 if ( pNode->
GetChar( nBreakPos-1 ) ==
' ' )
2131 bCompressBlank =
true;
2134 if ( bCompressBlank || bHangingPunctuation )
2138 DBG_ASSERT( nBreakPos > pLine->
GetStart(),
"SplitTextPortion at the beginning of the line?" );
2139 sal_Int32 nPosInArray = nBreakPos - 1 - pLine->
GetStart();
2146 else if ( bHyphenated )
2151 if ( (cAlternateReplChar || cAlternateExtraChar) && bAltFullRight )
2156 pHyphPortion->
SetLen( nAltDelChar );
2157 if (cAlternateReplChar && !bAltFullLeft) pHyphPortion->
SetExtraValue( cAlternateReplChar );
2176 DBG_ASSERT( nRemainingSpace > 0,
"AdjustBlocks: Somewhat too little..." );
2177 assert( pLine &&
"AdjustBlocks: Line ?!" );
2178 if ( ( nRemainingSpace < 0 ) || pLine->
IsEmpty() )
2181 const sal_Int32 nFirstChar = pLine->
GetStart();
2182 const sal_Int32 nLastChar = pLine->
GetEnd() -1;
2185 DBG_ASSERT( nLastChar < pNode->Len(),
"AdjustBlocks: Out of range!" );
2188 std::vector<sal_Int32> aPositions;
2192 auto nKashidas = aPositions.size();
2194 sal_uInt16 nLastScript = i18n::ScriptType::LATIN;
2195 for ( sal_Int32 nChar = nFirstChar; nChar <= nLastChar; nChar++ )
2197 EditPaM aPaM( pNode, nChar+1 );
2204 if ( pNode->
GetChar(nChar) ==
' ' )
2207 aPositions.push_back( nChar );
2209 else if (nChar > nFirstChar)
2211 if (nLastScript == i18n::ScriptType::ASIAN)
2215 aPositions.push_back( nChar-1 );
2217 else if (nScript == i18n::ScriptType::ASIAN)
2220 aPositions.push_back( nChar-1 );
2224 nLastScript = nScript;
2227 if ( aPositions.empty() )
2233 if ( ( pNode->
GetChar( nLastChar ) ==
' ' ) && ( aPositions.size() > 1 ) &&
2236 aPositions.pop_back();
2237 sal_Int32 nPortionStart, nPortion;
2242 if ( nLastChar > nPortionStart )
2249 DBG_ASSERT( ( nPortionStart + rLastPortion.
GetLen() ) == ( nLastChar+1 ),
"Blank actually not at the end of the portion!?");
2251 nRemainingSpace += nBlankWidth;
2256 size_t nGaps = aPositions.size();
2257 const tools::Long nMore4Everyone = nRemainingSpace / nGaps;
2258 tools::Long nSomeExtraSpace = nRemainingSpace - nMore4Everyone*nGaps;
2260 DBG_ASSERT( nSomeExtraSpace <
static_cast<tools::Long>(nGaps),
"AdjustBlocks: ExtraSpace too large" );
2261 DBG_ASSERT( nSomeExtraSpace >= 0,
"AdjustBlocks: ExtraSpace < 0 " );
2268 for (
size_t i = 0;
i < nKashidas;
i++)
2270 auto nChar = aPositions[
i];
2271 if ( nChar < nLastChar )
2278 for (
auto const& nChar : aPositions)
2280 if ( nChar < nLastChar )
2282 sal_Int32 nPortionStart, nPortion;
2288 if (nSomeExtraSpace)
2294 sal_Int32 nPortionEnd = nPortionStart + rLastPortion.
GetLen();
2295 for ( sal_Int32 _n = nChar; _n < nPortionEnd; _n++ )
2298 if ( nSomeExtraSpace )
2302 if ( nSomeExtraSpace )
2318 std::vector<sal_Int32> aKashidaArray;
2323 aWordSel =
SelectWord( aWordSel, css::i18n::WordType::DICTIONARY_WORD );
2329 const sal_Int32 nSavPos = aWordSel.
Max().
GetIndex();
2338 sal_Int32 nIdx = 0, nPrevIdx = 0;
2339 sal_Int32 nKashidaPos = -1;
2342 int nPriorityLevel = 7;
2345 sal_Int32 nWordLen = aWord.getLength();
2351 while ( nIdx < nWordLen )
2353 cCh = aWord[ nIdx ];
2365 if (nPriorityLevel >= 1 && nIdx < nWordLen - 1)
2368 && (aWord[ nIdx+1 ] != 0x200C) )
2377 if ( nPriorityLevel >= 2 && nIdx > 0 )
2381 (
isHehChar ( cCh ) && nIdx == nWordLen - 1))
2384 SAL_WARN_IF( 0 == cPrevCh,
"editeng",
"No previous character" );
2388 nKashidaPos = aWordSel.
Min().
GetIndex() + nPrevIdx;
2396 if ( nPriorityLevel >= 3 && nIdx > 0 )
2403 && nIdx == nWordLen - 1))
2405 SAL_WARN_IF( 0 == cPrevCh,
"editeng",
"No previous character" );
2409 nKashidaPos = aWordSel.
Min().
GetIndex() + nPrevIdx;
2417 if ( nPriorityLevel >= 4 && nIdx > 0 && nIdx < nWordLen - 1 )
2425 SAL_WARN_IF( 0 == cPrevCh,
"editeng",
"No previous character" );
2429 nKashidaPos = aWordSel.
Min().
GetIndex() + nPrevIdx;
2438 if ( nPriorityLevel >= 5 && nIdx > 0 )
2445 && nIdx == nWordLen - 1))
2447 SAL_WARN_IF( 0 == cPrevCh,
"editeng",
"No previous character" );
2451 nKashidaPos = aWordSel.
Min().
GetIndex() + nPrevIdx;
2458 if ( nPriorityLevel >= 6 && nIdx > 0 )
2463 SAL_WARN_IF( 0 == cPrevCh,
"editeng",
"No previous character" );
2467 nKashidaPos = aWordSel.
Min().
GetIndex() + nPrevIdx;
2484 if ( nKashidaPos>=0 )
2485 aKashidaArray.push_back( nKashidaPos );
2487 aWordSel =
WordRight( aWordSel.
Max(), css::i18n::WordType::DICTIONARY_WORD );
2488 aWordSel =
SelectWord( aWordSel, css::i18n::WordType::DICTIONARY_WORD );
2492 std::vector<sal_Int32> aDropped(aKashidaArray.size());
2496 aKashidaArray.size(), aKashidaArray.data(), aDropped.data());
2499 for (
auto const&
pos : aKashidaArray)
2500 if (std::find(aDropped.begin(), aDropped.end(),
pos) == aDropped.end())
2501 rArray.push_back(
pos);
2510 assert( pPortion &&
"SplitTextPortion: Which ?" );
2512 sal_Int32 nSplitPortion;
2513 sal_Int32 nTmpPos = 0;
2516 for ( nSplitPortion = 0; nSplitPortion < nPortions; nSplitPortion++ )
2519 nTmpPos = nTmpPos + rTP.
GetLen();
2520 if ( nTmpPos >=
nPos )
2522 if ( nTmpPos ==
nPos )
2524 return nSplitPortion;
2526 pTextPortion = &rTP;
2531 DBG_ASSERT( pTextPortion,
"Position outside the area!" );
2538 sal_Int32 nOverlapp = nTmpPos -
nPos;
2539 pTextPortion->
SetLen( pTextPortion->
GetLen() - nOverlapp );
2546 assert(
nPos > pCurLine->
GetStart() &&
"SplitTextPortion at the beginning of the line?" );
2559 nTxtPortionStart, pTextPortion->
GetLen(),
nullptr );
2567 return nSplitPortion;
2572 sal_Int32 nStartPos = rStart;
2574 DBG_ASSERT( pNode->
Len(),
"CreateTextPortions should not be used for empty paragraphs!" );
2579 for (std::size_t nAttr = 0;; ++nAttr)
2596 aPositions.
insert( rType.nStartPos );
2600 aPositions.
insert( rWritingDirection.nStartPos );
2619 sal_Int32 nPortionStart = 0;
2620 sal_Int32 nInvPortion = 0;
2625 nPortionStart = nPortionStart + rTmpPortion.
GetLen();
2626 if ( nPortionStart >= nStartPos )
2628 nPortionStart = nPortionStart - rTmpPortion.
GetLen();
2629 rStart = nPortionStart;
2635 if ( nInvPortion && ( nPortionStart+pParaPortion->
GetTextPortions()[nInvPortion].GetLen() > nStartPos ) )
2641 nPortionStart = nPortionStart - pParaPortion->
GetTextPortions()[nInvPortion].GetLen();
2646 aPositions.
insert( nPortionStart );
2648 auto nInvPos = aPositions.
find( nPortionStart );
2653 while (
i != aPositions.
end() )
2660#if OSL_DEBUG_LEVEL > 0
2668 DBG_ASSERT( nNewChars,
"RecalcTextPortion with Diff == 0" );
2671 if ( nNewChars > 0 )
2677 sal_Int32 nNewPortionPos = 0;
2683 if ( ( nNewPortionPos < pParaPortion->GetTextPortions().
Count() ) &&
2698 sal_Int32 nPortionStart;
2700 FindPortion( nStartPos, nPortionStart );
2715 sal_Int32 nPortion = 0;
2717 sal_Int32 nEnd = nStartPos-nNewChars;
2720 for ( nPortion = 0; nPortion < nPortions; nPortion++ )
2731 assert( pTP &&
"RecalcTextPortion: Portion not found" );
2749 DBG_ASSERT( pTP->
GetLen() > (-nNewChars),
"Portion too small to shrink! ");
2754 assert( nPortionCount );
2758 sal_Int32 nLastPortion = nPortionCount - 1;
2764 if ( nLastPortion && pTP->
GetLen() )
2775#if OSL_DEBUG_LEVEL > 0
2828 assert(nColumns >= 1);
2833 SAL_WARN(
"editeng",
"bad nColumns value, ignoring");
2876 if ( ( nScriptTypeI18N == i18n::ScriptType::ASIAN ) || ( nScriptTypeI18N == i18n::ScriptType::COMPLEX ) )
2902 pOut->SetTextLineColor();
2908 pOut->SetOverlineColor();
2927 if ( ( pAttrib->
Which() != 0 ) &&
2929 || ( !pNode->
Len() ) ) )
2948 pAttrib =
GetAttrib( rAttribs, ++nAttr );
2952 if ( !pCJKLanguageItem )
2989 double fNewHeight = fHeightRounded * (
mfFontScaleY / 100.0);
3002 double fNewWidth = fWidthRounded * (
mfFontScaleX / 100.0);
3019 if (nKerning < 0 && mfFontScaleX > 100.0)
3024 else if ( nKerning )
3033 if ( nRelWidth != 100 )
3067 if ( nAttr & ExtTextInputAttr::Underline )
3069 else if ( nAttr & ExtTextInputAttr::DoubleUnderline )
3071 else if ( nAttr & ExtTextInputAttr::BoldUnderline )
3073 else if ( nAttr & ExtTextInputAttr::DottedUnderline )
3075 else if ( nAttr & ExtTextInputAttr::DashDotUnderline )
3077 else if ( nAttr & ExtTextInputAttr::RedText )
3079 else if ( nAttr & ExtTextInputAttr::HalfToneText )
3081 if ( nAttr & ExtTextInputAttr::Highlight )
3088 else if ( nAttr & ExtTextInputAttr::GrayWaveline )
3099 sal_uInt16 nPropr = rFont.
GetPropr();
3101 if ( nPropr != 100 )
3106 sal_uInt16 nAscent, nDescent;
3109 nAscent =
static_cast<sal_uInt16
>(aMetric.
GetAscent());
3111 nAscent = sal::static_int_cast< sal_uInt16 >(
3113 nDescent =
static_cast<sal_uInt16
>(aMetric.
GetDescent());
3117 nAscent = sal::static_int_cast< sal_uInt16 >( rFont.
GetFontHeight() );
3129 aMetric = pVDev->GetFontMetric();
3133 nAscent =
static_cast<sal_uInt16
>(aMetric.
GetAscent());
3134 nDescent =
static_cast<sal_uInt16
>(aMetric.
GetDescent());
3150 nAscent =
static_cast<sal_uInt16
>(
static_cast<tools::Long>(nAscent)*nPropr/100 + nDiff);
3156 nDescent =
static_cast<sal_uInt16
>(
static_cast<tools::Long>(nDescent)*nPropr/100 - nDiff);
3191 ptDest.
setX(ptSrc.
X());
3193 ptDest.
setY(ptSrc.
Y());
3199 ptDest.
setY(ptSrc.
Y());
3201 ptDest.
setX(ptSrc.
Y());
3211 nRes = rectMax.
Left() -
pt.X();
3213 nRes =
pt.X() - rectMax.
Right();
3220 return pt.X() > rectMax.
Right();
3225 return pt.Y() < rectMax.
Top();
3234 return -rect.
Left();
3236 return rect.
Right();
3242 return { rect.
Left(), rect.
Top() };
3245 return { rect.
Top(), -rect.
Right() };
3259 const Point aOld = rMovePos;
3266 Point aOtherCorner = aOrigin;
3271 if (pnHeightNeededToNotWrap)
3272 *pnHeightNeededToNotWrap = nNeeded;
3289 return rMovePos - aOld;
3313 const Point aOrigin( aStartPos );
3318 const bool bMetafileValid( pMtf !=
nullptr );
3322 sal_Int16 nColumn = 0;
3329 assert( pPortion &&
"NULL-Pointer in TokenList in Paint" );
3335 if ( pPDFExtOutDevData )
3350 const sal_Int32 nLastLine = nLines-1;
3352 bool bEndOfParagraphWritten(
false);
3359 bool bPaintBullet (
false);
3361 for ( sal_Int32 nLine = 0; nLine < nLines; nLine++ )
3364 assert( pLine &&
"NULL-Pointer in the line iterator in UpdateViews" );
3367 if (nLine != nLastLine)
3368 nLineHeight += nVertLineSpacing;
3370 aTmpPos = aStartPos;
3378 bPaintBullet =
false;
3386 Point aLineStart(aStartPos);
3392 bPaintBullet = rBulletState.
GetValue();
3398 bool bParsingFields =
false;
3399 std::vector< sal_Int32 >::iterator itSubLines;
3401 for ( sal_Int32 nPortion = pLine->
GetStartPortion(); nPortion <= pLine->GetEndPortion(); nPortion++ )
3412 switch ( rTextPortion.
GetKind() )
3420 bool bDrawFrame =
false;
3432#if OSL_DEBUG_LEVEL > 2
3459 sal_Int32 nTextStart = 0;
3460 sal_Int32 nTextLen = 0;
3469 nTextLen = rTextPortion.
GetLen();
3488 const sal_Int32 nTmpEnd = nTextStart + rTextPortion.
GetLen();
3490 for ( nTmpIdx = nTextStart; nTmpIdx <= nTmpEnd ; ++nTmpIdx )
3492 const sal_Unicode cChar = ( nTmpIdx != aText.getLength() && ( nTmpIdx != nTextStart || 0 == nTextStart ) ) ?
3496 if ( 0x200B == cChar || 0x2060 == cChar )
3499 " ", 0, 1,
nullptr ).
Width() / 2;
3501 const tools::Long nAdvanceX = ( nTmpIdx == nTmpEnd ?
3503 pDXArray[ nTmpIdx - nTextStart ] ) - nHalfBlankWidth;
3506 Point aTopLeftRectPos( aTmpPos );
3510 Point aBottomRightRectPos( aTopLeftRectPos );
3525 if ( 0x200B == cChar )
3527 const OUString aSlash(
'/' );
3536 aSlash, 0, 1,
nullptr );
3537 Point aSlashPos( aTmpPos );
3542 aTmpFont.
QuickDrawText( &rOutDev, aSlashPos, aSlash, 0, 1, {} );
3555 assert( pAttr &&
"Field not found");
3559 nTextLen = aText.getLength();
3571 bParsingFields =
true;
3575 if( bParsingFields )
3587 std::vector< sal_Int32 >::iterator curIt = itSubLines;
3591 nTextStart = *curIt;
3592 nTextLen = *itSubLines - nTextStart;
3596 nTextStart = *curIt;
3597 nTextLen = nTextLen - nTextStart;
3598 bParsingFields =
false;
3600 if (nLine + 1 < nLines)
3606 && pOutlEditEng->GetCompatFlag(SdrCompatibilityFlag::IgnoreBreakAfterMultilineField)
3609 int nStartNextLine = pPortion->
GetLines()[nLine + 1].GetStartPortion();
3623 pDXArray = rKernArray;
3626 if( bMetafileValid )
3644 nTextLen = aText.getLength();
3652 pDXArray = rKernArray;
3657 Point aOutPos( aTmpPos );
3658 Point aRedLineTmpPos = aTmpPos;
3672 if(pWrongs && !pWrongs->
empty())
3674 size_t nStart =
nIndex, nEnd = 0;
3675 bool bWrong = pWrongs->
NextWrong(nStart, nEnd);
3680 if(nStart >= nMaxEnd)
3696 aWrongSpellVector.emplace_back(nStart, nEnd);
3703 bWrong = pWrongs->
NextWrong(nStart, nEnd);
3722 pFieldData = pFieldItem->
GetField();
3733 const bool bEndOfParagraph(bEndOfLine && nLine + 1 == nLines);
3750 !aWrongSpellVector.empty() ? &aWrongSpellVector :
nullptr,
3752 bEndOfLine, bEndOfParagraph,
3760 bEndOfParagraphWritten =
true;
3773 aRedLineTmpPos = aOutPos;
3795 bool bSpecialUnderline =
false;
3805 bSpecialUnderline =
true;
3807 if ( !bSpecialUnderline && ( pPrev->
GetEnd() < pPortion->
GetNode()->
Len() ) )
3811 bSpecialUnderline =
true;
3814 if ( bSpecialUnderline )
3821 OUStringBuffer aBlanks(nTextLen);
3823 Point aUnderlinePos( aOutPos );
3826 aUnderlinePos = aTmpPos;
3829 rOutDev.
DrawStretchText( aUnderlinePos, aSz.
Width(), aBlanks.makeStringAndClear(), 0, nTextLen );
3832 if ( !nOrientation )
3838 Point aRealOutPos( aOutPos );
3849 pDXArray[ nTextLen - 1 ] ==
3850 pDXArray[ nTextLen - 2 ] &&
3851 ' ' == aText[nTextStart + nTextLen - 1] )
3855 aTmpFont.
QuickDrawText( &rOutDev, aRealOutPos, aText, nTextStart, nTextLen, pDXArray, pKashidaArray );
3859 Point aTopLeft( aTmpPos );
3868 if ( pPDFExtOutDevData )
3877 if (
auto pUrlField =
dynamic_cast< const SvxURLField*
>( pFieldData ) )
3879 Point aTopLeft( aTmpPos );
3884 aBookmark.
nLinkId = pPDFExtOutDevData->
CreateLink(aRect, pUrlField->GetRepresentation());
3885 aBookmark.
aBookmark = pUrlField->GetURL();
3886 std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->
GetBookmarks();
3887 rBookmarks.push_back( aBookmark );
3907 lcl_DrawRedLines( rOutDev, aTmpFont.
GetFontSize().
Height(), aRedLineTmpPos,
static_cast<size_t>(
nIndex),
static_cast<size_t>(
nIndex) + rTextPortion.
GetLen(), pDXArray, pPortion->
GetNode()->
GetWrongList(), nOrientation, aOrigin,
IsEffectivelyVertical(), rTextPortion.
IsRightToLeft() );
3917 if( bMetafileValid )
3920 assert( pAttr &&
"Field not found" );
3923 DBG_ASSERT( pFieldItem !=
nullptr,
"Wrong type of field!" );
3947 sal_Int32 nChars = 2;
3952 else if ( nChars == 2 )
3955 OUStringBuffer
aBuf(nChars);
3957 OUString aText(
aBuf.makeStringAndClear());
3958 aTmpFont.
QuickDrawText( &rOutDev, aTmpPos, aText, 0, aText.getLength(), {} );
3965 const bool bEndOfParagraph(bEndOfLine && nLine + 1 == nLines);
3975 bEndOfLine, bEndOfParagraph,
3976 aOverlineColor, aTextLineColor);
3979 else if ( bStripOnly )
3985 const bool bEndOfParagraph(bEndOfLine && nLine + 1 == nLines);
3991 aTmpPos, OUString(), 0, 0, {}, {},
3995 bEndOfLine, bEndOfParagraph,
4004 if( bParsingFields )
4034 if(!bEndOfParagraphWritten && !bPaintBullet && bStripOnly)
4040 aTmpPos, OUString(), 0, 0, {}, {},
4055 if ( pPDFExtOutDevData )
4069 assert( pView &&
"No View - No Paint!" );
4097 if ( aClipRect.
Left() > nMaxX )
4099 if ( aClipRect.
Right() > nMaxX )
4103 bool bClipRegion =
rTarget.IsClipRegion();
4105 rTarget.IntersectClipRegion( aClipRect );
4110 rTarget.SetClipRegion( aOldRegion );
4119 DBG_ASSERT( pNode,
"NULL-Pointer in InsertContent! " );
4130 DBG_ASSERT( pNode,
"Invalid Node in SplitContent" );
4132 DBG_ASSERT( nSepPos <= pNode->Len(),
"Index out of range: SplitContent" );
4133 EditPaM aPaM( pNode, nSepPos );
4141 DBG_ASSERT( pLeftNode,
"Invalid left node in ConnectContents ");
4142 DBG_ASSERT( pRightNode,
"Invalid right node in ConnectContents ");
4160 return bPrevUpdateLayout;
4166 DBG_ASSERT( pPPortion,
"ShowParagraph: Paragraph does not exist! ");
4167 if ( !(pPPortion && ( pPPortion->
IsVisible() != bShow )) )
4176 aDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pPPortion->
GetNode(), nParagraph ));
4230 sal_Int32 nFirstPortion = std::min(
static_cast<sal_Int32
>(aOldPositions.
Min()), nNewPos );
4231 sal_Int32 nLastPortion = std::max(
static_cast<sal_Int32
>(aOldPositions.
Max()), nNewPos );
4235 if (pUpperPortion && pLowerPortion)
4249 sal_Int32 nFirstInvPara = std::min(
static_cast<sal_Int32
>(aOldPositions.
Min()), nNewPos );
4260 if ( nFirstInvPara != 0 )
4294 DBG_ASSERT( pPortion,
"GetPrevVisibleNode: No matching portion!" );
4304 DBG_ASSERT( pPortion,
"GetNextVisibleNode: No matching portion!" );
4316 while ( pPortion && !pPortion->
IsVisible() )
4327 while ( pPortion && !pPortion->
IsVisible() )
4336 sal_Int32 nTotalLineCount = 0;
4338 sal_Int32 nParaCount = rParaPortions.
Count();
4340 for (sal_Int32
i = 0;
i < nParaCount; ++
i)
4357 sal_Int32 nLineCount = rLines.
Count();
4358 nTotalLineCount += nLineCount;
4359 for (sal_Int32 j = 0; j < nLineCount; ++j)
4362 nTotalOccupiedHeight += rLine.
GetHeight();
4363 if (j < nLineCount-1)
4364 nTotalOccupiedHeight += nSBL;
4365 nTotalOccupiedHeight += nUL;
4370 nTotalSpace -= nTotalOccupiedHeight;
4371 if (nTotalSpace <= 0 || nTotalLineCount <= 1)
4378 return nTotalSpace / (nTotalLineCount-1);
4389 assert(pNode &&
"Not a single paragraph in InsertParagraph ?");
4403 std::optional<EditSelection> pSel;
4405 SAL_WARN_IF( !pNode,
"editeng",
"Paragraph does not exist: SelectParagraph" );
4421 if (bCalledFromUndo)
4507 sal_Int32 *pnSpaceBefore, sal_Int32 *pnMinLabelWidth )
const
4517 sal_Int32 nSpaceBefore = 0;
4518 sal_Int32 nMinLabelWidth = 0;
4523 nSpaceBefore = pNumFmt->
GetAbsLSpace() - nMinLabelWidth;
4524 DBG_ASSERT( nMinLabelWidth >= 0,
"ImpEditEngine::GetSpaceBeforeAndMinLabelWidth: min-label-width < 0 encountered" );
4527 *pnSpaceBefore = nSpaceBefore;
4528 if (pnMinLabelWidth)
4529 *pnMinLabelWidth = nMinLabelWidth;
4531 return nSpaceBefore + nMinLabelWidth;
4564 OUStringBuffer
aBuf(rString);
4565 for (sal_Int32 nIdx = nStt, nEnd = nStt + nLen; nIdx < nEnd; ++nIdx)
4568 if (cChar >=
'0' && cChar <=
'9')
4571 return aBuf.makeStringAndClear();
4593 bCTL = nScriptType == i18n::ScriptType::COMPLEX;
4602 nLayoutMode &=
~vcl::text::ComplexTextLayoutFlags::BiDiRtl;
4604 if ( !bCTL && !bR2L)
4613 nLayoutMode &=
~vcl::text::ComplexTextLayoutFlags::BiDiStrong;
4631 Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
4632 xBI = i18n::BreakIterator::create( xContext );
4641 Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
4642 xISC = i18n::InputSequenceChecker::create( xContext );
4678 sal_Int32* pDXArray, sal_uInt16 n100thPercentFromMax,
4679 bool bManipulateDXArray)
4682 DBG_ASSERT( pTextPortion->
GetLen(),
"ImplCalcAsianCompression - Empty Portion?" );
4685 if ( n100thPercentFromMax == 10000 )
4688 bool bCompressed =
false;
4693 sal_Int32 nPortionLen = pTextPortion->
GetLen();
4694 for ( sal_Int32
n = 0;
n < nPortionLen;
n++ )
4702 if ( bCompressPunctuation || bCompressKana )
4715 if ( (
n+1) < nPortionLen )
4717 nOldCharWidth = pDXArray[
n];
4721 if ( bManipulateDXArray )
4726 nOldCharWidth -= (
n ? pDXArray[
n-1] : 0 );
4730 if ( bCompressPunctuation )
4732 nCompress = nOldCharWidth / 2;
4736 nCompress = nOldCharWidth / 10;
4739 if ( n100thPercentFromMax != 10000 )
4741 nCompress *= n100thPercentFromMax;
4748 nNewPortionWidth -= nCompress;
4754 if ( bManipulateDXArray && ( pTextPortion->
GetLen() > 1 ) )
4765 for ( sal_Int32
i =
n-1;
i < (nPortionLen-1);
i++ )
4766 pDXArray[
i] -= nCompress;
4777 for ( sal_Int32
i =
n;
i < (nPortionLen-1);
i++ )
4778 pDXArray[
i] -= nCompress;
4785 if ( bCompressed && ( n100thPercentFromMax == 10000 ) )
4788 pTextPortion->
setWidth(nNewPortionWidth);
4790 if ( pTextPortion->
GetExtraInfos() && ( n100thPercentFromMax != 10000 ) )