LibreOffice Module sw (master) 1
itratr.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <sal/config.h>
21
22#include <algorithm>
23
24#include <hintids.hxx>
26#include <svl/itemiter.hxx>
27#include <svx/svdobj.hxx>
28#include <vcl/svapp.hxx>
29#include <fmtanchr.hxx>
30#include <fmtfsize.hxx>
31#include <fmtornt.hxx>
32#include <fmtflcnt.hxx>
33#include <fmtcntnt.hxx>
34#include <fmtftn.hxx>
35#include <frmatr.hxx>
36#include <frmfmt.hxx>
37#include <fmtfld.hxx>
38#include <doc.hxx>
40#include <txatbase.hxx>
41#include <viewsh.hxx>
42#include <rootfrm.hxx>
43#include <docary.hxx>
44#include <ndtxt.hxx>
45#include <fldbas.hxx>
46#include <pam.hxx>
47#include "itratr.hxx"
48#include <htmltbl.hxx>
49#include <swtable.hxx>
50#include "redlnitr.hxx"
51#include <redline.hxx>
52#include <fmtsrnd.hxx>
53#include "itrtxt.hxx"
54#include <breakit.hxx>
55#include <com/sun/star/i18n/WordType.hpp>
56#include <com/sun/star/i18n/XBreakIterator.hpp>
57#include <editeng/lrspitem.hxx>
58#include <calbck.hxx>
59#include <frameformats.hxx>
60#include <sortedobjs.hxx>
61#include <anchoredobject.hxx>
62#include <flyfrm.hxx>
63#include <flyfrms.hxx>
64
65using namespace ::com::sun::star::i18n;
66using namespace ::com::sun::star;
67
68static sal_Int32 GetNextAttrImpl(SwTextNode const* pTextNode,
69 size_t nStartIndex, size_t nEndIndex, sal_Int32 nPosition);
70
72 : m_pViewShell(nullptr)
73 , m_pFont(nullptr)
74 , m_pScriptInfo(nullptr)
75 , m_pLastOut(nullptr)
76 , m_nChgCnt(0)
77 , m_nStartIndex(0)
78 , m_nEndIndex(0)
79 , m_nPosition(0)
80 , m_nPropFont(0)
81 , m_pTextNode(pTextNode)
82 , m_pMergedPara(nullptr)
83{
85}
86
87SwAttrIter::SwAttrIter(SwTextNode& rTextNode, SwScriptInfo& rScrInf, SwTextFrame const*const pFrame)
88 : m_pViewShell(nullptr)
89 , m_pFont(nullptr)
90 , m_pScriptInfo(nullptr)
91 , m_pLastOut(nullptr)
92 , m_nChgCnt(0)
93 , m_nPropFont(0)
94 , m_pTextNode(&rTextNode)
95 , m_pMergedPara(nullptr)
96{
97 CtorInitAttrIter(rTextNode, rScrInf, pFrame);
98}
99
100void SwAttrIter::Chg( SwTextAttr const *pHt )
101{
102 assert(pHt && m_pFont && "No attribute of font available for change");
103 if( m_pRedline && m_pRedline->IsOn() )
104 m_pRedline->ChangeTextAttr( m_pFont, *pHt, true );
105 else
107 m_nChgCnt++;
108}
109
110void SwAttrIter::Rst( SwTextAttr const *pHt )
111{
112 assert(pHt && m_pFont && "No attribute of font available for reset");
113 // get top from stack after removing pHt
114 if( m_pRedline && m_pRedline->IsOn() )
115 m_pRedline->ChangeTextAttr( m_pFont, *pHt, false );
116 else
118 m_nChgCnt--;
119}
120
122{
123 m_pRedline.reset();
124 delete m_pFont;
125}
126
128{
129 return nullptr != m_pTextNode->GetpSwpHints() || nullptr != m_pMergedPara;
130}
131
148{
149 std::pair<SwTextNode const*, sal_Int32> const pos( m_pMergedPara
150 ? sw::MapViewToModel(*m_pMergedPara, nPosition)
151 : std::make_pair(m_pTextNode, sal_Int32(nPosition)));
152 return pos.first->GetTextAttrForCharAt(pos.second);
153}
154
156{
157 std::pair<SwTextNode const*, sal_Int32> const pos( m_pMergedPara
159 : std::make_pair(m_pTextNode, sal_Int32(nNewPos)));
160 bool bChg = m_nStartIndex && pos.first == m_pTextNode && pos.second == m_nPosition
161 ? m_pFont->IsFntChg()
162 : Seek( nNewPos );
163 if ( m_pLastOut.get() != pOut )
164 {
166 m_pFont->SetFntChg( true );
167 bChg = true;
168 }
169 if( bChg )
170 {
171 // if the change counter is zero, we know the cache id of the wanted font
172 if ( !m_nChgCnt && !m_nPropFont )
176 }
177
178 return bChg;
179}
180
182{
183 Seek( nNewPos );
184 if ( !m_nChgCnt && !m_nPropFont )
187 return m_pFont->IsSymbol( m_pViewShell );
188}
189
191{
192 SwTextInfo info(const_cast<SwTextFrame*>(this));
193 SwTextIter iter(const_cast<SwTextFrame*>(this), &info);
194 return iter.IsSymbol(nPos);
195}
196
197bool SwAttrIter::SeekStartAndChgAttrIter( OutputDevice* pOut, const bool bParaFont )
198{
199 SwTextNode const*const pFirstTextNode(m_pMergedPara ? m_pMergedPara->pFirstNode : m_pTextNode);
200 if ( m_pRedline && m_pRedline->ExtOn() )
201 m_pRedline->LeaveExtend(*m_pFont, pFirstTextNode->GetIndex(), 0);
202
203 if (m_pTextNode != pFirstTextNode)
204 {
205 assert(m_pMergedPara);
208 m_pMergedPara->mergedText, nullptr, nullptr);
209 }
210
211 // reset font to its original state
214
215 m_nStartIndex = 0;
216 m_nEndIndex = 0;
217 m_nPosition = 0;
218 m_nChgCnt = 0;
219 if( m_nPropFont )
221 if( m_pRedline )
222 {
223 m_pRedline->Clear( m_pFont );
224 if( !bParaFont )
225 m_nChgCnt = m_nChgCnt + m_pRedline->Seek(*m_pFont, pFirstTextNode->GetIndex(), 0, COMPLETE_STRING);
226 else
227 m_pRedline->Reset();
228 }
229
230 SwpHints const*const pHints(m_pTextNode->GetpSwpHints());
231 if (pHints && !bParaFont)
232 {
233 SwTextAttr *pTextAttr;
234 // While we've not reached the end of the StartArray && the TextAttribute starts at position 0...
235 while ((m_nStartIndex < pHints->Count()) &&
236 !((pTextAttr = pHints->Get(m_nStartIndex))->GetStart()))
237 {
238 // open the TextAttributes
239 Chg( pTextAttr );
241 }
242 }
243
244 bool bChg = m_pFont->IsFntChg();
245 if ( m_pLastOut.get() != pOut )
246 {
248 m_pFont->SetFntChg( true );
249 bChg = true;
250 }
251 if( bChg )
252 {
253 // if the application counter is zero, we know the cache id of the wanted font
254 if ( !m_nChgCnt && !m_nPropFont )
258 }
259 return bChg;
260}
261
262// AMA: New AttrIter Nov 94
263void SwAttrIter::SeekFwd(const sal_Int32 nOldPos, const sal_Int32 nNewPos)
264{
265 SwpHints const*const pHints(m_pTextNode->GetpSwpHints());
266 SwTextAttr *pTextAttr;
267 const auto nHintsCount = pHints->Count();
268
269 if ( m_nStartIndex ) // If attributes have been opened at all ...
270 {
271 // Close attributes that are currently open, but stop at nNewPos+1
272
273 // As long as we've not yet reached the end of EndArray and the
274 // TextAttribute ends before or at the new position ...
275 while ((m_nEndIndex < nHintsCount) &&
276 ((pTextAttr = pHints->GetSortedByEnd(m_nEndIndex))->GetAnyEnd() <= nNewPos))
277 {
278 // Close the TextAttributes, whose StartPos were before or at
279 // the old nPos and are currently open
280 if (pTextAttr->GetStart() <= nOldPos) Rst( pTextAttr );
281 m_nEndIndex++;
282 }
283 }
284 else // skip the not opened ends
285 {
286 while ((m_nEndIndex < nHintsCount) &&
287 (pHints->GetSortedByEnd(m_nEndIndex)->GetAnyEnd() <= nNewPos))
288 {
289 m_nEndIndex++;
290 }
291 }
292
293 // As long as we've not yet reached the end of EndArray and the
294 // TextAttribute ends before or at the new position...
295 while ((m_nStartIndex < nHintsCount) &&
296 ((pTextAttr = pHints->Get(m_nStartIndex))->GetStart() <= nNewPos))
297 {
298
299 // open the TextAttributes, whose ends lie behind the new position
300 if ( pTextAttr->GetAnyEnd() > nNewPos ) Chg( pTextAttr );
302 }
303
304}
305
307{
308 // note: nNewPos isn't necessarily an index returned from GetNextAttr
309 std::pair<SwTextNode const*, sal_Int32> const newPos( m_pMergedPara
311 : std::make_pair(m_pTextNode, sal_Int32(nNewPos)));
312
313 if ( m_pRedline && m_pRedline->ExtOn() )
314 m_pRedline->LeaveExtend(*m_pFont, newPos.first->GetIndex(), newPos.second);
315 if (m_pTextNode->GetIndex() < newPos.first->GetIndex())
316 {
317 // Skipping to a different node - first seek until the end of this node
318 // to get rid of all hint items
320 {
321 sal_Int32 nPos(m_nPosition);
322 do
323 {
324 sal_Int32 const nOldPos(nPos);
326 if (nPos <= m_pTextNode->Len())
327 {
328 SeekFwd(nOldPos, nPos);
329 }
330 else
331 {
332 SeekFwd(nOldPos, m_pTextNode->Len());
333 }
334 }
335 while (nPos < m_pTextNode->Len());
336 }
337 // Unapply current para items:
338 // the SwAttrHandler doesn't appear to be capable of *unapplying*
339 // items at all; it can only apply a previously effective item.
340 // So do this by recreating the font from scratch.
341 // Apply new para items:
342 assert(m_pMergedPara);
344 m_pMergedPara->mergedText, nullptr, nullptr);
345 // reset to next
346 m_pTextNode = newPos.first;
347 m_nStartIndex = 0;
348 m_nEndIndex = 0;
349 m_nPosition = 0;
350 assert(m_pRedline);
351 }
352
353 // sw_redlinehide: Seek(0) must move before the first character, which
354 // has a special case where the first node starts with delete redline.
355 if ((!nNewPos && !m_pMergedPara)
356 || newPos.first != m_pTextNode
357 || newPos.second < m_nPosition)
358 {
359 if (m_pMergedPara)
360 {
361 if (m_pTextNode != newPos.first)
362 {
363 m_pTextNode = newPos.first;
364 // sw_redlinehide: hope it's okay to use the current text node
365 // here; the AttrHandler shouldn't care about non-char items
367 m_pMergedPara->mergedText, nullptr, nullptr);
368 }
369 }
371 {
372 if( m_pRedline )
373 m_pRedline->Clear( nullptr );
374
375 // reset font to its original state
378
379 if( m_nPropFont )
381 m_nStartIndex = 0;
382 m_nEndIndex = 0;
383 m_nPosition = 0;
384 m_nChgCnt = 0;
385
386 // Attention!
387 // resetting the font here makes it necessary to apply any
388 // changes for extended input directly to the font
389 if ( m_pRedline && m_pRedline->ExtOn() )
390 {
391 m_pRedline->UpdateExtFont( *m_pFont );
392 ++m_nChgCnt;
393 }
394 }
395 }
396
398 {
399 if (m_pMergedPara)
400 {
401 // iterate hint by hint: SeekFwd does not mix ends and starts,
402 // it always applies all the starts last, so it must be called once
403 // per position where hints start/end!
404 sal_Int32 nPos(m_nPosition);
405 do
406 {
407 sal_Int32 const nOldPos(nPos);
409 if (nPos <= newPos.second)
410 {
411 SeekFwd(nOldPos, nPos);
412 }
413 else
414 {
415 SeekFwd(nOldPos, newPos.second);
416 }
417 }
418 while (nPos < newPos.second);
419 }
420 else
421 {
422 SeekFwd(m_nPosition, newPos.second);
423 }
424 }
425
427
428 if( m_pRedline )
429 m_nChgCnt = m_nChgCnt + m_pRedline->Seek(*m_pFont, m_pTextNode->GetIndex(), newPos.second, m_nPosition);
430 m_nPosition = newPos.second;
431
432 if( m_nPropFont )
434
435 return m_pFont->IsFntChg();
436}
437
438static void InsertCharAttrs(SfxPoolItem const** pAttrs, SfxItemSet const& rItems)
439{
440 SfxItemIter iter(rItems);
441 for (SfxPoolItem const* pItem = iter.GetCurItem(); pItem; pItem = iter.NextItem())
442 {
443 auto const nWhich(pItem->Which());
444 if (isCHRATR(nWhich) && RES_CHRATR_RSID != nWhich)
445 {
446 pAttrs[nWhich - RES_CHRATR_BEGIN] = pItem;
447 }
448 else if (nWhich == RES_TXTATR_UNKNOWN_CONTAINER)
449 {
450 pAttrs[RES_CHRATR_END - RES_CHRATR_BEGIN] = pItem;
451 }
452 }
453}
454
455// if return false: portion ends at start of redline, indexes unchanged
456// if return true: portion end not known (past end of redline), indexes point to first hint past end of redline
458 SwTextNode const& rStartNode, sal_Int32 const nStartRedline,
459 SwRangeRedline const& rRedline,
460 size_t & rStartIndex, size_t & rEndIndex,
461 bool const isTheAnswerYes)
462{
463 size_t nStartIndex(rStartIndex);
464 size_t nEndIndex(rEndIndex);
465 SwPosition const*const pRLEnd(rRedline.End());
466 if (!pRLEnd->GetNode().IsTextNode() // if fully deleted...
467 || pRLEnd->GetContentIndex() == pRLEnd->GetNode().GetTextNode()->Len())
468 {
469 // shortcut: nothing follows redline
470 // current state is end state
471 return false;
472 }
473 std::vector<SwTextAttr*> activeCharFmts;
474 // can't compare the SwFont that's stored somewhere, it doesn't have compare
475 // operator, so try to recreate the situation with some temp arrays here
476 SfxPoolItem const* activeCharAttrsStart[RES_CHRATR_END - RES_CHRATR_BEGIN + 1] = { nullptr, };
477 if (rStartNode != pRLEnd->GetNode())
478 { // nodes' attributes are only needed if there are different nodes
479 InsertCharAttrs(activeCharAttrsStart, rStartNode.GetSwAttrSet());
480 }
481 if (SwpHints const*const pStartHints = rStartNode.GetpSwpHints())
482 {
483 // check hint ends of hints that start before and end within
484 sal_Int32 const nRedlineEnd(rStartNode == pRLEnd->GetNode()
485 ? pRLEnd->GetContentIndex()
486 : rStartNode.Len());
487 for ( ; nEndIndex < pStartHints->Count(); ++nEndIndex)
488 {
489 SwTextAttr *const pAttr(pStartHints->GetSortedByEnd(nEndIndex));
490 if (!pAttr->End())
491 {
492 continue;
493 }
494 if (nRedlineEnd < *pAttr->End())
495 {
496 break;
497 }
498 if (nStartRedline <= pAttr->GetStart())
499 {
500 continue;
501 }
502 if (pAttr->IsFormatIgnoreEnd())
503 {
504 continue;
505 }
506 switch (pAttr->Which())
507 {
508 // if any of these ends inside RL then we need a new portion
511 case RES_TXTATR_META: // actually these 2 aren't allowed to overlap ???
517 {
518 if (!isTheAnswerYes) return false; // always break
519 }
520 break;
521 // these are guaranteed not to overlap
522 // and come in order of application
525 {
526 if (pAttr->Which() == RES_TXTATR_CHARFMT)
527 {
528 activeCharFmts.push_back(pAttr);
529 }
530 // pure formatting hints may end inside the redline &
531 // start again inside the redline, which must not cause
532 // a new text portion if they have the same items - so
533 // store the effective items & compare all at the end
534 SfxItemSet const& rSet((pAttr->Which() == RES_TXTATR_CHARFMT)
535 ? static_cast<SfxItemSet const&>(pAttr->GetCharFormat().GetCharFormat()->GetAttrSet())
536 : *pAttr->GetAutoFormat().GetStyleHandle());
537 InsertCharAttrs(activeCharAttrsStart, rSet);
538 }
539 break;
540 // SwTextNode::SetAttr puts it into AUTOFMT which is quite
541 // sensible so it doesn't actually exist as a hint
543 default: assert(false);
544 }
545 }
546 assert(nEndIndex == pStartHints->Count() ||
547 pRLEnd->GetContentIndex() < pStartHints->GetSortedByEnd(nEndIndex)->GetAnyEnd());
548 }
549
550 if (rStartNode != pRLEnd->GetNode())
551 {
552 nStartIndex = 0;
553 nEndIndex = 0;
554 }
555
556 // treat para properties as text properties
557 // ... with the FormatToTextAttr we get autofmts that correspond to the *effective* attr set difference
558 // effective attr set: para props + charfmts + autofmt *in that order*
559 // ... and the charfmt must be *nominally* the same
560
561 SfxPoolItem const* activeCharAttrsEnd[RES_CHRATR_END - RES_CHRATR_BEGIN + 1] = { nullptr, };
562 if (rStartNode != pRLEnd->GetNode())
563 { // nodes' attributes are only needed if there are different nodes
564 InsertCharAttrs(activeCharAttrsEnd,
565 pRLEnd->GetNode().GetTextNode()->GetSwAttrSet());
566 }
567
568 if (SwpHints *const pEndHints = pRLEnd->GetNode().GetTextNode()->GetpSwpHints())
569 {
570 // check hint starts of hints that start within and end after
571#ifndef NDEBUG
572 sal_Int32 const nRedlineStart(rStartNode == pRLEnd->GetNode()
573 ? nStartRedline
574 : 0);
575#endif
576 for ( ; nStartIndex < pEndHints->Count(); ++nStartIndex)
577 {
578 SwTextAttr *const pAttr(pEndHints->Get(nStartIndex));
579 // compare with < here, not <=, to get the effective formatting
580 // of the 1st char after the redline; should not cause problems
581 // with consecutive delete redlines because those are handed by
582 // GetNextRedln() and here we have the last end pos.
583 if (pRLEnd->GetContentIndex() < pAttr->GetStart())
584 {
585 break;
586 }
587 if (!pAttr->End())
588 continue;
589 if (pAttr->IsFormatIgnoreStart())
590 {
591 continue;
592 }
593 assert(nRedlineStart <= pAttr->GetStart()); // we wouldn't be here otherwise?
594 if (*pAttr->End() <= pRLEnd->GetContentIndex())
595 {
596 continue;
597 }
598 switch (pAttr->Which())
599 {
602 case RES_TXTATR_META: // actually these 2 aren't allowed to overlap ???
608 {
609 if (!isTheAnswerYes) return false;
610 }
611 break;
614 {
615 // char formats must be *nominally* the same
616 if (pAttr->Which() == RES_TXTATR_CHARFMT)
617 {
618 auto iter = std::find_if(activeCharFmts.begin(), activeCharFmts.end(),
619 [&pAttr](const SwTextAttr* pCharFmt) { return *pCharFmt == *pAttr; });
620 if (iter != activeCharFmts.end())
621 activeCharFmts.erase(iter);
622 else if (!isTheAnswerYes)
623 return false;
624 }
625 SfxItemSet const& rSet((pAttr->Which() == RES_TXTATR_CHARFMT)
626 ? static_cast<SfxItemSet const&>(pAttr->GetCharFormat().GetCharFormat()->GetAttrSet())
627 : *pAttr->GetAutoFormat().GetStyleHandle());
628 InsertCharAttrs(activeCharAttrsEnd, rSet);
629
630 }
631 break;
632 // SwTextNode::SetAttr puts it into AUTOFMT which is quite
633 // sensible so it doesn't actually exist as a hint
635 default: assert(false);
636 }
637 }
638 if (rStartNode != pRLEnd->GetNode())
639 {
640 // need to iterate the nEndIndex forward too so the loop in the
641 // caller can look for the right ends in the next iteration
642 for (nEndIndex = 0; nEndIndex < pEndHints->Count(); ++nEndIndex)
643 {
644 SwTextAttr *const pAttr(pEndHints->GetSortedByEnd(nEndIndex));
645 if (!pAttr->End())
646 continue;
647 if (pRLEnd->GetContentIndex() < *pAttr->End())
648 {
649 break;
650 }
651 }
652 }
653 }
654
655 // if we didn't find a matching start for any end, then it really ends inside
656 if (!activeCharFmts.empty())
657 {
658 if (!isTheAnswerYes) return false;
659 }
660 for (size_t i = 0; i < SAL_N_ELEMENTS(activeCharAttrsStart); ++i)
661 {
662 // all of these are poolable
663// assert(!activeCharAttrsStart[i] || activeCharAttrsStart[i]->GetItemPool()->IsItemPoolable(*activeCharAttrsStart[i]));
664 if (activeCharAttrsStart[i] != activeCharAttrsEnd[i])
665 {
666 if (!isTheAnswerYes) return false;
667 }
668 }
669 rStartIndex = nStartIndex;
670 rEndIndex = nEndIndex;
671 return true;
672}
673
674static sal_Int32 GetNextAttrImpl(SwTextNode const*const pTextNode,
675 size_t const nStartIndex, size_t const nEndIndex,
676 sal_Int32 const nPosition)
677{
678 // note: this used to be COMPLETE_STRING, but was set to Len() + 1 below,
679 // which is rather silly, so set it to Len() instead
680 sal_Int32 nNext = pTextNode->Len();
681 if (SwpHints const*const pHints = pTextNode->GetpSwpHints())
682 {
683 // are there attribute starts left?
684 for (size_t i = nStartIndex; i < pHints->Count(); ++i)
685 {
686 SwTextAttr *const pAttr(pHints->Get(i));
687 if (!pAttr->IsFormatIgnoreStart())
688 {
689 nNext = pAttr->GetStart();
690 break;
691 }
692 }
693 // are there attribute ends left?
694 for (size_t i = nEndIndex; i < pHints->Count(); ++i)
695 {
696 SwTextAttr *const pAttr(pHints->GetSortedByEnd(i));
697 if (!pAttr->IsFormatIgnoreEnd())
698 {
699 sal_Int32 const nNextEnd = pAttr->GetAnyEnd();
700 nNext = std::min(nNext, nNextEnd); // pick nearest one
701 break;
702 }
703 }
704 }
705 // TODO: maybe use hints like FieldHints for this instead of looking at the text...
706 const sal_Int32 l = std::min(nNext, pTextNode->Len());
707 sal_Int32 p = nPosition;
708 const sal_Unicode* pStr = pTextNode->GetText().getStr();
709 while (p < l)
710 {
711 sal_Unicode aChar = pStr[p];
712 switch (aChar)
713 {
718 goto break_; // sigh...
719 default:
720 ++p;
721 }
722 }
723break_:
724 assert(p <= nNext);
725 if (p < l)
726 {
727 // found a CH_TXT_ATR_FIELD*: if it's same as current position,
728 // skip behind it so that both before- and after-positions are returned
729 nNext = (nPosition < p) ? p : p + 1;
730 }
731 return nNext;
732}
733
735{
736 size_t nStartIndex(m_nStartIndex);
737 size_t nEndIndex(m_nEndIndex);
738 size_t nPosition(m_nPosition);
739 SwTextNode const* pTextNode(m_pTextNode);
741
742 while (true)
743 {
744 sal_Int32 nNext = GetNextAttrImpl(pTextNode, nStartIndex, nEndIndex, nPosition);
745 if( m_pRedline )
746 {
747 std::pair<sal_Int32, std::pair<SwRangeRedline const*, size_t>> const redline(
748 m_pRedline->GetNextRedln(nNext, pTextNode, nActRedline));
749 if (redline.second.first)
750 {
751 assert(m_pMergedPara);
752 assert(redline.second.first->End()->GetNodeIndex() <= m_pMergedPara->pLastNode->GetIndex()
753 || !redline.second.first->End()->GetNode().IsTextNode());
754 if (CanSkipOverRedline(*pTextNode, redline.first, *redline.second.first,
755 nStartIndex, nEndIndex, m_nPosition == redline.first))
756 { // if current position is start of the redline, must skip!
757 nActRedline += redline.second.second;
758 if (&redline.second.first->End()->GetNode() != pTextNode)
759 {
760 pTextNode = redline.second.first->End()->GetNode().GetTextNode();
761 nPosition = redline.second.first->End()->GetContentIndex();
762 }
763 else
764 {
765 nPosition = redline.second.first->End()->GetContentIndex();
766 }
767 }
768 else
769 {
770 return sw::MapModelToView(*m_pMergedPara, pTextNode, redline.first);
771 }
772 }
773 else
774 {
775 return m_pMergedPara
776 ? sw::MapModelToView(*m_pMergedPara, pTextNode, redline.first)
777 : TextFrameIndex(redline.first);
778 }
779 }
780 else
781 {
782 return TextFrameIndex(nNext);
783 }
784 }
785}
786
787namespace {
788
789class SwMinMaxArgs
790{
791public:
793 SwViewShell const* m_pSh;
794 sal_uLong& m_rMin;
795 sal_uLong& m_rAbsMin;
796 tools::Long m_nRowWidth;
797 tools::Long m_nWordWidth;
798 tools::Long m_nWordAdd;
799 sal_Int32 m_nNoLineBreak;
800 SwMinMaxArgs(OutputDevice* pOutI, SwViewShell const* pShI, sal_uLong& rMinI, sal_uLong& rAbsI)
801 : m_pOut(pOutI)
802 , m_pSh(pShI)
803 , m_rMin(rMinI)
804 , m_rAbsMin(rAbsI)
805 , m_nRowWidth(0)
806 , m_nWordWidth(0)
807 , m_nWordAdd(0)
808 , m_nNoLineBreak(COMPLETE_STRING)
809 { }
810 void Minimum( tools::Long nNew ) const {
811 if (static_cast<tools::Long>(m_rMin) < nNew)
812 m_rMin = nNew;
813 }
814 void NewWord() { m_nWordAdd = m_nWordWidth = 0; }
815};
816
817}
818
819static bool lcl_MinMaxString( SwMinMaxArgs& rArg, SwFont* pFnt, const OUString &rText,
820 sal_Int32 nIdx, sal_Int32 nEnd )
821{
822 bool bRet = false;
823 while( nIdx < nEnd )
824 {
825 sal_Int32 nStop = nIdx;
826 LanguageType eLang = pFnt->GetLanguage();
827 assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
828
829 bool bClear = CH_BLANK == rText[ nStop ];
830 Boundary aBndry( g_pBreakIt->GetBreakIter()->getWordBoundary( rText, nIdx,
831 g_pBreakIt->GetLocale( eLang ),
832 WordType::DICTIONARY_WORD, true ) );
833 nStop = aBndry.endPos;
834 if (nIdx <= aBndry.startPos && nIdx && nIdx - 1 != rArg.m_nNoLineBreak)
835 rArg.NewWord();
836 if( nStop == nIdx )
837 ++nStop;
838 if( nStop > nEnd )
839 nStop = nEnd;
840
841 SwDrawTextInfo aDrawInf(rArg.m_pSh, *rArg.m_pOut, rText, nIdx, nStop - nIdx);
842 tools::Long nCurrentWidth = pFnt->GetTextSize_( aDrawInf ).Width();
843 rArg.m_nRowWidth += nCurrentWidth;
844 if( bClear )
845 rArg.NewWord();
846 else
847 {
848 rArg.m_nWordWidth += nCurrentWidth;
849 if (static_cast<tools::Long>(rArg.m_rAbsMin) < rArg.m_nWordWidth)
850 rArg.m_rAbsMin = rArg.m_nWordWidth;
851 rArg.Minimum(rArg.m_nWordWidth + rArg.m_nWordAdd);
852 bRet = true;
853 }
854 nIdx = nStop;
855 }
856 return bRet;
857}
858
859bool SwTextNode::IsSymbolAt(const sal_Int32 nBegin) const
860{
861 SwScriptInfo aScriptInfo;
862 SwAttrIter aIter( *const_cast<SwTextNode*>(this), aScriptInfo );
863 aIter.Seek( TextFrameIndex(nBegin) );
864 return aIter.GetFnt()->IsSymbol( getIDocumentLayoutAccess().GetCurrentViewShell() );
865}
866
867namespace {
868
869class SwMinMaxNodeArgs
870{
871public:
872 sal_uLong m_nMaxWidth; // sum of all frame widths
873 tools::Long m_nMinWidth; // biggest frame
874 tools::Long m_nLeftRest; // space not already covered by frames in the left margin
875 tools::Long m_nRightRest; // space not already covered by frames in the right margin
876 tools::Long m_nLeftDiff; // Min/Max-difference of the frame in the left margin
877 tools::Long m_nRightDiff; // Min/Max-difference of the frame in the right margin
878 SwNodeOffset m_nIndex; // index of the node
879 void Minimum( tools::Long nNew ) {
880 if (nNew > m_nMinWidth)
881 m_nMinWidth = nNew;
882 }
883};
884
885}
886
887static void lcl_MinMaxNode(SwFrameFormat* pNd, SwMinMaxNodeArgs& rIn)
888{
889 const SwFormatAnchor& rFormatA = pNd->GetAnchor();
890
891 if ((RndStdIds::FLY_AT_PARA != rFormatA.GetAnchorId()) &&
892 (RndStdIds::FLY_AT_CHAR != rFormatA.GetAnchorId()))
893 {
894 return;
895 }
896
897 const SwNode *pAnchorNode = rFormatA.GetAnchorNode();
898 OSL_ENSURE(pAnchorNode, "Unexpected NULL arguments");
899 if (!pAnchorNode || rIn.m_nIndex != pAnchorNode->GetIndex())
900 return;
901
902 tools::Long nMin, nMax;
903 SwHTMLTableLayout *pLayout = nullptr;
904 const bool bIsDrawFrameFormat = pNd->Which()==RES_DRAWFRMFMT;
905 if( !bIsDrawFrameFormat )
906 {
907 // Does the frame contain a table at the start or the end?
908 const SwNodes& rNodes = pNd->GetDoc()->GetNodes();
909 const SwFormatContent& rFlyContent = pNd->GetContent();
910 SwNodeOffset nStt = rFlyContent.GetContentIdx()->GetIndex();
911 SwTableNode* pTableNd = rNodes[nStt+1]->GetTableNode();
912 if( !pTableNd )
913 {
914 SwNode *pNd2 = rNodes[nStt];
915 pNd2 = rNodes[pNd2->EndOfSectionIndex()-1];
916 if( pNd2->IsEndNode() )
917 pTableNd = pNd2->StartOfSectionNode()->GetTableNode();
918 }
919
920 if( pTableNd )
921 pLayout = pTableNd->GetTable().GetHTMLTableLayout();
922 }
923
924 const SwFormatHoriOrient& rOrient = pNd->GetHoriOrient();
925 sal_Int16 eHoriOri = rOrient.GetHoriOrient();
926
927 tools::Long nDiff;
928 if( pLayout )
929 {
930 nMin = pLayout->GetMin();
931 nMax = pLayout->GetMax();
932 nDiff = nMax - nMin;
933 }
934 else
935 {
936 if( bIsDrawFrameFormat )
937 {
938 const SdrObject* pSObj = pNd->FindSdrObject();
939 if( pSObj )
940 nMin = pSObj->GetCurrentBoundRect().GetWidth();
941 else
942 nMin = 0;
943
944 }
945 else
946 {
947 const SwFormatFrameSize &rSz = pNd->GetFrameSize();
948 nMin = rSz.GetWidth();
949 }
950 nMax = nMin;
951 nDiff = 0;
952 }
953
954 const SvxLRSpaceItem &rLR = pNd->GetLRSpace();
955 nMin += rLR.GetLeft();
956 nMin += rLR.GetRight();
957 nMax += rLR.GetLeft();
958 nMax += rLR.GetRight();
959
960 if( css::text::WrapTextMode_THROUGH == pNd->GetSurround().GetSurround() )
961 {
962 rIn.Minimum( nMin );
963 return;
964 }
965
966 // Frames, which are left- or right-aligned are only party considered
967 // when calculating the maximum, since the border is already being considered.
968 // Only if the frame extends into the text body, this part is being added
969 switch( eHoriOri )
970 {
971 case text::HoriOrientation::RIGHT:
972 {
973 if( nDiff )
974 {
975 rIn.m_nRightRest -= rIn.m_nRightDiff;
976 rIn.m_nRightDiff = nDiff;
977 }
978 if( text::RelOrientation::FRAME != rOrient.GetRelationOrient() )
979 {
980 if (rIn.m_nRightRest > 0)
981 rIn.m_nRightRest = 0;
982 }
983 rIn.m_nRightRest -= nMin;
984 break;
985 }
986 case text::HoriOrientation::LEFT:
987 {
988 if( nDiff )
989 {
990 rIn.m_nLeftRest -= rIn.m_nLeftDiff;
991 rIn.m_nLeftDiff = nDiff;
992 }
993 if (text::RelOrientation::FRAME != rOrient.GetRelationOrient() && rIn.m_nLeftRest < 0)
994 rIn.m_nLeftRest = 0;
995 rIn.m_nLeftRest -= nMin;
996 break;
997 }
998 default:
999 {
1000 rIn.m_nMaxWidth += nMax;
1001 rIn.Minimum(nMin);
1002 }
1003 }
1004}
1005
1006#define FLYINCNT_MIN_WIDTH 284
1007
1013 sal_uLong& rAbsMin ) const
1014{
1016 OutputDevice* pOut = nullptr;
1017 if( pSh )
1018 pOut = pSh->GetWin()->GetOutDev();
1019 if( !pOut )
1021
1022 MapMode aOldMap( pOut->GetMapMode() );
1023 pOut->SetMapMode( MapMode( MapUnit::MapTwip ) );
1024
1025 rMin = 0;
1026 rMax = 0;
1027 rAbsMin = 0;
1028
1029 SvxTextLeftMarginItem const& rTextLeftMargin(GetSwAttrSet().GetTextLeftMargin());
1030 SvxRightMarginItem const& rRightMargin(GetSwAttrSet().GetRightMargin());
1031 tools::Long nLROffset = rTextLeftMargin.GetTextLeft() + GetLeftMarginWithNum( true );
1032 short nFLOffs;
1033 // For enumerations a negative first line indentation is probably filled already
1034 if( !GetFirstLineOfsWithNum( nFLOffs ) || nFLOffs > nLROffset )
1035 nLROffset = nFLOffs;
1036
1037 SwMinMaxNodeArgs aNodeArgs;
1038 aNodeArgs.m_nMinWidth = 0;
1039 aNodeArgs.m_nMaxWidth = 0;
1040 aNodeArgs.m_nLeftRest = nLROffset;
1041 aNodeArgs.m_nRightRest = rRightMargin.GetRight();
1042 aNodeArgs.m_nLeftDiff = 0;
1043 aNodeArgs.m_nRightDiff = 0;
1044 if( nIndex )
1045 {
1047 if(pSpzs)
1048 {
1049 aNodeArgs.m_nIndex = nIndex;
1050 for(auto pFormat: *pSpzs)
1051 lcl_MinMaxNode(pFormat, aNodeArgs);
1052 }
1053 }
1054 if (aNodeArgs.m_nLeftRest < 0)
1055 aNodeArgs.Minimum(nLROffset - aNodeArgs.m_nLeftRest);
1056 aNodeArgs.m_nLeftRest -= aNodeArgs.m_nLeftDiff;
1057 if (aNodeArgs.m_nLeftRest < 0)
1058 aNodeArgs.m_nMaxWidth -= aNodeArgs.m_nLeftRest;
1059
1060 if (aNodeArgs.m_nRightRest < 0)
1061 aNodeArgs.Minimum(rRightMargin.GetRight() - aNodeArgs.m_nRightRest);
1062 aNodeArgs.m_nRightRest -= aNodeArgs.m_nRightDiff;
1063 if (aNodeArgs.m_nRightRest < 0)
1064 aNodeArgs.m_nMaxWidth -= aNodeArgs.m_nRightRest;
1065
1066 SwScriptInfo aScriptInfo;
1067 SwAttrIter aIter( *const_cast<SwTextNode*>(this), aScriptInfo );
1068 TextFrameIndex nIdx(0);
1069 aIter.SeekAndChgAttrIter( nIdx, pOut );
1070 TextFrameIndex nLen(m_Text.getLength());
1071 tools::Long nCurrentWidth = 0;
1072 tools::Long nAdd = 0;
1073 SwMinMaxArgs aArg( pOut, pSh, rMin, rAbsMin );
1074 while( nIdx < nLen )
1075 {
1076 TextFrameIndex nNextChg = aIter.GetNextAttr();
1077 TextFrameIndex nStop = aScriptInfo.NextScriptChg( nIdx );
1078 if( nNextChg > nStop )
1079 nNextChg = nStop;
1080 SwTextAttr *pHint = nullptr;
1081 sal_Unicode cChar = CH_BLANK;
1082 nStop = nIdx;
1083 while( nStop < nLen && nStop < nNextChg &&
1084 CH_TAB != (cChar = m_Text[sal_Int32(nStop)]) &&
1085 CH_BREAK != cChar && CHAR_HARDBLANK != cChar &&
1086 CHAR_HARDHYPHEN != cChar && CHAR_SOFTHYPHEN != cChar &&
1087 CH_TXT_ATR_INPUTFIELDSTART != cChar &&
1088 CH_TXT_ATR_INPUTFIELDEND != cChar &&
1089 CH_TXT_ATR_FORMELEMENT != cChar &&
1090 CH_TXT_ATR_FIELDSTART != cChar &&
1091 CH_TXT_ATR_FIELDSEP != cChar &&
1092 CH_TXT_ATR_FIELDEND != cChar &&
1093 !pHint )
1094 {
1095 // this looks like some defensive programming to handle dummy char
1096 // with missing hint? but it's rather silly because it may pass the
1097 // dummy char to lcl_MinMaxString in that case...
1098 if( ( CH_TXTATR_BREAKWORD != cChar && CH_TXTATR_INWORD != cChar )
1099 || ( nullptr == ( pHint = aIter.GetAttr( nStop ) ) ) )
1100 ++nStop;
1101 }
1102 if (lcl_MinMaxString(aArg, aIter.GetFnt(), m_Text, sal_Int32(nIdx), sal_Int32(nStop)))
1103 {
1104 nAdd = 20;
1105 }
1106 nIdx = nStop;
1107 aIter.SeekAndChgAttrIter( nIdx, pOut );
1108 switch( cChar )
1109 {
1110 case CH_BREAK :
1111 {
1112 if (static_cast<tools::Long>(rMax) < aArg.m_nRowWidth)
1113 rMax = aArg.m_nRowWidth;
1114 aArg.m_nRowWidth = 0;
1115 aArg.NewWord();
1116 aIter.SeekAndChgAttrIter( ++nIdx, pOut );
1117 }
1118 break;
1119 case CH_TAB :
1120 {
1121 aArg.NewWord();
1122 aIter.SeekAndChgAttrIter( ++nIdx, pOut );
1123 }
1124 break;
1125 case CHAR_SOFTHYPHEN:
1126 ++nIdx;
1127 break;
1128 case CHAR_HARDBLANK:
1129 case CHAR_HARDHYPHEN:
1130 {
1131 OUString sTmp( cChar );
1132 SwDrawTextInfo aDrawInf( pSh,
1133 *pOut, sTmp, 0, 1, 0, false );
1134 nCurrentWidth = aIter.GetFnt()->GetTextSize_( aDrawInf ).Width();
1135 aArg.m_nWordWidth += nCurrentWidth;
1136 aArg.m_nRowWidth += nCurrentWidth;
1137 if (static_cast<tools::Long>(rAbsMin) < aArg.m_nWordWidth)
1138 rAbsMin = aArg.m_nWordWidth;
1139 aArg.Minimum(aArg.m_nWordWidth + aArg.m_nWordAdd);
1140 aArg.m_nNoLineBreak = sal_Int32(nIdx++);
1141 }
1142 break;
1144 case CH_TXTATR_INWORD:
1145 {
1146 if( !pHint )
1147 break;
1148 tools::Long nOldWidth = aArg.m_nWordWidth;
1149 tools::Long nOldAdd = aArg.m_nWordAdd;
1150 aArg.NewWord();
1151
1152 switch( pHint->Which() )
1153 {
1154 case RES_TXTATR_FLYCNT :
1155 {
1156 SwFrameFormat *pFrameFormat = pHint->GetFlyCnt().GetFrameFormat();
1157 const SvxLRSpaceItem &rLR = pFrameFormat->GetLRSpace();
1158 if( RES_DRAWFRMFMT == pFrameFormat->Which() )
1159 {
1160 const SdrObject* pSObj = pFrameFormat->FindSdrObject();
1161 if( pSObj )
1162 nCurrentWidth = pSObj->GetCurrentBoundRect().GetWidth();
1163 else
1164 nCurrentWidth = 0;
1165 }
1166 else
1167 {
1168 const SwFormatFrameSize& rTmpSize = pFrameFormat->GetFrameSize();
1169 if( RES_FLYFRMFMT == pFrameFormat->Which()
1170 && rTmpSize.GetWidthPercent() )
1171 {
1172 // This is a hack for the following situation: In the paragraph there's a
1173 // text frame with relative size. Then let's take 0.5 cm as minimum width
1174 // and USHRT_MAX as maximum width
1175 // It were cleaner and maybe necessary later on to iterate over the content
1176 // of the text frame and call GetMinMaxSize recursively
1177 nCurrentWidth = FLYINCNT_MIN_WIDTH; // 0.5 cm
1178 rMax = std::max(rMax, sal_uLong(USHRT_MAX));
1179 }
1180 else
1181 nCurrentWidth = pFrameFormat->GetFrameSize().GetWidth();
1182 }
1183 nCurrentWidth += rLR.GetLeft();
1184 nCurrentWidth += rLR.GetRight();
1185 aArg.m_nWordAdd = nOldWidth + nOldAdd;
1186 aArg.m_nWordWidth = nCurrentWidth;
1187 aArg.m_nRowWidth += nCurrentWidth;
1188 if (static_cast<tools::Long>(rAbsMin) < aArg.m_nWordWidth)
1189 rAbsMin = aArg.m_nWordWidth;
1190 aArg.Minimum(aArg.m_nWordWidth + aArg.m_nWordAdd);
1191 break;
1192 }
1193 case RES_TXTATR_FTN :
1194 {
1195 const OUString aText = pHint->GetFootnote().GetNumStr();
1196 if( lcl_MinMaxString( aArg, aIter.GetFnt(), aText, 0,
1197 aText.getLength() ) )
1198 nAdd = 20;
1199 break;
1200 }
1201
1202 case RES_TXTATR_FIELD :
1204 {
1205 SwField *pField = const_cast<SwField*>(pHint->GetFormatField().GetField());
1206 const OUString aText = pField->ExpandField(true, nullptr);
1207 if( lcl_MinMaxString( aArg, aIter.GetFnt(), aText, 0,
1208 aText.getLength() ) )
1209 nAdd = 20;
1210 break;
1211 }
1212 default:
1213 aArg.m_nWordWidth = nOldWidth;
1214 aArg.m_nWordAdd = nOldAdd;
1215 }
1216 aIter.SeekAndChgAttrIter( ++nIdx, pOut );
1217 }
1218 break;
1225 { // just skip it and continue with the content...
1226 aIter.SeekAndChgAttrIter( ++nIdx, pOut );
1227 }
1228 break;
1229 }
1230 }
1231 if (static_cast<tools::Long>(rMax) < aArg.m_nRowWidth)
1232 rMax = aArg.m_nRowWidth;
1233
1234 nLROffset += rRightMargin.GetRight();
1235
1236 rAbsMin += nLROffset;
1237 rAbsMin += nAdd;
1238 rMin += nLROffset;
1239 rMin += nAdd;
1240 if (static_cast<tools::Long>(rMin) < aNodeArgs.m_nMinWidth)
1241 rMin = aNodeArgs.m_nMinWidth;
1242 if (static_cast<tools::Long>(rAbsMin) < aNodeArgs.m_nMinWidth)
1243 rAbsMin = aNodeArgs.m_nMinWidth;
1244 rMax += aNodeArgs.m_nMaxWidth;
1245 rMax += nLROffset;
1246 rMax += nAdd;
1247 if( rMax < rMin ) // e.g. Frames with flow through only contribute to the minimum
1248 rMax = rMin;
1249 pOut->SetMapMode( aOldMap );
1250}
1251
1262 TextFrameIndex nStart, TextFrameIndex nEnd)
1263{
1264 assert(GetOffset() <= nStart && (!GetFollow() || nStart < GetFollow()->GetOffset()));
1265 SwViewShell const*const pSh = getRootFrame()->GetCurrShell();
1266 assert(pSh);
1267 OutputDevice *const pOut = &pSh->GetRefDev();
1268 assert(pOut);
1269
1270 MapMode aOldMap( pOut->GetMapMode() );
1271 pOut->SetMapMode( MapMode( MapUnit::MapTwip ) );
1272
1273 if (nStart == nEnd)
1274 {
1275 assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
1276
1277 SwScriptInfo aScriptInfo;
1278 SwAttrIter aIter(*GetTextNodeFirst(), aScriptInfo, this);
1279 aIter.SeekAndChgAttrIter( nStart, pOut );
1280
1281 Boundary aBound = g_pBreakIt->GetBreakIter()->getWordBoundary(
1282 GetText(), sal_Int32(nStart),
1283 g_pBreakIt->GetLocale( aIter.GetFnt()->GetLanguage() ),
1284 WordType::DICTIONARY_WORD, true );
1285
1286 if (sal_Int32(nStart) == aBound.startPos)
1287 {
1288 // cursor is at left or right border of word
1289 pOut->SetMapMode( aOldMap );
1290 return 100;
1291 }
1292
1293 nStart = TextFrameIndex(aBound.startPos);
1294 nEnd = TextFrameIndex(aBound.endPos);
1295
1296 if (nStart == nEnd)
1297 {
1298 pOut->SetMapMode( aOldMap );
1299 return 100;
1300 }
1301 }
1302
1303 SwScriptInfo aScriptInfo;
1304 SwAttrIter aIter(*GetTextNodeFirst(), aScriptInfo, this);
1305
1306 // We do not want scaling attributes to be considered during this
1307 // calculation. For this, we push a temporary scaling attribute with
1308 // scaling value 100 and priority flag on top of the scaling stack
1309 SwAttrHandler& rAH = aIter.GetAttrHandler();
1311 SwTextAttrEnd aAttr( aItem, 0, COMPLETE_STRING );
1312 aAttr.SetPriorityAttr( true );
1313 rAH.PushAndChg( aAttr, *(aIter.GetFnt()) );
1314
1315 TextFrameIndex nIdx = nStart;
1316
1317 sal_uLong nWidth = 0;
1318 sal_uLong nProWidth = 0;
1319
1320 while( nIdx < nEnd )
1321 {
1322 aIter.SeekAndChgAttrIter( nIdx, pOut );
1323
1324 // scan for end of portion
1325 TextFrameIndex const nNextChg = std::min(aIter.GetNextAttr(), aScriptInfo.NextScriptChg(nIdx));
1326
1327 TextFrameIndex nStop = nIdx;
1328 sal_Unicode cChar = CH_BLANK;
1329 SwTextAttr* pHint = nullptr;
1330
1331 // stop at special characters in [ nIdx, nNextChg ]
1332 while( nStop < nEnd && nStop < nNextChg )
1333 {
1334 cChar = GetText()[sal_Int32(nStop)];
1335 if (
1336 CH_TAB == cChar ||
1337 CH_BREAK == cChar ||
1338 CHAR_HARDBLANK == cChar ||
1339 CHAR_HARDHYPHEN == cChar ||
1340 CHAR_SOFTHYPHEN == cChar ||
1341 CH_TXT_ATR_INPUTFIELDSTART == cChar ||
1342 CH_TXT_ATR_INPUTFIELDEND == cChar ||
1343 CH_TXT_ATR_FORMELEMENT == cChar ||
1344 CH_TXT_ATR_FIELDSTART == cChar ||
1345 CH_TXT_ATR_FIELDSEP == cChar ||
1346 CH_TXT_ATR_FIELDEND == cChar ||
1347 (
1348 (CH_TXTATR_BREAKWORD == cChar || CH_TXTATR_INWORD == cChar) &&
1349 (nullptr == (pHint = aIter.GetAttr(nStop)))
1350 )
1351 )
1352 {
1353 break;
1354 }
1355 else
1356 ++nStop;
1357 }
1358
1359 // calculate text widths up to cChar
1360 if ( nStop > nIdx )
1361 {
1362 SwDrawTextInfo aDrawInf(pSh, *pOut, GetText(), sal_Int32(nIdx), sal_Int32(nStop - nIdx));
1363 nProWidth += aIter.GetFnt()->GetTextSize_( aDrawInf ).Width();
1364 }
1365
1366 nIdx = nStop;
1367 aIter.SeekAndChgAttrIter( nIdx, pOut );
1368
1369 if ( cChar == CH_BREAK )
1370 {
1371 nWidth = std::max( nWidth, nProWidth );
1372 nProWidth = 0;
1373 nIdx++;
1374 }
1375 else if ( cChar == CH_TAB )
1376 {
1377 // tab receives width of one space
1378 SwDrawTextInfo aDrawInf(pSh, *pOut, OUStringChar(CH_BLANK), 0, 1);
1379 nProWidth += aIter.GetFnt()->GetTextSize_( aDrawInf ).Width();
1380 nIdx++;
1381 }
1382 else if ( cChar == CHAR_SOFTHYPHEN )
1383 ++nIdx;
1384 else if ( cChar == CHAR_HARDBLANK || cChar == CHAR_HARDHYPHEN )
1385 {
1386 OUString sTmp( cChar );
1387 SwDrawTextInfo aDrawInf(pSh, *pOut, sTmp, 0, 1);
1388 nProWidth += aIter.GetFnt()->GetTextSize_( aDrawInf ).Width();
1389 nIdx++;
1390 }
1391 else if ( pHint && ( cChar == CH_TXTATR_BREAKWORD || cChar == CH_TXTATR_INWORD ) )
1392 {
1393 switch( pHint->Which() )
1394 {
1395 case RES_TXTATR_FTN :
1396 {
1397 const OUString aText = pHint->GetFootnote().GetNumStr();
1398 SwDrawTextInfo aDrawInf(pSh, *pOut, aText, 0, aText.getLength());
1399
1400 nProWidth += aIter.GetFnt()->GetTextSize_( aDrawInf ).Width();
1401 break;
1402 }
1403
1404 case RES_TXTATR_FIELD :
1406 {
1407 SwField *pField = const_cast<SwField*>(pHint->GetFormatField().GetField());
1408 OUString const aText = pField->ExpandField(true, getRootFrame());
1409 SwDrawTextInfo aDrawInf(pSh, *pOut, aText, 0, aText.getLength());
1410
1411 nProWidth += aIter.GetFnt()->GetTextSize_( aDrawInf ).Width();
1412 break;
1413 }
1414
1415 default:
1416 {
1417 // any suggestions for a default action?
1418 }
1419 } // end of switch
1420 nIdx++;
1421 }
1422 else if (CH_TXT_ATR_INPUTFIELDSTART == cChar ||
1423 CH_TXT_ATR_INPUTFIELDEND == cChar ||
1424 CH_TXT_ATR_FORMELEMENT == cChar ||
1425 CH_TXT_ATR_FIELDSTART == cChar ||
1426 CH_TXT_ATR_FIELDSEP == cChar ||
1427 CH_TXT_ATR_FIELDEND == cChar)
1428 { // just skip it and continue with the content...
1429 ++nIdx;
1430 }
1431 } // end of while
1432
1433 nWidth = std::max( nWidth, nProWidth );
1434
1435 // search for the line containing nStart
1436 if (HasPara())
1437 {
1438 SwTextInfo aInf(this);
1439 SwTextIter aLine(this, &aInf);
1440 aLine.CharToLine( nStart );
1441 pOut->SetMapMode( aOldMap );
1442 return o3tl::narrowing<sal_uInt16>( nWidth ?
1443 ( ( 100 * aLine.GetCurr()->Height() ) / nWidth ) : 0 );
1444 }
1445 // no frame or no paragraph, we take the height of the character
1446 // at nStart as line height
1447
1448 aIter.SeekAndChgAttrIter( nStart, pOut );
1449 pOut->SetMapMode( aOldMap );
1450
1451 SwDrawTextInfo aDrawInf(pSh, *pOut, GetText(), sal_Int32(nStart), 1);
1452 return o3tl::narrowing<sal_uInt16>( nWidth ? ((100 * aIter.GetFnt()->GetTextSize_( aDrawInf ).Height()) / nWidth ) : 0 );
1453}
1454
1455std::vector<SwFlyAtContentFrame*> SwTextFrame::GetSplitFlyDrawObjs() const
1456{
1457 std::vector<SwFlyAtContentFrame*> aObjs;
1458 const SwSortedObjs* pSortedObjs = GetDrawObjs();
1459 if (!pSortedObjs)
1460 {
1461 return aObjs;
1462 }
1463
1464 for (const auto& pSortedObj : *pSortedObjs)
1465 {
1466 SwFlyFrame* pFlyFrame = pSortedObj->DynCastFlyFrame();
1467 if (!pFlyFrame)
1468 {
1469 continue;
1470 }
1471
1472 if (!pFlyFrame->IsFlySplitAllowed())
1473 {
1474 continue;
1475 }
1476
1477 aObjs.push_back(static_cast<SwFlyAtContentFrame*>(pFlyFrame));
1478 }
1479
1480 return aObjs;
1481}
1482
1484{
1485 const SwTextFrame* pFollow = GetFollow();
1486 if (!pFollow)
1487 {
1488 return false;
1489 }
1490
1491 if (mnOffset != pFollow->GetOffset())
1492 {
1493 return false;
1494 }
1495
1496 // At this point we know what we're part of a chain that is an anchor for split fly frames, but
1497 // we're not the last one. See if we have a matching fly.
1498
1499 // Look up the master of the anchor.
1500 const SwTextFrame* pAnchor = this;
1501 while (pAnchor->IsFollow())
1502 {
1503 pAnchor = pAnchor->FindMaster();
1504 }
1505 for (const auto& pFly : pAnchor->GetSplitFlyDrawObjs())
1506 {
1507 // Nominally all flys are anchored in the master; see if this fly is effectively anchored in
1508 // us.
1509 SwTextFrame* pFlyAnchor = pFly->FindAnchorCharFrame();
1510 if (pFlyAnchor != this)
1511 {
1512 continue;
1513 }
1514 if (pFly->GetFollow())
1515 {
1516 return true;
1517 }
1518 }
1519
1520 return false;
1521}
1522
1524{
1525 if (!IsEmptyMaster())
1526 {
1527 return false;
1528 }
1529
1530 if (!m_pDrawObjs || m_pDrawObjs->size() != 1)
1531 {
1532 return false;
1533 }
1534
1535 SwFlyFrame* pFlyFrame = (*m_pDrawObjs)[0]->DynCastFlyFrame();
1536 if (!pFlyFrame || !pFlyFrame->IsFlySplitAllowed())
1537 {
1538 return false;
1539 }
1540
1541 if (mnOffset != GetFollow()->GetOffset())
1542 {
1543 return false;
1544 }
1545
1546 return true;
1547}
1548
1550{
1551 if (IsFollow())
1552 {
1553 return false;
1554 }
1555
1556 if (GetTextNodeFirst()->GetSwAttrSet().HasItem(RES_PAGEDESC))
1557 {
1558 return false;
1559 }
1560
1562 {
1563 return false;
1564 }
1565
1566 // This is a master that doesn't fit the current parent.
1567 if (!m_pDrawObjs || m_pDrawObjs->size() != 1)
1568 {
1569 return false;
1570 }
1571
1572 SwFlyFrame* pFlyFrame = (*m_pDrawObjs)[0]->DynCastFlyFrame();
1573 if (!pFlyFrame || !pFlyFrame->IsFlySplitAllowed())
1574 {
1575 return false;
1576 }
1577
1578 // It has a split fly anchored to it.
1579 if (pFlyFrame->GetFrameFormat().GetVertOrient().GetPos() >= 0)
1580 {
1581 return false;
1582 }
1583
1584 // Negative vertical offset means that visually it already may have a first line.
1585 // Consider that, we may need to split the frame, so the fly frame is on one page and the empty
1586 // paragraph's frame is on a next page.
1587 return true;
1588}
1589
1591{
1592 SwTwips nRet = 0;
1593
1594 sal_Int32 nIdx = 0;
1595
1596 while ( nIdx < GetText().getLength() )
1597 {
1598 const sal_Unicode cCh = GetText()[nIdx];
1599 if ( cCh!='\t' && cCh!=' ' )
1600 {
1601 break;
1602 }
1603 ++nIdx;
1604 }
1605
1606 if ( nIdx > 0 )
1607 {
1608 SwPosition aPos( *this, nIdx );
1609
1610 // Find the non-follow text frame:
1612 for( SwTextFrame* pFrame = aIter.First(); pFrame; pFrame = aIter.Next() )
1613 {
1614 // Only consider master frames:
1615 if (!pFrame->IsFollow() &&
1616 pFrame->GetTextNodeForFirstText() == this)
1617 {
1618 SwRectFnSet aRectFnSet(pFrame);
1619 SwRect aRect;
1620 pFrame->GetCharRect( aRect, aPos );
1621 nRet = pFrame->IsRightToLeft() ?
1622 aRectFnSet.GetPrtRight(*pFrame) - aRectFnSet.GetRight(aRect) :
1623 aRectFnSet.GetLeft(aRect) - aRectFnSet.GetPrtLeft(*pFrame);
1624 break;
1625 }
1626 }
1627 }
1628
1629 return nRet;
1630}
1631
1632/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
sal_Int32 m_nPosition
o3tl::strong_int< sal_Int32, struct Tag_TextFrameIndex > TextFrameIndex
Denotes a character index in a text frame at a layout level, after extent mapping from a text node at...
SwBreakIt * g_pBreakIt
Definition: breakit.cxx:34
static OutputDevice * GetDefaultDevice()
virtual const SwViewShell * GetCurrentViewShell() const =0
Returns the layout set at the document.
virtual const tools::Rectangle & GetCurrentBoundRect() const
const SfxPoolItem * GetCurItem() const
const SfxPoolItem * NextItem()
constexpr tools::Long Height() const
constexpr tools::Long Width() const
tools::Long GetRight() const
tools::Long GetLeft() const
tools::Long GetRight() const
tools::Long GetWidth() const
tools::Long GetTextLeft() const
Used by Attribute Iterators to organize attributes on stacks to find the valid attribute in each cate...
Definition: atrhndl.hxx:38
void PushAndChg(const SwTextAttr &rAttr, SwFont &rFnt)
Definition: atrstck.cxx:337
void ResetFont(SwFont &rFnt) const
Definition: atrhndl.hxx:104
void Reset()
Definition: atrstck.cxx:331
void PopAndChg(const SwTextAttr &rAttr, SwFont &rFnt)
Definition: atrstck.cxx:422
size_t m_nStartIndex
current iteration index in HintStarts
Definition: itratr.hxx:48
sal_Int32 m_nPosition
current iteration index in text node
Definition: itratr.hxx:52
void Rst(SwTextAttr const *pHt)
Definition: itratr.cxx:110
size_t m_nEndIndex
current iteration index in HintEnds
Definition: itratr.hxx:50
SwAttrHandler & GetAttrHandler()
Definition: itratr.hxx:109
bool SeekAndChgAttrIter(TextFrameIndex nPos, OutputDevice *pOut)
Executes ChgPhysFnt if Seek() returns true and change font to merge character border with neighbours.
Definition: itratr.cxx:155
SwFont * GetFnt()
Definition: itratr.hxx:103
virtual ~SwAttrIter()
Definition: itratr.cxx:121
o3tl::enumarray< SwFontScript, sal_uInt16 > m_aFontIdx
Definition: itratr.hxx:55
void SeekFwd(sal_Int32 nOldPos, sal_Int32 nNewPos)
Definition: itratr.cxx:263
o3tl::enumarray< SwFontScript, const void * > m_aFontCacheIds
Definition: itratr.hxx:54
bool MaybeHasHints() const
Definition: itratr.cxx:127
bool IsSymbol(TextFrameIndex nPos)
Definition: itratr.cxx:181
sal_uInt8 m_nPropFont
Definition: itratr.hxx:53
bool SeekStartAndChgAttrIter(OutputDevice *pOut, const bool bParaFont)
Definition: itratr.cxx:197
short m_nChgCnt
count currently open hints, redlines, ext-input
Definition: itratr.hxx:45
void Chg(SwTextAttr const *pHt)
Definition: itratr.cxx:100
std::unique_ptr< SwRedlineItr, o3tl::default_delete< SwRedlineItr > > m_pRedline
Definition: itratr.hxx:46
void CtorInitAttrIter(SwTextNode &rTextNode, SwScriptInfo &rScrInf, SwTextFrame const *pFrame=nullptr)
Definition: redlnitr.cxx:582
SwAttrHandler m_aAttrHandler
Definition: itratr.hxx:37
sw::MergedPara const * m_pMergedPara
Definition: itratr.hxx:58
SwScriptInfo * m_pScriptInfo
Definition: itratr.hxx:40
SwAttrIter(SwTextNode const *pTextNode)
Definition: itratr.cxx:71
TextFrameIndex GetNextAttr() const
Definition: itratr.cxx:734
SwViewShell * m_pViewShell
Definition: itratr.hxx:38
bool Seek(TextFrameIndex nPos)
Enables the attributes used at char pos nPos in the logical font.
Definition: itratr.cxx:306
SwTextAttr * GetAttr(TextFrameIndex nPos) const
Returns the attribute for a position.
Definition: itratr.cxx:147
VclPtr< OutputDevice > m_pLastOut
Definition: itratr.hxx:43
void InitFontAndAttrHandler(SwTextNode const &rPropsNode, SwTextNode const &rTextNode, std::u16string_view aText, bool const *pbVertLayout, bool const *pbVertLayoutLRBT)
Definition: redlnitr.cxx:506
const SwTextNode * m_pTextNode
input: the current text node
Definition: itratr.hxx:57
SwFont * m_pFont
Definition: itratr.hxx:39
css::uno::Reference< css::i18n::XBreakIterator > const & GetBreakIter() const
Definition: breakit.hxx:63
const css::lang::Locale & GetLocale(const LanguageType aLang)
Definition: breakit.hxx:68
SwTextFrame * FindMaster() const
Definition: flowfrm.cxx:762
const SwAttrSet & GetSwAttrSet() const
Does node has already its own auto-attributes? Access to SwAttrSet.
Definition: node.hxx:727
SwNodes & GetNodes()
Definition: doc.hxx:422
IDocumentLayoutAccess const & getIDocumentLayoutAccess() const
Definition: doc.cxx:419
const sw::FrameFormats< sw::SpzFrameFormat * > * GetSpzFrameFormats() const
Definition: doc.hxx:759
Base class of all fields.
Definition: fldbas.hxx:296
OUString ExpandField(bool bCached, SwRootFrame const *pLayout) const
expand the field.
Definition: fldbas.cxx:491
Flys that are anchored to content (at-para, at-char) but not in content (as-char).
Definition: flyfrms.hxx:163
general base class for all free-flowing frames
Definition: flyfrm.hxx:79
bool IsFlySplitAllowed() const
Is this fly allowed to split across pages? (Disabled by default.)
Definition: fly.cxx:662
virtual const SwFlyFrame * DynCastFlyFrame() const override
Definition: fly.cxx:3230
virtual SwFrameFormat & GetFrameFormat() override
Definition: fly.cxx:3044
To take Asian or other languages into consideration, an SwFont object consists of 3 SwSubFonts (Latin...
Definition: swfont.hxx:135
Size GetTextSize_(SwDrawTextInfo &rInf)
Definition: swfont.hxx:313
void SetProportion(const sal_uInt8 nNewPropr)
Definition: swfont.hxx:772
void SetFntChg(const bool bNew)
Definition: swfont.hxx:212
void SetFontCacheId(const void *nNewFontCacheId, const sal_uInt16 nIdx, SwFontScript nWhich)
Definition: swfont.hxx:203
SwFontScript GetActual() const
Definition: swfont.hxx:187
bool IsSymbol(SwViewShell const *pSh)
Definition: swfont.hxx:273
LanguageType GetLanguage() const
Definition: swfont.hxx:286
bool IsFntChg() const
Definition: swfont.hxx:211
void ChgPhysFnt(SwViewShell const *pSh, OutputDevice &rOut)
Definition: swfont.cxx:893
void SetActual(SwFontScript nNew)
Definition: swfont.hxx:754
FlyAnchors.
Definition: fmtanchr.hxx:37
RndStdIds GetAnchorId() const
Definition: fmtanchr.hxx:67
SwNode * GetAnchorNode() const
Definition: atrfrm.cxx:1614
const std::shared_ptr< SfxItemSet > & GetStyleHandle() const
Definition: fmtautofmt.hxx:49
SwCharFormat * GetCharFormat() const
Definition: fchrfmt.hxx:70
Content, content of frame (header, footer, fly).
Definition: fmtcntnt.hxx:32
const SwNodeIndex * GetContentIdx() const
Definition: fmtcntnt.hxx:46
const SwField * GetField() const
Definition: fmtfld.hxx:131
SwFrameFormat * GetFrameFormat() const
Definition: fmtflcnt.hxx:45
const OUString & GetNumStr() const
Definition: fmtftn.hxx:72
sal_uInt8 GetWidthPercent() const
Definition: fmtfsize.hxx:91
Defines the horizontal position of a fly frame.
Definition: fmtornt.hxx:73
sal_Int16 GetHoriOrient() const
Definition: fmtornt.hxx:94
sal_Int16 GetRelationOrient() const
Definition: fmtornt.hxx:95
css::text::WrapTextMode GetSurround() const
Definition: fmtsrnd.hxx:51
SwTwips GetPos() const
Definition: fmtornt.hxx:62
const SwDoc * GetDoc() const
The document is set in SwAttrPool now, therefore you always can access it.
Definition: format.hxx:139
const SwFormatFrameSize & GetFrameSize(bool=true) const
Definition: fmtfsize.hxx:104
const SvxLRSpaceItem & GetLRSpace(bool=true) const
Definition: frmatr.hxx:98
sal_uInt16 Which() const
for Querying of Writer-functions.
Definition: format.hxx:82
const SwFormatVertOrient & GetVertOrient(bool=true) const
Definition: fmtornt.hxx:113
const SwFormatAnchor & GetAnchor(bool=true) const
Definition: fmtanchr.hxx:88
const SwAttrSet & GetAttrSet() const
For querying the attribute array.
Definition: format.hxx:136
const SwFormatSurround & GetSurround(bool=true) const
Definition: fmtsrnd.hxx:66
const SwFormatHoriOrient & GetHoriOrient(bool=true) const
Definition: fmtornt.hxx:115
const SwFormatContent & GetContent(bool=true) const
Definition: fmtcntnt.hxx:55
const SwRect & getFrameArea() const
Definition: frame.hxx:179
const SwRect & getFramePrintArea() const
Definition: frame.hxx:180
Style of a layout element.
Definition: frmfmt.hxx:72
SdrObject * FindSdrObject()
Definition: frmfmt.hxx:153
std::unique_ptr< SwSortedObjs > m_pDrawObjs
Definition: frame.hxx:413
const SwSortedObjs * GetDrawObjs() const
Definition: frame.hxx:568
SwLayoutFrame * GetUpper()
Definition: frame.hxx:684
SwRootFrame * getRootFrame()
Definition: frame.hxx:685
sal_uLong GetMin() const
Definition: htmltbl.hxx:280
sal_uLong GetMax() const
Definition: htmltbl.hxx:281
TElementType * Next()
Definition: calbck.hxx:380
TElementType * First()
Definition: calbck.hxx:372
virtual void Height(const SwTwips nNew, const bool bText=true) override
Definition: porlay.cxx:231
SwNodeOffset GetIndex() const
Definition: ndindex.hxx:111
Base class of the Writer document model elements.
Definition: node.hxx:98
SwTextNode * GetTextNode()
Inline methods from Node.hxx.
Definition: ndtxt.hxx:901
SwNodeOffset GetIndex() const
Definition: node.hxx:312
SwDoc & GetDoc()
Definition: node.hxx:233
bool IsEndNode() const
Definition: node.hxx:189
bool IsTextNode() const
Definition: node.hxx:190
const SwStartNode * StartOfSectionNode() const
Definition: node.hxx:153
SwNodeOffset EndOfSectionIndex() const
Definition: node.hxx:691
SwTableNode * GetTableNode()
Definition: node.hxx:650
const IDocumentLayoutAccess & getIDocumentLayoutAccess() const
Provides access to the document layout interface.
Definition: node.cxx:2143
const SwPosition * End() const
Definition: pam.hxx:263
tools::Long GetPrtRight(const SwFrame &rFrame) const
Definition: frame.hxx:1417
tools::Long GetLeft(const SwRect &rRect) const
Definition: frame.hxx:1384
tools::Long GetPrtLeft(const SwFrame &rFrame) const
Definition: frame.hxx:1416
tools::Long GetRight(const SwRect &rRect) const
Definition: frame.hxx:1385
Of course Writer needs its own rectangles.
Definition: swrect.hxx:35
static constexpr size_type npos
Definition: docary.hxx:224
vector_type::size_type size_type
Definition: docary.hxx:223
SwViewShell * GetCurrShell() const
Definition: rootfrm.hxx:215
SwFontScript WhichFont(TextFrameIndex nIdx) const
Definition: porlay.cxx:892
TextFrameIndex NextScriptChg(TextFrameIndex nPos) const
Definition: porlay.cxx:1858
class for collecting anchored objects
Definition: sortedobjs.hxx:49
const SwTable & GetTable() const
Definition: node.hxx:542
SwHTMLTableLayout * GetHTMLTableLayout()
Definition: swtable.hxx:182
A wrapper around SfxPoolItem to store the start position of (usually) a text portion,...
Definition: txatbase.hxx:44
sal_Int32 GetAnyEnd() const
end (if available), else start
Definition: txatbase.hxx:161
bool IsFormatIgnoreStart() const
Definition: txatbase.hxx:108
const sal_Int32 * End() const
Definition: txatbase.hxx:156
const SwFormatFlyCnt & GetFlyCnt() const
Definition: txatbase.hxx:226
const SwFormatFootnote & GetFootnote() const
Definition: txatbase.hxx:208
sal_Int32 GetStart() const
Definition: txatbase.hxx:88
const SwFormatCharFormat & GetCharFormat() const
Definition: txatbase.hxx:187
const SwFormatAutoFormat & GetAutoFormat() const
Definition: txatbase.hxx:193
sal_uInt16 Which() const
Definition: txatbase.hxx:116
void SetPriorityAttr(bool bFlag)
Definition: txatbase.hxx:104
bool IsFormatIgnoreEnd() const
Definition: txatbase.hxx:109
const SwFormatField & GetFormatField() const
Definition: txatbase.hxx:199
Represents the visualization of a paragraph.
Definition: txtfrm.hxx:168
SwTextFrame * GetFollow()
Definition: txtfrm.hxx:889
bool IsEmptyWithSplitFly() const
This text frame is not split, doesn't fit the upper, has a single split fly anchored to it with a neg...
Definition: itratr.cxx:1549
TextFrameIndex GetOffset() const
Definition: txtfrm.hxx:453
bool HasPara() const
Definition: txtfrm.hxx:853
bool IsEmptyMasterWithSplitFly() const
This text frame has a follow and the text frame don't contain text.
Definition: itratr.cxx:1523
bool IsEmptyMaster() const
If there's a Follow and we don't contain text ourselves.
Definition: txtfrm.hxx:461
bool IsSymbolAt(TextFrameIndex) const
Definition: itratr.cxx:190
sal_uInt16 GetScalingOfSelectedText(TextFrameIndex nStt, TextFrameIndex nEnd)
Calculates the width of the text part specified by nStart and nEnd, the height of the line containing...
Definition: itratr.cxx:1261
bool HasNonLastSplitFlyDrawObj() const
This text frame may have a split fly frames anchored to it.
Definition: itratr.cxx:1483
SwTextNode * GetTextNodeFirst()
Definition: txtfrm.hxx:472
const OUString & GetText() const
Returns the text portion we want to edit (for inline see underneath)
Definition: txtfrm.cxx:1380
std::vector< SwFlyAtContentFrame * > GetSplitFlyDrawObjs() const
Like GetDrawObjs(), but limit to fly frames which are allowed to split.
Definition: itratr.cxx:1455
TextFrameIndex mnOffset
Definition: txtfrm.hxx:207
void CharToLine(TextFrameIndex)
Definition: itrtxt.cxx:194
const SwLineLayout * GetCurr() const
Definition: itrtxt.hxx:83
SwTextNode is a paragraph in the document model.
Definition: ndtxt.hxx:112
OUString m_Text
Definition: ndtxt.hxx:129
virtual sal_Int32 Len() const override
Definition: ndtxt.cxx:291
tools::Long GetLeftMarginWithNum(bool bTextLeft=false) const
Returns the additional indents of this text node and its numbering.
Definition: ndtxt.cxx:3277
bool IsSymbolAt(sal_Int32 nBegin) const
in ndcopy.cxx
Definition: itratr.cxx:859
SwTwips GetWidthOfLeadingTabs() const
Returns the width of leading tabs/blanks in this paragraph.
Definition: itratr.cxx:1590
bool GetFirstLineOfsWithNum(short &rFirstOffset) const
Returns the combined first line indent of this text node and its numbering.
Definition: ndtxt.cxx:3334
void GetMinMaxSize(SwNodeOffset nIndex, sal_uLong &rMin, sal_uLong &rMax, sal_uLong &rAbs) const
Is in itratr.
Definition: itratr.cxx:1012
SwpHints * GetpSwpHints()
Definition: ndtxt.hxx:252
const OUString & GetText() const
Definition: ndtxt.hxx:244
vcl::Window * GetWin() const
Definition: viewsh.hxx:364
vcl::RenderContext & GetRefDev() const
Definition: viewsh.cxx:2168
An SwTextAttr container, stores all directly formatted text portions for a text node.
Definition: ndhints.hxx:68
SwTextAttr * Get(size_t nPos) const
Definition: ndhints.hxx:144
size_t Count() const
Definition: ndhints.hxx:142
SwTextAttr * GetSortedByEnd(size_t nPos) const
Definition: ndhints.hxx:158
reference_type * get() const
constexpr tools::Long GetWidth() const
::OutputDevice const * GetOutDev() const
@ Minimum
Value in Var-direction gives minimum (can be exceeded but not be less).
#define CH_TXT_ATR_FIELDSEP
Definition: hintids.hxx:184
#define CH_TXT_ATR_INPUTFIELDSTART
Definition: hintids.hxx:178
#define CH_TXT_ATR_FORMELEMENT
Definition: hintids.hxx:181
constexpr TypedWhichId< SwFormatFootnote > RES_TXTATR_FTN(59)
bool isCHRATR(const sal_uInt16 nWhich)
Definition: hintids.hxx:468
constexpr sal_uInt16 RES_CHRATR_END(46)
constexpr TypedWhichId< SwFormatAutoFormat > RES_TXTATR_AUTOFMT(50)
constexpr TypedWhichId< SwFormatINetFormat > RES_TXTATR_INETFMT(51)
constexpr TypedWhichId< SwFormatPageDesc > RES_PAGEDESC(99)
constexpr TypedWhichId< SvxCharScaleWidthItem > RES_CHRATR_SCALEW(35)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_ANNOTATION(60)
constexpr TypedWhichId< SwFlyFrameFormat > RES_FLYFRMFMT(162)
constexpr sal_uInt16 RES_CHRATR_BEGIN(HINT_BEGIN)
constexpr TypedWhichId< SwFormatContentControl > RES_TXTATR_CONTENTCONTROL(56)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_FIELD(RES_TXTATR_NOEND_BEGIN)
constexpr TypedWhichId< SwFormatCharFormat > RES_TXTATR_CHARFMT(52)
constexpr TypedWhichId< SwDrawFrameFormat > RES_DRAWFRMFMT(165)
constexpr TypedWhichId< SwFormatFlyCnt > RES_TXTATR_FLYCNT(58)
constexpr TypedWhichId< SvxRsidItem > RES_CHRATR_RSID(39)
#define CH_TXTATR_INWORD
Definition: hintids.hxx:175
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_METAFIELD(49)
constexpr TypedWhichId< SvXMLAttrContainerItem > RES_TXTATR_UNKNOWN_CONTAINER(54)
constexpr TypedWhichId< SwFormatRefMark > RES_TXTATR_REFMARK(RES_TXTATR_WITHEND_BEGIN)
constexpr TypedWhichId< SwFormatMeta > RES_TXTATR_META(48)
#define CH_TXT_ATR_INPUTFIELDEND
Definition: hintids.hxx:179
constexpr TypedWhichId< SwTOXMark > RES_TXTATR_TOXMARK(47)
constexpr TypedWhichId< SwFormatRuby > RES_TXTATR_CJK_RUBY(53)
constexpr TypedWhichId< SwFormatField > RES_TXTATR_INPUTFIELD(55)
#define CH_TXT_ATR_FIELDEND
Definition: hintids.hxx:185
#define CH_TXT_ATR_FIELDSTART
Definition: hintids.hxx:183
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:174
sal_Int32 nIndex
#define FLYINCNT_MIN_WIDTH
Definition: itratr.cxx:1006
static bool lcl_MinMaxString(SwMinMaxArgs &rArg, SwFont *pFnt, const OUString &rText, sal_Int32 nIdx, sal_Int32 nEnd)
Definition: itratr.cxx:819
static void lcl_MinMaxNode(SwFrameFormat *pNd, SwMinMaxNodeArgs &rIn)
Definition: itratr.cxx:887
static void InsertCharAttrs(SfxPoolItem const **pAttrs, SfxItemSet const &rItems)
Definition: itratr.cxx:438
static sal_Int32 GetNextAttrImpl(SwTextNode const *pTextNode, size_t nStartIndex, size_t nEndIndex, sal_Int32 nPosition)
Definition: itratr.cxx:674
static bool CanSkipOverRedline(SwTextNode const &rStartNode, sal_Int32 const nStartRedline, SwRangeRedline const &rRedline, size_t &rStartIndex, size_t &rEndIndex, bool const isTheAnswerYes)
Definition: itratr.cxx:457
void * p
sal_uInt16 nPos
#define SAL_N_ELEMENTS(arr)
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
double getLength(const B2DPolygon &rCandidate)
int i
const T * HasItem(const ww8::PoolItems &rItems, sal_uInt16 eType)
TextFrameIndex MapModelToView(MergedPara const &, SwTextNode const *pNode, sal_Int32 nIndex)
Definition: txtfrm.cxx:1270
std::pair< SwTextNode *, sal_Int32 > MapViewToModel(MergedPara const &, TextFrameIndex nIndex)
Definition: txtfrm.cxx:1251
long Long
SwNodeOffset min(const SwNodeOffset &a, const SwNodeOffset &b)
Definition: nodeoffset.hxx:35
static SfxItemSet & rSet
sal_uIntPtr sal_uLong
Marks a position in the document model.
Definition: pam.hxx:38
SwNode & GetNode() const
Definition: pam.hxx:81
sal_Int32 GetContentIndex() const
Definition: pam.hxx:85
OUString mergedText
note: cannot be const currently to avoid UB because SwTextGuess::Guess const_casts it and modifies it...
Definition: txtfrm.hxx:996
SwTextNode *const pFirstNode
except break attributes, those are taken from the first node
Definition: txtfrm.hxx:1000
SwTextNode * pParaPropsNode
most paragraph properties are taken from the first non-empty node
Definition: txtfrm.hxx:998
SwTextNode const * pLastNode
mainly for sanity checks
Definition: txtfrm.hxx:1002
const sal_Unicode CH_TAB
Definition: swfont.hxx:44
const sal_Unicode CH_BREAK
Definition: swfont.hxx:43
const sal_Unicode CH_BLANK
Definition: swfont.hxx:42
#define CHAR_HARDBLANK
Definition: swtypes.hxx:173
tools::Long SwTwips
Definition: swtypes.hxx:51
#define CHAR_SOFTHYPHEN
Definition: swtypes.hxx:175
#define CHAR_HARDHYPHEN
Definition: swtypes.hxx:174
constexpr sal_Int32 COMPLETE_STRING
Definition: swtypes.hxx:57
sal_uInt16 sal_Unicode
Count
oslFileHandle & pOut
size_t pos