1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <viewopt.hxx>
21 #include <IDocumentSettingAccess.hxx>
22 #include <SwPortionHandler.hxx>
26 TextFrameIndex
SwExpandPortion::GetModelPositionForViewPoint(const SwTwips nOfst
) const
27 { return SwLinePortion::GetModelPositionForViewPoint( nOfst
); }
29 bool SwExpandPortion::GetExpText( const SwTextSizeInfo
&, OUString
&rText
) const
32 // Do not do: return 0 != rText.Len();
33 // Reason being: empty fields replace CH_TXTATR with an empty string
37 void SwExpandPortion::HandlePortion( SwPortionHandler
& rPH
) const
39 rPH
.Special( GetLen(), OUString(), GetWhichPor() );
42 void SwExpandPortion::dumpAsXml(xmlTextWriterPtr pWriter
, const OUString
& rText
,
43 TextFrameIndex
& nOffset
) const
45 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwExpandPortion"));
46 dumpAsXmlAttributes(pWriter
, rText
, nOffset
);
49 (void)xmlTextWriterEndElement(pWriter
);
52 SwPosSize
SwExpandPortion::GetTextSize( const SwTextSizeInfo
&rInf
) const
54 SwTextSlot
aDiffText( &rInf
, this, false, false );
55 return rInf
.GetTextSize();
58 bool SwExpandPortion::Format( SwTextFormatInfo
&rInf
)
60 SwTextSlot
aDiffText( &rInf
, this, true, false );
61 TextFrameIndex
const nFullLen
= rInf
.GetLen();
63 // As odd as it may seem: the query for GetLen() must return
64 // false due to the ExpandPortions _after_ the aDiffText (see SoftHyphs)
65 // caused by the SetFull ...
68 // Do not Init(), because we need height and ascent
72 return SwTextPortion::Format( rInf
);
75 void SwExpandPortion::Paint( const SwTextPaintInfo
&rInf
) const
77 rInf
.DrawCSDFHighlighting(*this); // here it detects as CS and not DF
79 SwTextSlot
aDiffText( &rInf
, this, true, true );
80 const SwFont aOldFont
= *rInf
.GetFont();
81 if( GetJoinBorderWithPrev() )
82 const_cast<SwTextPaintInfo
&>(rInf
).GetFont()->SetLeftBorder(nullptr);
83 if( GetJoinBorderWithNext() )
84 const_cast<SwTextPaintInfo
&>(rInf
).GetFont()->SetRightBorder(nullptr);
85 // rInf.DrawCSDFHighlighting(*this); // here it detects as DF and only the '/' is detected as CS
87 rInf
.DrawBackBrush( *this );
88 rInf
.DrawBorder( *this );
90 // Do we have to repaint a post it portion?
91 if( rInf
.OnWin() && mpNextPortion
&& !mpNextPortion
->Width() )
92 mpNextPortion
->PrePaint( rInf
, this );
94 // The contents of field portions is not considered during the
95 // calculation of the directions. Therefore we let vcl handle
96 // the calculation by removing the BIDI_STRONG_FLAG temporarily.
97 SwLayoutModeModifier
aLayoutModeModifier( *rInf
.GetOut() );
98 aLayoutModeModifier
.SetAuto();
101 if ( rInf
.GetSmartTags() || rInf
.GetGrammarCheckList() )
102 rInf
.DrawMarkedText( *this, rInf
.GetLen(), false,
103 nullptr != rInf
.GetSmartTags(), nullptr != rInf
.GetGrammarCheckList() );
105 rInf
.DrawText( *this, rInf
.GetLen() );
107 if( GetJoinBorderWithPrev() || GetJoinBorderWithNext() )
108 *const_cast<SwTextPaintInfo
&>(rInf
).GetFont() = aOldFont
;
111 SwLinePortion
*SwBlankPortion::Compress() { return this; }
114 * If a Line is full of HardBlanks and overflows, we must not generate
116 * Causes problems with Fly
118 sal_uInt16
SwBlankPortion::MayUnderflow( const SwTextFormatInfo
&rInf
,
119 TextFrameIndex
const nIdx
, bool bUnderflow
)
121 if( rInf
.StopUnderflow() )
123 const SwLinePortion
*pPos
= rInf
.GetRoot();
124 if( pPos
->GetNextPortion() )
125 pPos
= pPos
->GetNextPortion();
126 while( pPos
&& pPos
->IsBlankPortion() )
127 pPos
= pPos
->GetNextPortion();
128 if( !pPos
|| !rInf
.GetIdx() || ( !pPos
->GetLen() && pPos
== rInf
.GetRoot() ) )
129 return 0; // There are just BlankPortions left
131 // If a Blank is preceding us, we do not need to trigger underflow
132 // If a Blank is succeeding us, we do not need to pass on the underflow
134 && nIdx
+ TextFrameIndex(1) < TextFrameIndex(rInf
.GetText().getLength())
135 && CH_BLANK
== rInf
.GetText()[sal_Int32(nIdx
) + 1])
139 if( nIdx
&& !const_cast<SwTextFormatInfo
&>(rInf
).GetFly() )
141 while( pPos
&& !pPos
->IsFlyPortion() )
142 pPos
= pPos
->GetNextPortion();
145 // We check to see if there are useful line breaks, blanks or fields etc. left
146 // In case there still are some, no underflow
147 // If there are Flys, we still allow the underflow
148 TextFrameIndex nBlank
= nIdx
;
149 while( --nBlank
> rInf
.GetLineStart() )
151 const sal_Unicode cCh
= rInf
.GetChar( nBlank
);
152 if( CH_BLANK
== cCh
||
153 (( CH_TXTATR_BREAKWORD
== cCh
|| CH_TXTATR_INWORD
== cCh
)
154 && rInf
.HasHint( nBlank
) ) )
157 if( nBlank
<= rInf
.GetLineStart() )
161 if (nIdx
< TextFrameIndex(2))
163 sal_Unicode
const cCh(rInf
.GetChar(nIdx
- TextFrameIndex(1)));
166 if( CH_BREAK
== cCh
)
174 void SwBlankPortion::FormatEOL( SwTextFormatInfo
&rInf
)
176 sal_uInt16 nMay
= MayUnderflow( rInf
, rInf
.GetIdx() - mnLineLength
, true );
182 if( rInf
.GetLast() == this )
183 rInf
.SetLast( FindPrevPortion( rInf
.GetRoot() ) );
184 rInf
.X( rInf
.X() - PrtWidth() );
185 rInf
.SetIdx( rInf
.GetIdx() - GetLen() );
188 rInf
.SetUnderflow( this );
189 if( rInf
.GetLast()->IsKernPortion() )
190 rInf
.SetUnderflow( rInf
.GetLast() );
194 * Pass on the underflows and trigger them ourselves!
196 bool SwBlankPortion::Format( SwTextFormatInfo
&rInf
)
198 const bool bFull
= rInf
.IsUnderflow() || SwExpandPortion::Format( rInf
);
199 if( bFull
&& MayUnderflow( rInf
, rInf
.GetIdx(), rInf
.IsUnderflow() ) )
202 rInf
.SetUnderflow( this );
203 if( rInf
.GetLast()->IsKernPortion() )
204 rInf
.SetUnderflow( rInf
.GetLast() );
209 void SwBlankPortion::Paint( const SwTextPaintInfo
&rInf
) const
211 // Draw field shade (can be disabled individually)
212 if (!m_bMulti
) // No gray background for multiportion brackets
213 rInf
.DrawViewOpt(*this, PortionType::Blank
);
214 SwExpandPortion::Paint(rInf
);
216 if (rInf
.GetOpt().IsViewMetaChars() && rInf
.GetOpt().IsHardBlank())
218 // Draw tilde or degree sign
219 OUString aMarker
= (m_cChar
== CHAR_HARDBLANK
?
220 rInf
.GetTextFrame()->GetDoc().getIDocumentSettingAccess()
221 .get(DocumentSettingId::USE_VARIABLE_WIDTH_NBSP
)
224 : u
"-"_ustr
); //CHAR_HARDHYPHEN
226 SwPosSize
aMarkerSize(rInf
.GetTextSize(aMarker
));
227 Point
aPos(rInf
.GetPos());
229 std::shared_ptr
<SwRect
> pPortionRect
= std::make_shared
<SwRect
>();
230 rInf
.CalcRect(*this, pPortionRect
.get());
231 aPos
.AdjustX((pPortionRect
->Width() / 2) - (aMarkerSize
.Width() / 2));
233 SwTextPaintInfo
aInf(rInf
, &aMarker
);
235 SwTextPortion aMarkerPor
;
236 aMarkerPor
.Width(aMarkerSize
.Width());
237 aMarkerPor
.Height(aMarkerSize
.Height());
238 aMarkerPor
.SetAscent(GetAscent());
240 Color colorBackup
= aInf
.GetFont()->GetColor();
241 aInf
.GetFont()->SetColor(SwViewOption::GetCurrentViewOptions().GetNonPrintingCharacterColor());
242 aInf
.DrawText(aMarkerPor
, TextFrameIndex(aMarker
.getLength()), true);
243 aInf
.GetFont()->SetColor(colorBackup
);
247 bool SwBlankPortion::GetExpText( const SwTextSizeInfo
& rInf
, OUString
&rText
) const
249 if (m_cChar
== CHAR_HARDBLANK
250 && rInf
.GetTextFrame()->GetDoc().getIDocumentSettingAccess().get(
251 DocumentSettingId::USE_VARIABLE_WIDTH_NBSP
))
252 rText
= OUString(CH_BLANK
);
254 rText
= OUString(m_cChar
);
259 void SwBlankPortion::HandlePortion( SwPortionHandler
& rPH
) const
261 rPH
.Special( GetLen(), OUString( m_cChar
), GetWhichPor() );
264 void SwBlankPortion::dumpAsXml(xmlTextWriterPtr pWriter
, const OUString
& rText
,
265 TextFrameIndex
& nOffset
) const
267 (void)xmlTextWriterStartElement(pWriter
, BAD_CAST("SwBlankPortion"));
268 dumpAsXmlAttributes(pWriter
, rText
, nOffset
);
271 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("char"),
272 BAD_CAST(OUString(m_cChar
).toUtf8().getStr()));
273 (void)xmlTextWriterWriteAttribute(pWriter
, BAD_CAST("multi"),
274 BAD_CAST(OString::boolean(m_bMulti
).getStr()));
276 (void)xmlTextWriterEndElement(pWriter
);
279 SwPostItsPortion::SwPostItsPortion( bool bScrpt
)
280 : m_bScript( bScrpt
)
282 mnLineLength
= TextFrameIndex(1);
283 SetWhichPor( PortionType::PostIts
);
286 void SwPostItsPortion::Paint( const SwTextPaintInfo
&rInf
) const
288 if( rInf
.OnWin() && Width() )
289 rInf
.DrawPostIts( IsScript() );
292 SwTwips
SwPostItsPortion::GetViewWidth(const SwTextSizeInfo
& rInf
) const
294 // Unbelievable: PostIts are always visible
295 return rInf
.OnWin() ? SwViewOption::GetPostItsWidth( rInf
.GetOut() ) : 0;
298 bool SwPostItsPortion::Format( SwTextFormatInfo
&rInf
)
300 const bool bRet
= SwLinePortion::Format( rInf
);
301 // PostIts should not have an effect on line height etc.
307 bool SwPostItsPortion::GetExpText( const SwTextSizeInfo
&rInf
, OUString
&rText
) const
309 if( rInf
.OnWin() && rInf
.GetOpt().IsPostIts() )
316 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */