/* -*- 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 .
*/
//JP 16.12.99: definition: // from pos cPosEnDash to cPosEmDash all chars changed to em dashes, // from pos cPosEmDash to cPosEnd all chars changed to em dashes // all other chars are changed to the user configuration
// Number of num-/bullet-paragraph templates. MAXLEVEL will soon be raised // to x, but not the number of templates. (Artifact from <= 4.0) const sal_uInt16 cnNumBullColls = 4;
class SwAutoFormat
{
SvxSwAutoFormatFlags m_aFlags;
SwPaM m_aDelPam; // a Pam that can be used
SwNodeIndex m_aNdIdx; // the index on the current TextNode
SwNodeIndex m_aEndNdIdx; // index on the end of the area
SwEditShell* m_pEditShell;
SwDoc* m_pDoc;
SwTextNode* m_pCurTextNd; // the current TextNode
SwTextFrame* m_pCurTextFrame; // frame of the current TextNode bool m_bIsRightToLeft; // text direction of the current frame
SwNodeOffset m_nEndNdIdx; // for the percentage-display mutable std::optional<CharClass> m_oCharClass; // Character classification mutable LanguageType m_eCharClassLang;
// AutoCorrect actions case STR_AUTOFMTREDL_USE_REPLACE: case STR_AUTOFMTREDL_CPTL_STT_WORD: case STR_AUTOFMTREDL_CPTL_STT_SENT: case STR_AUTOFMTREDL_TYPO: case STR_AUTOFMTREDL_UNDER: case STR_AUTOFMTREDL_BOLD: case STR_AUTOFMTREDL_FRACTION: case STR_AUTOFMTREDL_DASH: case STR_AUTOFMTREDL_ORDINAL: case STR_AUTOFMTREDL_NON_BREAK_SPACE: case STR_AUTOFMTREDL_TRANSLITERATE_RTL: case STR_AUTOFMTREDL_ITALIC: case STR_AUTOFMTREDL_STRIKETHROUGH:
nSeqNo = ++m_nRedlAutoFormatSeqId; break;
}
} #if OSL_DEBUG_LEVEL > 0 else
sText = "Action text is missing"; #endif
void SwAutoFormat::GoNextPara()
{
SwNode* pNewNd = nullptr; do { // has to be checked twice before and after incrementation if( m_aNdIdx.GetIndex() >= m_aEndNdIdx.GetIndex() )
{
m_bEnd = true; return;
}
bool SwAutoFormat::HasObjects(const SwTextFrame & rFrame)
{ // Is there something bound to the paragraph in the paragraph // like Frames, DrawObjects, ...
SwNodeIndex node(*rFrame.GetTextNodeFirst()); do
{ if (!node.GetNode().GetAnchoredFlys().empty()) returntrue;
++node;
} while (sw::FrameContainsNode(rFrame, node.GetIndex())); returnfalse;
}
const SwTextFrame* SwAutoFormat::GetNextNode(boolconst isCheckEnd) const
{
SwNodeIndex tmp(m_aNdIdx);
sw::GotoNextLayoutTextFrame(tmp, m_pEditShell->GetLayout()); if ((isCheckEnd && m_aEndNdIdx <= tmp) || !tmp.GetNode().IsTextNode()) return nullptr; // note: the returned frame is not necessarily formatted, have to call // EnsureFormatted for that returnstatic_cast<SwTextFrame*>(tmp.GetNode().GetTextNode()->getLayoutFrame(m_pEditShell->GetLayout()));
}
// -, +, * separated by blank ?? if (TextFrameIndex(nMinLen) < nLen && IsSpace(rText[sal_Int32(nBlanks) + 1]))
{ if (StrChr(pBulletChar, rText[sal_Int32(nBlanks)])) returntrue; // Should there be a symbol font at the position?
SwTextFrameInfo aFInfo( EnsureFormatted(rFrame) ); if (aFInfo.IsBullet(nBlanks)) returntrue;
}
if (RES_POOLCOLL_TEXT_MOVE == rFrame.GetTextNodeForParaProps()->GetTextColl()->GetPoolFormatId())
{ if( m_aFlags.bAFormatByInput )
{ // this is very non-obvious: on the *first* invocation of // AutoFormat, the node will have the tabs (any number) converted // to a fixed indent in BuildTextIndent(), and the number of tabs // is stored in the node; // on the *second* invocation of AutoFormat, CalcLevel() will // retrieve the stored number, and it will be used by // BuildHeadLine() to select the corresponding heading style.
nLvl = rFrame.GetTextNodeForParaProps()->GetAutoFormatLvl(); const_cast<SwTextNode *>(rFrame.GetTextNodeForParaProps())->SetAutoFormatLvl(0); if( nLvl ) return nLvl;
}
++nLvl;
}
if( 2 < nCnt )
{ // then underline the previous paragraph if one exists
DelEmptyLine( false ); // -> point will be on end of current paragraph // WARNING: rText may be deleted now, m_pCurTextFrame may be nullptr
m_aDelPam.SetMark(); // apply to last node & rely on InsertItemSet to apply it to props-node
editeng::SvxBorderLine aLine; switch( eState )
{ case 1: // single, hairline
aLine.SetBorderLineStyle(SvxBorderLineStyle::SOLID);
aLine.SetWidth( SvxBorderLineWidth::Hairline ); break; case 2: // single, thin
aLine.SetBorderLineStyle(SvxBorderLineStyle::SOLID);
aLine.SetWidth( SvxBorderLineWidth::Thin ); break; case 3: // double, thin
aLine.SetBorderLineStyle(SvxBorderLineStyle::DOUBLE);
aLine.SetWidth( SvxBorderLineWidth::Thin ); break; case 4: // double, thick/thin
aLine.SetBorderLineStyle(SvxBorderLineStyle::THICKTHIN_SMALLGAP);
aLine.SetWidth( SvxBorderLineWidth::Thick ); break; case 5: // double, thin/thick
aLine.SetBorderLineStyle(SvxBorderLineStyle::THINTHICK_SMALLGAP);
aLine.SetWidth( SvxBorderLineWidth::Thick ); break; case 6: // double, medium
aLine.SetBorderLineStyle(SvxBorderLineStyle::DOUBLE);
aLine.SetWidth( SvxBorderLineWidth::Medium ); break;
}
SfxItemSetFixed<RES_PARATR_CONNECT_BORDER, RES_PARATR_CONNECT_BORDER,
RES_BOX, RES_BOX> aSet(m_pDoc->GetAttrPool());
aSet.Put( SwParaConnectBorderItem( false ) );
SvxBoxItem aBox( RES_BOX );
aBox.SetLine( &aLine, SvxBoxItemLine::BOTTOM );
aBox.SetDistance(42, SvxBoxItemLine::BOTTOM ); // ~0,75 mm
aSet.Put(aBox);
m_pDoc->getIDocumentContentOperations().InsertItemSet(m_aDelPam, aSet,
SetAttrMode::DEFAULT, m_pEditShell->GetLayout());
if( 1 < aPosArr.size() )
{ // get the text node's alignment
sal_uInt16 nColCnt = aPosArr.size() - 1;
SwTwips nSttPos = aPosArr[ 0 ];
sal_Int16 eHori; switch (m_pCurTextFrame->GetTextNodeForParaProps()->GetSwAttrSet().GetAdjust().GetAdjust())
{ case SvxAdjust::Center: eHori = text::HoriOrientation::CENTER; break; case SvxAdjust::Right: eHori = text::HoriOrientation::RIGHT; break;
default: if( nSttPos )
{
eHori = text::HoriOrientation::NONE; // then - as last - we need to add the current frame width into the array
aPosArr.push_back( o3tl::narrowing<sal_uInt16>(m_pCurTextFrame->getFrameArea().Width()) );
} else
eHori = text::HoriOrientation::LEFT; break;
}
// then create a table that matches the character
DelEmptyLine(); // WARNING: rTmp may be deleted now, m_pCurTextFrame may be nullptr
SwNodeIndex aIdx( m_aDelPam.GetPoint()->GetNode() );
m_aDelPam.Move( fnMoveForward );
m_pDoc->InsertTable( SwInsertTableOptions( SwInsertTableFlags::All , 1 ),
*m_aDelPam.GetPoint(), 1, nColCnt, eHori,
nullptr, &aPosArr );
m_aDelPam.GetPoint()->Assign(aIdx);
} return 1 < aPosArr.size();
}
OUString SwAutoFormat::DelLeadingBlanks( const OUString& rStr )
{
sal_Int32 nL, n; for( nL = rStr.getLength(), n = 0; n < nL && IsSpace( rStr[n] ); ++n )
; if( n ) // no Spaces return rStr.copy(n); return rStr;
}
sal_uInt16 nStart = 0;
sal_uInt8 nDigitLvl = 0, nDigitCnt = 0; // count number of parenthesis to assure a sensible order is found
sal_uInt16 nOpeningParentheses = 0;
sal_uInt16 nClosingParentheses = 0;
while (nPos < rText.getLength() && nDigitLvl < MAXLEVEL - 1)
{ autoconst pair = rFrame.MapViewToModel(TextFrameIndex(nPos));
CharClass& rCC = GetCharClass(pair.first->GetSwAttrSet().GetLanguage().GetLanguage()); const sal_Unicode cCurrentChar = rText[nPos]; if( ('0' <= cCurrentChar && '9' >= cCurrentChar) ||
(0xff10 <= cCurrentChar && 0xff19 >= cCurrentChar) )
{ if( eScan & DELIM )
{ if( eScan & CHG ) // not if it starts with a number
{
++nDigitLvl; if( pPostfix )
*pPostfix += "\x01";
}
/// Is there a dot at the end? bool SwAutoFormat::IsSentenceAtEnd(const SwTextFrame & rTextFrame)
{ const OUString& rStr = rTextFrame.GetText();
sal_Int32 n = rStr.getLength(); if( !n ) returntrue;
while( --n && IsSpace( rStr[ n ] ) )
; return'.' == rStr[ n ];
}
/// Delete beginning and/or end in a node void SwAutoFormat::DeleteLeadingTrailingBlanks(bool bStart, bool bEnd)
{ if( !(m_aFlags.bAFormatByInput
? m_aFlags.bAFormatByInpDelSpacesAtSttEnd
: m_aFlags.bAFormatDelSpacesAtSttEnd) ) return;
// delete blanks at the end of the current and at the beginning of the next one
m_aDelPam.DeleteMark();
TextFrameIndex nPos(GetLeadingBlanks(m_pCurTextFrame->GetText())); if (bStart && TextFrameIndex(0) != nPos)
{
*m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(TextFrameIndex(0));
m_aDelPam.SetMark();
*m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nPos);
DeleteSel( m_aDelPam );
m_aDelPam.DeleteMark();
}
nPos = TextFrameIndex(GetTrailingBlanks(m_pCurTextFrame->GetText())); if (bEnd && TextFrameIndex(m_pCurTextFrame->GetText().getLength()) != nPos)
{
*m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(
TextFrameIndex(m_pCurTextFrame->GetText().getLength()));
m_aDelPam.SetMark();
*m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(nPos);
DeleteSel( m_aDelPam );
m_aDelPam.DeleteMark();
}
}
void SwAutoFormat::DeleteSelImpl(SwPaM & rDelPam, SwPaM & rPamToCorrect)
{ if (m_aFlags.bWithRedlining || &rDelPam != &rPamToCorrect)
{ // Add to Shell-Cursor-Ring so that DelPam will be moved as well!
SwPaM* pShCursor = m_pEditShell->GetCursor_();
SwPaM aTmp( *m_pCurTextNd, 0, pShCursor );
// and remove Pam again:
SwPaM* p;
SwPaM* pNext = &rPamToCorrect; do {
p = pNext;
pNext = p->GetNext();
p->MoveTo( &rPamToCorrect );
} while( p != pPrev );
m_aNdIdx = aTmp.GetPoint()->GetNode();
m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
m_pCurTextFrame = GetFrame(*m_pCurTextNd); // keep it up to date
} else
m_pEditShell->DeleteSel(rDelPam, true);
}
bool SwAutoFormat::DeleteJoinCurNextPara(SwTextFrame const*const pNextFrame, boolconst bIgnoreLeadingBlanks)
{ // delete blanks at the end of the current and at the beginning of the next one
m_aDelPam.DeleteMark();
TextFrameIndex nTrailingPos(GetTrailingBlanks(m_pCurTextFrame->GetText()));
// Is there a Blank at the beginning or end? // Do not delete it, it will be inserted again. bool bHasBlnks = HasSelBlanks(m_pCurTextFrame, nTrailingPos, pEndFrame, nLeadingPos);
m_aDelPam.GetMark()->Assign( m_pCurTextFrame->GetTextNodeFirst()->GetIndex() - 1 );
SwTextNode* pTNd = m_aDelPam.GetMarkNode().GetTextNode(); if( pTNd ) // first use the previous text node
m_aDelPam.GetMark()->SetContent(pTNd->GetText().getLength()); elseif( bTstNextPara )
{ // then try the next (at the beginning of a Doc, table cells, frames, ...) const SwTextNode* pNext = m_pCurTextFrame->GetMergedPara()
? m_pCurTextFrame->GetMergedPara()->pLastNode
: m_pCurTextNd;
m_aDelPam.GetMark()->Assign(pNext->GetIndex() + 1);
pTNd = m_aDelPam.GetMarkNode().GetTextNode(); if( pTNd )
{
*m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(
TextFrameIndex(m_pCurTextFrame->GetText().getLength()));
}
} if( pTNd )
{ // join with previous or next paragraph
DeleteSel(m_aDelPam);
}
assert(m_aDelPam.GetPointNode().IsTextNode());
assert(!m_aDelPam.HasMark());
m_aDelPam.SetMark(); // mark remains at join position
m_pCurTextFrame = GetFrame(*m_aDelPam.GetPointNode().GetTextNode()); // replace until the end of the merged paragraph
*m_aDelPam.GetPoint() = m_pCurTextFrame->MapViewToModelPos(
TextFrameIndex(m_pCurTextFrame->GetText().getLength())); if (*m_aDelPam.GetPoint() != *m_aDelPam.GetMark())
{ // tdf#137245 replace (not delete) to preserve any flys
m_pDoc->getIDocumentContentOperations().ReplaceRange(m_aDelPam, u""_ustr, false);
}
void SwAutoFormat::BuildNegIndent( SwTwips nSpaces )
{
SetRedlineText( STR_AUTOFMTREDL_SET_TMPL_NEG_INDENT ); // Test of contraposition (n words, divided by spaces/tabs, with same indentation in 2nd line)
// read all succeeding paragraphs that belong to this enumeration bool bBreak = true;
TextFrameIndex nSpacePos(0); const sal_Int32 nTextPos = GetBigIndent( nSpacePos ); if( m_bMoreLines )
DelMoreLinesBlanks( true ); else
bBreak = !IsFastFullLine(*m_pCurTextFrame)
|| (!nTextPos && IsBlanksInString(*m_pCurTextFrame))
|| IsSentenceAtEnd(*m_pCurTextFrame);
do { while (nPos < TextFrameIndex(pText->getLength())
&& IsSpace(cChar = (*pText)[sal_Int32(nPos)]))
++nPos; if (nPos == TextFrameIndex(pText->getLength())) break; // that's it
if (pATst->FnChgWeightUnderl(aACorrDoc, *pText, sal_Int32(nPos)))
{ if (m_aFlags.bWithRedlining)
{
m_aNdIdx = m_aDelPam.GetPoint()->GetNode();
m_pCurTextNd = m_aNdIdx.GetNode().GetTextNode();
m_pCurTextFrame = GetFrame(*m_pCurTextNd);
pText = &m_pCurTextFrame->GetText();
m_aDelPam.SetMark();
m_aDelPam.DeleteMark();
aFInfo.SetFrame(nullptr);
} //#125102# in case of the mode RedlineFlags::ShowDelete the // or -- are still contained in pText if (m_pDoc->getIDocumentRedlineAccess().GetRedlineFlags() & RedlineFlags::ShowDelete)
{
nPos = m_pCurTextFrame->MapModelToViewPos(*m_aDelPam.GetPoint())
- TextFrameIndex(1);
bBreak++;
} // Was a character deleted before starting? if (cBlank && cBlank != (*pText)[sal_Int32(nSttPos) - 1])
--nSttPos;
}
}
} break;
case'.': case'!': case'?': if( m_aFlags.bCapitalStartSentence )
bFirstSent = true;
[[fallthrough]]; default: if (!(rAppCC.isBase(*pText, sal_Int32(nPos))
|| '/' == cChar )) // '/' should not be a word separator (e.g. '1/2' needs to be handled as one word for replacement)
{
--nPos; // revert ++nPos which was decremented in for loop
++bBreak;
} break;
}
}
// set area for autoformatting if( pSttNd )
{
assert(pEndNd);
m_aNdIdx = *pSttNd; // for GoNextPara, one paragraph prior to that
sw::GotoPrevLayoutTextFrame(m_aNdIdx, m_pEditShell->GetLayout());
m_aEndNdIdx = *pEndNd;
sw::GotoNextLayoutTextFrame(m_aEndNdIdx, m_pEditShell->GetLayout());
// This is the automat for autoformatting
eStat = READ_NEXT_PARA; while( !m_bEnd )
{ switch( eStat )
{ case READ_NEXT_PARA:
{
GoNextPara();
eStat = m_bEnd ? IS_END : TST_EMPTY_LINE;
} break;
case TST_EMPTY_LINE:
assert(m_pCurTextFrame); if (IsEmptyLine(*m_pCurTextFrame))
{ if (m_aFlags.bDelEmptyNode && !HasObjects(*m_pCurTextFrame))
{
bEmptyLine = true;
SwNodeOffset nOldCnt = m_pDoc->GetNodes().Count();
DelEmptyLine(); // Was there really a deletion of a node? if( nOldCnt != m_pDoc->GetNodes().Count() )
{ // do not skip the next paragraph
sw::GotoPrevLayoutTextFrame(m_aNdIdx, m_pEditShell->GetLayout());
}
}
eStat = READ_NEXT_PARA;
} else
eStat = TST_ALPHA_LINE; break;
case TST_ALPHA_LINE:
assert(m_pCurTextFrame); if (IsNoAlphaLine(*m_pCurTextFrame))
{ // recognize a table definition +---+---+ if( m_aFlags.bAFormatByInput && m_aFlags.bCreateTable && DoTable() )
{ //JP 30.09.96: DoTable() builds on PopCursor and MoveCursor after AutoFormat!
pEdShell->Pop(SwCursorShell::PopMode::DeleteCurrent); static_cast<SwPaM&>(*pEdShell->GetCursor()) = m_aDelPam;
pEdShell->Push();
// Check for 3 "---" or "===". In this case, the previous paragraph should be // underlined and the current be deleted! if( !DoUnderline() && bReplaceStyles )
{
SetColl( RES_POOLCOLL_STANDARD, true );
bEmptyLine = true;
}
eStat = READ_NEXT_PARA;
} else
eStat = GET_ALL_INFO; break;
case GET_ALL_INFO:
{
assert(m_pCurTextFrame); if (m_pCurTextFrame->GetTextNodeForParaProps()->GetNumRule())
{ // do nothing in numbering, go to next
bEmptyLine = false;
eStat = READ_NEXT_PARA; // delete all blanks at beginning/end and in between //JP 29.04.98: first only "all in between"
DelMoreLinesBlanks(); // auto correct paragraphs that fail to enter state HAS_FMTCOLL
AutoCorrect(); break;
}
aFInfo.SetFrame( m_pCurTextFrame );
// so far: if there were templates assigned, keep these and go to next node
sal_uInt16 nPoolId = m_pCurTextFrame->GetTextNodeForParaProps()->GetTextColl()->GetPoolFormatId(); if( IsPoolUserFormat( nPoolId )
? !m_aFlags.bChgUserColl
: ( RES_POOLCOLL_STANDARD != nPoolId &&
( !m_aFlags.bAFormatByInput ||
(RES_POOLCOLL_TEXT_MOVE != nPoolId &&
RES_POOLCOLL_TEXT != nPoolId )) ))
{
eStat = HAS_FMTCOLL; break;
}
// replace custom styles with text body if ( IsPoolUserFormat( nPoolId ) && m_aFlags.bChgUserColl )
{
SetColl( RES_POOLCOLL_TEXT, true );
}
// check for left margin set by the style if( IsPoolUserFormat( nPoolId ) ||
RES_POOLCOLL_STANDARD == nPoolId )
{
SvxFirstLineIndentItem const*const pFirstLineIndent(
m_pCurTextFrame->GetTextNodeForParaProps()
->GetSwAttrSet().GetItemIfSet(RES_MARGIN_FIRSTLINE));
SvxTextLeftMarginItem const*const pTextLeftMargin(
m_pCurTextFrame->GetTextNodeForParaProps()
->GetSwAttrSet().GetItemIfSet(RES_MARGIN_TEXTLEFT));
// Unit conversion is not needed here: check the sign only double dIndentValue = 0.0; if (pFirstLineIndent)
dIndentValue = pFirstLineIndent->GetTextFirstLineOffset().m_dValue;
if (0.0 != dIndentValue
|| (pTextLeftMargin && (0.0 != pTextLeftMargin->GetTextLeft().m_dValue)))
{ // exception: numbering/enumeration can have an indentation if (IsEnumericChar(*m_pCurTextFrame))
{
nLevel = CalcLevel(*m_pCurTextFrame, &nDigitLvl); if( nLevel >= MAXLEVEL )
nLevel = MAXLEVEL-1;
BuildEnum( nLevel, nDigitLvl );
eStat = READ_NEXT_PARA; break;
}
// never merge (maybe only indent as exception)
m_bMoreLines = true;
if( bReplaceStyles )
{ // then use one of our templates if (0.0 < dIndentValue) // positive 1st line indentation
BuildIndent(); elseif (0.0 > dIndentValue) // negative 1st line indentation
BuildNegIndent( aFInfo.GetLineStart() ); elseif (pTextLeftMargin
&& (pTextLeftMargin->GetTextLeft().m_dValue
!= 0.0)) // is indentation
BuildTextIndent();
}
eStat = READ_NEXT_PARA; break;
}
}
nLevel = CalcLevel( *m_pCurTextFrame, &nDigitLvl );
m_bMoreLines = !IsOneLine(*m_pCurTextFrame); // note: every use of pNextFrame in following states, until the // next READ_NEXT_PARA, relies on this update
pNextFrame = GetNextNode(); if (pNextFrame)
{
bNxtEmpty = IsEmptyLine(*pNextFrame);
bNxtAlpha = IsNoAlphaLine(*pNextFrame);
nNxtLevel = CalcLevel(*pNextFrame);
if (!bEmptyLine && HasBreakAttr(*m_pCurTextFrame))
bEmptyLine = true; if (!bNxtEmpty && HasBreakAttr(*pNextFrame))
bNxtEmpty = true;
case HAS_FMTCOLL:
{ // so far: if there were templates assigned, keep these and go to next node
bEmptyLine = false;
eStat = READ_NEXT_PARA; // delete all blanks at beginning/end and in between //JP 29.04.98: first only "all in between"
DelMoreLinesBlanks();
// handle hard attributes if (m_pCurTextFrame->GetTextNodeForParaProps()->HasSwAttrSet())
{
SvxFirstLineIndentItem const*const pFirstLineIndent(
m_pCurTextFrame->GetTextNodeForParaProps()
->GetSwAttrSet().GetItemIfSet(RES_MARGIN_FIRSTLINE, false));
SvxTextLeftMarginItem const*const pTextLeftMargin(
m_pCurTextFrame->GetTextNodeForParaProps()
->GetSwAttrSet().GetItemIfSet(RES_MARGIN_TEXTLEFT, false));
// Unit conversion is not needed here: check the sign only double dIndentValue = 0.0; if (pFirstLineIndent)
dIndentValue = pFirstLineIndent->GetTextFirstLineOffset().m_dValue;
if (bReplaceStyles
&& (0.0 != dIndentValue
|| (pTextLeftMargin
&& (0.0 != pTextLeftMargin->GetTextLeft().m_dValue))))
{ // then use one of our templates if (0.0 < dIndentValue) // positive 1st line indentation
BuildIndent(); elseif (0.0 > dIndentValue) // negative 1st line indentation
{
BuildNegIndent( aFInfo.GetLineStart() );
} elseif (pTextLeftMargin
&& (0.0
!= pTextLeftMargin->GetTextLeft().m_dValue)) // is indentation
BuildTextIndent(); else
BuildText();
}
} // force auto correct
AutoCorrect();
} break;
//JP 15.12.98: copy BulletChar and Font into "normal" ones // because AutoFormat can only work with the latter!
pEditFlags->cBullet = pFlags->cByInputBullet;
pEditFlags->aBulletFont = pFlags->aByInputBulletFont;
pEditFlags->cByInputBullet = pFlags->cByInputBullet;
pEditFlags->aByInputBulletFont = pFlags->aByInputBulletFont;
}
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.