/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* * This file is part of the LibreOffice project. * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * This file incorporates work covered by the following license notice: * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed * with this work for additional information regarding copyright * ownership. The ASF licenses this file to you under the Apache * License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
// Returns for how many characters an extra space has to be added // (for justified alignment). static TextFrameIndex lcl_AddSpace(const SwTextSizeInfo &rInf, const OUString* pStr, const SwLinePortion& rPor)
{
TextFrameIndex nPos, nEnd; const SwScriptInfo* pSI = nullptr;
if ( pStr )
{ // passing a string means we are inside a field
nPos = TextFrameIndex(0);
nEnd = TextFrameIndex(pStr->getLength());
} else
{
nPos = rInf.GetIdx();
nEnd = rInf.GetIdx() + rPor.GetLen();
pStr = &rInf.GetText();
pSI = &const_cast<SwParaPortion*>(rInf.GetParaPortion())->GetScriptInfo();
}
TextFrameIndex nCnt(0);
sal_uInt8 nScript = 0;
// If portion consists of Asian characters and language is not // Korean, we add extra space to each character. // first we get the script type if ( pSI )
nScript = pSI->ScriptType( nPos ); else
nScript = static_cast<sal_uInt8>(
g_pBreakIt->GetBreakIter()->getScriptType(*pStr, sal_Int32(nPos)));
// Note: rInf.GetIdx() can differ from nPos, // e.g., when rPor is a field portion. nPos refers to the string passed // to the function, rInf.GetIdx() refers to the original string.
// We try to find out which justification mode is required. This is done by // evaluating the script type and the language attribute set for this portion
// Asian Justification: Each character get some extra space if ( nEnd > nPos && ASIAN == nScript )
{
LanguageType aLang =
rInf.GetTextFrame()->GetLangOfChar(rInf.GetIdx(), nScript);
// Thai Justification: Each character cell gets some extra space if ( nEnd > nPos && COMPLEX == nScript )
{
LanguageType aLang =
rInf.GetTextFrame()->GetLangOfChar(rInf.GetIdx(), nScript);
// Here starts the good old "Look for blanks and add space to them" part. // Note: We do not want to add space to an isolated latin blank in front // of some complex characters in RTL environment constbool bDoNotAddSpace =
LATIN == nScript && (nEnd == nPos + TextFrameIndex(1)) && pSI &&
( i18n::ScriptType::COMPLEX ==
pSI->ScriptType(nPos + TextFrameIndex(1))) &&
rInf.GetTextFrame() && rInf.GetTextFrame()->IsRightToLeft();
// We still have to examine the next character: // If the next character is ASIAN and not KOREAN we have // to add an extra space // nPos refers to the original string, even if a field string has // been passed to this function
nPos = rInf.GetIdx() + rPor.GetLen(); if (nPos < TextFrameIndex(rInf.GetText().getLength()))
{
sal_uInt8 nNextScript = 0; const SwLinePortion* pPor = rPor.GetNextPortion(); if ( pPor && pPor->IsKernPortion() )
pPor = pPor->GetNextPortion();
if (!pPor || pPor->InFixMargGrp()) return nCnt;
// next character is inside a field? if ( CH_TXTATR_BREAKWORD == rInf.GetChar( nPos ) && pPor->InExpGrp() )
{ bool bOldOnWin = rInf.OnWin(); const_cast<SwTextSizeInfo &>(rInf).SetOnWin( false );
staticbool IsPaintTrailingSpaceDecorations(const SwTextFormatInfo& rInf)
{ // We underline (and show background of) the trailing whitespace, when either Word-compatible // trailing blanks are off, or underline Word-compatible trailing space is on. constauto& settings = rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess(); return !settings.get(DocumentSettingId::MS_WORD_COMP_TRAILING_BLANKS)
|| settings.get(DocumentSettingId::MS_WORD_UL_TRAIL_SPACE);
}
void SwTextPortion::BreakCut( SwTextFormatInfo &rInf, const SwTextGuess &rGuess )
{ // The word/char is larger than the line // Special case 1: The word is larger than the line // We truncate ... const SwTwips nLineWidth = rInf.Width() - rInf.X();
TextFrameIndex nLen = rGuess.CutPos() - rInf.GetIdx(); if (nLen > TextFrameIndex(0))
{ // special case: guess does not always provide the correct // width, only in common cases. if ( !rGuess.BreakWidth() )
{
rInf.SetLen( nLen );
SetLen( nLen );
CalcTextSize( rInf );
// changing these values requires also changing them in // guess.cxx
SwTwips nItalic = 0; if( ITALIC_NONE != rInf.GetFont()->GetItalic() && !rInf.NotEOL() )
{
nItalic = Height() / 12;
}
Width( Width() + nItalic );
} else
{
Width( rGuess.BreakWidth() );
SetLen( nLen );
}
} // special case: first character does not fit to line elseif ( rGuess.CutPos() == rInf.GetLineStart() )
{
SetLen( TextFrameIndex(1) );
Width( nLineWidth );
} else
{
SetLen( TextFrameIndex(0) );
Width( 0 );
ExtraShrunkWidth( 0 );
ExtraSpaceSize( 0 );
}
}
bool SwTextPortion::Format_( SwTextFormatInfo &rInf )
{ // 5744: If only the hyphen does not fit anymore, we still need to wrap // the word, or else return true! if( rInf.IsUnderflow() && rInf.GetSoftHyphPos() )
{ // soft hyphen portion has triggered an underflow event because // of an alternative spelling position bool bFull = false; constbool bHyph = rInf.ChgHyph( true ); if( rInf.IsHyphenate() )
{
SwTextGuess aGuess; // check for alternative spelling left from the soft hyphen // this should usually be true but
aGuess.AlternativeSpelling(rInf, rInf.GetSoftHyphPos() - TextFrameIndex(1));
bFull = CreateHyphen( rInf, aGuess );
OSL_ENSURE( bFull, "Problem with hyphenation!!!" );
}
rInf.ChgHyph( bHyph );
rInf.SetSoftHyphPos( TextFrameIndex(0) ); return bFull;
}
// tdf#158776 for the last full text portion, call Guess() again to allow more text in the // adjusted line by shrinking spaces using the know space count from the first Guess() call
SvxAdjustItem aAdjustItem = rInf.GetTextFrame()->GetTextNodeForParaProps()->GetSwAttrSet().GetAdjust(); const SvxAdjust aAdjust = aAdjustItem.GetAdjust(); bool bFullJustified = bFull && aAdjust == SvxAdjust::Block &&
pGuess->BreakPos() != TextFrameIndex(COMPLETE_STRING); bool bInteropSmartJustify = bFullJustified &&
rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
DocumentSettingId::JUSTIFY_LINES_WITH_SHRINKING); bool bNoWordSpacing = aAdjustItem.GetPropWordSpacing() == 100 &&
aAdjustItem.GetPropWordSpacingMinimum() == 100 &&
aAdjustItem.GetPropWordSpacingMaximum() == 100; // support old ODT documents, where only JustifyLinesWithShrinking was set bool bOldInterop = bInteropSmartJustify && bNoWordSpacing; bool bWordSpacing = bFullJustified && (!bNoWordSpacing || bOldInterop); bool bWordSpacingMaximum = bWordSpacing && !bOldInterop &&
aAdjustItem.GetPropWordSpacingMaximum() > aAdjustItem.GetPropWordSpacing(); bool bWordSpacingMinimum = bWordSpacing && ( bOldInterop ||
aAdjustItem.GetPropWordSpacingMinimum() < aAdjustItem.GetPropWordSpacing() );
if ( ( bInteropSmartJustify || bWordSpacing || bWordSpacingMaximum || bWordSpacingMinimum ) && // tdf#164499 no shrinking in tabulated line
( !rInf.GetLast() || !rInf.GetLast()->InTabGrp() ) && // tdf#158436 avoid shrinking at underflow, e.g. no-break space after a // very short word resulted endless loop
!rInf.IsUnderflow() )
{
sal_Int32 nSpacesInLine = rInf.GetLineSpaceCount( pGuess->BreakPos() );
sal_Int32 nSpacesInLineOrig = nSpacesInLine;
SwTextSizeInfo aOrigInf( rInf );
// call with an extra space: shrinking can result a new word in the line // and a new space before that, which is also a shrank space // (except if the line was already broken inside a word with hyphenation) // TODO: handle the case, if the line contains extra amount of spaces if ( // no automatic hyphenation
!pGuess->HyphWord().is() && // no hyphenation at soft hyphen
pGuess->BreakPos() < TextFrameIndex(rInf.GetText().getLength()) &&
rInf.GetText()[sal_Int32(pGuess->BreakPos())] != CHAR_SOFTHYPHEN )
{
++nSpacesInLine;
}
// there are spaces in the line, so it's possible to shrink them if ( nSpacesInLineOrig > 0 )
{
SwTwips nOldWidth = pGuess->BreakWidth(); bool bIsPortion = rInf.GetLineWidth() < rInf.GetBreakWidth();
bool bOrigHyphenated = pGuess->HyphWord().is() &&
pGuess->BreakPos() > rInf.GetLineStart(); // calculate line breaking with desired word spacing, also // if the desired word spacing is 100%, but there is a greater // maximum word spacing, and the word is hyphenated at the desired // word spacing: to skip hyphenation, if the maximum word spacing allows it if ( bWordSpacing || ( bWordSpacingMaximum && bOrigHyphenated ) )
{
pGuess.emplace();
bFull = !pGuess->Guess( *this, rInf, Height(), nSpacesInLine, aAdjustItem.GetPropWordSpacing(), nSpaceWidth );
sal_Int32 nSpacesInLine2 = rInf.GetLineSpaceCount( pGuess->BreakPos() );
sal_Int32 nSpacesInLineShrink = 0; // TODO if both maximum word spacing or minimum word spacing can disable hyphenation, prefer the last one if ( bWordSpacingMinimum )
{
std::optional<SwTextGuess> pGuess2(std::in_place);
SwTwips nOldExtraSpace = rInf.GetExtraSpace(); // break the line after the hyphenated word, if it's possible // (hyphenation is disabled in Guess(), when called with GetPropWordSpacingMinimum())
sal_uInt16 nMinimum = bOldInterop ? 75 : aAdjustItem.GetPropWordSpacingMinimum(); bool bFull2 = !pGuess2->Guess( *this, rInf, Height(), nSpacesInLine, nMinimum, nSpaceWidth );
nSpacesInLineShrink = rInf.GetLineSpaceCount( pGuess2->BreakPos() ); if ( pGuess2->BreakWidth() > nOldWidth )
{ // instead of the maximum shrinking, break after the word which was hyphenated before
sal_Int32 i = sal_Int32(pGuess->BreakPos());
sal_Int32 j = sal_Int32(pGuess2->BreakPos()); // skip terminal spaces for (; i < j && rInf.GetText()[i] == CH_BLANK; ++i); for (; j > i && rInf.GetText()[i] == CH_BLANK; --j);
sal_Int32 nOldBreakTrim = i;
sal_Int32 nOldBreak = j - i; for (; i < j; ++i)
{
sal_Unicode cChar = rInf.GetText()[i]; // first space after the hyphenated word, and it's not the chosen one if ( cChar == CH_BLANK )
{ // using a weighted word spacing, try to break the line after the hyphenated word
sal_Int32 nNewBreak = i - nOldBreakTrim;
SwTwips nWeightedSpacing = nMinimum * (1.0 * nNewBreak/nOldBreak) +
aAdjustItem.GetPropWordSpacing() * (1.0 * (nOldBreak - nNewBreak)/nOldBreak);
std::optional<SwTextGuess> pGuess3(std::in_place);
pGuess3->Guess( *this, rInf, Height(), nSpacesInLineShrink-1, nWeightedSpacing, nSpaceWidth );
// these are the possible cases: // A Portion fits to current line // B Portion does not fit to current line but a possible line break // within the portion has been found by the break iterator, 2 subcases // B1 break is hyphen // B2 break is word end // C Portion does not fit to current line and no possible line break // has been found by break iterator, 2 subcases: // C1 break iterator found a possible line break in portion before us // ==> this break is used (underflow) // C2 break iterator does not found a possible line break at all: // ==> line break
// case A: line not yet full if ( !bFull )
{
Width( pGuess->BreakWidth() );
ExtraBlankWidth(pGuess->ExtraBlankWidth()); // Caution! if( !InExpGrp() || InFieldGrp() )
SetLen( rInf.GetLen() );
short nKern = rInf.GetFont()->CheckKerning(); if( nKern > 0 && rInf.Width() < rInf.X() + Width() + nKern )
{
nKern = static_cast<short>(rInf.Width() - rInf.X() - Width() - 1); if( nKern < 0 )
nKern = 0;
} if( nKern ) new SwKernPortion( *this, nKern );
} // special case: hanging portion elseif( pGuess->GetHangingPortion() )
{
Width( pGuess->BreakWidth() );
SetLen( pGuess->BreakPos() - rInf.GetIdx() );
pGuess->GetHangingPortion()->SetAscent( GetAscent() );
Insert( pGuess->ReleaseHangingPortion() );
} // breakPos >= index elseif (pGuess->BreakPos() >= rInf.GetIdx() && pGuess->BreakPos() != TextFrameIndex(COMPLETE_STRING))
{ // case B1 if( pGuess->HyphWord().is() && pGuess->BreakPos() > rInf.GetLineStart()
&& ( pGuess->BreakPos() > rInf.GetIdx() ||
( rInf.GetLast() && ! rInf.GetLast()->IsFlyPortion() ) ) )
{
CreateHyphen( rInf, *pGuess ); if ( rInf.GetFly() )
rInf.GetRoot()->SetMidHyph( true ); else
rInf.GetRoot()->SetEndHyph( true );
} // case C1 // - Footnote portions with fake line start (i.e., not at beginning of line) // should keep together with the text portion. (Note: no keep together // with only footnote portions. // - TabPortions not at beginning of line should keep together with the // text portion, if they are not followed by a blank // (work around different definition of tab stop character - breaking or // non breaking character - in compatibility mode) elseif ( ( IsFootnotePortion() && rInf.IsFakeLineStart() &&
rInf.IsOtherThanFootnoteInside() ) ||
( rInf.GetLast() &&
rInf.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::TAB_COMPAT) &&
rInf.GetLast()->InTabGrp() &&
rInf.GetLineStart() + rInf.GetLast()->GetLen() < rInf.GetIdx() &&
pGuess->BreakPos() == rInf.GetIdx() &&
CH_BLANK != rInf.GetChar( rInf.GetIdx() ) &&
CH_FULL_BLANK != rInf.GetChar( rInf.GetIdx() ) &&
CH_SIX_PER_EM != rInf.GetChar( rInf.GetIdx() ) ) )
BreakUnderflow( rInf ); // case B2 elseif( rInf.GetIdx() > rInf.GetLineStart() ||
pGuess->BreakPos() > rInf.GetIdx() || // this is weird: during formatting the follow of a field // the values rInf.GetIdx and rInf.GetLineStart are replaced // IsFakeLineStart indicates GetIdx > GetLineStart
rInf.IsFakeLineStart() ||
rInf.GetFly() ||
rInf.IsFirstMulti() ||
( rInf.GetLast() &&
( rInf.GetLast()->IsFlyPortion() ||
( rInf.GetLast()->InFieldGrp() &&
! rInf.GetLast()->InNumberGrp() &&
! rInf.GetLast()->IsErgoSumPortion() &&
lcl_HasContent(*static_cast<SwFieldPortion*>(rInf.GetLast()),rInf ) ) ) ) )
{
Width( pGuess->BreakWidth() );
SetLen( pGuess->BreakPos() - rInf.GetIdx() );
// Clamp layout context to the end of the line if(auto stClampedContext = GetLayoutContext(); stClampedContext.has_value()) {
stClampedContext->m_nEnd = pGuess->BreakPos().get();
SetLayoutContext(stClampedContext);
}
OSL_ENSURE( pGuess->BreakStart() >= pGuess->FieldDiff(), "Trouble with expanded field portions during line break" );
TextFrameIndex const nRealStart = pGuess->BreakStart() - pGuess->FieldDiff(); if( pGuess->BreakPos() < nRealStart && !InExpGrp() )
{
TextFrameIndex nTotalExtraLen(nRealStart - pGuess->BreakPos());
TextFrameIndex nExtraLen(nTotalExtraLen);
TextFrameIndex nExtraLenOutOfLine(0);
SwTwips nTotalExtraWidth(pGuess->ExtraBlankWidth());
SwTwips nExtraWidth(nTotalExtraWidth);
SwTwips nExtraWidthOutOfLine(0);
SwTwips nAvailableLineWidth(rInf.GetLineWidth() - Width()); bool bPaintSpaceDecorations(IsPaintTrailingSpaceDecorations(rInf)); if (nExtraWidth > nAvailableLineWidth && bPaintSpaceDecorations)
{
GetLimitedStringPart(rInf, pGuess->BreakPos(), nTotalExtraLen, GetMaxComp(rInf),
nTotalExtraWidth, nAvailableLineWidth, nExtraLen,
nExtraWidth); if (nExtraLen)
{
nExtraLenOutOfLine = nTotalExtraLen - nExtraLen;
nExtraWidthOutOfLine = nTotalExtraWidth - nExtraWidth;
} else
{ // Not a single space fits to the available width - don't create decorated // hole portion
nExtraLen = nTotalExtraLen;
nExtraWidth = nTotalExtraWidth;
bPaintSpaceDecorations = false;
}
}
if (nExtraWidthOutOfLine)
{ // Out-of-line hole portion - will not show underline
SwHolePortion* pNewOutOfLine = new SwHolePortion(*this, false);
pNewOutOfLine->SetLen(nExtraLenOutOfLine);
pNewOutOfLine->ExtraBlankWidth(nExtraWidthOutOfLine);
pNew->Insert(pNewOutOfLine);
}
// UAX #14 Unicode Line Breaking Algorithm Non-tailorable Line breaking rule LB6: // https://www.unicode.org/reports/tr14/#LB6 Do not break before hard line breaks if (auto ch = rInf.GetChar(pGuess->BreakStart()); !ch || ch == CH_BREAK)
bFull = false; // Keep following SwBreakPortion / para break in the same line
}
} else// case C2, last exit
BreakCut( rInf, *pGuess );
} // breakPos < index or no breakpos at all else
{ bool bFirstPor = rInf.GetLineStart() == rInf.GetIdx(); if (pGuess->BreakPos() != TextFrameIndex(COMPLETE_STRING) &&
pGuess->BreakPos() != rInf.GetLineStart() &&
( !bFirstPor || rInf.GetFly() || rInf.GetLast()->IsFlyPortion() ||
rInf.IsFirstMulti() ) &&
( !rInf.GetLast()->IsBlankPortion() ||
SwBlankPortion::MayUnderflow(rInf, rInf.GetIdx() - TextFrameIndex(1), true)))
{ // case C1 (former BreakUnderflow())
BreakUnderflow( rInf );
} else // case C2, last exit
BreakCut(rInf, *pGuess);
}
// Format end of line // 5083: We can have awkward cases e.g.: // "from {Santa}" // Santa wraps, "from " turns into "from" and " " in a justified // paragraph, in which the glue gets expanded instead of merged // with the MarginPortion.
// rInf.nIdx points to the next word, nIdx-1 is the portion's last char void SwTextPortion::FormatEOL( SwTextFormatInfo &rInf )
{ if( ( GetNextPortion() &&
( !GetNextPortion()->IsKernPortion() || GetNextPortion()->GetNextPortion() ) ) ||
!GetLen() ||
rInf.GetIdx() >= TextFrameIndex(rInf.GetText().getLength()) ||
TextFrameIndex(1) >= rInf.GetIdx() || ' ' != rInf.GetChar(rInf.GetIdx() - TextFrameIndex(1)) ||
rInf.GetLast()->IsHolePortion() ) return;
// Responsible for the justified paragraph. They calculate the blank // count and the resulting added space.
TextFrameIndex SwTextPortion::GetSpaceCnt(const SwTextSizeInfo &rInf,
TextFrameIndex& rCharCnt) const
{
TextFrameIndex nCnt(0);
TextFrameIndex nPos(0);
if ( rInf.SnapToGrid() )
{
SwTextGridItem const*const pGrid(GetGridItem(rInf.GetTextFrame()->FindPageFrame())); if (pGrid && SwTextGrid::LinesAndChars == pGrid->GetGridType() && pGrid->IsSnapToChars()) return TextFrameIndex(0);
}
if ( InExpGrp() || PortionType::InputField == GetWhichPor() )
{ if (OUString ExpOut;
(!IsBlankPortion()
|| (GetExpText(rInf, ExpOut) && OUStringChar(CH_BLANK) == ExpOut))
&& !InNumberGrp() && !IsCombinedPortion())
{ // OnWin() likes to return a blank instead of an empty string from // time to time. We cannot use that here at all, however. bool bOldOnWin = rInf.OnWin(); const_cast<SwTextSizeInfo &>(rInf).SetOnWin( false );
if ( rInf.SnapToGrid() )
{
SwTextGridItem const*const pGrid(GetGridItem(rInf.GetTextFrame()->FindPageFrame())); if (pGrid && SwTextGrid::LinesAndChars == pGrid->GetGridType() && pGrid->IsSnapToChars()) return 0;
}
if ( InExpGrp() || PortionType::InputField == GetWhichPor() )
{ if (OUString ExpOut;
(!IsBlankPortion()
|| (GetExpText(rInf, ExpOut) && OUStringChar(CH_BLANK) == ExpOut))
&& !InNumberGrp() && !IsCombinedPortion())
{ // OnWin() likes to return a blank instead of an empty string from // time to time. We cannot use that here at all, however. bool bOldOnWin = rInf.OnWin(); const_cast<SwTextSizeInfo &>(rInf).SetOnWin( false );
// we do not want an extra space in front of margin portions if ( nCnt )
{ while ( pPor && !pPor->Width() && ! pPor->IsHolePortion() )
pPor = pPor->GetNextPortion();
// The GetTextSize() assumes that the own length is correct
SwPositiveSize SwHolePortion::GetTextSize(const SwTextSizeInfo& rInf) const
{
SwPositiveSize aSize = rInf.GetTextSize(); if (!GetJoinBorderWithPrev())
aSize.Width(aSize.Width() + rInf.GetFont()->GetLeftBorderSpace()); if (!GetJoinBorderWithNext())
aSize.Width(aSize.Width() + rInf.GetFont()->GetRightBorderSpace());
// #i16816# export stuff only needed for tagged pdf support if (bPDFExport && !SwTaggedPDFHelper::IsExportTaggedPDF( *rInf.GetOut()) ) return;
// #i68503# the hole must have no decoration for a consistent visual appearance const SwFont* pOrigFont = rInf.GetFont();
std::unique_ptr<SwFont> pHoleFont;
std::optional<SwFontSave> oFontSave; if( !m_bShowUnderline && (pOrigFont->GetUnderline() != LINESTYLE_NONE
|| pOrigFont->GetOverline() != LINESTYLE_NONE
|| pOrigFont->GetStrikeout() != STRIKEOUT_NONE) )
{
pHoleFont.reset(new SwFont( *pOrigFont ));
pHoleFont->SetUnderline(LINESTYLE_NONE);
pHoleFont->SetOverline( LINESTYLE_NONE );
pHoleFont->SetStrikeout( STRIKEOUT_NONE );
oFontSave.emplace( rInf, pHoleFont.get() );
}
if (bPDFExport)
{
rInf.DrawText(u" "_ustr, *this, TextFrameIndex(0), TextFrameIndex(1));
} else
{ if (m_bShowUnderline)
{
rInf.DrawBackBrush(*this);
rInf.DrawBorder(*this);
} // tdf#43244: Paint spaces even at end of line, // but only if this paint is not called for pdf export, to keep that pdf export intact
rInf.DrawText(*this, rInf.GetLen());
}
bool SwFieldFormCheckboxPortion::Format( SwTextFormatInfo & rInf )
{
SwPosition const aPosition(rInf.GetTextFrame()->MapViewToModelPos(rInf.GetIdx()));
Fieldmark const*const pBM = rInf.GetTextFrame()->GetDoc().getIDocumentMarkAccess()->getFieldmarkAt(aPosition);
OSL_ENSURE(pBM && pBM->GetFieldname( ) == ODF_FORMCHECKBOX, "Where is my form field bookmark???"); if (pBM && pBM->GetFieldname( ) == ODF_FORMCHECKBOX)
{ // the width of the checkbox portion is the same as its height since it's a square // and that size depends on the font size. // See: // http://document-foundation-mail-archive.969070.n3.nabble.com/Wrong-copy-paste-in-SwFieldFormCheckboxPortion-Format-td4269112.html
Width( rInf.GetTextHeight( ) );
Height( rInf.GetTextHeight( ) );
SetAscent( rInf.GetAscent( ) );
} returnfalse;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.