tdf#35361 Add a Quick Look plugins for .od* files on macOS
[LibreOffice.git] / sw / source / core / text / porexp.cxx
blob78f7de5a8b3bc3538ad6bd82a9dbde2b6127560f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
23 #include "inftxt.hxx"
24 #include "porexp.hxx"
26 TextFrameIndex SwExpandPortion::GetModelPositionForViewPoint(const SwTwips nOfst) const
27 { return SwLinePortion::GetModelPositionForViewPoint( nOfst ); }
29 bool SwExpandPortion::GetExpText( const SwTextSizeInfo&, OUString &rText ) const
31 rText.clear();
32 // Do not do: return 0 != rText.Len();
33 // Reason being: empty fields replace CH_TXTATR with an empty string
34 return true;
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);
47 nOffset += GetLen();
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 ...
66 if( !nFullLen )
68 // Do not Init(), because we need height and ascent
69 Width(0);
70 return false;
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();
100 // ST2
101 if ( rInf.GetSmartTags() || rInf.GetGrammarCheckList() )
102 rInf.DrawMarkedText( *this, rInf.GetLen(), false,
103 nullptr != rInf.GetSmartTags(), nullptr != rInf.GetGrammarCheckList() );
104 else
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
115 * underflows!
116 * Causes problems with Fly
118 sal_uInt16 SwBlankPortion::MayUnderflow( const SwTextFormatInfo &rInf,
119 TextFrameIndex const nIdx, bool bUnderflow)
121 if( rInf.StopUnderflow() )
122 return 0;
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
133 if (bUnderflow
134 && nIdx + TextFrameIndex(1) < TextFrameIndex(rInf.GetText().getLength())
135 && CH_BLANK == rInf.GetText()[sal_Int32(nIdx) + 1])
137 return 0;
139 if( nIdx && !const_cast<SwTextFormatInfo&>(rInf).GetFly() )
141 while( pPos && !pPos->IsFlyPortion() )
142 pPos = pPos->GetNextPortion();
143 if( !pPos )
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 ) ) )
155 break;
157 if( nBlank <= rInf.GetLineStart() )
158 return 0;
161 if (nIdx < TextFrameIndex(2))
162 return 1;
163 sal_Unicode const cCh(rInf.GetChar(nIdx - TextFrameIndex(1)));
164 if (CH_BLANK == cCh)
165 return 1;
166 if( CH_BREAK == cCh )
167 return 0;
168 return 2;
172 * Format End of Line
174 void SwBlankPortion::FormatEOL( SwTextFormatInfo &rInf )
176 sal_uInt16 nMay = MayUnderflow( rInf, rInf.GetIdx() - mnLineLength, true );
177 if( !nMay )
178 return;
180 if( nMay > 1 )
182 if( rInf.GetLast() == this )
183 rInf.SetLast( FindPrevPortion( rInf.GetRoot() ) );
184 rInf.X( rInf.X() - PrtWidth() );
185 rInf.SetIdx( rInf.GetIdx() - GetLen() );
187 Truncate();
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() ) )
201 Truncate();
202 rInf.SetUnderflow( this );
203 if( rInf.GetLast()->IsKernPortion() )
204 rInf.SetUnderflow( rInf.GetLast() );
206 return bFull;
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)
222 ? u"~"_ustr
223 : u"°"_ustr
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);
234 aInf.SetPos(aPos);
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);
253 else
254 rText = OUString(m_cChar);
256 return true;
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);
269 nOffset += GetLen();
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.
302 SetAscent( 1 );
303 Height( 1 );
304 return bRet;
307 bool SwPostItsPortion::GetExpText( const SwTextSizeInfo &rInf, OUString &rText ) const
309 if( rInf.OnWin() && rInf.GetOpt().IsPostIts() )
310 rText = " ";
311 else
312 rText.clear();
313 return true;
316 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */