LibreOffice Module editeng (master) 1
editdoc.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 <editeng/tstpitem.hxx>
21#include <editeng/colritem.hxx>
22#include <editeng/fontitem.hxx>
24#include <editeng/fhgtitem.hxx>
25#include <editeng/flditem.hxx>
26#include <editeng/postitem.hxx>
27#include <editeng/kernitem.hxx>
28#include <editeng/wrlmitem.hxx>
29#include <editeng/wghtitem.hxx>
30#include <editeng/udlnitem.hxx>
31#include <editeng/cmapitem.hxx>
34#include <editeng/shdditem.hxx>
36#include <editeng/langitem.hxx>
40#include <editeng/editids.hrc>
41#include <editeng/editdata.hxx>
42#include <editeng/lrspitem.hxx>
43#include <editeng/ulspitem.hxx>
44#include <editeng/lspcitem.hxx>
45
46#include <editdoc.hxx>
47#include <editeng/eerdll.hxx>
48#include <eerdll2.hxx>
49#include "impedit.hxx"
50
51#include <rtl/ustrbuf.hxx>
52#include <sal/log.hxx>
53#include <o3tl/safeint.hxx>
54#include <osl/diagnose.h>
55
56#include <svl/grabbagitem.hxx>
57#include <tools/debug.hxx>
58#include <com/sun/star/i18n/ScriptType.hpp>
59#include <libxml/xmlwriter.h>
60
61#include <algorithm>
62#include <cassert>
63#include <cstddef>
64#include <limits>
65#include <memory>
66#include <set>
67#include <string_view>
68#include <utility>
69
70using namespace ::com::sun::star;
71
72
73sal_uInt16 GetScriptItemId( sal_uInt16 nItemId, SvtScriptType nScriptType )
74{
75 sal_uInt16 nId = nItemId;
76
77 if ( ( nScriptType == SvtScriptType::ASIAN ) ||
78 ( nScriptType == SvtScriptType::COMPLEX ) )
79 {
80 switch ( nItemId )
81 {
83 nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_LANGUAGE_CJK : EE_CHAR_LANGUAGE_CTL;
84 break;
86 nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_FONTINFO_CJK : EE_CHAR_FONTINFO_CTL;
87 break;
89 nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_FONTHEIGHT_CJK : EE_CHAR_FONTHEIGHT_CTL;
90 break;
91 case EE_CHAR_WEIGHT:
92 nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_WEIGHT_CJK : EE_CHAR_WEIGHT_CTL;
93 break;
94 case EE_CHAR_ITALIC:
95 nId = ( nScriptType == SvtScriptType::ASIAN ) ? EE_CHAR_ITALIC_CJK : EE_CHAR_ITALIC_CTL;
96 break;
97 }
98 }
99
100 return nId;
101}
102
103bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType )
104{
105 bool bValid = true;
106
107 switch ( nItemId )
108 {
109 case EE_CHAR_LANGUAGE:
110 bValid = nScriptType == i18n::ScriptType::LATIN;
111 break;
113 bValid = nScriptType == i18n::ScriptType::ASIAN;
114 break;
116 bValid = nScriptType == i18n::ScriptType::COMPLEX;
117 break;
118 case EE_CHAR_FONTINFO:
119 bValid = nScriptType == i18n::ScriptType::LATIN;
120 break;
122 bValid = nScriptType == i18n::ScriptType::ASIAN;
123 break;
125 bValid = nScriptType == i18n::ScriptType::COMPLEX;
126 break;
128 bValid = nScriptType == i18n::ScriptType::LATIN;
129 break;
131 bValid = nScriptType == i18n::ScriptType::ASIAN;
132 break;
134 bValid = nScriptType == i18n::ScriptType::COMPLEX;
135 break;
136 case EE_CHAR_WEIGHT:
137 bValid = nScriptType == i18n::ScriptType::LATIN;
138 break;
140 bValid = nScriptType == i18n::ScriptType::ASIAN;
141 break;
143 bValid = nScriptType == i18n::ScriptType::COMPLEX;
144 break;
145 case EE_CHAR_ITALIC:
146 bValid = nScriptType == i18n::ScriptType::LATIN;
147 break;
149 bValid = nScriptType == i18n::ScriptType::ASIAN;
150 break;
152 bValid = nScriptType == i18n::ScriptType::COMPLEX;
153 break;
154 }
155
156 return bValid;
157}
158
160 { SID_ATTR_FRAMEDIRECTION, true }, // EE_PARA_WRITINGDIR
161 { 0, true }, // EE_PARA_XMLATTRIBS
162 { SID_ATTR_PARA_HANGPUNCTUATION, true }, // EE_PARA_HANGINGPUNCTUATION
163 { SID_ATTR_PARA_FORBIDDEN_RULES, true }, // EE_PARA_FORBIDDENRULES
164 { SID_ATTR_PARA_SCRIPTSPACE, true }, // EE_PARA_ASIANCJKSPACING
165 { SID_ATTR_NUMBERING_RULE, true }, // EE_PARA_NUMBULL
166 { 0, true }, // EE_PARA_HYPHENATE
167 { 0, true }, // EE_PARA_HYPHENATE_NO_CAPS
168 { 0, true }, // EE_PARA_HYPHENATE_NO_LAST_WORD
169 { 0, true }, // EE_PARA_BULLETSTATE
170 { 0, true }, // EE_PARA_OUTLLRSPACE
171 { SID_ATTR_PARA_OUTLLEVEL, true }, // EE_PARA_OUTLLEVEL
172 { SID_ATTR_PARA_BULLET, true }, // EE_PARA_BULLET
173 { SID_ATTR_LRSPACE, true }, // EE_PARA_LRSPACE
174 { SID_ATTR_ULSPACE, true }, // EE_PARA_ULSPACE
175 { SID_ATTR_PARA_LINESPACE, true }, // EE_PARA_SBL
176 { SID_ATTR_PARA_ADJUST, true }, // EE_PARA_JUST
177 { SID_ATTR_TABSTOP, true }, // EE_PARA_TABS
178 { SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD, true }, // EE_PARA_JUST_METHOD
179 { SID_ATTR_ALIGN_VER_JUSTIFY, true }, // EE_PARA_VER_JUST
180 { SID_ATTR_CHAR_COLOR, true }, // EE_CHAR_COLOR
181 { SID_ATTR_CHAR_FONT, true }, // EE_CHAR_FONTINFO
182 { SID_ATTR_CHAR_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT
183 { SID_ATTR_CHAR_SCALEWIDTH, true }, // EE_CHAR_FONTWIDTH
184 { SID_ATTR_CHAR_WEIGHT, true }, // EE_CHAR_WEIGHT
185 { SID_ATTR_CHAR_UNDERLINE, true }, // EE_CHAR_UNDERLINE
186 { SID_ATTR_CHAR_STRIKEOUT, true }, // EE_CHAR_STRIKEOUT
187 { SID_ATTR_CHAR_POSTURE, true }, // EE_CHAR_ITALIC
188 { SID_ATTR_CHAR_CONTOUR, true }, // EE_CHAR_OUTLINE
189 { SID_ATTR_CHAR_SHADOWED, true }, // EE_CHAR_SHADOW
190 { SID_ATTR_CHAR_ESCAPEMENT, true }, // EE_CHAR_ESCAPEMENT
191 { SID_ATTR_CHAR_AUTOKERN, true }, // EE_CHAR_PAIRKERNING
192 { SID_ATTR_CHAR_KERNING, true }, // EE_CHAR_KERNING
193 { SID_ATTR_CHAR_WORDLINEMODE, true }, // EE_CHAR_WLM
194 { SID_ATTR_CHAR_LANGUAGE, true }, // EE_CHAR_LANGUAGE
195 { SID_ATTR_CHAR_CJK_LANGUAGE, true }, // EE_CHAR_LANGUAGE_CJK
196 { SID_ATTR_CHAR_CTL_LANGUAGE, true }, // EE_CHAR_LANGUAGE_CTL
197 { SID_ATTR_CHAR_CJK_FONT, true }, // EE_CHAR_FONTINFO_CJK
198 { SID_ATTR_CHAR_CTL_FONT, true }, // EE_CHAR_FONTINFO_CTL
199 { SID_ATTR_CHAR_CJK_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT_CJK
200 { SID_ATTR_CHAR_CTL_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT_CTL
201 { SID_ATTR_CHAR_CJK_WEIGHT, true }, // EE_CHAR_WEIGHT_CJK
202 { SID_ATTR_CHAR_CTL_WEIGHT, true }, // EE_CHAR_WEIGHT_CTL
203 { SID_ATTR_CHAR_CJK_POSTURE, true }, // EE_CHAR_ITALIC_CJK
204 { SID_ATTR_CHAR_CTL_POSTURE, true }, // EE_CHAR_ITALIC_CTL
205 { SID_ATTR_CHAR_EMPHASISMARK, true }, // EE_CHAR_EMPHASISMARK
206 { SID_ATTR_CHAR_RELIEF, true }, // EE_CHAR_RELIEF
207 { 0, true }, // EE_CHAR_RUBI_DUMMY
208 { 0, true }, // EE_CHAR_XMLATTRIBS
209 { SID_ATTR_CHAR_OVERLINE, true }, // EE_CHAR_OVERLINE
210 { SID_ATTR_CHAR_CASEMAP, true }, // EE_CHAR_CASEMAP
211 { SID_ATTR_CHAR_GRABBAG, true }, // EE_CHAR_GRABBAG
212 { SID_ATTR_CHAR_BACK_COLOR, true }, // EE_CHAR_BKGCOLOR
213 { 0, true }, // EE_FEATURE_TAB
214 { 0, true }, // EE_FEATURE_LINEBR
215 { SID_ATTR_CHAR_CHARSETCOLOR, true }, // EE_FEATURE_NOTCONV
216 { SID_FIELD, false }, // EE_FEATURE_FIELD
217};
218
219EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE )
220{
221 // Create a new attribute in the pool
222 const SfxPoolItem& rNew = rPool.Put( rAttr );
223
224 EditCharAttrib* pNew = nullptr;
225 switch( rNew.Which() )
226 {
227 case EE_CHAR_LANGUAGE:
230 {
231 pNew = new EditCharAttribLanguage( static_cast<const SvxLanguageItem&>(rNew), nS, nE );
232 }
233 break;
234 case EE_CHAR_COLOR:
235 {
236 pNew = new EditCharAttribColor( static_cast<const SvxColorItem&>(rNew), nS, nE );
237 }
238 break;
239 case EE_CHAR_FONTINFO:
242 {
243 pNew = new EditCharAttribFont( static_cast<const SvxFontItem&>(rNew), nS, nE );
244 }
245 break;
249 {
250 pNew = new EditCharAttribFontHeight( static_cast<const SvxFontHeightItem&>(rNew), nS, nE );
251 }
252 break;
254 {
255 pNew = new EditCharAttribFontWidth( static_cast<const SvxCharScaleWidthItem&>(rNew), nS, nE );
256 }
257 break;
258 case EE_CHAR_WEIGHT:
261 {
262 pNew = new EditCharAttribWeight( static_cast<const SvxWeightItem&>(rNew), nS, nE );
263 }
264 break;
266 {
267 pNew = new EditCharAttribUnderline( static_cast<const SvxUnderlineItem&>(rNew), nS, nE );
268 }
269 break;
270 case EE_CHAR_OVERLINE:
271 {
272 pNew = new EditCharAttribOverline( static_cast<const SvxOverlineItem&>(rNew), nS, nE );
273 }
274 break;
276 {
277 pNew = new EditCharAttribEmphasisMark( static_cast<const SvxEmphasisMarkItem&>(rNew), nS, nE );
278 }
279 break;
280 case EE_CHAR_RELIEF:
281 {
282 pNew = new EditCharAttribRelief( static_cast<const SvxCharReliefItem&>(rNew), nS, nE );
283 }
284 break;
286 {
287 pNew = new EditCharAttribStrikeout( static_cast<const SvxCrossedOutItem&>(rNew), nS, nE );
288 }
289 break;
290 case EE_CHAR_ITALIC:
293 {
294 pNew = new EditCharAttribItalic( static_cast<const SvxPostureItem&>(rNew), nS, nE );
295 }
296 break;
297 case EE_CHAR_OUTLINE:
298 {
299 pNew = new EditCharAttribOutline( static_cast<const SvxContourItem&>(rNew), nS, nE );
300 }
301 break;
302 case EE_CHAR_SHADOW:
303 {
304 pNew = new EditCharAttribShadow( static_cast<const SvxShadowedItem&>(rNew), nS, nE );
305 }
306 break;
308 {
309 pNew = new EditCharAttribEscapement( static_cast<const SvxEscapementItem&>(rNew), nS, nE );
310 }
311 break;
313 {
314 pNew = new EditCharAttribPairKerning( static_cast<const SvxAutoKernItem&>(rNew), nS, nE );
315 }
316 break;
317 case EE_CHAR_KERNING:
318 {
319 pNew = new EditCharAttribKerning( static_cast<const SvxKerningItem&>(rNew), nS, nE );
320 }
321 break;
322 case EE_CHAR_WLM:
323 {
324 pNew = new EditCharAttribWordLineMode( static_cast<const SvxWordLineModeItem&>(rNew), nS, nE );
325 }
326 break;
328 {
329 pNew = new EditCharAttrib( rNew, nS, nE ); // Attribute is only for holding XML information...
330 }
331 break;
332 case EE_CHAR_CASEMAP:
333 {
334 pNew = new EditCharAttribCaseMap( static_cast<const SvxCaseMapItem&>(rNew), nS, nE );
335 }
336 break;
337 case EE_CHAR_GRABBAG:
338 {
339 pNew = new EditCharAttribGrabBag( static_cast<const SfxGrabBagItem&>(rNew), nS, nE );
340 }
341 break;
342 case EE_FEATURE_TAB:
343 {
344 pNew = new EditCharAttribTab( static_cast<const SfxVoidItem&>(rNew), nS );
345 }
346 break;
348 {
349 pNew = new EditCharAttribLineBreak( static_cast<const SfxVoidItem&>(rNew), nS );
350 }
351 break;
352 case EE_FEATURE_FIELD:
353 {
354 pNew = new EditCharAttribField( static_cast<const SvxFieldItem&>(rNew), nS );
355 }
356 break;
357 case EE_CHAR_BKGCOLOR:
358 {
359 pNew = new EditCharAttribBackgroundColor( static_cast<const SvxColorItem&>(rNew), nS, nE );
360 }
361 break;
362 default:
363 {
364 OSL_FAIL( "Invalid Attribute!" );
365 }
366 }
367 return pNew;
368}
369
371{
372}
373
375{
376 Reset();
377}
378
380{
381 maPortions.clear();
382}
383
385{
386 assert((nDelFrom < static_cast<sal_Int32>(maPortions.size())) || ((nDelFrom == 0) && maPortions.empty()));
387 PortionsType::iterator it = maPortions.begin();
388 std::advance(it, nDelFrom);
389 maPortions.erase(it, maPortions.end());
390}
391
392sal_Int32 TextPortionList::Count() const
393{
394 return static_cast<sal_Int32>(maPortions.size());
395}
396
397const TextPortion& TextPortionList::operator[](sal_Int32 nPos) const
398{
399 return *maPortions[nPos];
400}
401
403{
404 return *maPortions[nPos];
405}
406
408{
409 maPortions.push_back(std::unique_ptr<TextPortion>(p));
410}
411
412void TextPortionList::Insert(sal_Int32 nPos, TextPortion* p)
413{
414 maPortions.insert(maPortions.begin()+nPos, std::unique_ptr<TextPortion>(p));
415}
416
417void TextPortionList::Remove(sal_Int32 nPos)
418{
419 maPortions.erase(maPortions.begin()+nPos);
420}
421
422namespace {
423
424class FindTextPortionByAddress
425{
426 const TextPortion* mp;
427public:
428 explicit FindTextPortionByAddress(const TextPortion* p) : mp(p) {}
429 bool operator() (const std::unique_ptr<TextPortion>& v) const
430 {
431 return v.get() == mp;
432 }
433};
434
435}
436
437sal_Int32 TextPortionList::GetPos(const TextPortion* p) const
438{
439 PortionsType::const_iterator it =
440 std::find_if(maPortions.begin(), maPortions.end(), FindTextPortionByAddress(p));
441
442 if (it == maPortions.end())
443 return std::numeric_limits<sal_Int32>::max(); // not found.
444
445 return std::distance(maPortions.begin(), it);
446}
447
449 sal_Int32 nCharPos, sal_Int32& nPortionStart, bool bPreferStartingPortion) const
450{
451 // When nCharPos at portion limit, the left portion is found
452 sal_Int32 nTmpPos = 0;
453 sal_Int32 n = maPortions.size();
454 for (sal_Int32 i = 0; i < n; ++i)
455 {
456 const TextPortion& rPortion = *maPortions[i];
457 nTmpPos = nTmpPos + rPortion.GetLen();
458 if ( nTmpPos >= nCharPos )
459 {
460 // take this one if we don't prefer the starting portion, or if it's the last one
461 if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( i == n-1 ) )
462 {
463 nPortionStart = nTmpPos - rPortion.GetLen();
464 return i;
465 }
466 }
467 }
468 OSL_FAIL( "FindPortion: Not found!" );
469 return n - 1;
470}
471
472sal_Int32 TextPortionList::GetStartPos(sal_Int32 nPortion)
473{
474 sal_Int32 nPos = 0;
475 for (sal_Int32 i = 0; i < nPortion; ++i)
476 {
477 const TextPortion& rPortion = *maPortions[i];
478 nPos = nPos + rPortion.GetLen();
479 }
480 return nPos;
481}
482
484: nOrgWidth(0)
485, nWidthFullCompression(0)
486, nPortionOffsetX(0)
487, nMaxCompression100thPercent(0)
488, nAsianCompressionTypes(AsianCompressionFlags::Normal)
489, bFirstCharIsRightPunktuation(false)
490, bCompressed(false)
491{
492}
493
495{
496}
497
498void ExtraPortionInfo::SaveOrgDXArray( const sal_Int32* pDXArray, sal_Int32 nLen )
499{
500 if (pDXArray)
501 {
502 pOrgDXArray.reset(new sal_Int32[nLen]);
503 memcpy( pOrgDXArray.get(), pDXArray, nLen * sizeof(sal_Int32) );
504 }
505 else
506 pOrgDXArray.reset();
507}
508
510 pNode(pN),
511 nHeight(0),
512 nInvalidPosStart(0),
514 nBulletX(0),
515 nInvalidDiff(0),
516 bInvalid(true),
517 bSimple(false),
518 bVisible(true),
519 bForceRepaint(false)
520{
521}
522
524{
525}
526
527void ParaPortion::MarkInvalid( sal_Int32 nStart, sal_Int32 nDiff )
528{
529 if ( !bInvalid )
530 {
531// nInvalidPosEnd = nStart; // ??? => CreateLines
532 nInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff );
533 nInvalidDiff = nDiff;
534 }
535 else
536 {
537 // Simple tap in succession
538 if ( ( nDiff > 0 ) && ( nInvalidDiff > 0 ) &&
539 ( ( nInvalidPosStart+nInvalidDiff ) == nStart ) )
540 {
541 nInvalidDiff = nInvalidDiff + nDiff;
542 }
543 // Simple delete in succession
544 else if ( ( nDiff < 0 ) && ( nInvalidDiff < 0 ) && ( nInvalidPosStart == nStart ) )
545 {
547 nInvalidDiff = nInvalidDiff + nDiff;
548 }
549 else
550 {
551// nInvalidPosEnd = pNode->Len();
552 DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" );
553 nInvalidPosStart = std::min( nInvalidPosStart, ( nDiff < 0 ? nStart+nDiff : nDiff ) );
554 nInvalidDiff = 0;
555 bSimple = false;
556 }
557 }
558 bInvalid = true;
559 aScriptInfos.clear();
561}
562
563void ParaPortion::MarkSelectionInvalid( sal_Int32 nStart )
564{
565 if ( !bInvalid )
566 {
567 nInvalidPosStart = nStart;
568 }
569 else
570 {
571 nInvalidPosStart = std::min( nInvalidPosStart, nStart );
572 }
573 nInvalidDiff = 0;
574 bInvalid = true;
575 bSimple = false;
576 aScriptInfos.clear();
578}
579
580sal_Int32 ParaPortion::GetLineNumber( sal_Int32 nIndex ) const
581{
582 SAL_WARN_IF( !aLineList.Count(), "editeng", "Empty ParaPortion in GetLine!" );
583 DBG_ASSERT( bVisible, "Why GetLine() on an invisible paragraph?" );
584
585 for ( sal_Int32 nLine = 0; nLine < aLineList.Count(); nLine++ )
586 {
587 if ( aLineList[nLine].IsIn( nIndex ) )
588 return nLine;
589 }
590
591 // Then it should be at the end of the last line!
592 DBG_ASSERT( nIndex == aLineList[ aLineList.Count() - 1 ].GetEnd(), "Index dead wrong!" );
593 return (aLineList.Count()-1);
594}
595
596void ParaPortion::SetVisible( bool bMakeVisible )
597{
598 bVisible = bMakeVisible;
599}
600
601void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormattedLine )
602{
603 sal_Int32 nLines = aLineList.Count();
604 DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Empty Portion?" );
605 if ( nLastFormattedLine < ( nLines - 1 ) )
606 {
607 const EditLine& rLastFormatted = aLineList[ nLastFormattedLine ];
608 const EditLine& rUnformatted = aLineList[ nLastFormattedLine+1 ];
609 sal_Int32 nPortionDiff = rUnformatted.GetStartPortion() - rLastFormatted.GetEndPortion();
610 sal_Int32 nTextDiff = rUnformatted.GetStart() - rLastFormatted.GetEnd();
611 nTextDiff++; // LastFormatted->GetEnd() was included => 1 deducted too much!
612
613 // The first unformatted must begin exactly one Portion behind the last
614 // of the formatted:
615 // If the modified line was split into one portion, can
616 // nLastEnd > nNextStart!
617 int nPDiff = -( nPortionDiff-1 );
618 int nTDiff = -( nTextDiff-1 );
619 if ( nPDiff || nTDiff )
620 {
621 for ( sal_Int32 nL = nLastFormattedLine+1; nL < nLines; nL++ )
622 {
623 EditLine& rLine = aLineList[ nL ];
624
625 rLine.GetStartPortion() = rLine.GetStartPortion() + nPDiff;
626 rLine.GetEndPortion() = rLine.GetEndPortion() + nPDiff;
627
628 rLine.GetStart() = rLine.GetStart() + nTDiff;
629 rLine.GetEnd() = rLine.GetEnd() + nTDiff;
630
631 rLine.SetValid();
632 }
633 }
634 }
635 DBG_ASSERT( aLineList[ aLineList.Count()-1 ].GetEnd() == pNode->Len(), "CorrectLines: The end is not right!" );
636}
637
638// Shared reverse lookup acceleration pieces ...
639
640namespace {
641
642template<typename Array, typename Val>
643sal_Int32 FastGetPos(const Array& rArray, const Val* p, sal_Int32& rLastPos)
644{
645 sal_Int32 nArrayLen = rArray.size();
646
647 // Through certain filter code-paths we do a lot of appends, which in
648 // turn call GetPos - creating some N^2 nightmares. If we have a
649 // non-trivially large list, do a few checks from the end first.
650 if (rLastPos > 16 && nArrayLen > 16)
651 {
652 sal_Int32 nEnd;
653 if (rLastPos > nArrayLen - 2)
654 nEnd = nArrayLen;
655 else
656 nEnd = rLastPos + 2;
657
658 for (sal_Int32 nIdx = rLastPos - 2; nIdx < nEnd; ++nIdx)
659 {
660 if (rArray.at(nIdx).get() == p)
661 {
662 rLastPos = nIdx;
663 return nIdx;
664 }
665 }
666 }
667 // The world's lamest linear search from svarray...
668 for (sal_Int32 nIdx = 0; nIdx < nArrayLen; ++nIdx)
669 if (rArray.at(nIdx).get() == p)
670 {
671 rLastPos = nIdx;
672 return rLastPos;
673 }
674
675 // XXX "not found" condition for sal_Int32 indexes
676 return EE_PARA_NOT_FOUND;
677}
678
679}
680
682{
683}
684
686{
687}
688
689sal_Int32 ParaPortionList::GetPos(const ParaPortion* p) const
690{
691 return FastGetPos(maPortions, p, nLastCache);
692}
693
695{
696 return 0 <= nPos && o3tl::make_unsigned(nPos) < maPortions.size() ? maPortions[nPos].get() : nullptr;
697}
698
699const ParaPortion* ParaPortionList::operator [](sal_Int32 nPos) const
700{
701 return 0 <= nPos && o3tl::make_unsigned(nPos) < maPortions.size() ? maPortions[nPos].get() : nullptr;
702}
703
704std::unique_ptr<ParaPortion> ParaPortionList::Release(sal_Int32 nPos)
705{
706 if (nPos < 0 || maPortions.size() <= o3tl::make_unsigned(nPos))
707 {
708 SAL_WARN( "editeng", "ParaPortionList::Release - out of bounds pos " << nPos);
709 return nullptr;
710 }
711 std::unique_ptr<ParaPortion> p = std::move(maPortions[nPos]);
712 maPortions.erase(maPortions.begin()+nPos);
713 return p;
714}
715
716void ParaPortionList::Remove(sal_Int32 nPos)
717{
718 if (nPos < 0 || maPortions.size() <= o3tl::make_unsigned(nPos))
719 {
720 SAL_WARN( "editeng", "ParaPortionList::Remove - out of bounds pos " << nPos);
721 return;
722 }
723 maPortions.erase(maPortions.begin()+nPos);
724}
725
726void ParaPortionList::Insert(sal_Int32 nPos, std::unique_ptr<ParaPortion> p)
727{
728 if (nPos < 0 || maPortions.size() < o3tl::make_unsigned(nPos))
729 {
730 SAL_WARN( "editeng", "ParaPortionList::Insert - out of bounds pos " << nPos);
731 return;
732 }
733 maPortions.insert(maPortions.begin()+nPos, std::move(p));
734}
735
736void ParaPortionList::Append(std::unique_ptr<ParaPortion> p)
737{
738 maPortions.push_back(std::move(p));
739}
740
741sal_Int32 ParaPortionList::Count() const
742{
743 size_t nSize = maPortions.size();
744 if (nSize > SAL_MAX_INT32)
745 {
746 SAL_WARN( "editeng", "ParaPortionList::Count - overflow " << nSize);
747 return SAL_MAX_INT32;
748 }
749 return nSize;
750}
751
753{
754 maPortions.clear();
755}
756
758{
759 tools::Long nHeight = 0;
760 for (const auto & rPortion : maPortions)
761 {
762 const ParaPortion* pTmpPortion = rPortion.get();
763 if ( pTmpPortion == pPPortion )
764 return nHeight;
765 nHeight += pTmpPortion->GetHeight();
766 }
767 OSL_FAIL( "GetYOffset: Portion not found" );
768 return nHeight;
769}
770
772{
773 tools::Long nY = 0;
774 for (size_t i = 0, n = maPortions.size(); i < n; ++i)
775 {
776 nY += maPortions[i]->GetHeight(); // should also be correct even in bVisible!
777 if ( nY > nYOffset )
778 return i <= SAL_MAX_INT32 ? static_cast<sal_Int32>(i) : SAL_MAX_INT32;
779 }
780 return EE_PARA_NOT_FOUND;
781}
782
783const ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos) const
784{
785 return 0 <= nPos && o3tl::make_unsigned(nPos) < maPortions.size() ? maPortions[nPos].get() : nullptr;
786}
787
789{
790 return 0 <= nPos && o3tl::make_unsigned(nPos) < maPortions.size() ? maPortions[nPos].get() : nullptr;
791}
792
793#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
794void
796{
797 assert(rParas.Count() == rDoc.Count());
798 for (sal_Int32 i = 0; i < rParas.Count(); ++i)
799 {
800 assert(rParas.SafeGetObject(i) != nullptr);
801 assert(rParas.SafeGetObject(i)->GetNode() != nullptr);
802 assert(rParas.SafeGetObject(i)->GetNode() == rDoc.GetObject(i));
803 }
804}
805#endif
806
808 aPrevParaAttribs(std::move( aParaAttribs))
809{
810}
811
813{
814 for (const std::unique_ptr<EditCharAttrib>& rAttrib : aPrevCharAttribs)
815 rPool.Remove(*rAttrib->GetItem());
816}
817
819{
820 aPrevCharAttribs.push_back(std::unique_ptr<EditCharAttrib>(pNew));
821}
822
823void ConvertItem( std::unique_ptr<SfxPoolItem>& rPoolItem, MapUnit eSourceUnit, MapUnit eDestUnit )
824{
825 DBG_ASSERT( eSourceUnit != eDestUnit, "ConvertItem - Why?!" );
826
827 switch ( rPoolItem->Which() )
828 {
829 case EE_PARA_LRSPACE:
830 {
831 assert(dynamic_cast<const SvxLRSpaceItem *>(rPoolItem.get()) != nullptr);
832 SvxLRSpaceItem& rItem = static_cast<SvxLRSpaceItem&>(*rPoolItem);
833 rItem.SetTextFirstLineOffset( sal::static_int_cast< short >( OutputDevice::LogicToLogic( rItem.GetTextFirstLineOffset(), eSourceUnit, eDestUnit ) ) );
834 rItem.SetTextLeft( OutputDevice::LogicToLogic( rItem.GetTextLeft(), eSourceUnit, eDestUnit ) );
835 rItem.SetRight( OutputDevice::LogicToLogic( rItem.GetRight(), eSourceUnit, eDestUnit ) );
836 }
837 break;
838 case EE_PARA_ULSPACE:
839 {
840 assert(dynamic_cast<const SvxULSpaceItem *>(rPoolItem.get()) != nullptr);
841 SvxULSpaceItem& rItem = static_cast<SvxULSpaceItem&>(*rPoolItem);
842 rItem.SetUpper( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetUpper(), eSourceUnit, eDestUnit ) ) );
843 rItem.SetLower( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetLower(), eSourceUnit, eDestUnit ) ) );
844 }
845 break;
846 case EE_PARA_SBL:
847 {
848 assert(dynamic_cast<const SvxLineSpacingItem *>(rPoolItem.get()) != nullptr);
849 SvxLineSpacingItem& rItem = static_cast<SvxLineSpacingItem&>(*rPoolItem);
850 // SetLineHeight changes also eLineSpace!
852 rItem.SetLineHeight( sal::static_int_cast< sal_uInt16 >( OutputDevice::LogicToLogic( rItem.GetLineHeight(), eSourceUnit, eDestUnit ) ) );
853 }
854 break;
855 case EE_PARA_TABS:
856 {
857 assert(dynamic_cast<const SvxTabStopItem *>(rPoolItem.get()) != nullptr);
858 SvxTabStopItem& rItem = static_cast<SvxTabStopItem&>(*rPoolItem);
860
861 if (sal_Int32 nDefTabDistance = rItem.GetDefaultDistance())
862 {
863 pNewItem->SetDefaultDistance(
864 OutputDevice::LogicToLogic(nDefTabDistance, eSourceUnit, eDestUnit));
865 }
866
867 for ( sal_uInt16 i = 0; i < rItem.Count(); i++ )
868 {
869 const SvxTabStop& rTab = rItem[i];
870 SvxTabStop aNewStop( OutputDevice::LogicToLogic( rTab.GetTabPos(), eSourceUnit, eDestUnit ), rTab.GetAdjustment(), rTab.GetDecimal(), rTab.GetFill() );
871 pNewItem->Insert( aNewStop );
872 }
873 rPoolItem.reset(pNewItem);
874 }
875 break;
879 {
880 assert(dynamic_cast<const SvxFontHeightItem *>(rPoolItem.get()) != nullptr);
881 SvxFontHeightItem& rItem = static_cast<SvxFontHeightItem&>(*rPoolItem);
882 rItem.SetHeight( OutputDevice::LogicToLogic( rItem.GetHeight(), eSourceUnit, eDestUnit ) );
883 }
884 break;
885 }
886}
887
888void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const MapUnit* pSourceUnit, const MapUnit* pDestUnit )
889{
890 const SfxItemPool* pSourcePool = rSource.GetPool();
891 const SfxItemPool* pDestPool = rDest.GetPool();
892
893 for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
894 {
895 // If possible go through SlotID ...
896
897 sal_uInt16 nSourceWhich = nWhich;
898 sal_uInt16 nSlot = pDestPool->GetTrueSlotId( nWhich );
899 if ( nSlot )
900 {
901 sal_uInt16 nW = pSourcePool->GetTrueWhich( nSlot );
902 if ( nW )
903 nSourceWhich = nW;
904 }
905
906 if ( rSource.GetItemState( nSourceWhich, false ) == SfxItemState::SET )
907 {
908 MapUnit eSourceUnit = pSourceUnit ? *pSourceUnit : pSourcePool->GetMetric( nSourceWhich );
909 MapUnit eDestUnit = pDestUnit ? *pDestUnit : pDestPool->GetMetric( nWhich );
910 if ( eSourceUnit != eDestUnit )
911 {
912 std::unique_ptr<SfxPoolItem> pItem(rSource.Get( nSourceWhich ).Clone());
913 ConvertItem( pItem, eSourceUnit, eDestUnit );
914 pItem->SetWhich(nWhich);
915 rDest.Put( std::move(pItem) );
916 }
917 else
918 {
919 rDest.Put( rSource.Get( nSourceWhich ).CloneSetWhich(nWhich) );
920 }
921 }
922 }
923}
924
926 nTxtWidth(0),
927 nStartPosX(0),
928 nStart(0),
929 nEnd(0),
930 nStartPortion(0), // to be able to tell the difference between a line
931 // without Portions from one with the Portion number 0
932 nEndPortion(0),
933 nHeight(0),
934 nTxtHeight(0),
935 nMaxAscent(0),
936 bHangingPunctuation(false),
937 bInvalid(true)
938{
939}
940
942 nTxtWidth(0),
943 nStartPosX(0),
944 nStart(r.nStart),
945 nEnd(r.nEnd),
946 nStartPortion(r.nStartPortion),
947 nEndPortion(r.nEndPortion),
948 nHeight(0),
949 nTxtHeight(0),
950 nMaxAscent(0),
951 bHangingPunctuation(r.bHangingPunctuation),
952 bInvalid(true)
953{
954}
955
957{
958}
959
960
962{
963 EditLine* pL = new EditLine;
966 pL->nStart = nStart;
967 pL->nEnd = nEnd;
970 pL->nHeight = nHeight;
971 pL->nTxtWidth = nTxtWidth;
974
975 return pL;
976}
977
978bool operator == ( const EditLine& r1, const EditLine& r2 )
979{
980 if ( r1.nStart != r2.nStart )
981 return false;
982
983 if ( r1.nEnd != r2.nEnd )
984 return false;
985
986 if ( r1.nStartPortion != r2.nStartPortion )
987 return false;
988
989 if ( r1.nEndPortion != r2.nEndPortion )
990 return false;
991
992 return true;
993}
994
996{
997 nEnd = r.nEnd;
998 nStart = r.nStart;
1001 return *this;
1002}
1003
1004
1005void EditLine::SetHeight( sal_uInt16 nH, sal_uInt16 nTxtH )
1006{
1007 nHeight = nH;
1008 nTxtHeight = ( nTxtH ? nTxtH : nH );
1009}
1010
1011void EditLine::SetStartPosX( sal_Int32 start )
1012{
1013 if (start > 0)
1014 nStartPosX = start;
1015 else
1016 nStartPosX = 0;
1017}
1018
1020{
1021 Size aSz;
1022 Size aTmpSz;
1023
1024 DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize before CreatePortions !" );
1025
1026 for ( sal_Int32 n = nStartPortion; n <= nEndPortion; n++ )
1027 {
1028 TextPortion& rPortion = rParaPortion.GetTextPortions()[n];
1029 switch ( rPortion.GetKind() )
1030 {
1031 case PortionKind::TEXT:
1032 case PortionKind::FIELD:
1034 {
1035 aTmpSz = rPortion.GetSize();
1036 aSz.AdjustWidth(aTmpSz.Width() );
1037 if ( aSz.Height() < aTmpSz.Height() )
1038 aSz.setHeight( aTmpSz.Height() );
1039 }
1040 break;
1041 case PortionKind::TAB:
1042 {
1043 aSz.AdjustWidth(rPortion.GetSize().Width() );
1044 }
1045 break;
1046 case PortionKind::LINEBREAK: break;
1047 }
1048 }
1049
1050 SetHeight( static_cast<sal_uInt16>(aSz.Height()) );
1051 return aSz;
1052}
1053
1055{
1056}
1057
1059{
1060 Reset();
1061}
1062
1064{
1065 maLines.clear();
1066}
1067
1068void EditLineList::DeleteFromLine(sal_Int32 nDelFrom)
1069{
1070 assert(nDelFrom <= (static_cast<sal_Int32>(maLines.size()) - 1));
1071 LinesType::iterator it = maLines.begin();
1072 std::advance(it, nDelFrom);
1073 maLines.erase(it, maLines.end());
1074}
1075
1076sal_Int32 EditLineList::FindLine(sal_Int32 nChar, bool bInclEnd)
1077{
1078 sal_Int32 n = maLines.size();
1079 for (sal_Int32 i = 0; i < n; ++i)
1080 {
1081 const EditLine& rLine = *maLines[i];
1082 if ( (bInclEnd && (rLine.GetEnd() >= nChar)) ||
1083 (rLine.GetEnd() > nChar) )
1084 {
1085 return i;
1086 }
1087 }
1088
1089 DBG_ASSERT( !bInclEnd, "Line not found: FindLine" );
1090 return n - 1;
1091}
1092
1093sal_Int32 EditLineList::Count() const
1094{
1095 return maLines.size();
1096}
1097
1098const EditLine& EditLineList::operator[](sal_Int32 nPos) const
1099{
1100 return *maLines[nPos];
1101}
1102
1104{
1105 return *maLines[nPos];
1106}
1107
1109{
1110 maLines.push_back(std::unique_ptr<EditLine>(p));
1111}
1112
1113void EditLineList::Insert(sal_Int32 nPos, EditLine* p)
1114{
1115 maLines.insert(maLines.begin()+nPos, std::unique_ptr<EditLine>(p));
1116}
1117
1118EditPaM::EditPaM() : pNode(nullptr), nIndex(0) {}
1119EditPaM::EditPaM(ContentNode* p, sal_Int32 n) : pNode(p), nIndex(n) {}
1120
1121
1123{
1124 pNode = p;
1125}
1126
1127bool EditPaM::DbgIsBuggy( EditDoc const & rDoc ) const
1128{
1129 return !pNode ||
1130 rDoc.GetPos( pNode ) >= rDoc.Count() ||
1131 nIndex > pNode->Len();
1132}
1133
1134bool EditSelection::DbgIsBuggy( EditDoc const & rDoc ) const
1135{
1136 return aStartPaM.DbgIsBuggy( rDoc ) || aEndPaM.DbgIsBuggy( rDoc );
1137}
1138
1140{
1141}
1142
1144 aStartPaM(rStartAndAnd),
1145 aEndPaM(rStartAndAnd)
1146{
1147}
1148
1149EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd ) :
1150 aStartPaM(rStart),
1151 aEndPaM(rEnd)
1152{
1153}
1154
1156{
1157 aStartPaM = rPaM;
1158 aEndPaM = rPaM;
1159 return *this;
1160}
1161
1162void EditSelection::Adjust( const EditDoc& rNodes )
1163{
1164 DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in Adjust(1)" );
1165 DBG_ASSERT( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index out of range in Adjust(2)" );
1166
1167 const ContentNode* pStartNode = aStartPaM.GetNode();
1168 const ContentNode* pEndNode = aEndPaM.GetNode();
1169
1170 sal_Int32 nStartNode = rNodes.GetPos( pStartNode );
1171 sal_Int32 nEndNode = rNodes.GetPos( pEndNode );
1172
1173 DBG_ASSERT( nStartNode != SAL_MAX_INT32, "Node out of range in Adjust(1)" );
1174 DBG_ASSERT( nEndNode != SAL_MAX_INT32, "Node out of range in Adjust(2)" );
1175
1176 const bool bSwap = ( nStartNode > nEndNode ) ||
1177 ( ( nStartNode == nEndNode ) &&
1178 ( aStartPaM.GetIndex() > aEndPaM.GetIndex() ) );
1179
1180 if ( bSwap )
1181 {
1182 EditPaM aTmpPaM( aStartPaM );
1184 aEndPaM = aTmpPaM;
1185 }
1186}
1187
1188bool operator == ( const EditPaM& r1, const EditPaM& r2 )
1189{
1190 return ( r1.GetNode() == r2.GetNode() ) &&
1191 ( r1.GetIndex() == r2.GetIndex() );
1192}
1193
1194bool operator != ( const EditPaM& r1, const EditPaM& r2 )
1195{
1196 return !( r1 == r2 );
1197}
1198
1199ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool )
1200{
1201}
1202
1203ContentNode::ContentNode( const OUString& rStr, const ContentAttribs& rContentAttribs ) :
1204 maString(rStr), aContentAttribs(rContentAttribs)
1205{
1206}
1207
1209{
1210}
1211
1212void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew, SfxItemPool& rItemPool )
1213{
1214 if ( !nNew )
1215 return;
1216
1217#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
1219#endif
1220
1221 // Since features are treated differently than normal character attributes,
1222 // but can also affect the order of the start list. // In every if ..., in the next (n) opportunities due to bFeature or
1223 // an existing special case, must (n-1) opportunities be provided with
1224 // bResort. The most likely possibility receives no bResort, so that is
1225 // not sorted anew when all attributes are the same.
1226 bool bResort = false;
1227 bool bExpandedEmptyAtIndexNull = false;
1228
1229 std::size_t nAttr = 0;
1231 EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr);
1232 while ( pAttrib )
1233 {
1234 if ( pAttrib->GetEnd() >= nIndex )
1235 {
1236 // Move all attributes behind the insertion point...
1237 if ( pAttrib->GetStart() > nIndex )
1238 {
1239 pAttrib->MoveForward( nNew );
1240 }
1241 // 0: Expand empty attribute, if at insertion point
1242 else if ( pAttrib->IsEmpty() )
1243 {
1244 // Do not check Index, an empty one could only be there
1245 // When later checking it anyhow:
1246 // Special case: Start == 0; AbsLen == 1, nNew = 1
1247 // => Expand, because of paragraph break!
1248 // Start <= nIndex, End >= nIndex => Start=End=nIndex!
1249// if ( pAttrib->GetStart() == nIndex )
1250 pAttrib->Expand( nNew );
1251 bResort = true;
1252 if ( pAttrib->GetStart() == 0 )
1253 bExpandedEmptyAtIndexNull = true;
1254 }
1255 // 1: Attribute starts before, goes to index ...
1256 else if ( pAttrib->GetEnd() == nIndex ) // Start must be before
1257 {
1258 // Only expand when there is no feature
1259 // and if not in exclude list!
1260 // Otherwise, a UL will go on until a new ULDB, expanding both
1261// if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) )
1262 if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) )
1263 {
1264 if ( !pAttrib->IsEdge() )
1265 pAttrib->Expand( nNew );
1266 }
1267 else
1268 bResort = true;
1269 }
1270 // 2: Attribute starts before, goes past the Index...
1271 else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
1272 {
1273 DBG_ASSERT( !pAttrib->IsFeature(), "Large Feature?!" );
1274 pAttrib->Expand( nNew );
1275 }
1276 // 3: Attribute starts on index...
1277 else if ( pAttrib->GetStart() == nIndex )
1278 {
1279 if ( pAttrib->IsFeature() )
1280 {
1281 pAttrib->MoveForward( nNew );
1282 bResort = true;
1283 }
1284 else
1285 {
1286 bool bExpand = false;
1287 if ( nIndex == 0 )
1288 {
1289 bExpand = true;
1290 if( bExpandedEmptyAtIndexNull )
1291 {
1292 // Check if this kind of attribute was empty and expanded here...
1293 sal_uInt16 nW = pAttrib->GetItem()->Which();
1294 for ( std::size_t nA = 0; nA < nAttr; nA++ )
1295 {
1296 const EditCharAttrib& r = *aCharAttribList.GetAttribs()[nA];
1297 if ( ( r.GetStart() == 0 ) && ( r.GetItem()->Which() == nW ) )
1298 {
1299 bExpand = false;
1300 break;
1301 }
1302 }
1303
1304 }
1305 }
1306 if ( bExpand )
1307 {
1308 pAttrib->Expand( nNew );
1309 bResort = true;
1310 }
1311 else
1312 {
1313 pAttrib->MoveForward( nNew );
1314 }
1315 }
1316 }
1317 }
1318
1319 if ( pAttrib->IsEdge() )
1320 pAttrib->SetEdge(false);
1321
1322 DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
1323
1324 DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribute distorted!" );
1325 DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attribute larger than paragraph!" );
1326 if ( pAttrib->IsEmpty() )
1327 {
1328 OSL_FAIL( "Empty Attribute after ExpandAttribs?" );
1329 bResort = true;
1330 rItemPool.Remove( *pAttrib->GetItem() );
1331 rAttribs.erase(rAttribs.begin()+nAttr);
1332 }
1333 else
1334 {
1335 ++nAttr;
1336 }
1337 pAttrib = GetAttrib(rAttribs, nAttr);
1338 }
1339
1340 if ( bResort )
1342
1343 if (mpWrongList)
1344 {
1345 bool bSep = ( maString[ nIndex ] == ' ' ) || IsFeature( nIndex );
1346 mpWrongList->TextInserted( nIndex, nNew, bSep );
1347 }
1348
1349#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
1351#endif
1352}
1353
1354void ContentNode::CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDeleted, SfxItemPool& rItemPool )
1355{
1356 if ( !nDeleted )
1357 return;
1358
1359#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
1361#endif
1362
1363 // Since features are treated differently than normal character attributes,
1364 // but can also affect the order of the start list
1365 bool bResort = false;
1366 sal_Int32 nEndChanges = nIndex+nDeleted;
1367
1368 std::size_t nAttr = 0;
1370 EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr);
1371 while ( pAttrib )
1372 {
1373 bool bDelAttr = false;
1374 if ( pAttrib->GetEnd() >= nIndex )
1375 {
1376 // Move all Attribute behind the insert point...
1377 if ( pAttrib->GetStart() >= nEndChanges )
1378 {
1379 pAttrib->MoveBackward( nDeleted );
1380 }
1381 // 1. Delete Internal attributes...
1382 else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) )
1383 {
1384 // Special case: Attribute covers the area exactly
1385 // => keep as empty Attribute.
1386 if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) )
1387 {
1388 pAttrib->GetEnd() = nIndex; // empty
1389 bResort = true;
1390 }
1391 else
1392 bDelAttr = true;
1393 }
1394 // 2. Attribute starts earlier, ends inside or behind it ...
1395 else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) )
1396 {
1397 DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" );
1398 if ( pAttrib->GetEnd() <= nEndChanges ) // ends inside
1399 pAttrib->GetEnd() = nIndex;
1400 else
1401 pAttrib->Collaps( nDeleted ); // ends behind
1402 }
1403 // 3. Attribute starts inside, ending behind ...
1404 else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) )
1405 {
1406 // Features not allowed to expand!
1407 if ( pAttrib->IsFeature() )
1408 {
1409 pAttrib->MoveBackward( nDeleted );
1410 bResort = true;
1411 }
1412 else
1413 {
1414 pAttrib->GetStart() = nEndChanges;
1415 pAttrib->MoveBackward( nDeleted );
1416 }
1417 }
1418 }
1419 DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" );
1420
1421 DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collapse: Attribute distorted!" );
1422 DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collapse: Attribute larger than paragraph!" );
1423 if ( bDelAttr )
1424 {
1425 bResort = true;
1426 rItemPool.Remove( *pAttrib->GetItem() );
1427 rAttribs.erase(rAttribs.begin()+nAttr);
1428 }
1429 else
1430 {
1431 if ( pAttrib->IsEmpty() )
1433 nAttr++;
1434 }
1435
1436 pAttrib = GetAttrib(rAttribs, nAttr);
1437 }
1438
1439 if ( bResort )
1441
1442 if (mpWrongList)
1443 mpWrongList->TextDeleted(nIndex, nDeleted);
1444
1445#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
1447#endif
1448}
1449
1450void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, bool bKeepEndingAttribs )
1451{
1452 assert(pPrevNode);
1453
1454#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
1457#endif
1458
1459 sal_Int32 nCut = pPrevNode->Len();
1460
1461 std::size_t nAttr = 0;
1462 CharAttribList::AttribsType& rPrevAttribs = pPrevNode->GetCharAttribs().GetAttribs();
1463 EditCharAttrib* pAttrib = GetAttrib(rPrevAttribs, nAttr);
1464 while ( pAttrib )
1465 {
1466 if ( pAttrib->GetEnd() < nCut )
1467 {
1468 // remain unchanged...
1469 nAttr++;
1470 }
1471 else if ( pAttrib->GetEnd() == nCut )
1472 {
1473 // must be copied as an empty attributes.
1474 if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) )
1475 {
1476 EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 );
1477 assert(pNewAttrib);
1478 aCharAttribList.InsertAttrib( pNewAttrib );
1479 }
1480 nAttr++;
1481 }
1482 else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) )
1483 {
1484 // If cut is done right at the front then the attribute must be
1485 // kept! Has to be copied and changed.
1486 EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut );
1487 assert(pNewAttrib);
1488 aCharAttribList.InsertAttrib( pNewAttrib );
1489 pAttrib->GetEnd() = nCut;
1490 nAttr++;
1491 }
1492 else
1493 {
1494 // Move all attributes in the current node (this)
1495 CharAttribList::AttribsType::iterator it = rPrevAttribs.begin() + nAttr;
1496 aCharAttribList.InsertAttrib(it->release());
1497 rPrevAttribs.erase(it);
1498 pAttrib->MoveBackward( nCut );
1499 }
1500 pAttrib = GetAttrib(rPrevAttribs, nAttr);
1501 }
1502
1503#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
1506#endif
1507}
1508
1510{
1511 assert(pNextNode);
1512
1513 sal_Int32 nNewStart = maString.getLength();
1514
1515#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
1518#endif
1519
1520 std::size_t nAttr = 0;
1521 CharAttribList::AttribsType& rNextAttribs = pNextNode->GetCharAttribs().GetAttribs();
1522 EditCharAttrib* pAttrib = GetAttrib(rNextAttribs, nAttr);
1523 while ( pAttrib )
1524 {
1525 // Move all attributes in the current node (this)
1526 bool bMelted = false;
1527 if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) )
1528 {
1529 // Attributes can possibly be summarized as:
1530 std::size_t nTmpAttr = 0;
1531 EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
1532 while ( !bMelted && pTmpAttrib )
1533 {
1534 ++nTmpAttr;
1535 if ( pTmpAttrib->GetEnd() == nNewStart )
1536 {
1537 if (pTmpAttrib->Which() == pAttrib->Which())
1538 {
1539 // prevent adding 2 0-length attributes at same position
1540 if ((*(pTmpAttrib->GetItem()) == *(pAttrib->GetItem()))
1541 || (0 == pAttrib->GetLen()))
1542 {
1543 pTmpAttrib->GetEnd() =
1544 pTmpAttrib->GetEnd() + pAttrib->GetLen();
1545 rNextAttribs.erase(rNextAttribs.begin()+nAttr);
1546 // Unsubscribe from the pool?!
1547 bMelted = true;
1548 }
1549 else if (0 == pTmpAttrib->GetLen())
1550 {
1551 --nTmpAttr; // to cancel earlier increment...
1552 aCharAttribList.Remove(nTmpAttr);
1553 }
1554 }
1555 }
1556 pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr );
1557 }
1558 }
1559
1560 if ( !bMelted )
1561 {
1562 pAttrib->GetStart() = pAttrib->GetStart() + nNewStart;
1563 pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart;
1564 CharAttribList::AttribsType::iterator it = rNextAttribs.begin() + nAttr;
1565 aCharAttribList.InsertAttrib(it->release());
1566 rNextAttribs.erase(it);
1567 }
1568 pAttrib = GetAttrib(rNextAttribs, nAttr);
1569 }
1570 // For the Attributes that just moved over:
1571 rNextAttribs.clear();
1572
1573#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
1576#endif
1577}
1578
1580{
1581 // First use the information from the style ...
1583 if ( pS )
1584 CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() );
1585
1586 // ... then iron out the hard paragraph formatting...
1587 CreateFont( GetCharAttribs().GetDefFont(),
1588 GetContentAttribs().GetItems(), pS == nullptr );
1589}
1590
1591void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle )
1592{
1594
1595
1596 // First use the information from the style ...
1597 GetCharAttribs().GetDefFont() = rFontFromStyle;
1598 // ... then iron out the hard paragraph formatting...
1599 CreateFont( GetCharAttribs().GetDefFont(),
1600 GetContentAttribs().GetItems(), pS == nullptr );
1601}
1602
1603void ContentNode::SetStyleSheet( SfxStyleSheet* pS, bool bRecalcFont )
1604{
1606 if ( bRecalcFont )
1607 CreateDefFont();
1608}
1609
1610bool ContentNode::IsFeature( sal_Int32 nPos ) const
1611{
1612 return maString[nPos] == CH_FEATURE;
1613}
1614
1615sal_Int32 ContentNode::Len() const
1616{
1617 return maString.getLength();
1618}
1619
1621{
1622 sal_Int32 nLen = maString.getLength();
1623
1624 // Fields can be longer than the placeholder in the Node
1626 for (sal_Int32 nAttr = rAttrs.size(); nAttr; )
1627 {
1628 const EditCharAttrib& rAttr = *rAttrs[--nAttr];
1629 if (rAttr.Which() == EE_FEATURE_FIELD)
1630 {
1631 nLen += static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength();
1632 --nLen; // Standalone, to avoid corner cases when previous getLength() returns 0
1633 }
1634 }
1635
1636 return nLen;
1637}
1638
1639OUString ContentNode::GetExpandedText(sal_Int32 nStartPos, sal_Int32 nEndPos) const
1640{
1641 if ( nEndPos < 0 || nEndPos > Len() )
1642 nEndPos = Len();
1643
1644 DBG_ASSERT( nStartPos <= nEndPos, "Start and End reversed?" );
1645
1646 sal_Int32 nIndex = nStartPos;
1647 OUStringBuffer aStr(256);
1648 const EditCharAttrib* pNextFeature = GetCharAttribs().FindFeature( nIndex );
1649 while ( nIndex < nEndPos )
1650 {
1651 sal_Int32 nEnd = nEndPos;
1652 if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) )
1653 nEnd = pNextFeature->GetStart();
1654 else
1655 pNextFeature = nullptr; // Feature does not interest the below
1656
1657 DBG_ASSERT( nEnd >= nIndex, "End in front of the index?" );
1659 if (nEnd > nIndex)
1660 aStr.append( GetString().subView(nIndex, nEnd - nIndex) );
1661
1662 if ( pNextFeature )
1663 {
1664 switch ( pNextFeature->GetItem()->Which() )
1665 {
1666 case EE_FEATURE_TAB: aStr.append( "\t" );
1667 break;
1668 case EE_FEATURE_LINEBR: aStr.append( "\x0A" );
1669 break;
1670 case EE_FEATURE_FIELD:
1671 aStr.append( static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue() );
1672 break;
1673 default: OSL_FAIL( "What feature?" );
1674 }
1675 pNextFeature = GetCharAttribs().FindFeature( ++nEnd );
1676 }
1677 nIndex = nEnd;
1678 }
1679 return aStr.makeStringAndClear();
1680}
1681
1682void ContentNode::UnExpandPosition( sal_Int32 &rPos, bool bBiasStart )
1683{
1684 sal_Int32 nOffset = 0;
1685
1687 for (size_t nAttr = 0; nAttr < rAttrs.size(); ++nAttr )
1688 {
1689 const EditCharAttrib& rAttr = *rAttrs[nAttr];
1690 assert (!(nAttr < rAttrs.size() - 1) ||
1691 rAttrs[nAttr]->GetStart() <= rAttrs[nAttr + 1]->GetStart());
1692
1693 nOffset = rAttr.GetStart();
1694
1695 if (nOffset >= rPos) // happens after the position
1696 return;
1697
1698 if (rAttr.Which() == EE_FEATURE_FIELD)
1699 {
1700 sal_Int32 nChunk = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength();
1701 nChunk--; // Character representing the field in the string
1702
1703 if (nOffset + nChunk >= rPos) // we're inside the field
1704 {
1705 if (bBiasStart)
1706 rPos = rAttr.GetStart();
1707 else
1708 rPos = rAttr.GetEnd();
1709 return;
1710 }
1711 // Adjust for the position
1712 rPos -= nChunk;
1713 }
1714 }
1715 assert (rPos <= Len());
1716}
1717
1718/*
1719 * Fields are represented by a single character in the underlying string
1720 * and/or selection, however, they can be expanded to the full value of
1721 * the field. When we're dealing with selection / offsets however we need
1722 * to deal in character positions inside the real (unexpanded) string.
1723 * This method maps us back to character offsets.
1724 */
1725void ContentNode::UnExpandPositions( sal_Int32 &rStartPos, sal_Int32 &rEndPos )
1726{
1727 UnExpandPosition( rStartPos, true );
1728 UnExpandPosition( rEndPos, false );
1729}
1730
1731void ContentNode::SetChar(sal_Int32 nPos, sal_Unicode c)
1732{
1733 maString = maString.replaceAt(nPos, 1, rtl::OUStringChar(c));
1734}
1735
1736void ContentNode::Insert(std::u16string_view rStr, sal_Int32 nPos)
1737{
1738 maString = maString.replaceAt(nPos, 0, rStr);
1739}
1740
1741void ContentNode::Append(std::u16string_view rStr)
1742{
1743 maString += rStr;
1744}
1745
1746void ContentNode::Erase(sal_Int32 nPos)
1747{
1748 maString = maString.copy(0, nPos);
1749}
1750
1751void ContentNode::Erase(sal_Int32 nPos, sal_Int32 nCount)
1752{
1753 maString = maString.replaceAt(nPos, nCount, u"");
1754}
1755
1756OUString ContentNode::Copy(sal_Int32 nPos) const
1757{
1758 return maString.copy(nPos);
1759}
1760
1761OUString ContentNode::Copy(sal_Int32 nPos, sal_Int32 nCount) const
1762{
1763 return maString.copy(nPos, nCount);
1764}
1765
1767{
1768 return maString[nPos];
1769}
1770
1772{
1773 if (!mpWrongList)
1775}
1776
1778{
1779 return mpWrongList.get();
1780}
1781
1783{
1784 return mpWrongList.get();
1785}
1786
1788{
1789 mpWrongList.reset(p);
1790}
1791
1793{
1794 SAL_WARN_IF( mpWrongList && !mpWrongList->empty(), "editeng", "WrongList already exist!");
1795 if (!mpWrongList || !mpWrongList->empty())
1796 mpWrongList.reset(new WrongList);
1797}
1798
1800{
1801 mpWrongList.reset();
1802}
1803
1805{
1806 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentNode"));
1807 (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("maString"), BAD_CAST(maString.toUtf8().getStr()));
1808 aContentAttribs.dumpAsXml(pWriter);
1809 aCharAttribList.dumpAsXml(pWriter);
1810 (void)xmlTextWriterEndElement(pWriter);
1811}
1812
1813
1815: pStyle(nullptr)
1816, aAttribSet( rPool )
1817{
1818}
1819
1820
1821SvxTabStop ContentAttribs::FindTabStop( sal_Int32 nCurPos, sal_uInt16 nDefTab )
1822{
1823 const SvxTabStopItem& rTabs = GetItem( EE_PARA_TABS );
1824 for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ )
1825 {
1826 const SvxTabStop& rTab = rTabs[i];
1827 if ( rTab.GetTabPos() > nCurPos )
1828 return rTab;
1829 }
1830
1831 // if there's a default tab size defined for this item use that instead
1832 if (rTabs.GetDefaultDistance())
1833 nDefTab = rTabs.GetDefaultDistance();
1834
1835 // Determine DefTab ...
1836 SvxTabStop aTabStop;
1837 const sal_Int32 x = nCurPos / nDefTab + 1;
1838 aTabStop.GetTabPos() = nDefTab * x;
1839 return aTabStop;
1840}
1841
1843{
1844 bool bStyleChanged = ( pStyle != pS );
1845 pStyle = pS;
1846 // Only when other style sheet, not when current style sheet modified
1847 if ( !(pStyle && bStyleChanged) )
1848 return;
1849
1850 // Selectively remove the attributes from the paragraph formatting
1851 // which are specified in the style, so that the attributes of the
1852 // style can have an affect.
1853 const SfxItemSet& rStyleAttribs = pStyle->GetItemSet();
1854 for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ )
1855 {
1856 // Don't change bullet on/off
1857 if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SfxItemState::SET ) )
1858 aAttribSet.ClearItem( nWhich );
1859 }
1860}
1861
1862const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich ) const
1863{
1864 // Hard paragraph attributes take precedence!
1865 const SfxItemSet* pTakeFrom = &aAttribSet;
1866 if ( pStyle && ( aAttribSet.GetItemState( nWhich, false ) != SfxItemState::SET ) )
1867 pTakeFrom = &pStyle->GetItemSet();
1868
1869 return pTakeFrom->Get( nWhich );
1870}
1871
1872bool ContentAttribs::HasItem( sal_uInt16 nWhich ) const
1873{
1874 bool bHasItem = false;
1875 if ( aAttribSet.GetItemState( nWhich, false ) == SfxItemState::SET )
1876 bHasItem = true;
1877 else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SfxItemState::SET )
1878 bHasItem = true;
1879
1880 return bHasItem;
1881}
1882
1884{
1885 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentAttribs"));
1886 (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("style"), "%s", pStyle->GetName().toUtf8().getStr());
1887 aAttribSet.dumpAsXml(pWriter);
1888 (void)xmlTextWriterEndElement(pWriter);
1889}
1890
1891
1892ItemList::ItemList() : CurrentItem( 0 )
1893{
1894}
1895
1897{
1898 CurrentItem = 0;
1899 return aItemPool.empty() ? nullptr : aItemPool[ 0 ];
1900}
1901
1903{
1904 if ( CurrentItem + 1 < static_cast<sal_Int32>(aItemPool.size()) )
1905 {
1906 ++CurrentItem;
1907 return aItemPool[ CurrentItem ];
1908 }
1909 return nullptr;
1910}
1911
1912void ItemList::Insert( const SfxPoolItem* pItem )
1913{
1914 aItemPool.push_back( pItem );
1915 CurrentItem = aItemPool.size() - 1;
1916}
1917
1918
1920 nLastCache(0),
1921 pItemPool(pPool ? pPool : new EditEngineItemPool()),
1922 nDefTab(DEFTAB),
1923 bIsVertical(false),
1924 mnRotation(TextRotation::NONE),
1925 bIsFixedCellHeight(false),
1926 bModified(false),
1927 bDisableAttributeExpanding(false)
1928{
1929 // Don't create an empty node, Clear() will be called in EditEngine-CTOR
1930};
1931
1933{
1935}
1936
1937namespace {
1938
1939class RemoveEachItemFromPool
1940{
1941 EditDoc& mrDoc;
1942public:
1943 explicit RemoveEachItemFromPool(EditDoc& rDoc) : mrDoc(rDoc) {}
1944 void operator() (const std::unique_ptr<ContentNode>& rNode)
1945 {
1946 mrDoc.RemoveItemsFromPool(*rNode);
1947 }
1948};
1949
1950struct ClearSpellErrorsHandler
1951{
1952 void operator() (std::unique_ptr<ContentNode> const & rNode)
1953 {
1954 rNode->DestroyWrongList();
1955 }
1956};
1957
1958}
1959
1961{
1962 std::for_each(maContents.begin(), maContents.end(), RemoveEachItemFromPool(*this));
1963 maContents.clear();
1964}
1965
1967{
1968 for (sal_Int32 nAttr = 0; nAttr < rNode.GetCharAttribs().Count(); ++nAttr)
1969 {
1970 const EditCharAttrib& rAttr = *rNode.GetCharAttribs().GetAttribs()[nAttr];
1971 GetItemPool().Remove(*rAttr.GetItem());
1972 }
1973}
1974
1975void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, SvtScriptType nScriptType )
1976{
1977 vcl::Font aPrevFont( rFont );
1979
1980 sal_uInt16 nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType );
1981 sal_uInt16 nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType );
1982 sal_uInt16 nWhich_FontHeight = GetScriptItemId( EE_CHAR_FONTHEIGHT, nScriptType );
1983 sal_uInt16 nWhich_Weight = GetScriptItemId( EE_CHAR_WEIGHT, nScriptType );
1984 sal_uInt16 nWhich_Italic = GetScriptItemId( EE_CHAR_ITALIC, nScriptType );
1985
1986 if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontInfo ) == SfxItemState::SET ) )
1987 {
1988 const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(rSet.Get( nWhich_FontInfo ));
1989 rFont.SetFamilyName( rFontItem.GetFamilyName() );
1990 rFont.SetFamily( rFontItem.GetFamily() );
1991 rFont.SetPitch( rFontItem.GetPitch() );
1992 rFont.SetCharSet( rFontItem.GetCharSet() );
1993 }
1994 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Language ) == SfxItemState::SET ) )
1995 rFont.SetLanguage( static_cast<const SvxLanguageItem&>(rSet.Get( nWhich_Language )).GetLanguage() );
1996 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SfxItemState::SET ) )
1997 rFont.SetColor( rSet.Get( EE_CHAR_COLOR ).GetValue() );
1998 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_BKGCOLOR ) == SfxItemState::SET ) )
1999 {
2000 auto& aColor = rSet.Get( EE_CHAR_BKGCOLOR ).GetValue();
2001 rFont.SetTransparent(aColor.IsTransparent());
2002 rFont.SetFillColor(aColor);
2003 }
2004 if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SfxItemState::SET ) )
2005 rFont.SetFontSize( Size( rFont.GetFontSize().Width(), static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich_FontHeight ) ).GetHeight() ) );
2006 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SfxItemState::SET ) )
2007 rFont.SetWeight( static_cast<const SvxWeightItem&>(rSet.Get( nWhich_Weight )).GetWeight() );
2008 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_UNDERLINE ) == SfxItemState::SET ) )
2009 rFont.SetUnderline( rSet.Get( EE_CHAR_UNDERLINE ).GetLineStyle() );
2010 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OVERLINE ) == SfxItemState::SET ) )
2011 rFont.SetOverline( rSet.Get( EE_CHAR_OVERLINE ).GetLineStyle() );
2012 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_STRIKEOUT ) == SfxItemState::SET ) )
2013 rFont.SetStrikeout( rSet.Get( EE_CHAR_STRIKEOUT ).GetStrikeout() );
2014 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_CASEMAP ) == SfxItemState::SET ) )
2015 rFont.SetCaseMap( rSet.Get( EE_CHAR_CASEMAP ).GetCaseMap() );
2016 if ( bSearchInParent || ( rSet.GetItemState( nWhich_Italic ) == SfxItemState::SET ) )
2017 rFont.SetItalic( static_cast<const SvxPostureItem&>(rSet.Get( nWhich_Italic )).GetPosture() );
2018 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_OUTLINE ) == SfxItemState::SET ) )
2019 rFont.SetOutline( rSet.Get( EE_CHAR_OUTLINE ).GetValue() );
2020 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_SHADOW ) == SfxItemState::SET ) )
2021 rFont.SetShadow( rSet.Get( EE_CHAR_SHADOW ).GetValue() );
2022 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_ESCAPEMENT ) == SfxItemState::SET ) )
2023 {
2025
2026 sal_uInt16 const nProp = rEsc.GetProportionalHeight();
2027 rFont.SetPropr( static_cast<sal_uInt8>(nProp) );
2028
2029 short nEsc = rEsc.GetEsc();
2030 rFont.SetNonAutoEscapement( nEsc );
2031 }
2032 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_PAIRKERNING ) == SfxItemState::SET ) )
2033 rFont.SetKerning( rSet.Get( EE_CHAR_PAIRKERNING ).GetValue() ? FontKerning::FontSpecific : FontKerning::NONE );
2034 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_KERNING ) == SfxItemState::SET ) )
2035 rFont.SetFixKerning( rSet.Get( EE_CHAR_KERNING ).GetValue() );
2036 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_WLM ) == SfxItemState::SET ) )
2037 rFont.SetWordLineMode( rSet.Get( EE_CHAR_WLM ).GetValue() );
2038 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_EMPHASISMARK ) == SfxItemState::SET ) )
2039 rFont.SetEmphasisMark( rSet.Get( EE_CHAR_EMPHASISMARK ).GetEmphasisMark() );
2040 if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_RELIEF ) == SfxItemState::SET ) )
2041 rFont.SetRelief( rSet.Get( EE_CHAR_RELIEF ).GetValue() );
2042
2043 // Operator == compares the individual members of the font if the impl pointer is
2044 // not equal. If all members are the same, this assignment makes
2045 // sure that both also point to the same internal instance of the font.
2046 // To avoid this assignment, you would need to check in
2047 // every if statement above whether or not the new value differs from the
2048 // old value before making an assignment.
2049 if ( rFont == aPrevFont )
2050 rFont = aPrevFont; // => The same ImpPointer for IsSameInstance
2051}
2052
2053void EditDoc::CreateDefFont( bool bUseStyles )
2054{
2056 CreateFont(maDefFont, aTmpSet);
2059
2060 for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ )
2061 {
2062 ContentNode* pNode = GetObject( nNode );
2063 pNode->GetCharAttribs().GetDefFont() = maDefFont;
2064 if ( bUseStyles )
2065 pNode->CreateDefFont();
2066 }
2067}
2068
2070{
2071 return (bIsVertical && mnRotation == TextRotation::NONE) ||
2073}
2074
2076{
2077 return (bIsVertical && mnRotation == TextRotation::NONE) ||
2079}
2080
2082{
2083 return bIsVertical;
2084}
2085
2086sal_Int32 EditDoc::GetPos(const ContentNode* p) const
2087{
2088 return FastGetPos(maContents, p, nLastCache);
2089}
2090
2091const ContentNode* EditDoc::GetObject(sal_Int32 nPos) const
2092{
2093 return 0 <= nPos && o3tl::make_unsigned(nPos) < maContents.size() ? maContents[nPos].get() : nullptr;
2094}
2095
2097{
2098 return 0 <= nPos && o3tl::make_unsigned(nPos) < maContents.size() ? maContents[nPos].get() : nullptr;
2099}
2100
2101const ContentNode* EditDoc::operator[](sal_Int32 nPos) const
2102{
2103 return GetObject(nPos);
2104}
2105
2107{
2108 return GetObject(nPos);
2109}
2110
2111void EditDoc::Insert(sal_Int32 nPos, ContentNode* p)
2112{
2113 if (nPos < 0 || nPos == SAL_MAX_INT32)
2114 {
2115 SAL_WARN( "editeng", "EditDoc::Insert - overflow pos " << nPos);
2116 return;
2117 }
2118 maContents.insert(maContents.begin()+nPos, std::unique_ptr<ContentNode>(p));
2119}
2120
2121void EditDoc::Remove(sal_Int32 nPos)
2122{
2123 if (nPos < 0 || o3tl::make_unsigned(nPos) >= maContents.size())
2124 {
2125 SAL_WARN( "editeng", "EditDoc::Remove - out of bounds pos " << nPos);
2126 return;
2127 }
2128 maContents.erase(maContents.begin() + nPos);
2129}
2130
2131void EditDoc::Release(sal_Int32 nPos)
2132{
2133 if (nPos < 0 || o3tl::make_unsigned(nPos) >= maContents.size())
2134 {
2135 SAL_WARN( "editeng", "EditDoc::Release - out of bounds pos " << nPos);
2136 return;
2137 }
2138 // coverity[leaked_storage] - this is on purpose, ownership should be transferred to undo/redo
2139 (void)maContents[nPos].release();
2140 maContents.erase(maContents.begin() + nPos);
2141}
2142
2143sal_Int32 EditDoc::Count() const
2144{
2145 size_t nSize = maContents.size();
2146 if (nSize > SAL_MAX_INT32)
2147 {
2148 SAL_WARN( "editeng", "EditDoc::Count - overflow " << nSize);
2149 return SAL_MAX_INT32;
2150 }
2151 return nSize;
2152}
2153
2155{
2156 if ( eEnd == LINEEND_CR )
2157 return "\015"; // 0x0d
2158 if ( eEnd == LINEEND_LF )
2159 return "\012"; // 0x0a
2160 return "\015\012"; // 0x0d, 0x0a
2161}
2162
2163OUString EditDoc::GetText( LineEnd eEnd ) const
2164{
2165 const sal_Int32 nNodes = Count();
2166 if (nNodes == 0)
2167 return OUString();
2168
2169 const OUString aSep = EditDoc::GetSepStr( eEnd );
2170 const sal_Int32 nSepSize = aSep.getLength();
2171 const sal_Int32 nLen = GetTextLen() + (nNodes - 1)*nSepSize;
2172
2173 OUStringBuffer aBuffer(nLen + 16); // leave some slack
2174
2175 for ( sal_Int32 nNode = 0; nNode < nNodes; nNode++ )
2176 {
2177 if ( nSepSize && nNode>0 )
2178 {
2179 aBuffer.append(aSep);
2180 }
2181 aBuffer.append(GetParaAsString( GetObject(nNode) ));
2182 }
2183
2184 return aBuffer.makeStringAndClear();
2185}
2186
2187OUString EditDoc::GetParaAsString( sal_Int32 nNode ) const
2188{
2189 return GetParaAsString( GetObject( nNode ) );
2190}
2191
2193 const ContentNode* pNode, sal_Int32 nStartPos, sal_Int32 nEndPos)
2194{
2195 return pNode->GetExpandedText(nStartPos, nEndPos);
2196}
2197
2199{
2200 ContentNode* p = const_cast<ContentNode*>(GetObject(0));
2201 return EditPaM(p, 0);
2202}
2203
2205{
2206 ContentNode* pLastNode = const_cast<ContentNode*>(GetObject(Count()-1));
2207 return EditPaM( pLastNode, pLastNode->Len() );
2208}
2209
2210sal_Int32 EditDoc::GetTextLen() const
2211{
2212 sal_Int32 nLen = 0;
2213 for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ )
2214 {
2215 const ContentNode* pNode = GetObject( nNode );
2216 nLen += pNode->GetExpandedLen();
2217 }
2218 return nLen;
2219}
2220
2222{
2224
2225 ContentNode* pNode = new ContentNode( GetItemPool() );
2226 Insert(0, pNode);
2227
2228 CreateDefFont(false);
2229
2230 SetModified(false);
2231
2232 return EditPaM( pNode, 0 );
2233}
2234
2236{
2237 std::for_each(maContents.begin(), maContents.end(), ClearSpellErrorsHandler());
2238}
2239
2241{
2242 bModified = b;
2243 if ( bModified )
2244 {
2245 aModifyHdl.Call( nullptr );
2246 }
2247}
2248
2250{
2251 // Keep the old ItemSet, to keep the chart Font.
2252 ContentNode* pPrevFirstNode = GetObject(0);
2253 SfxStyleSheet* pPrevStyle = pPrevFirstNode->GetStyleSheet();
2254 SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() );
2255 vcl::Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() );
2256
2258
2259 ContentNode* pNode = new ContentNode( GetItemPool() );
2260 Insert(0, pNode);
2261
2262 pNode->SetStyleSheet(pPrevStyle, false);
2263 pNode->GetContentAttribs().GetItems().Set( aPrevSet );
2264 pNode->GetCharAttribs().GetDefFont() = aPrevFont;
2265
2266 SetModified(true);
2267
2268 return EditPaM( pNode, 0 );
2269}
2270
2271EditPaM EditDoc::InsertText( EditPaM aPaM, std::u16string_view rStr )
2272{
2273 DBG_ASSERT( rStr.find( 0x0A ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" );
2274 DBG_ASSERT( rStr.find( 0x0D ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" );
2275 DBG_ASSERT( rStr.find( '\t' ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" );
2276 assert(aPaM.GetNode());
2277
2278 aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() );
2279 aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.size(), GetItemPool() );
2280 aPaM.SetIndex( aPaM.GetIndex() + rStr.size() );
2281
2282 SetModified( true );
2283
2284 return aPaM;
2285}
2286
2287EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, bool bKeepEndingAttribs )
2288{
2289 assert(aPaM.GetNode());
2290 ContentNode* pCurNode = aPaM.GetNode();
2291 sal_Int32 nPos = GetPos( pCurNode );
2292 OUString aStr = aPaM.GetNode()->Copy( aPaM.GetIndex() );
2293 aPaM.GetNode()->Erase( aPaM.GetIndex() );
2294
2295 // the paragraph attributes...
2296 ContentAttribs aContentAttribs( aPaM.GetNode()->GetContentAttribs() );
2297
2298 // for a new paragraph we like to have the bullet/numbering visible by default
2299 aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, true) );
2300
2301 // ContentNode constructor copies also the paragraph attributes
2302 ContentNode* pNode = new ContentNode( aStr, std::move(aContentAttribs) );
2303
2304 // Copy the Default Font
2306 SfxStyleSheet* pStyle = aPaM.GetNode()->GetStyleSheet();
2307 if ( pStyle )
2308 {
2309 OUString aFollow( pStyle->GetFollow() );
2310 if ( !aFollow.isEmpty() && ( aFollow != pStyle->GetName() ) )
2311 {
2312 SfxStyleSheetBase* pNext = pStyle->GetPool()->Find( aFollow, pStyle->GetFamily() );
2313 pNode->SetStyleSheet( static_cast<SfxStyleSheet*>(pNext) );
2314 }
2315 }
2316
2317 // Character attributes may need to be copied or trimmed:
2318 pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs );
2319
2320 Insert(nPos+1, pNode);
2321
2322 SetModified(true);
2323
2324 aPaM.SetNode( pNode );
2325 aPaM.SetIndex( 0 );
2326 return aPaM;
2327}
2328
2330{
2331 assert(aPaM.GetNode());
2332
2333 aPaM.GetNode()->Insert( rtl::OUStringChar(CH_FEATURE), aPaM.GetIndex() );
2334 aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() );
2335
2336 // Create a feature-attribute for the feature...
2337 EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 );
2338 assert(pAttrib);
2339 aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttrib );
2340
2341 SetModified( true );
2342
2343 aPaM.SetIndex( aPaM.GetIndex() + 1 );
2344 return aPaM;
2345}
2346
2348{
2349 const EditPaM aPaM( pLeft, pLeft->Len() );
2350
2351 // First the attributes, otherwise nLen will not be correct!
2352 pLeft->AppendAttribs( pRight );
2353 // then the Text...
2354 pLeft->Append(pRight->GetString());
2355
2356 // the one to the right disappears.
2357 RemoveItemsFromPool(*pRight);
2358 sal_Int32 nRight = GetPos( pRight );
2359 Remove( nRight );
2360
2361 SetModified(true);
2362
2363 return aPaM;
2364}
2365
2366void EditDoc::RemoveChars( EditPaM aPaM, sal_Int32 nChars )
2367{
2368 // Maybe remove Features!
2369 aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars );
2370 aPaM.GetNode()->CollapseAttribs( aPaM.GetIndex(), nChars, GetItemPool() );
2371
2372 SetModified( true );
2373}
2374
2375void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, const SfxPoolItem& rPoolItem )
2376{
2377 assert(pNode);
2378 DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribute too large!" );
2379
2380 // for Optimization:
2381 // This ends at the beginning of the selection => can be expanded
2382 EditCharAttrib* pEndingAttrib = nullptr;
2383 // This starts at the end of the selection => can be expanded
2384 EditCharAttrib* pStartingAttrib = nullptr;
2385
2386 DBG_ASSERT( nStart <= nEnd, "Small miscalculations in InsertAttribInSelection" );
2387
2388 RemoveAttribs( pNode, nStart, nEnd, pStartingAttrib, pEndingAttrib, rPoolItem.Which() );
2389
2390 // tdf#132288 By default inserting an attribute beside another that is of
2391 // the same type expands the original instead of inserting another. But the
2392 // spell check dialog doesn't want that behaviour
2394 {
2395 pStartingAttrib = nullptr;
2396 pEndingAttrib = nullptr;
2397 }
2398
2399 if ( pStartingAttrib && pEndingAttrib &&
2400 ( *(pStartingAttrib->GetItem()) == rPoolItem ) &&
2401 ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
2402 {
2403 // Will become a large Attribute.
2404 pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd();
2405 GetItemPool().Remove( *(pStartingAttrib->GetItem()) );
2406 pNode->GetCharAttribs().Remove(pStartingAttrib);
2407 }
2408 else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) )
2409 pStartingAttrib->GetStart() = nStart;
2410 else if ( pEndingAttrib && ( *(pEndingAttrib->GetItem()) == rPoolItem ) )
2411 pEndingAttrib->GetEnd() = nEnd;
2412 else
2413 InsertAttrib( rPoolItem, pNode, nStart, nEnd );
2414
2415 if ( pStartingAttrib )
2416 pNode->GetCharAttribs().ResortAttribs();
2417
2418 SetModified(true);
2419}
2420
2421bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, sal_uInt16 nWhich )
2422{
2423 EditCharAttrib* pStarting;
2424 EditCharAttrib* pEnding;
2425 return RemoveAttribs( pNode, nStart, nEnd, pStarting, pEnding, nWhich );
2426}
2427
2428bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, EditCharAttrib*& rpStarting, EditCharAttrib*& rpEnding, sal_uInt16 nWhich )
2429{
2430
2431 assert(pNode);
2432 DBG_ASSERT( nEnd <= pNode->Len(), "InsertAttrib: Attribute too large!" );
2433
2434 // This ends at the beginning of the selection => can be expanded
2435 rpEnding = nullptr;
2436 // This starts at the end of the selection => can be expanded
2437 rpStarting = nullptr;
2438
2439 bool bChanged = false;
2440 bool bNeedsSorting = false;
2441
2442 DBG_ASSERT( nStart <= nEnd, "Small miscalculations in InsertAttribInSelection" );
2443
2444#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
2446#endif
2447
2448 // iterate over the attributes ...
2449 std::size_t nAttr = 0;
2451 EditCharAttrib* pAttr = GetAttrib(rAttribs, nAttr);
2452 while ( pAttr )
2453 {
2454 bool bRemoveAttrib = false;
2455 sal_uInt16 nAttrWhich = pAttr->Which();
2456 if ( ( nAttrWhich < EE_FEATURE_START ) && ( !nWhich || ( nAttrWhich == nWhich ) ) )
2457 {
2458 // Attribute starts in Selection
2459 if ( ( pAttr->GetStart() >= nStart ) && ( pAttr->GetStart() <= nEnd ) )
2460 {
2461 bChanged = true;
2462 if ( pAttr->GetEnd() > nEnd )
2463 {
2464 bNeedsSorting = true;
2465 pAttr->GetStart() = nEnd; // then it starts after this
2466 rpStarting = pAttr;
2467 if ( nWhich )
2468 break; // There can be no further attributes here
2469 }
2470 else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
2471 {
2472 // Delete feature only if on the exact spot
2473 bRemoveAttrib = true;
2474 }
2475 }
2476
2477 // Attribute ends in Selection
2478 else if ( ( pAttr->GetEnd() >= nStart ) && ( pAttr->GetEnd() <= nEnd ) )
2479 {
2480 bChanged = true;
2481 if ( ( pAttr->GetStart() < nStart ) && !pAttr->IsFeature() )
2482 {
2483 pAttr->GetEnd() = nStart; // then it ends here
2484 rpEnding = pAttr;
2485 }
2486 else if ( !pAttr->IsFeature() || ( pAttr->GetStart() == nStart ) )
2487 {
2488 // Delete feature only if on the exact spot
2489 bRemoveAttrib = true;
2490 }
2491 }
2492 // Attribute overlaps the selection
2493 else if ( ( pAttr->GetStart() <= nStart ) && ( pAttr->GetEnd() >= nEnd ) )
2494 {
2495 bChanged = true;
2496 if ( pAttr->GetStart() == nStart )
2497 {
2498 bNeedsSorting = true;
2499 pAttr->GetStart() = nEnd;
2500 rpStarting = pAttr;
2501 if ( nWhich )
2502 break; // There can be further attributes!
2503 }
2504 else if ( pAttr->GetEnd() == nEnd )
2505 {
2506 pAttr->GetEnd() = nStart;
2507 rpEnding = pAttr;
2508 if ( nWhich )
2509 break; // There can be further attributes!
2510 }
2511 else // Attribute must be split ...
2512 {
2513 bNeedsSorting = true;
2514 sal_Int32 nOldEnd = pAttr->GetEnd();
2515 pAttr->GetEnd() = nStart;
2516 rpEnding = pAttr;
2517 InsertAttrib( *pAttr->GetItem(), pNode, nEnd, nOldEnd );
2518 if ( nWhich )
2519 break; // There can be further attributes!
2520 }
2521 }
2522 }
2523 if ( bRemoveAttrib )
2524 {
2525 DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Delete and retain the same attribute?" );
2526 DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" );
2527 GetItemPool().Remove( *pAttr->GetItem() );
2528 rAttribs.erase(rAttribs.begin()+nAttr);
2529 }
2530 else
2531 {
2532 nAttr++;
2533 }
2534 pAttr = GetAttrib(rAttribs, nAttr);
2535 }
2536
2537 if ( bChanged )
2538 {
2539 // char attributes need to be sorted by start again
2540 if (bNeedsSorting)
2541 pNode->GetCharAttribs().ResortAttribs();
2542 SetModified(true);
2543 }
2544
2545#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
2547#endif
2548
2549 return bChanged;
2550}
2551
2552void EditDoc::InsertAttrib( const SfxPoolItem& rPoolItem, ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd )
2553{
2554 // This method no longer checks whether a corresponding attribute already
2555 // exists at this place!
2556 EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rPoolItem, nStart, nEnd );
2557 assert(pAttrib);
2558 pNode->GetCharAttribs().InsertAttrib( pAttrib );
2559
2560 SetModified( true );
2561}
2562
2563void EditDoc::InsertAttrib( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, const SfxPoolItem& rPoolItem )
2564{
2565 if ( nStart != nEnd )
2566 {
2567 InsertAttribInSelection( pNode, nStart, nEnd, rPoolItem );
2568 }
2569 else
2570 {
2571 // Check whether already a new attribute with WhichId exists at this place:
2572 CharAttribList& rAttrList = pNode->GetCharAttribs();
2573 EditCharAttrib* pAttr = rAttrList.FindEmptyAttrib( rPoolItem.Which(), nStart );
2574 if ( pAttr )
2575 {
2576 // Remove attribute...
2577 rAttrList.Remove(pAttr);
2578 }
2579
2580 // check whether 'the same' attribute exist at this place.
2581 pAttr = rAttrList.FindAttrib( rPoolItem.Which(), nStart );
2582 if ( pAttr )
2583 {
2584 if ( pAttr->IsInside( nStart ) ) // split
2585 {
2586 // check again if really splitting, or return !
2587 sal_Int32 nOldEnd = pAttr->GetEnd();
2588 pAttr->GetEnd() = nStart;
2589 EditCharAttrib* pNew = MakeCharAttrib( GetItemPool(), *(pAttr->GetItem()), nStart, nOldEnd );
2590 rAttrList.InsertAttrib(pNew);
2591 }
2592 else if ( pAttr->GetEnd() == nStart )
2593 {
2594 DBG_ASSERT( !pAttr->IsEmpty(), "Still an empty attribute?" );
2595 // Check if exactly the same attribute
2596 if ( *(pAttr->GetItem()) == rPoolItem )
2597 return;
2598 }
2599 }
2600 InsertAttrib( rPoolItem, pNode, nStart, nStart );
2601 }
2602
2603 SetModified( true );
2604}
2605
2606void EditDoc::FindAttribs( ContentNode* pNode, sal_Int32 nStartPos, sal_Int32 nEndPos, SfxItemSet& rCurSet )
2607{
2608 assert(pNode);
2609 DBG_ASSERT( nStartPos <= nEndPos, "Invalid region!" );
2610
2611 std::size_t nAttr = 0;
2612 EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
2613 // No Selection...
2614 if ( nStartPos == nEndPos )
2615 {
2616 while ( pAttr && ( pAttr->GetStart() <= nEndPos) )
2617 {
2618 const SfxPoolItem* pItem = nullptr;
2619 // Attribute is about...
2620 if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
2621 pItem = pAttr->GetItem();
2622 // Attribute ending here is not empty
2623 else if ( ( pAttr->GetStart() < nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
2624 {
2625 if ( !pNode->GetCharAttribs().FindEmptyAttrib( pAttr->GetItem()->Which(), nStartPos ) )
2626 pItem = pAttr->GetItem();
2627 }
2628 // Attribute ending here is empty
2629 else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() == nStartPos ) )
2630 {
2631 pItem = pAttr->GetItem();
2632 }
2633 // Attribute starts here
2634 else if ( ( pAttr->GetStart() == nStartPos ) && ( pAttr->GetEnd() > nStartPos ) )
2635 {
2636 if ( nStartPos == 0 ) // special case
2637 pItem = pAttr->GetItem();
2638 }
2639
2640 if ( pItem )
2641 {
2642 sal_uInt16 nWhich = pItem->Which();
2643 if ( rCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT )
2644 {
2645 rCurSet.Put( *pItem );
2646 }
2647 else if ( rCurSet.GetItemState( nWhich ) == SfxItemState::SET )
2648 {
2649 const SfxPoolItem& rItem = rCurSet.Get( nWhich );
2650 if ( rItem != *pItem )
2651 {
2652 rCurSet.InvalidateItem( nWhich );
2653 }
2654 }
2655 }
2656 nAttr++;
2657 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
2658 }
2659 }
2660 else // Selection
2661 {
2662 while ( pAttr && ( pAttr->GetStart() < nEndPos) )
2663 {
2664 const SfxPoolItem* pItem = nullptr;
2665 // Attribute is about...
2666 if ( ( pAttr->GetStart() <= nStartPos ) && ( pAttr->GetEnd() >= nEndPos ) )
2667 pItem = pAttr->GetItem();
2668 // Attribute starts right in the middle ...
2669 else if ( pAttr->GetStart() >= nStartPos )
2670 {
2671 // !!! pItem = pAttr->GetItem();
2672 // PItem is simply not enough, since one for example in case
2673 // of Shadow, would never find an unequal item, since such a
2674 // item represents its presence by absence!
2675 // If (...)
2676 // It needs to be examined on exactly the same attribute at the
2677 // break point, which is quite expensive.
2678 // Since optimization is done when inserting the attributes
2679 // this case does not appear so fast...
2680 // So based on the need for speed:
2681 rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
2682
2683 }
2684 // Attribute ends in the middle of it ...
2685 else if ( pAttr->GetEnd() > nStartPos )
2686 {
2687 rCurSet.InvalidateItem( pAttr->GetItem()->Which() );
2688 }
2689
2690 if ( pItem )
2691 {
2692 sal_uInt16 nWhich = pItem->Which();
2693 if ( rCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT )
2694 {
2695 rCurSet.Put( *pItem );
2696 }
2697 else if ( rCurSet.GetItemState( nWhich ) == SfxItemState::SET )
2698 {
2699 const SfxPoolItem& rItem = rCurSet.Get( nWhich );
2700 if ( rItem != *pItem )
2701 {
2702 rCurSet.InvalidateItem( nWhich );
2703 }
2704 }
2705 }
2706 nAttr++;
2707 pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr );
2708 }
2709 }
2710}
2711
2713{
2714 bool bOwns = false;
2715 if (!pWriter)
2716 {
2717 pWriter = xmlNewTextWriterFilename("editdoc.xml", 0);
2718 xmlTextWriterSetIndent(pWriter,1);
2719 (void)xmlTextWriterSetIndentString(pWriter, BAD_CAST(" "));
2720 (void)xmlTextWriterStartDocument(pWriter, nullptr, nullptr, nullptr);
2721 bOwns = true;
2722 }
2723
2724 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("EditDoc"));
2725 for (auto const & i : maContents)
2726 {
2727 i->dumpAsXml(pWriter);
2728 }
2729 (void)xmlTextWriterEndElement(pWriter);
2730
2731 if (bOwns)
2732 {
2733 (void)xmlTextWriterEndDocument(pWriter);
2734 xmlFreeTextWriter(pWriter);
2735 }
2736}
2737
2738
2739namespace {
2740
2741struct LessByStart
2742{
2743 bool operator() (const std::unique_ptr<EditCharAttrib>& left, const std::unique_ptr<EditCharAttrib>& right) const
2744 {
2745 return left->GetStart() < right->GetStart();
2746 }
2747};
2748
2749}
2750
2752: bHasEmptyAttribs(false)
2753{
2754}
2755
2757{
2758}
2759
2761{
2762// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2763// optimize: binary search? !
2764// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2765
2766 // Maybe just simply iterate backwards:
2767 // The most common and critical case: Attributes are already sorted
2768 // (InsertTextObject!) binary search would not be optimal here.
2769 // => Would bring something!
2770
2771 const sal_Int32 nStart = pAttrib->GetStart(); // may be better for Comp.Opt.
2772
2773#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
2775#endif
2776
2777 if ( pAttrib->IsEmpty() )
2778 bHasEmptyAttribs = true;
2779
2780 bool bInsert(true);
2781 for (sal_Int32 i = 0, n = aAttribs.size(); i < n; ++i)
2782 {
2783 const EditCharAttrib& rCurAttrib = *aAttribs[i];
2784 if (rCurAttrib.GetStart() > nStart)
2785 {
2786 aAttribs.insert(aAttribs.begin()+i, std::unique_ptr<EditCharAttrib>(pAttrib));
2787 bInsert = false;
2788 break;
2789 }
2790 }
2791
2792 if (bInsert) aAttribs.push_back(std::unique_ptr<EditCharAttrib>(pAttrib));
2793
2794#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
2796#endif
2797}
2798
2800{
2801 std::sort(aAttribs.begin(), aAttribs.end(), LessByStart());
2802
2803#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
2805#endif
2806}
2807
2809{
2810#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
2812#endif
2813 for (sal_Int32 i = 0; i < static_cast<sal_Int32>(aAttribs.size()); ++i)
2814 {
2815 EditCharAttrib& rAttr = *aAttribs[i];
2816 for (sal_Int32 nNext = i+1; nNext < static_cast<sal_Int32>(aAttribs.size()); ++nNext)
2817 {
2818 EditCharAttrib& rNext = *aAttribs[nNext];
2819 if (!rAttr.IsFeature() && rNext.GetStart() == rAttr.GetEnd() && rNext.Which() == rAttr.Which())
2820 {
2821 if (*rNext.GetItem() == *rAttr.GetItem())
2822 {
2823 rAttr.GetEnd() = rNext.GetEnd();
2824 rItemPool.Remove(*rNext.GetItem());
2825 aAttribs.erase(aAttribs.begin()+nNext);
2826 }
2827 break; // only 1 attr with same which can start here.
2828 }
2829 else if (rNext.GetStart() > rAttr.GetEnd())
2830 {
2831 break;
2832 }
2833 }
2834 }
2835#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
2837#endif
2838}
2839
2840sal_Int32 CharAttribList::Count() const
2841{
2842 return aAttribs.size();
2843}
2844
2845const EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) const
2846{
2847 // Backwards, if one ends where the next starts.
2848 // => The starting one is the valid one ...
2849 AttribsType::const_reverse_iterator it = std::find_if(aAttribs.rbegin(), aAttribs.rend(),
2850 [&nWhich, &nPos](const AttribsType::value_type& rxAttr) {
2851 return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); });
2852 if (it != aAttribs.rend())
2853 {
2854 const EditCharAttrib& rAttr = **it;
2855 return &rAttr;
2856 }
2857 return nullptr;
2858}
2859
2860EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos )
2861{
2862 // Backwards, if one ends where the next starts.
2863 // => The starting one is the valid one ...
2864 AttribsType::reverse_iterator it = std::find_if(aAttribs.rbegin(), aAttribs.rend(),
2865 [&nWhich, &nPos](AttribsType::value_type& rxAttr) {
2866 return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); });
2867 if (it != aAttribs.rend())
2868 {
2869 EditCharAttrib& rAttr = **it;
2870 return &rAttr;
2871 }
2872 return nullptr;
2873}
2874
2875const EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_Int32 nFromPos ) const
2876{
2877 assert(nWhich);
2878 for (auto const& attrib : aAttribs)
2879 {
2880 const EditCharAttrib& rAttr = *attrib;
2881 if (rAttr.GetStart() >= nFromPos && rAttr.Which() == nWhich)
2882 return &rAttr;
2883 }
2884 return nullptr;
2885}
2886
2887bool CharAttribList::HasAttrib( sal_Int32 nStartPos, sal_Int32 nEndPos ) const
2888{
2889 return std::any_of(aAttribs.rbegin(), aAttribs.rend(),
2890 [&nStartPos, &nEndPos](const AttribsType::value_type& rxAttr) {
2891 return rxAttr->GetStart() < nEndPos && rxAttr->GetEnd() > nStartPos; });
2892}
2893
2894
2895namespace {
2896
2897class FindByAddress
2898{
2899 const EditCharAttrib* mpAttr;
2900public:
2901 explicit FindByAddress(const EditCharAttrib* p) : mpAttr(p) {}
2902 bool operator() (const std::unique_ptr<EditCharAttrib>& r) const
2903 {
2904 return r.get() == mpAttr;
2905 }
2906};
2907
2908}
2909
2911{
2912 AttribsType::iterator it = std::find_if(aAttribs.begin(), aAttribs.end(), FindByAddress(p));
2913 if (it != aAttribs.end())
2914 aAttribs.erase(it);
2915}
2916
2917void CharAttribList::Remove(sal_Int32 nPos)
2918{
2919 if (nPos >= static_cast<sal_Int32>(aAttribs.size()))
2920 return;
2921
2922 aAttribs.erase(aAttribs.begin()+nPos);
2923}
2924
2926{
2927 bHasEmptyAttribs = b;
2928}
2929
2930bool CharAttribList::HasBoundingAttrib( sal_Int32 nBound ) const
2931{
2932 // Backwards, if one ends where the next starts.
2933 // => The starting one is the valid one ...
2934 AttribsType::const_reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend();
2935 for (; it != itEnd; ++it)
2936 {
2937 const EditCharAttrib& rAttr = **it;
2938 if (rAttr.GetEnd() < nBound)
2939 return false;
2940
2941 if (rAttr.GetStart() == nBound || rAttr.GetEnd() == nBound)
2942 return true;
2943 }
2944 return false;
2945}
2946
2947EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_Int32 nPos )
2948{
2949 if ( !bHasEmptyAttribs )
2950 return nullptr;
2951
2952 for (const std::unique_ptr<EditCharAttrib>& rAttr : aAttribs)
2953 {
2954 if (rAttr->GetStart() == nPos && rAttr->GetEnd() == nPos && rAttr->Which() == nWhich)
2955 return rAttr.get();
2956 }
2957 return nullptr;
2958}
2959
2960namespace {
2961
2962class FindByStartPos
2963{
2964 sal_Int32 mnPos;
2965public:
2966 explicit FindByStartPos(sal_Int32 nPos) : mnPos(nPos) {}
2967 bool operator() (const std::unique_ptr<EditCharAttrib>& r) const
2968 {
2969 return r->GetStart() >= mnPos;
2970 }
2971};
2972
2973}
2974
2975const EditCharAttrib* CharAttribList::FindFeature( sal_Int32 nPos ) const
2976{
2977 // First, find the first attribute that starts at or after specified position.
2978 AttribsType::const_iterator it =
2979 std::find_if(aAttribs.begin(), aAttribs.end(), FindByStartPos(nPos));
2980
2981 if (it == aAttribs.end())
2982 // All attributes are before the specified position.
2983 return nullptr;
2984
2985 // And find the first attribute with feature.
2986 it = std::find_if(it, aAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsFeature(); } );
2987 return it == aAttribs.end() ? nullptr : it->get();
2988}
2989
2990namespace {
2991
2992class RemoveEmptyAttrItem
2993{
2994 SfxItemPool& mrItemPool;
2995public:
2996 explicit RemoveEmptyAttrItem(SfxItemPool& rPool) : mrItemPool(rPool) {}
2997 void operator() (const std::unique_ptr<EditCharAttrib>& r)
2998 {
2999 if (r->IsEmpty())
3000 mrItemPool.Remove(*r->GetItem());
3001 }
3002};
3003
3004}
3005
3007{
3008 std::for_each(aAttribs.begin(), aAttribs.end(), RemoveEmptyAttrItem(rItemPool));
3009 aAttribs.erase( std::remove_if(aAttribs.begin(), aAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsEmpty(); } ), aAttribs.end() );
3010 bHasEmptyAttribs = false;
3011}
3012
3013#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG
3015{
3016 std::set<std::pair<sal_Int32, sal_uInt16>> zero_set;
3017 for (const std::unique_ptr<EditCharAttrib>& rAttr : rAttribs.aAttribs)
3018 {
3019 assert(rAttr->GetStart() <= rAttr->GetEnd());
3020 assert(!rAttr->IsFeature() || rAttr->GetLen() == 1);
3021 if (0 == rAttr->GetLen())
3022 {
3023 // not sure if 0-length attributes allowed at all in non-empty para?
3024 assert(zero_set.insert(std::make_pair(rAttr->GetStart(), rAttr->Which())).second && "duplicate 0-length attribute detected");
3025 }
3026 }
3027 CheckOrderedList(rAttribs.GetAttribs());
3028}
3029#endif
3030
3032{
3033 (void)xmlTextWriterStartElement(pWriter, BAD_CAST("CharAttribList"));
3034 for (auto const & i : aAttribs) {
3035 i->dumpAsXml(pWriter);
3036 }
3037 (void)xmlTextWriterEndElement(pWriter);
3038}
3039
3041 : SfxItemPool( "EditEngineItemPool", EE_ITEMS_START, EE_ITEMS_END,
3042 aItemInfos, nullptr )
3043{
3045 SetDefaults(&m_xDefItems->getDefaults());
3046}
3047
3049{
3050 ClearDefaults();
3051 SetSecondaryPool(nullptr);
3052}
3053
3054/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: editdoc.cxx:3031
AttribsType & GetAttribs()
Definition: editdoc.hxx:222
const EditCharAttrib * FindFeature(sal_Int32 nPos) const
Definition: editdoc.cxx:2975
static void DbgCheckAttribs(CharAttribList const &rAttribs)
Definition: editdoc.cxx:3014
bool HasAttrib(sal_Int32 nStartPos, sal_Int32 nEndPos) const
Definition: editdoc.cxx:2887
bool HasBoundingAttrib(sal_Int32 nBound) const
Definition: editdoc.cxx:2930
EditCharAttrib * FindEmptyAttrib(sal_uInt16 nWhich, sal_Int32 nPos)
Definition: editdoc.cxx:2947
void InsertAttrib(EditCharAttrib *pAttrib)
Definition: editdoc.cxx:2760
sal_Int32 Count() const
Definition: editdoc.cxx:2840
bool bHasEmptyAttribs
Definition: editdoc.hxx:191
void OptimizeRanges(SfxItemPool &rItemPool)
Definition: editdoc.cxx:2808
void ResortAttribs()
Definition: editdoc.cxx:2799
std::vector< std::unique_ptr< EditCharAttrib > > AttribsType
Definition: editdoc.hxx:186
SvxFont & GetDefFont()
Definition: editdoc.hxx:215
const EditCharAttrib * FindNextAttrib(sal_uInt16 nWhich, sal_Int32 nFromPos) const
Definition: editdoc.cxx:2875
void Remove(const EditCharAttrib *p)
Definition: editdoc.cxx:2910
void SetHasEmptyAttribs(bool b)
Definition: editdoc.cxx:2925
const EditCharAttrib * FindAttrib(sal_uInt16 nWhich, sal_Int32 nPos) const
Definition: editdoc.cxx:2845
AttribsType aAttribs
Definition: editdoc.hxx:189
void DeleteEmptyAttribs(SfxItemPool &rItemPool)
Definition: editdoc.cxx:3006
CharAttribsType aPrevCharAttribs
Definition: editdoc.hxx:117
ContentAttribsInfo(SfxItemSet aParaAttribs)
Definition: editdoc.cxx:807
void RemoveAllCharAttribsFromPool(SfxItemPool &rPool) const
Definition: editdoc.cxx:812
void AppendCharAttrib(EditCharAttrib *pNew)
Definition: editdoc.cxx:818
SfxItemSetFixed< EE_PARA_START, EE_CHAR_END > aAttribSet
Definition: editdoc.hxx:158
SvxTabStop FindTabStop(sal_Int32 nCurPos, sal_uInt16 nDefTab)
Definition: editdoc.cxx:1821
bool HasItem(sal_uInt16 nWhich) const
Definition: editdoc.cxx:1872
SfxItemSet & GetItems()
Definition: editdoc.hxx:166
const SfxPoolItem & GetItem(sal_uInt16 nWhich) const
Definition: editdoc.cxx:1862
SfxStyleSheet * pStyle
Definition: editdoc.hxx:157
const SfxStyleSheet * GetStyleSheet() const
Definition: editdoc.hxx:168
void SetStyleSheet(SfxStyleSheet *pS)
Definition: editdoc.cxx:1842
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: editdoc.cxx:1883
ContentAttribs(SfxItemPool &rItemPool)
Definition: editdoc.cxx:1814
ContentNode(SfxItemPool &rItemPool)
Definition: editdoc.cxx:1199
void CollapseAttribs(sal_Int32 nIndex, sal_Int32 nDelChars, SfxItemPool &rItemPool)
Definition: editdoc.cxx:1354
void EnsureWrongList()
Definition: editdoc.cxx:1771
OUString maString
Definition: editdoc.hxx:238
void SetChar(sal_Int32 nPos, sal_Unicode c)
Definition: editdoc.cxx:1731
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: editdoc.cxx:1804
CharAttribList & GetCharAttribs()
Definition: editdoc.hxx:256
sal_Unicode GetChar(sal_Int32 nPos) const
Definition: editdoc.cxx:1766
void UnExpandPosition(sal_Int32 &rStartPos, bool bBiasStart)
Definition: editdoc.cxx:1682
ContentAttribs aContentAttribs
Definition: editdoc.hxx:239
bool IsFeature(sal_Int32 nPos) const
Definition: editdoc.cxx:1610
const OUString & GetString() const
Definition: editdoc.hxx:281
ContentAttribs & GetContentAttribs()
Definition: editdoc.hxx:254
WrongList * GetWrongList()
Definition: editdoc.cxx:1777
void CopyAndCutAttribs(ContentNode *pPrevNode, SfxItemPool &rPool, bool bKeepEndingAttribs)
Definition: editdoc.cxx:1450
void CreateDefFont()
Definition: editdoc.cxx:1579
void Insert(std::u16string_view rStr, sal_Int32 nPos)
Definition: editdoc.cxx:1736
void Erase(sal_Int32 nPos)
Definition: editdoc.cxx:1746
void UnExpandPositions(sal_Int32 &rStartPos, sal_Int32 &rEndPos)
re-write offsets in the expanded text to string offsets
Definition: editdoc.cxx:1725
void ExpandAttribs(sal_Int32 nIndex, sal_Int32 nNewChars, SfxItemPool &rItemPool)
Definition: editdoc.cxx:1212
void AppendAttribs(ContentNode *pNextNode)
Definition: editdoc.cxx:1509
void Append(std::u16string_view rStr)
Definition: editdoc.cxx:1741
OUString Copy(sal_Int32 nPos) const
Definition: editdoc.cxx:1756
CharAttribList aCharAttribList
Definition: editdoc.hxx:240
OUString GetExpandedText(sal_Int32 nStartPos=0, sal_Int32 nEndPos=-1) const
return content including expanded fields
Definition: editdoc.cxx:1639
void SetWrongList(WrongList *p)
Definition: editdoc.cxx:1787
std::unique_ptr< WrongList > mpWrongList
Definition: editdoc.hxx:241
sal_Int32 GetExpandedLen() const
return length including expanded fields
Definition: editdoc.cxx:1620
SfxStyleSheet * GetStyleSheet()
Definition: editdoc.hxx:266
sal_Int32 Len() const
Definition: editdoc.cxx:1615
void SetStyleSheet(SfxStyleSheet *pS, bool bRecalcFont=true)
Definition: editdoc.cxx:1603
void CreateWrongList()
Definition: editdoc.cxx:1792
void DestroyWrongList()
Definition: editdoc.cxx:1799
void SetEdge(bool b)
Definition: editattr.hxx:114
void MoveForward(sal_Int32 nDiff)
Definition: editattr.hxx:123
sal_Int32 & GetStart()
Definition: editattr.hxx:87
const SfxPoolItem * GetItem() const
Definition: editattr.hxx:85
void MoveBackward(sal_Int32 nDiff)
Definition: editattr.hxx:130
sal_uInt16 Which() const
Definition: editattr.hxx:84
bool IsEmpty() const
Definition: editattr.hxx:107
void Expand(sal_Int32 nDiff)
Definition: editattr.hxx:137
bool IsInside(sal_Int32 nIndex) const
Definition: editattr.hxx:105
sal_Int32 & GetEnd()
Definition: editattr.hxx:88
void Collaps(sal_Int32 nDiff)
Definition: editattr.hxx:144
bool IsFeature() const
Definition: editattr.hxx:110
sal_Int32 GetLen() const
Definition: editattr.hxx:117
bool IsEdge() const
Definition: editattr.hxx:113
GlobalEditData * GetGlobalData() const
Definition: eerdll.hxx:46
static EditDLL & Get()
Definition: eerdll.cxx:71
void ImplDestroyContents()
Definition: editdoc.cxx:1960
bool bModified
Definition: editdoc.hxx:759
EditPaM GetEndPaM() const
Definition: editdoc.cxx:2204
void Insert(sal_Int32 nPos, ContentNode *p)
Definition: editdoc.cxx:2111
bool IsEffectivelyVertical() const
Definition: editdoc.cxx:2069
void SetModified(bool b)
Definition: editdoc.cxx:2240
void InsertAttrib(const SfxPoolItem &rItem, ContentNode *pNode, sal_Int32 nStart, sal_Int32 nEnd)
Definition: editdoc.cxx:2552
void RemoveItemsFromPool(const ContentNode &rNode)
Definition: editdoc.cxx:1966
bool IsTopToBottom() const
Definition: editdoc.cxx:2075
sal_Int32 GetPos(const ContentNode *pNode) const
Definition: editdoc.cxx:2086
static void FindAttribs(ContentNode *pNode, sal_Int32 nStartPos, sal_Int32 nEndPos, SfxItemSet &rCurSet)
Definition: editdoc.cxx:2606
void RemoveChars(EditPaM aPaM, sal_Int32 nChars)
Definition: editdoc.cxx:2366
SfxItemPool & GetItemPool()
Definition: editdoc.hxx:812
std::vector< std::unique_ptr< ContentNode > > maContents
Definition: editdoc.hxx:748
EditPaM Clear()
Definition: editdoc.cxx:2221
~EditDoc()
Definition: editdoc.cxx:1932
bool bIsVertical
Definition: editdoc.hxx:755
void Remove(sal_Int32 nPos)
deletes
Definition: editdoc.cxx:2121
OUString GetParaAsString(sal_Int32 nNode) const
Definition: editdoc.cxx:2187
OUString GetText(LineEnd eEnd) const
Definition: editdoc.cxx:2163
const ContentNode * GetObject(sal_Int32 nPos) const
Definition: editdoc.cxx:2091
bool RemoveAttribs(ContentNode *pNode, sal_Int32 nStart, sal_Int32 nEnd, sal_uInt16 nWhich)
Definition: editdoc.cxx:2421
bool bDisableAttributeExpanding
Definition: editdoc.hxx:760
sal_Int32 nLastCache
Definition: editdoc.hxx:747
TextRotation mnRotation
Definition: editdoc.hxx:756
sal_Int32 Count() const
Definition: editdoc.cxx:2143
void InsertAttribInSelection(ContentNode *pNode, sal_Int32 nStart, sal_Int32 nEnd, const SfxPoolItem &rPoolItem)
Definition: editdoc.cxx:2375
EditPaM ConnectParagraphs(ContentNode *pLeft, ContentNode *pRight)
Definition: editdoc.cxx:2347
static OUString GetSepStr(LineEnd eEnd)
Definition: editdoc.cxx:2154
void CreateDefFont(bool bUseStyles)
Definition: editdoc.cxx:2053
Link< LinkParamNone *, void > aModifyHdl
Definition: editdoc.hxx:751
void ClearSpellErrors()
Definition: editdoc.cxx:2235
EditPaM InsertText(EditPaM aPaM, std::u16string_view rStr)
Definition: editdoc.cxx:2271
void Release(sal_Int32 nPos)
does not delete
Definition: editdoc.cxx:2131
EditPaM RemoveText()
Definition: editdoc.cxx:2249
EditPaM InsertParaBreak(EditPaM aPaM, bool bKeepEndingAttribs)
Definition: editdoc.cxx:2287
void dumpAsXml(xmlTextWriterPtr pWriter) const
Definition: editdoc.cxx:2712
SvxFont maDefFont
Definition: editdoc.hxx:753
EditPaM InsertFeature(EditPaM aPaM, const SfxPoolItem &rItem)
Definition: editdoc.cxx:2329
bool GetVertical() const
Definition: editdoc.cxx:2081
sal_Int32 GetTextLen() const
Definition: editdoc.cxx:2210
const ContentNode * operator[](sal_Int32 nPos) const
Definition: editdoc.cxx:2101
EditDoc(SfxItemPool *pItemPool)
Definition: editdoc.cxx:1919
EditPaM GetStartPaM() const
Definition: editdoc.cxx:2198
virtual ~EditEngineItemPool() override
Definition: editdoc.cxx:3048
std::shared_ptr< DefItems > m_xDefItems
Definition: editdoc.hxx:851
sal_Int32 FindLine(sal_Int32 nChar, bool bInclEnd)
Definition: editdoc.cxx:1076
LinesType maLines
Definition: editdoc.hxx:571
void Append(EditLine *p)
Definition: editdoc.cxx:1108
sal_Int32 Count() const
Definition: editdoc.cxx:1093
void DeleteFromLine(sal_Int32 nDelFrom)
Definition: editdoc.cxx:1068
void Insert(sal_Int32 nPos, EditLine *p)
Definition: editdoc.cxx:1113
const EditLine & operator[](sal_Int32 nPos) const
Definition: editdoc.cxx:1098
void Reset()
Definition: editdoc.cxx:1063
sal_uInt16 nHeight
Definition: editdoc.hxx:495
void SetValid()
Definition: editdoc.hxx:550
sal_Int32 GetStartPortion() const
Definition: editdoc.hxx:521
sal_Int32 GetEndPortion() const
Definition: editdoc.hxx:525
CharPosArrayType aPositions
Definition: editdoc.hxx:487
void SetStartPosX(sal_Int32 start)
Definition: editdoc.cxx:1011
sal_Int32 nEnd
Definition: editdoc.hxx:492
EditLine & operator=(const EditLine &rLine)
Definition: editdoc.cxx:995
sal_uInt16 nTxtHeight
Definition: editdoc.hxx:496
sal_Int32 nStart
Definition: editdoc.hxx:491
sal_Int32 GetStart() const
Definition: editdoc.hxx:513
~EditLine()
Definition: editdoc.cxx:956
sal_Int32 nEndPortion
Definition: editdoc.hxx:494
sal_Int32 nStartPosX
Definition: editdoc.hxx:490
sal_uInt16 nMaxAscent
Definition: editdoc.hxx:497
EditLine()
Definition: editdoc.cxx:925
Size CalcTextSize(ParaPortion &rParaPortion)
Definition: editdoc.cxx:1019
sal_Int32 nTxtWidth
Definition: editdoc.hxx:489
EditLine * Clone() const
Definition: editdoc.cxx:961
void SetHeight(sal_uInt16 nH, sal_uInt16 nTxtH=0)
Definition: editdoc.cxx:1005
sal_Int32 nStartPortion
Definition: editdoc.hxx:493
sal_Int32 GetEnd() const
Definition: editdoc.hxx:517
sal_Int32 nIndex
Definition: editdoc.hxx:306
void SetIndex(sal_Int32 n)
Definition: editdoc.hxx:317
void SetNode(ContentNode *p)
Definition: editdoc.cxx:1122
ContentNode * pNode
Definition: editdoc.hxx:305
const ContentNode * GetNode() const
Definition: editdoc.hxx:312
sal_Int32 GetIndex() const
Definition: editdoc.hxx:316
bool DbgIsBuggy(EditDoc const &rDoc) const
Definition: editdoc.cxx:1127
EditPaM aEndPaM
Definition: editdoc.hxx:697
EditPaM aStartPaM
Definition: editdoc.hxx:696
EditSelection & operator=(const EditPaM &r)
Definition: editdoc.cxx:1155
bool DbgIsBuggy(EditDoc const &rDoc) const
Definition: editdoc.cxx:1134
void Adjust(const EditDoc &rNodes)
Definition: editdoc.cxx:1162
std::shared_ptr< DefItems > GetDefItems()
Definition: eerdll.cxx:165
void Insert(const SfxPoolItem *pItem)
Definition: editdoc.cxx:1912
DummyItemList aItemPool
Definition: editdoc.hxx:140
sal_Int32 CurrentItem
Definition: editdoc.hxx:141
const SfxPoolItem * Next()
Definition: editdoc.cxx:1902
const SfxPoolItem * First()
Definition: editdoc.cxx:1896
SAL_WARN_UNUSED_RESULT Point LogicToLogic(const Point &rPtSource, const MapMode *pMapModeSource, const MapMode *pMapModeDest) const
sal_Int32 nLastCache
Definition: editdoc.hxx:662
sal_Int32 GetPos(const ParaPortion *p) const
Definition: editdoc.cxx:689
sal_Int32 Count() const
Definition: editdoc.cxx:741
std::vector< std::unique_ptr< ParaPortion > > maPortions
Definition: editdoc.hxx:663
tools::Long GetYOffset(const ParaPortion *pPPortion) const
Definition: editdoc.cxx:757
static void DbgCheck(ParaPortionList const &, EditDoc const &rDoc)
Definition: editdoc.cxx:795
void Insert(sal_Int32 nPos, std::unique_ptr< ParaPortion > p)
Definition: editdoc.cxx:726
void Append(std::unique_ptr< ParaPortion > p)
Definition: editdoc.cxx:736
void Remove(sal_Int32 nPos)
Definition: editdoc.cxx:716
std::unique_ptr< ParaPortion > Release(sal_Int32 nPos)
Definition: editdoc.cxx:704
const ParaPortion * SafeGetObject(sal_Int32 nPos) const
Definition: editdoc.cxx:783
ParaPortion * operator[](sal_Int32 nPos)
Definition: editdoc.cxx:694
sal_Int32 FindParagraph(tools::Long nYOffset) const
Definition: editdoc.cxx:771
WritingDirectionInfos aWritingDirectionInfos
Definition: editdoc.hxx:600
ParaPortion(const ParaPortion &)=delete
TextPortionList & GetTextPortions()
Definition: editdoc.hxx:646
void MarkInvalid(sal_Int32 nStart, sal_Int32 nDiff)
Definition: editdoc.cxx:527
ContentNode * pNode
Definition: editdoc.hxx:596
sal_Int32 nInvalidDiff
Definition: editdoc.hxx:605
tools::Long GetHeight() const
Definition: editdoc.hxx:641
sal_Int32 nInvalidPosStart
Definition: editdoc.hxx:602
bool bInvalid
Definition: editdoc.hxx:607
bool bSimple
Definition: editdoc.hxx:608
ScriptTypePosInfos aScriptInfos
Definition: editdoc.hxx:599
sal_Int32 GetLineNumber(sal_Int32 nIndex) const
Definition: editdoc.cxx:580
ContentNode * GetNode() const
Definition: editdoc.hxx:645
void CorrectValuesBehindLastFormattedLine(sal_Int32 nLastFormattedLine)
Definition: editdoc.cxx:601
void SetVisible(bool bVisible)
Definition: editdoc.cxx:596
bool bVisible
Definition: editdoc.hxx:609
void MarkSelectionInvalid(sal_Int32 nStart)
Definition: editdoc.cxx:563
EditLineList aLineList
Definition: editdoc.hxx:594
void ClearDefaults()
sal_uInt16 GetTrueSlotId(sal_uInt16 nWhich) const
const T & Put(std::unique_ptr< T > xItem, sal_uInt16 nWhich=0)
void SetDefaults(std::vector< SfxPoolItem * > *pDefaults)
sal_uInt16 GetTrueWhich(sal_uInt16 nSlot, bool bDeep=true) const
void Remove(const SfxPoolItem &)
void SetSecondaryPool(SfxItemPool *pPool)
virtual MapUnit GetMetric(sal_uInt16 nWhich) const
SfxItemPool * GetPool() const
void dumpAsXml(xmlTextWriterPtr pWriter) const
sal_uInt16 ClearItem(sal_uInt16 nWhich=0)
SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent=true, const SfxPoolItem **ppItem=nullptr) const
const SfxPoolItem * Put(const SfxPoolItem &rItem, sal_uInt16 nWhich)
const SfxPoolItem & Get(sal_uInt16 nWhich, bool bSrchInParent=true) const
bool Set(const SfxItemSet &, bool bDeep=true)
void InvalidateItem(sal_uInt16 nWhich)
sal_uInt16 Which() const
std::unique_ptr< SfxPoolItem > CloneSetWhich(sal_uInt16 nNewWhich) const
virtual SfxPoolItem * Clone(SfxItemPool *pPool=nullptr) const=0
virtual SfxStyleSheetBase * Find(const OUString &, SfxStyleFamily eFam, SfxStyleSearchBits n=SfxStyleSearchBits::All)
const OUString & GetName() const
SfxStyleFamily GetFamily() const
virtual const OUString & GetFollow() const
virtual SfxItemSet & GetItemSet()
SfxStyleSheetBasePool * GetPool()
constexpr tools::Long Height() const
tools::Long AdjustWidth(tools::Long n)
void setHeight(tools::Long nHeight)
constexpr tools::Long Width() const
SvxColorItem item describes a color.
Definition: colritem.hxx:32
sal_uInt8 & GetProportionalHeight()
This item stores a field (SvxFieldData).
Definition: flditem.hxx:70
sal_uInt32 GetHeight() const
Definition: fhgtitem.hxx:74
void SetHeight(sal_uInt32 nNewHeight, const sal_uInt16 nNewProp=100, MapUnit eUnit=MapUnit::MapRelative)
Definition: textitem.cxx:893
This item describes a Font.
Definition: fontitem.hxx:30
FontFamily GetFamily() const
Definition: fontitem.hxx:81
FontPitch GetPitch() const
Definition: fontitem.hxx:90
rtl_TextEncoding GetCharSet() const
Definition: fontitem.hxx:99
const OUString & GetFamilyName() const
Definition: fontitem.hxx:63
void SetPropr(const sal_uInt8 nNewPropr)
Definition: svxfont.hxx:58
void SetNonAutoEscapement(short nNewEsc, const OutputDevice *pOutDev=nullptr)
Definition: svxfont.cxx:69
void SetCaseMap(const SvxCaseMap eNew)
Definition: svxfont.hxx:63
short GetTextFirstLineOffset() const
Definition: lrspitem.hxx:346
void SetRight(const tools::Long nR, const sal_uInt16 nProp=100)
Definition: frmitems.cxx:487
tools::Long GetRight() const
Definition: lrspitem.hxx:328
void SetTextLeft(const tools::Long nL, const sal_uInt16 nProp=100)
Definition: frmitems.cxx:539
tools::Long GetTextLeft() const
Definition: frmitems.cxx:567
void SetTextFirstLineOffset(const short nF, const sal_uInt16 nProp=100)
Definition: frmitems.cxx:504
LanguageType GetLanguage() const
Definition: langitem.hxx:60
SvxLineSpaceRule GetLineSpaceRule() const
Definition: lspcitem.hxx:89
sal_uInt16 GetLineHeight() const
Definition: lspcitem.hxx:73
void SetLineHeight(const sal_uInt16 nHeight)
Definition: lspcitem.hxx:74
FontItalic GetPosture() const
Definition: postitem.hxx:59
sal_uInt16 Count() const
Definition: tstpitem.hxx:116
void SetDefaultDistance(sal_Int32 nDefaultDistancenDefTabSize)
Definition: paraitem.cxx:824
bool Insert(const SvxTabStop &rTab)
Definition: paraitem.cxx:1045
sal_Int32 GetDefaultDistance() const
Definition: paraitem.cxx:829
sal_Unicode & GetFill()
Definition: tstpitem.hxx:62
sal_Int32 & GetTabPos()
Definition: tstpitem.hxx:53
sal_Unicode & GetDecimal()
Definition: tstpitem.hxx:59
SvxTabAdjust & GetAdjustment()
Definition: tstpitem.hxx:56
void SetLower(const sal_uInt16 nL, const sal_uInt16 nProp=100)
Definition: ulspitem.hxx:86
sal_uInt16 GetUpper() const
Definition: ulspitem.hxx:72
void SetUpper(const sal_uInt16 nU, const sal_uInt16 nProp=100)
Definition: ulspitem.hxx:82
sal_uInt16 GetLower() const
Definition: ulspitem.hxx:73
FontWeight GetWeight() const
Definition: wghtitem.hxx:59
void Append(TextPortion *p)
Definition: editdoc.cxx:407
sal_Int32 GetPos(const TextPortion *p) const
Definition: editdoc.cxx:437
sal_Int32 GetStartPos(sal_Int32 nPortion)
Definition: editdoc.cxx:472
sal_Int32 Count() const
Definition: editdoc.cxx:392
void DeleteFromPortion(sal_Int32 nDelFrom)
Definition: editdoc.cxx:384
const TextPortion & operator[](sal_Int32 nPos) const
Definition: editdoc.cxx:397
PortionsType maPortions
Definition: editdoc.hxx:456
void Remove(sal_Int32 nPos)
Definition: editdoc.cxx:417
sal_Int32 FindPortion(sal_Int32 nCharPos, sal_Int32 &rPortionStart, bool bPreferStartingPortion=false) const
Definition: editdoc.cxx:448
void Insert(sal_Int32 nPos, TextPortion *p)
Definition: editdoc.cxx:412
sal_Int32 GetLen() const
Definition: editdoc.hxx:409
PortionKind GetKind() const
Definition: editdoc.hxx:438
const Size & GetSize() const
Definition: editdoc.hxx:435
Keeps track of misspelled ranges in paragraph.
Definition: edtspell.hxx:55
void SetFontSize(const Size &)
void SetOrientation(Degree10 nLineOrientation)
void SetVertical(bool bVertical)
void SetOutline(bool bOutline)
void SetWordLineMode(bool bWordLine)
void SetPitch(FontPitch ePitch)
void SetTransparent(bool bTransparent)
void SetFillColor(const Color &)
void SetColor(const Color &)
void SetItalic(FontItalic)
void SetWeight(FontWeight)
void SetFamily(FontFamily)
void SetUnderline(FontLineStyle)
void SetCharSet(rtl_TextEncoding)
const Size & GetFontSize() const
void SetKerning(FontKerning nKerning)
void SetAlignment(TextAlign)
void SetFixKerning(const short nSpacing)
void SetOverline(FontLineStyle)
void SetFamilyName(const OUString &rFamilyName)
void SetLanguage(LanguageType)
void SetShadow(bool bShadow)
void SetRelief(FontRelief)
void SetEmphasisMark(FontEmphasisMark)
void SetStrikeout(FontStrikeout)
int nCount
const char * pS
#define DBG_ASSERT(sCon, aError)
OString right
OUString maString
float v
float u
float x
#define CH_FEATURE
Definition: editattr.hxx:55
#define EE_PARA_NOT_FOUND
Definition: editdata.hxx:48
void CheckOrderedList(const CharAttribList::AttribsType &rAttribs)
Definition: editdbg.cxx:519
bool IsScriptItemValid(sal_uInt16 nItemId, short nScriptType)
Definition: editdoc.cxx:103
bool operator!=(const EditPaM &r1, const EditPaM &r2)
Definition: editdoc.cxx:1194
EditCharAttrib * MakeCharAttrib(SfxItemPool &rPool, const SfxPoolItem &rAttr, sal_Int32 nS, sal_Int32 nE)
Definition: editdoc.cxx:219
sal_uInt16 GetScriptItemId(sal_uInt16 nItemId, SvtScriptType nScriptType)
Definition: editdoc.cxx:73
void ConvertItem(std::unique_ptr< SfxPoolItem > &rPoolItem, MapUnit eSourceUnit, MapUnit eDestUnit)
Definition: editdoc.cxx:823
void CreateFont(SvxFont &rFont, const SfxItemSet &rSet, bool bSearchInParent, SvtScriptType nScriptType)
Definition: editdoc.cxx:1975
bool operator==(const EditLine &r1, const EditLine &r2)
Definition: editdoc.cxx:978
const SfxItemInfo aItemInfos[EDITITEMCOUNT]
Definition: editdoc.cxx:159
void ConvertAndPutItems(SfxItemSet &rDest, const SfxItemSet &rSource, const MapUnit *pSourceUnit, const MapUnit *pDestUnit)
Definition: editdoc.cxx:888
AsianCompressionFlags
Definition: editdoc.hxx:339
#define DEFTAB
Definition: editdoc.hxx:44
EditCharAttrib * GetAttrib(CharAttribList::AttribsType &rAttribs, std::size_t nAttr)
Definition: editdoc.hxx:839
TextRotation
Definition: editobj.hxx:55
constexpr TypedWhichId< SvxContourItem > EE_CHAR_OUTLINE(EE_CHAR_START+8)
constexpr TypedWhichId< SvxKerningItem > EE_CHAR_KERNING(EE_CHAR_START+12)
constexpr TypedWhichId< SvxFontItem > EE_CHAR_FONTINFO_CJK(EE_CHAR_START+17)
constexpr TypedWhichId< SvxFieldItem > EE_FEATURE_FIELD(EE_FEATURE_NOTCONV+1)
constexpr TypedWhichId< SfxBoolItem > EE_PARA_BULLETSTATE(EE_PARA_START+9)
constexpr TypedWhichId< SvxTabStopItem > EE_PARA_TABS(EE_PARA_START+17)
constexpr sal_uInt16 EDITITEMCOUNT(EE_ITEMS_END - EE_ITEMS_START+1)
constexpr TypedWhichId< SvxUnderlineItem > EE_CHAR_UNDERLINE(EE_CHAR_START+5)
constexpr TypedWhichId< SvxFontHeightItem > EE_CHAR_FONTHEIGHT(EE_CHAR_START+2)
constexpr TypedWhichId< SvxAutoKernItem > EE_CHAR_PAIRKERNING(EE_CHAR_START+11)
constexpr TypedWhichId< SvxShadowedItem > EE_CHAR_SHADOW(EE_CHAR_START+9)
constexpr TypedWhichId< SvxULSpaceItem > EE_PARA_ULSPACE(EE_PARA_START+14)
constexpr TypedWhichId< SvxOverlineItem > EE_CHAR_OVERLINE(EE_CHAR_START+29)
constexpr sal_uInt16 EE_PARA_START(EE_ITEMS_START+0)
constexpr TypedWhichId< SvxLanguageItem > EE_CHAR_LANGUAGE_CTL(EE_CHAR_START+16)
constexpr sal_uInt16 EE_FEATURE_LINEBR(EE_FEATURE_TAB+1)
constexpr TypedWhichId< SvxWeightItem > EE_CHAR_WEIGHT(EE_CHAR_START+4)
constexpr TypedWhichId< SvxLRSpaceItem > EE_PARA_LRSPACE(EE_PARA_START+13)
constexpr sal_uInt16 EE_ITEMS_END(EE_FEATURE_END)
constexpr TypedWhichId< SvxColorItem > EE_CHAR_COLOR(EE_CHAR_START+0)
constexpr TypedWhichId< SvxWeightItem > EE_CHAR_WEIGHT_CTL(EE_CHAR_START+22)
constexpr TypedWhichId< SvxCrossedOutItem > EE_CHAR_STRIKEOUT(EE_CHAR_START+6)
constexpr TypedWhichId< SvxPostureItem > EE_CHAR_ITALIC(EE_CHAR_START+7)
constexpr TypedWhichId< SfxGrabBagItem > EE_CHAR_GRABBAG(EE_CHAR_START+31)
constexpr TypedWhichId< SvxLineSpacingItem > EE_PARA_SBL(EE_PARA_START+15)
constexpr TypedWhichId< SvxEmphasisMarkItem > EE_CHAR_EMPHASISMARK(EE_CHAR_START+25)
constexpr TypedWhichId< SvxEscapementItem > EE_CHAR_ESCAPEMENT(EE_CHAR_START+10)
constexpr sal_uInt16 EE_FEATURE_START(EE_CHAR_END+1)
constexpr sal_uInt16 EE_CHAR_END(EE_CHAR_START+32)
constexpr TypedWhichId< SvxFontHeightItem > EE_CHAR_FONTHEIGHT_CTL(EE_CHAR_START+20)
constexpr TypedWhichId< SvxWeightItem > EE_CHAR_WEIGHT_CJK(EE_CHAR_START+21)
constexpr TypedWhichId< SvxLanguageItem > EE_CHAR_LANGUAGE_CJK(EE_CHAR_START+15)
constexpr sal_uInt16 EE_FEATURE_TAB(EE_FEATURE_START+0)
constexpr TypedWhichId< SvxPostureItem > EE_CHAR_ITALIC_CJK(EE_CHAR_START+23)
constexpr TypedWhichId< SvxCaseMapItem > EE_CHAR_CASEMAP(EE_CHAR_START+30)
constexpr TypedWhichId< SvxFontItem > EE_CHAR_FONTINFO_CTL(EE_CHAR_START+18)
constexpr TypedWhichId< SvxColorItem > EE_CHAR_BKGCOLOR(EE_CHAR_START+32)
constexpr TypedWhichId< SvxPostureItem > EE_CHAR_ITALIC_CTL(EE_CHAR_START+24)
constexpr TypedWhichId< SvxCharScaleWidthItem > EE_CHAR_FONTWIDTH(EE_CHAR_START+3)
constexpr TypedWhichId< SvxLanguageItem > EE_CHAR_LANGUAGE(EE_CHAR_START+14)
constexpr TypedWhichId< SvXMLAttrContainerItem > EE_CHAR_XMLATTRIBS(EE_CHAR_START+28)
constexpr sal_uInt16 EE_ITEMS_START(OWN_ATTR_VALUE_END+1)
constexpr TypedWhichId< SvxWordLineModeItem > EE_CHAR_WLM(EE_CHAR_START+13)
constexpr TypedWhichId< SvxCharReliefItem > EE_CHAR_RELIEF(EE_CHAR_START+26)
constexpr TypedWhichId< SvxFontHeightItem > EE_CHAR_FONTHEIGHT_CJK(EE_CHAR_START+19)
constexpr TypedWhichId< SvxFontItem > EE_CHAR_FONTINFO(EE_CHAR_START+1)
struct _xmlTextWriter * xmlTextWriterPtr
ALIGN_BASELINE
sal_Int32 nIndex
void * p
sal_Int64 n
SvtScriptType
LineEnd
LINEEND_LF
LINEEND_CR
sal_uInt16 nPos
sal_Int32 nFirstLineOffset
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
MapUnit
aStr
NONE
int i
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
long Long
sal_Int16 nId
static SfxItemSet & rSet
void SaveOrgDXArray(const sal_Int32 *pDXArray, sal_Int32 nLen)
Definition: editdoc.cxx:498
std::unique_ptr< sal_Int32[]> pOrgDXArray
Definition: editdoc.hxx:366
bool bVisible
unsigned char sal_uInt8
#define SAL_MAX_INT32
sal_uInt16 sal_Unicode
sal_uInt64 left
std::unique_ptr< char[]> aBuffer