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 <comphelper/fileformat.h>
21 #include <tools/stream.hxx>
22 #include <sfx2/docfile.hxx>
23 #include <svl/zforlist.hxx>
24 #include <svl/zformat.hxx>
25 #include <unotools/configmgr.hxx>
26 #include <unotools/pathoptions.hxx>
27 #include <swtable.hxx>
28 #include <swtblfmt.hxx>
29 #include <com/sun/star/text/VertOrientation.hpp>
30 #include <swtypes.hxx>
31 #include <doc.hxx>
32 #include <poolfmt.hxx>
33 #include <tblafmt.hxx>
34 #include <cellatr.hxx>
35 #include <SwStyleNameMapper.hxx>
36 #include <hintids.hxx>
37 #include <fmtornt.hxx>
38 #include <editsh.hxx>
39 #include <fmtlsplt.hxx>
40 #include <fmtrowsplt.hxx>
41 #include <sal/log.hxx>
42 #include <osl/diagnose.h>
43 #include <osl/thread.h>
44 
45 #include <editeng/adjustitem.hxx>
46 #include <editeng/boxitem.hxx>
47 #include <editeng/brushitem.hxx>
48 #include <editeng/colritem.hxx>
49 #include <editeng/contouritem.hxx>
50 #include <editeng/crossedoutitem.hxx>
51 #include <editeng/fontitem.hxx>
52 #include <editeng/fhgtitem.hxx>
53 #include <editeng/justifyitem.hxx>
54 #include <editeng/legacyitem.hxx>
55 #include <editeng/lineitem.hxx>
56 #include <editeng/postitem.hxx>
57 #include <editeng/shdditem.hxx>
58 #include <editeng/udlnitem.hxx>
59 #include <editeng/wghtitem.hxx>
60 #include <svx/algitem.hxx>
61 #include <svx/rotmodit.hxx>
62 #include <legacyitem.hxx>
63 
64 #include <memory>
65 #include <vector>
66 
67 /*
68  * XXX: BIG RED NOTICE! Changes MUST be binary file format compatible and MUST
69  * be synchronized with Calc's ScAutoFormat sc/source/core/tool/autoform.cxx
70  */
71 
72 using ::editeng::SvxBorderLine;
73 
74 // until SO5PF
75 const sal_uInt16 AUTOFORMAT_ID_X        = 9501;
76 const sal_uInt16 AUTOFORMAT_ID_358      = 9601;
77 const sal_uInt16 AUTOFORMAT_DATA_ID_X   = 9502;
78 
79 // from SO5
80 //! In follow-up versions these IDs' values need to increase
81 const sal_uInt16 AUTOFORMAT_ID_504      = 9801;
82 const sal_uInt16 AUTOFORMAT_DATA_ID_504 = 9802;
83 
84 const sal_uInt16 AUTOFORMAT_DATA_ID_552 = 9902;
85 
86 // --- from 680/dr25 on: store strings as UTF-8
87 const sal_uInt16 AUTOFORMAT_ID_680DR25      = 10021;
88 
89 // --- Bug fix to fdo#31005: Table Autoformats does not save/apply all properties (Writer and Calc)
90 const sal_uInt16 AUTOFORMAT_ID_31005      = 10041;
91 const sal_uInt16 AUTOFORMAT_DATA_ID_31005 = 10042;
92 
93 // current version
94 const sal_uInt16 AUTOFORMAT_ID          = AUTOFORMAT_ID_31005;
95 const sal_uInt16 AUTOFORMAT_DATA_ID     = AUTOFORMAT_DATA_ID_31005;
96 const sal_uInt16 AUTOFORMAT_FILE_VERSION= SOFFICE_FILEFORMAT_50;
97 
98 SwBoxAutoFormat* SwTableAutoFormat::pDfltBoxAutoFormat = nullptr;
99 
100 #define AUTOTABLE_FORMAT_NAME "autotbl.fmt"
101 
102 namespace
103 {
104     /// Begins a writer-specific data block. Call before serializing any writer-specific properties.
BeginSwBlock(SvStream & rStream)105     sal_uInt64 BeginSwBlock(SvStream& rStream)
106     {
107         // We need to write down the offset of the end of the writer-specific data, so that
108         // calc can skip it. We'll only have that value after writing the data, so we
109         // write a placeholder value first, write the data, then jump back and write the
110         // real offset.
111 
112         // Note that we explicitly use sal_uInt64 instead of sal_Size (which can be 32
113         // or 64 depending on platform) to ensure 64-bit portability on this front. I don't
114         // actually know if autotbl.fmt as a whole is portable, since that requires all serialization
115         // logic to be written with portability in mind.
116         sal_uInt64 whereToWriteEndOfSwBlock = rStream.Tell();
117 
118         rStream.WriteUInt64( 0 ); // endOfSwBlock
119 
120         return whereToWriteEndOfSwBlock;
121     }
122 
123     /// Ends a writer-specific data block. Call after serializing writer-specific properties.
124     /// Closes a corresponding BeginSwBlock call.
EndSwBlock(SvStream & rStream,sal_uInt64 whereToWriteEndOfSwBlock)125     void EndSwBlock(SvStream& rStream, sal_uInt64 whereToWriteEndOfSwBlock)
126     {
127         sal_uInt64 endOfSwBlock = rStream.Tell();
128         rStream.Seek(whereToWriteEndOfSwBlock);
129         rStream.WriteUInt64( endOfSwBlock );
130         rStream.Seek(endOfSwBlock);
131     }
132 
133     /**
134     Helper class for writer-specific blocks. Begins a writer-specific block on construction,
135     and closes it on destruction.
136 
137     See also: BeginSwBlock and EndSwBlock.
138     */
139     class WriterSpecificAutoFormatBlock
140     {
141     public:
WriterSpecificAutoFormatBlock(SvStream & rStream)142         explicit WriterSpecificAutoFormatBlock(SvStream &rStream) : _rStream(rStream)
143         {
144             _whereToWriteEndOfBlock = BeginSwBlock(rStream);
145         }
146 
~WriterSpecificAutoFormatBlock()147         ~WriterSpecificAutoFormatBlock()
148         {
149             EndSwBlock(_rStream, _whereToWriteEndOfBlock);
150         }
151 
152     private:
153         WriterSpecificAutoFormatBlock(WriterSpecificAutoFormatBlock const&) = delete;
154         WriterSpecificAutoFormatBlock& operator=(WriterSpecificAutoFormatBlock const&) = delete;
155 
156         SvStream &_rStream;
157         sal_uInt64 _whereToWriteEndOfBlock;
158     };
159 
160     /// Checks whether a writer-specific block exists (i.e. size is not zero)
WriterSpecificBlockExists(SvStream & stream)161     sal_Int64 WriterSpecificBlockExists(SvStream &stream)
162     {
163         sal_uInt64 endOfSwBlock = 0;
164         stream.ReadUInt64( endOfSwBlock );
165 
166         // end-of-block pointing to itself indicates a zero-size block.
167         return endOfSwBlock - stream.Tell();
168     }
169 }
170 
171 // Struct with version numbers of the Items
172 
173 struct SwAfVersions : public AutoFormatVersions
174 {
175 public:
176     sal_uInt16 m_nTextOrientationVersion;
177     sal_uInt16 m_nVerticalAlignmentVersion;
178 
179     SwAfVersions();
180     void Load( SvStream& rStream, sal_uInt16 nVer );
181     static void Write(SvStream& rStream, sal_uInt16 fileVersion);
182 };
183 
SwAfVersions()184 SwAfVersions::SwAfVersions()
185 :   AutoFormatVersions(),
186     m_nTextOrientationVersion(0),
187     m_nVerticalAlignmentVersion(0)
188 {
189 }
190 
Load(SvStream & rStream,sal_uInt16 nVer)191 void SwAfVersions::Load( SvStream& rStream, sal_uInt16 nVer )
192 {
193     LoadBlockA(rStream, nVer);
194     if (nVer >= AUTOFORMAT_ID_31005 && WriterSpecificBlockExists(rStream))
195     {
196         rStream.ReadUInt16( m_nTextOrientationVersion );
197         rStream.ReadUInt16( m_nVerticalAlignmentVersion );
198     }
199     LoadBlockB(rStream, nVer);
200 }
201 
Write(SvStream & rStream,sal_uInt16 fileVersion)202 void SwAfVersions::Write(SvStream& rStream, sal_uInt16 fileVersion)
203 {
204     AutoFormatVersions::WriteBlockA(rStream, fileVersion);
205 
206     if (fileVersion >= SOFFICE_FILEFORMAT_50)
207     {
208         WriterSpecificAutoFormatBlock block(rStream);
209 
210         rStream.WriteUInt16(legacy::SvxFrameDirection::GetVersion(fileVersion));
211         rStream.WriteUInt16(legacy::SwFormatVert::GetVersion(fileVersion));
212     }
213 
214     AutoFormatVersions::WriteBlockB(rStream, fileVersion);
215 }
216 
217 
218 
SwBoxAutoFormat()219 SwBoxAutoFormat::SwBoxAutoFormat()
220 :   AutoFormatBase(),
221     m_aTextOrientation(std::make_unique<SvxFrameDirectionItem>(SvxFrameDirection::Environment, RES_FRAMEDIR)),
222     m_aVerticalAlignment(std::make_unique<SwFormatVertOrient>(0, css::text::VertOrientation::NONE, css::text::RelOrientation::FRAME)),
223     m_sNumFormatString(),
224     m_eSysLanguage(::GetAppLanguage()),
225     m_eNumFormatLanguage(::GetAppLanguage()),
226     m_wXObject()
227 {
228     // need to set default instances for base class AutoFormatBase here
229     // due to resource defines (e.g. RES_CHRATR_FONT) which are not available
230     // in svx and different in the different usages of derivations
231     m_aFont = std::make_unique<SvxFontItem>(*GetDfltAttr( RES_CHRATR_FONT ) );
232     m_aHeight = std::make_unique<SvxFontHeightItem>(240, 100, RES_CHRATR_FONTSIZE );
233     m_aWeight = std::make_unique<SvxWeightItem>(WEIGHT_NORMAL, RES_CHRATR_WEIGHT );
234     m_aPosture = std::make_unique<SvxPostureItem>(ITALIC_NONE, RES_CHRATR_POSTURE );
235     m_aCJKFont = std::make_unique<SvxFontItem>(*GetDfltAttr( RES_CHRATR_CJK_FONT ) );
236     m_aCJKHeight = std::make_unique<SvxFontHeightItem>(240, 100, RES_CHRATR_CJK_FONTSIZE );
237     m_aCJKWeight = std::make_unique<SvxWeightItem>(WEIGHT_NORMAL, RES_CHRATR_CJK_WEIGHT );
238     m_aCJKPosture = std::make_unique<SvxPostureItem>(ITALIC_NONE, RES_CHRATR_CJK_POSTURE );
239     m_aCTLFont = std::make_unique<SvxFontItem>(*GetDfltAttr( RES_CHRATR_CTL_FONT ) );
240     m_aCTLHeight = std::make_unique<SvxFontHeightItem>(240, 100, RES_CHRATR_CTL_FONTSIZE );
241     m_aCTLWeight = std::make_unique<SvxWeightItem>(WEIGHT_NORMAL, RES_CHRATR_CTL_WEIGHT );
242     m_aCTLPosture = std::make_unique<SvxPostureItem>(ITALIC_NONE, RES_CHRATR_CTL_POSTURE );
243     m_aUnderline = std::make_unique<SvxUnderlineItem>(LINESTYLE_NONE, RES_CHRATR_UNDERLINE );
244     m_aOverline = std::make_unique<SvxOverlineItem>(LINESTYLE_NONE, RES_CHRATR_OVERLINE );
245     m_aCrossedOut = std::make_unique<SvxCrossedOutItem>(STRIKEOUT_NONE, RES_CHRATR_CROSSEDOUT );
246     m_aContour = std::make_unique<SvxContourItem>(false, RES_CHRATR_CONTOUR );
247     m_aShadowed = std::make_unique<SvxShadowedItem>(false, RES_CHRATR_SHADOWED );
248     m_aColor = std::make_unique<SvxColorItem>(RES_CHRATR_COLOR );
249     m_aBox = std::make_unique<SvxBoxItem>(RES_BOX );
250     m_aTLBR = std::make_unique<SvxLineItem>(0 );
251     m_aBLTR = std::make_unique<SvxLineItem>(0 );
252     m_aBackground = std::make_unique<SvxBrushItem>(RES_BACKGROUND );
253     m_aAdjust = std::make_unique<SvxAdjustItem>(SvxAdjust::Left, RES_PARATR_ADJUST );
254     m_aHorJustify = std::make_unique<SvxHorJustifyItem>(SvxCellHorJustify::Standard, 0);
255     m_aVerJustify = std::make_unique<SvxVerJustifyItem>(SvxCellVerJustify::Standard, 0);
256     m_aStacked = std::make_unique<SfxBoolItem>(0 );
257     m_aMargin = std::make_unique<SvxMarginItem>(0 );
258     m_aLinebreak = std::make_unique<SfxBoolItem>(0 );
259     m_aRotateAngle = std::make_unique<SfxInt32Item>(0 );
260     m_aRotateMode = std::make_unique<SvxRotateModeItem>(SVX_ROTATE_MODE_STANDARD, 0 );
261 
262 // FIXME - add attribute IDs for the diagonal line items
263 //    aTLBR( RES_... ),
264 //    aBLTR( RES_... ),
265     m_aBox->SetAllDistances(55);
266 }
267 
SwBoxAutoFormat(const SwBoxAutoFormat & rNew)268 SwBoxAutoFormat::SwBoxAutoFormat( const SwBoxAutoFormat& rNew )
269 :   AutoFormatBase(rNew),
270     m_aTextOrientation(static_cast<SvxFrameDirectionItem*>(rNew.m_aTextOrientation->Clone())),
271     m_aVerticalAlignment(static_cast<SwFormatVertOrient*>(rNew.m_aVerticalAlignment->Clone())),
272     m_sNumFormatString( rNew.m_sNumFormatString ),
273     m_eSysLanguage( rNew.m_eSysLanguage ),
274     m_eNumFormatLanguage( rNew.m_eNumFormatLanguage ),
275     m_wXObject()
276 {
277 }
278 
~SwBoxAutoFormat()279 SwBoxAutoFormat::~SwBoxAutoFormat()
280 {
281 }
282 
operator =(const SwBoxAutoFormat & rRef)283 SwBoxAutoFormat& SwBoxAutoFormat::operator=(const SwBoxAutoFormat& rRef)
284 {
285     // check self-assignment
286     if(this == &rRef)
287     {
288         return *this;
289     }
290 
291     // call baseclass implementation
292     AutoFormatBase::operator=(rRef);
293 
294     // copy local members - this will use ::Clone() on all involved Items
295     SetTextOrientation(rRef.GetTextOrientation());
296     SetVerticalAlignment(rRef.GetVerticalAlignment());
297     SetNumFormatString(rRef.GetNumFormatString());
298     SetSysLanguage(rRef.GetSysLanguage());
299     SetNumFormatLanguage(rRef.GetNumFormatLanguage());
300 
301     // m_wXObject used to not be copied before 1e2682235cded9a7cd90e55f0bfc60a1285e9a46
302     // "WIP: Further preparations for deeper Item changes" by this operator, so do not do it now, too
303     // rRef.SetXObject(GetXObject());
304 
305     return *this;
306 }
307 
operator ==(const SwBoxAutoFormat & rRight)308 bool SwBoxAutoFormat::operator==(const SwBoxAutoFormat& rRight)
309 {
310     return GetBackground().GetColor() == rRight.GetBackground().GetColor();
311 }
312 
Load(SvStream & rStream,const SwAfVersions & rVersions,sal_uInt16 nVer)313 bool SwBoxAutoFormat::Load( SvStream& rStream, const SwAfVersions& rVersions, sal_uInt16 nVer )
314 {
315     LoadBlockA( rStream, rVersions, nVer );
316 
317     if (nVer >= AUTOFORMAT_DATA_ID_31005)
318     {
319         sal_Int64 const nSize(WriterSpecificBlockExists(rStream));
320         if (0 < nSize && nSize < std::numeric_limits<sal_uInt16>::max())
321         {
322             legacy::SvxFrameDirection::Create(*m_aTextOrientation, rStream, rVersions.m_nTextOrientationVersion);
323             // HORRIBLE HACK to read both 32-bit and 64-bit "long": abuse nSize
324             legacy::SwFormatVert::Create(*m_aVerticalAlignment, rStream, /*rVersions.m_nVerticalAlignmentVersion*/ nSize);
325         }
326     }
327 
328     LoadBlockB( rStream, rVersions, nVer );
329 
330     if( 0 == rVersions.nNumFormatVersion )
331     {
332         sal_uInt16 eSys, eLge;
333         // --- from 680/dr25 on: store strings as UTF-8
334         rtl_TextEncoding eCharSet = (nVer >= AUTOFORMAT_ID_680DR25) ? RTL_TEXTENCODING_UTF8 : rStream.GetStreamCharSet();
335         m_sNumFormatString = rStream.ReadUniOrByteString( eCharSet );
336         rStream.ReadUInt16( eSys ).ReadUInt16( eLge );
337         m_eSysLanguage = LanguageType(eSys);
338         m_eNumFormatLanguage = LanguageType(eLge);
339         if ( m_eSysLanguage == LANGUAGE_SYSTEM )      // from old versions (Calc)
340             m_eSysLanguage = ::GetAppLanguage();
341     }
342 
343     return ERRCODE_NONE == rStream.GetError();
344 }
345 
Save(SvStream & rStream,sal_uInt16 fileVersion) const346 bool SwBoxAutoFormat::Save( SvStream& rStream, sal_uInt16 fileVersion ) const
347 {
348     SaveBlockA( rStream, fileVersion );
349 
350     if (fileVersion >= SOFFICE_FILEFORMAT_50)
351     {
352         WriterSpecificAutoFormatBlock block(rStream);
353 
354         legacy::SvxFrameDirection::Store(*m_aTextOrientation, rStream, legacy::SvxFrameDirection::GetVersion(fileVersion));
355         legacy::SwFormatVert::Store(*m_aVerticalAlignment, rStream, legacy::SwFormatVert::GetVersion(fileVersion));
356     }
357 
358     SaveBlockB( rStream, fileVersion );
359 
360     // --- from 680/dr25 on: store strings as UTF-8
361     write_uInt16_lenPrefixed_uInt8s_FromOUString(rStream, m_sNumFormatString,
362         RTL_TEXTENCODING_UTF8);
363     rStream.WriteUInt16( static_cast<sal_uInt16>(m_eSysLanguage) ).WriteUInt16( static_cast<sal_uInt16>(m_eNumFormatLanguage) );
364 
365     return ERRCODE_NONE == rStream.GetError();
366 }
367 
SwTableAutoFormat(const OUString & rName)368 SwTableAutoFormat::SwTableAutoFormat( const OUString& rName )
369     : m_aName( rName )
370     , m_nStrResId( USHRT_MAX )
371     , m_aBreak(std::make_shared<SvxFormatBreakItem>(SvxBreak::NONE, RES_BREAK))
372     , m_aKeepWithNextPara(std::make_shared<SvxFormatKeepItem>(false, RES_KEEP))
373     , m_aRepeatHeading( 0 )
374     , m_bLayoutSplit( true )
375     , m_bRowSplit( true )
376     , m_bCollapsingBorders(true)
377     , m_aShadow(std::make_shared<SvxShadowItem>(RES_SHADOW))
378     , m_bHidden( false )
379     , m_bUserDefined( true )
380 {
381     m_bInclFont = true;
382     m_bInclJustify = true;
383     m_bInclFrame = true;
384     m_bInclBackground = true;
385     m_bInclValueFormat = true;
386     m_bInclWidthHeight = true;
387 }
388 
SwTableAutoFormat(const SwTableAutoFormat & rNew)389 SwTableAutoFormat::SwTableAutoFormat( const SwTableAutoFormat& rNew )
390     : m_aBreak()
391     , m_aKeepWithNextPara()
392     , m_aShadow(std::make_shared<SvxShadowItem>(RES_SHADOW))
393 {
394     for(SwBoxAutoFormat* & rp : m_aBoxAutoFormat)
395         rp = nullptr;
396     *this = rNew;
397 }
398 
operator =(const SwTableAutoFormat & rNew)399 SwTableAutoFormat& SwTableAutoFormat::operator=( const SwTableAutoFormat& rNew )
400 {
401     if (&rNew == this)
402         return *this;
403 
404     for( sal_uInt8 n = 0; n < 16; ++n )
405     {
406         if( m_aBoxAutoFormat[ n ] )
407             delete m_aBoxAutoFormat[ n ];
408 
409         SwBoxAutoFormat* pFormat = rNew.m_aBoxAutoFormat[ n ];
410         if( pFormat )      // if is set -> copy
411             m_aBoxAutoFormat[ n ] = new SwBoxAutoFormat( *pFormat );
412         else            // else default
413             m_aBoxAutoFormat[ n ] = nullptr;
414     }
415 
416     m_aName = rNew.m_aName;
417     m_nStrResId = rNew.m_nStrResId;
418     m_bInclFont = rNew.m_bInclFont;
419     m_bInclJustify = rNew.m_bInclJustify;
420     m_bInclFrame = rNew.m_bInclFrame;
421     m_bInclBackground = rNew.m_bInclBackground;
422     m_bInclValueFormat = rNew.m_bInclValueFormat;
423     m_bInclWidthHeight = rNew.m_bInclWidthHeight;
424 
425     m_aBreak.reset(static_cast<SvxFormatBreakItem*>(rNew.m_aBreak->Clone()));
426     m_aPageDesc = rNew.m_aPageDesc;
427     m_aKeepWithNextPara.reset(static_cast<SvxFormatKeepItem*>(rNew.m_aKeepWithNextPara->Clone()));
428     m_aRepeatHeading = rNew.m_aRepeatHeading;
429     m_bLayoutSplit = rNew.m_bLayoutSplit;
430     m_bRowSplit = rNew.m_bRowSplit;
431     m_bCollapsingBorders = rNew.m_bCollapsingBorders;
432     m_aShadow.reset(static_cast<SvxShadowItem*>(rNew.m_aShadow->Clone()));
433     m_bHidden = rNew.m_bHidden;
434     m_bUserDefined = rNew.m_bUserDefined;
435 
436     return *this;
437 }
438 
~SwTableAutoFormat()439 SwTableAutoFormat::~SwTableAutoFormat()
440 {
441     SwBoxAutoFormat** ppFormat = m_aBoxAutoFormat;
442     for( sal_uInt8 n = 0; n < 16; ++n, ++ppFormat )
443         if( *ppFormat )
444             delete *ppFormat;
445 }
446 
SetBoxFormat(const SwBoxAutoFormat & rNew,sal_uInt8 nPos)447 void SwTableAutoFormat::SetBoxFormat( const SwBoxAutoFormat& rNew, sal_uInt8 nPos )
448 {
449     OSL_ENSURE( nPos < 16, "wrong area" );
450 
451     SwBoxAutoFormat* pFormat = m_aBoxAutoFormat[ nPos ];
452     if( pFormat )      // if is set -> copy
453         *m_aBoxAutoFormat[ nPos ] = rNew;
454     else            // else set anew
455         m_aBoxAutoFormat[ nPos ] = new SwBoxAutoFormat( rNew );
456 }
457 
GetBoxFormat(sal_uInt8 nPos) const458 const SwBoxAutoFormat& SwTableAutoFormat::GetBoxFormat( sal_uInt8 nPos ) const
459 {
460     OSL_ENSURE( nPos < 16, "wrong area" );
461 
462     SwBoxAutoFormat* pFormat = m_aBoxAutoFormat[ nPos ];
463     if( pFormat )      // if is set -> copy
464         return *pFormat;
465     else            // else return the default
466     {
467         // If it doesn't exist yet:
468         if( !pDfltBoxAutoFormat )
469             pDfltBoxAutoFormat = new SwBoxAutoFormat;
470         return *pDfltBoxAutoFormat;
471     }
472 }
473 
GetBoxFormat(sal_uInt8 nPos)474 SwBoxAutoFormat& SwTableAutoFormat::GetBoxFormat( sal_uInt8 nPos )
475 {
476     SAL_WARN_IF(!(nPos < 16), "sw.core", "GetBoxFormat wrong area");
477 
478     SwBoxAutoFormat** pFormat = &m_aBoxAutoFormat[ nPos ];
479     if( !*pFormat )
480     {
481         // If default doesn't exist yet:
482         if( !pDfltBoxAutoFormat )
483             pDfltBoxAutoFormat = new SwBoxAutoFormat();
484         *pFormat = new SwBoxAutoFormat(*pDfltBoxAutoFormat);
485     }
486     return **pFormat;
487 }
488 
GetDefaultBoxFormat()489 const SwBoxAutoFormat& SwTableAutoFormat::GetDefaultBoxFormat()
490 {
491     if(!pDfltBoxAutoFormat)
492         pDfltBoxAutoFormat = new SwBoxAutoFormat();
493 
494     return *pDfltBoxAutoFormat;
495 }
496 
UpdateFromSet(sal_uInt8 nPos,const SfxItemSet & rSet,SwTableAutoFormatUpdateFlags eFlags,SvNumberFormatter const * pNFormatr)497 void SwTableAutoFormat::UpdateFromSet( sal_uInt8 nPos,
498                                     const SfxItemSet& rSet,
499                                     SwTableAutoFormatUpdateFlags eFlags,
500                                     SvNumberFormatter const * pNFormatr)
501 {
502     OSL_ENSURE( nPos < 16, "wrong area" );
503 
504     SwBoxAutoFormat* pFormat = m_aBoxAutoFormat[ nPos ];
505     if( !pFormat )     // if is set -> copy
506     {
507         pFormat = new SwBoxAutoFormat;
508         m_aBoxAutoFormat[ nPos ] = pFormat;
509     }
510 
511     if( SwTableAutoFormatUpdateFlags::Char & eFlags )
512     {
513         pFormat->SetFont( rSet.Get( RES_CHRATR_FONT ) );
514         pFormat->SetHeight( rSet.Get( RES_CHRATR_FONTSIZE ) );
515         pFormat->SetWeight( rSet.Get( RES_CHRATR_WEIGHT ) );
516         pFormat->SetPosture( rSet.Get( RES_CHRATR_POSTURE ) );
517         pFormat->SetCJKFont( rSet.Get( RES_CHRATR_CJK_FONT ) );
518         pFormat->SetCJKHeight( rSet.Get( RES_CHRATR_CJK_FONTSIZE ) );
519         pFormat->SetCJKWeight( rSet.Get( RES_CHRATR_CJK_WEIGHT ) );
520         pFormat->SetCJKPosture( rSet.Get( RES_CHRATR_CJK_POSTURE ) );
521         pFormat->SetCTLFont( rSet.Get( RES_CHRATR_CTL_FONT ) );
522         pFormat->SetCTLHeight( rSet.Get( RES_CHRATR_CTL_FONTSIZE ) );
523         pFormat->SetCTLWeight( rSet.Get( RES_CHRATR_CTL_WEIGHT ) );
524         pFormat->SetCTLPosture( rSet.Get( RES_CHRATR_CTL_POSTURE ) );
525         pFormat->SetUnderline( rSet.Get( RES_CHRATR_UNDERLINE ) );
526         pFormat->SetOverline( rSet.Get( RES_CHRATR_OVERLINE ) );
527         pFormat->SetCrossedOut( rSet.Get( RES_CHRATR_CROSSEDOUT ) );
528         pFormat->SetContour( rSet.Get( RES_CHRATR_CONTOUR ) );
529         pFormat->SetShadowed( rSet.Get( RES_CHRATR_SHADOWED ) );
530         pFormat->SetColor( rSet.Get( RES_CHRATR_COLOR ) );
531         pFormat->SetAdjust( rSet.Get( RES_PARATR_ADJUST ) );
532     }
533     if( SwTableAutoFormatUpdateFlags::Box & eFlags )
534     {
535         pFormat->SetBox( rSet.Get( RES_BOX ) );
536 // FIXME - add attribute IDs for the diagonal line items
537 //        pFormat->SetTLBR( (SvxLineItem&)rSet.Get( RES_... ) );
538 //        pFormat->SetBLTR( (SvxLineItem&)rSet.Get( RES_... ) );
539         pFormat->SetBackground( rSet.Get( RES_BACKGROUND ) );
540         pFormat->SetTextOrientation(rSet.Get(RES_FRAMEDIR));
541         pFormat->SetVerticalAlignment(rSet.Get(RES_VERT_ORIENT));
542 
543         const SwTableBoxNumFormat* pNumFormatItem;
544         const SvNumberformat* pNumFormat = nullptr;
545         if( SfxItemState::SET == rSet.GetItemState( RES_BOXATR_FORMAT, true,
546             reinterpret_cast<const SfxPoolItem**>(&pNumFormatItem) ) && pNFormatr &&
547             nullptr != (pNumFormat = pNFormatr->GetEntry( pNumFormatItem->GetValue() )) )
548             pFormat->SetValueFormat( pNumFormat->GetFormatstring(),
549                                     pNumFormat->GetLanguage(),
550                                     ::GetAppLanguage());
551         else
552         {
553             // default
554             pFormat->SetValueFormat( OUString(), LANGUAGE_SYSTEM,
555                                   ::GetAppLanguage() );
556         }
557     }
558 
559     // we cannot handle the rest, that's specific to StarCalc
560 }
561 
UpdateToSet(const sal_uInt8 nPos,const bool bSingleRowTable,const bool bSingleColTable,SfxItemSet & rSet,SwTableAutoFormatUpdateFlags eFlags,SvNumberFormatter * pNFormatr) const562 void SwTableAutoFormat::UpdateToSet(const sal_uInt8 nPos, const bool bSingleRowTable, const bool bSingleColTable, SfxItemSet& rSet,
563                                  SwTableAutoFormatUpdateFlags eFlags, SvNumberFormatter* pNFormatr) const
564 {
565     const SwBoxAutoFormat& rChg = GetBoxFormat( nPos );
566 
567     if( SwTableAutoFormatUpdateFlags::Char & eFlags )
568     {
569         if( IsFont() )
570         {
571             rSet.Put( rChg.GetFont() );
572             rSet.Put( rChg.GetHeight() );
573             rSet.Put( rChg.GetWeight() );
574             rSet.Put( rChg.GetPosture() );
575             // do not insert empty CJK font
576             const SvxFontItem& rCJKFont = rChg.GetCJKFont();
577             if (!rCJKFont.GetStyleName().isEmpty())
578             {
579                 rSet.Put( rChg.GetCJKFont() );
580                 rSet.Put( rChg.GetCJKHeight() );
581                 rSet.Put( rChg.GetCJKWeight() );
582                 rSet.Put( rChg.GetCJKPosture() );
583             }
584             else
585             {
586                 rSet.Put( rChg.GetHeight().CloneSetWhich(RES_CHRATR_CJK_FONTSIZE) );
587                 rSet.Put( rChg.GetWeight().CloneSetWhich(RES_CHRATR_CJK_WEIGHT) );
588                 rSet.Put( rChg.GetPosture().CloneSetWhich(RES_CHRATR_CJK_POSTURE) );
589             }
590             // do not insert empty CTL font
591             const SvxFontItem& rCTLFont = rChg.GetCTLFont();
592             if (!rCTLFont.GetStyleName().isEmpty())
593             {
594                 rSet.Put( rChg.GetCTLFont() );
595                 rSet.Put( rChg.GetCTLHeight() );
596                 rSet.Put( rChg.GetCTLWeight() );
597                 rSet.Put( rChg.GetCTLPosture() );
598             }
599             else
600             {
601                 rSet.Put( rChg.GetHeight().CloneSetWhich(RES_CHRATR_CTL_FONTSIZE) );
602                 rSet.Put( rChg.GetWeight().CloneSetWhich(RES_CHRATR_CTL_WEIGHT) );
603                 rSet.Put( rChg.GetPosture().CloneSetWhich(RES_CHRATR_CTL_POSTURE) );
604             }
605             rSet.Put( rChg.GetUnderline() );
606             rSet.Put( rChg.GetOverline() );
607             rSet.Put( rChg.GetCrossedOut() );
608             rSet.Put( rChg.GetContour() );
609             rSet.Put( rChg.GetShadowed() );
610             rSet.Put( rChg.GetColor() );
611         }
612         if( IsJustify() )
613             rSet.Put( rChg.GetAdjust() );
614     }
615 
616     if( SwTableAutoFormatUpdateFlags::Box & eFlags )
617     {
618         if( IsFrame() )
619         {
620             SvxBoxItem aAutoFormatBox = rChg.GetBox();
621 
622             // No format box is adequate to specify the borders of single column/row tables, so combine first/last.
623             if ( bSingleRowTable || bSingleColTable )
624             {
625                 sal_uInt8 nSingleRowOrColumnId = 15; //LAST_ROW_END_COLUMN
626                 if ( !bSingleRowTable )
627                     nSingleRowOrColumnId = nPos + 3;  //LAST COLUMN (3, 7, 11, 15)
628                 else if ( !bSingleColTable )
629                     nSingleRowOrColumnId = nPos + 12; //LAST ROW (12, 13, 14, 15)
630 
631                 assert( nSingleRowOrColumnId < 16 );
632                 const SvxBoxItem aLastAutoFormatBox( GetBoxFormat(nSingleRowOrColumnId).GetBox() );
633                 if ( bSingleRowTable )
634                     aAutoFormatBox.SetLine( aLastAutoFormatBox.GetLine(SvxBoxItemLine::BOTTOM), SvxBoxItemLine::BOTTOM );
635                 if ( bSingleColTable )
636                     aAutoFormatBox.SetLine( aLastAutoFormatBox.GetLine(SvxBoxItemLine::RIGHT), SvxBoxItemLine::RIGHT );
637             }
638 
639             rSet.Put( aAutoFormatBox );
640 // FIXME - uncomment the lines to put the diagonal line items
641 //            rSet.Put( rChg.GetTLBR() );
642 //            rSet.Put( rChg.GetBLTR() );
643         }
644         if( IsBackground() )
645             rSet.Put( rChg.GetBackground() );
646 
647         rSet.Put(rChg.GetTextOrientation());
648 
649         // Do not put a VertAlign when it has default value.
650         // It prevents the export of default value by automatic cell-styles export.
651         if (rChg.GetVerticalAlignment().GetVertOrient() != GetDefaultBoxFormat().GetVerticalAlignment().GetVertOrient())
652             rSet.Put(rChg.GetVerticalAlignment());
653 
654         if( IsValueFormat() && pNFormatr )
655         {
656             OUString sFormat;
657             LanguageType eLng, eSys;
658             rChg.GetValueFormat( sFormat, eLng, eSys );
659             if( !sFormat.isEmpty() )
660             {
661                 SvNumFormatType nType;
662                 bool bNew;
663                 sal_Int32 nCheckPos;
664                 sal_uInt32 nKey = pNFormatr->GetIndexPuttingAndConverting( sFormat, eLng,
665                                                                         eSys, nType, bNew, nCheckPos);
666                 rSet.Put( SwTableBoxNumFormat( nKey ));
667             }
668             else
669                 rSet.ClearItem( RES_BOXATR_FORMAT );
670         }
671     }
672 
673     // we cannot handle the rest, that's specific to StarCalc
674 }
675 
RestoreTableProperties(SwTable & table) const676 void SwTableAutoFormat::RestoreTableProperties(SwTable &table) const
677 {
678     SwTableFormat* pFormat = table.GetFrameFormat();
679     if (!pFormat)
680         return;
681 
682     SwDoc *pDoc = pFormat->GetDoc();
683     if (!pDoc)
684         return;
685 
686     SfxItemSet rSet(pDoc->GetAttrPool(), aTableSetRange);
687 
688     if ( m_aBreak->GetBreak() != SvxBreak::NONE )
689         rSet.Put(*m_aBreak);
690     rSet.Put(m_aPageDesc);
691     rSet.Put(SwFormatLayoutSplit(m_bLayoutSplit));
692     rSet.Put(SfxBoolItem(RES_COLLAPSING_BORDERS, m_bCollapsingBorders));
693     if ( m_aKeepWithNextPara->GetValue() )
694         rSet.Put(*m_aKeepWithNextPara);
695     rSet.Put(*m_aShadow);
696 
697     pFormat->SetFormatAttr(rSet);
698 
699     SwEditShell *pShell = pDoc->GetEditShell();
700     pDoc->SetRowSplit(*pShell->getShellCursor(false), SwFormatRowSplit(m_bRowSplit));
701 
702     table.SetRowsToRepeat(m_aRepeatHeading);
703 }
704 
StoreTableProperties(const SwTable & table)705 void SwTableAutoFormat::StoreTableProperties(const SwTable &table)
706 {
707     SwTableFormat* pFormat = table.GetFrameFormat();
708     if (!pFormat)
709         return;
710 
711     SwDoc *pDoc = pFormat->GetDoc();
712     if (!pDoc)
713         return;
714 
715     SwEditShell *pShell = pDoc->GetEditShell();
716     std::unique_ptr<SwFormatRowSplit> pRowSplit = SwDoc::GetRowSplit(*pShell->getShellCursor(false));
717     m_bRowSplit = pRowSplit && pRowSplit->GetValue();
718     pRowSplit.reset();
719 
720     const SfxItemSet &rSet = pFormat->GetAttrSet();
721 
722     m_aBreak.reset(static_cast<SvxFormatBreakItem*>(rSet.Get(RES_BREAK).Clone()));
723     m_aPageDesc = rSet.Get(RES_PAGEDESC);
724     const SwFormatLayoutSplit &layoutSplit = rSet.Get(RES_LAYOUT_SPLIT);
725     m_bLayoutSplit = layoutSplit.GetValue();
726     m_bCollapsingBorders = rSet.Get(RES_COLLAPSING_BORDERS).GetValue();
727 
728     m_aKeepWithNextPara.reset(static_cast<SvxFormatKeepItem*>(rSet.Get(RES_KEEP).Clone()));
729     m_aRepeatHeading = table.GetRowsToRepeat();
730     m_aShadow.reset(static_cast<SvxShadowItem*>(rSet.Get(RES_SHADOW).Clone()));
731 }
732 
FirstRowEndColumnIsRow()733 bool SwTableAutoFormat::FirstRowEndColumnIsRow()
734 {
735     return GetBoxFormat(3) == GetBoxFormat(2);
736 }
FirstRowStartColumnIsRow()737 bool SwTableAutoFormat::FirstRowStartColumnIsRow()
738 {
739     return GetBoxFormat(0) == GetBoxFormat(1);
740 }
LastRowEndColumnIsRow()741 bool SwTableAutoFormat::LastRowEndColumnIsRow()
742 {
743     return GetBoxFormat(14) == GetBoxFormat(15);
744 }
LastRowStartColumnIsRow()745 bool SwTableAutoFormat::LastRowStartColumnIsRow()
746 {
747     return GetBoxFormat(12) == GetBoxFormat(13);
748 }
749 
Load(SvStream & rStream,const SwAfVersions & rVersions)750 bool SwTableAutoFormat::Load( SvStream& rStream, const SwAfVersions& rVersions )
751 {
752     sal_uInt16  nVal = 0;
753     rStream.ReadUInt16( nVal );
754     bool bRet = ERRCODE_NONE == rStream.GetError();
755 
756     if( bRet && (nVal == AUTOFORMAT_DATA_ID_X ||
757             (AUTOFORMAT_DATA_ID_504 <= nVal && nVal <= AUTOFORMAT_DATA_ID)) )
758     {
759         bool b;
760         // --- from 680/dr25 on: store strings as UTF-8
761         rtl_TextEncoding eCharSet = (nVal >= AUTOFORMAT_ID_680DR25) ? RTL_TEXTENCODING_UTF8 : rStream.GetStreamCharSet();
762         m_aName = rStream.ReadUniOrByteString( eCharSet );
763         if( AUTOFORMAT_DATA_ID_552 <= nVal )
764         {
765             rStream.ReadUInt16( m_nStrResId );
766             // start from 3d because default is added via constructor
767             if( m_nStrResId < RES_POOLTABSTYLE_END - RES_POOLTABLESTYLE_3D )
768             {
769                 m_aName = SwStyleNameMapper::GetUIName(RES_POOLTABLESTYLE_3D + m_nStrResId, m_aName);
770             }
771             else
772                 m_nStrResId = USHRT_MAX;
773         }
774         rStream.ReadCharAsBool( b ); m_bInclFont = b;
775         rStream.ReadCharAsBool( b ); m_bInclJustify = b;
776         rStream.ReadCharAsBool( b ); m_bInclFrame = b;
777         rStream.ReadCharAsBool( b ); m_bInclBackground = b;
778         rStream.ReadCharAsBool( b ); m_bInclValueFormat = b;
779         rStream.ReadCharAsBool( b ); m_bInclWidthHeight = b;
780 
781         if (nVal >= AUTOFORMAT_DATA_ID_31005 && WriterSpecificBlockExists(rStream))
782         {
783             legacy::SvxFormatBreak::Create(*m_aBreak, rStream, AUTOFORMAT_FILE_VERSION);
784 //unimplemented            READ(m_aPageDesc, SwFormatPageDesc, AUTOFORMAT_FILE_VERSION);
785             legacy::SvxFormatKeep::Create(*m_aKeepWithNextPara, rStream, AUTOFORMAT_FILE_VERSION);
786 
787             rStream.ReadUInt16( m_aRepeatHeading ).ReadCharAsBool( m_bLayoutSplit ).ReadCharAsBool( m_bRowSplit ).ReadCharAsBool( m_bCollapsingBorders );
788 
789             legacy::SvxShadow::Create(*m_aShadow, rStream, AUTOFORMAT_FILE_VERSION);
790         }
791 
792         bRet = ERRCODE_NONE== rStream.GetError();
793 
794         for( sal_uInt8 i = 0; bRet && i < 16; ++i )
795         {
796             SwBoxAutoFormat* pFormat = new SwBoxAutoFormat;
797             bRet = pFormat->Load( rStream, rVersions, nVal );
798             if( bRet )
799                 m_aBoxAutoFormat[ i ] = pFormat;
800             else
801             {
802                 delete pFormat;
803                 break;
804             }
805         }
806     }
807     m_bUserDefined = false;
808     return bRet;
809 }
810 
Save(SvStream & rStream,sal_uInt16 fileVersion) const811 bool SwTableAutoFormat::Save( SvStream& rStream, sal_uInt16 fileVersion ) const
812 {
813     rStream.WriteUInt16( AUTOFORMAT_DATA_ID );
814     // --- from 680/dr25 on: store strings as UTF-8
815     write_uInt16_lenPrefixed_uInt8s_FromOUString(rStream, m_aName,
816         RTL_TEXTENCODING_UTF8 );
817     rStream.WriteUInt16( m_nStrResId );
818     rStream.WriteBool( m_bInclFont );
819     rStream.WriteBool( m_bInclJustify );
820     rStream.WriteBool( m_bInclFrame );
821     rStream.WriteBool( m_bInclBackground );
822     rStream.WriteBool( m_bInclValueFormat );
823     rStream.WriteBool( m_bInclWidthHeight );
824 
825     {
826         WriterSpecificAutoFormatBlock block(rStream);
827 
828         legacy::SvxFormatBreak::Store(*m_aBreak, rStream, legacy::SvxFormatBreak::GetVersion(fileVersion));
829 //unimplemented        m_aPageDesc.Store(rStream, m_aPageDesc.GetVersion(fileVersion));
830         legacy::SvxFormatKeep::Store(*m_aKeepWithNextPara, rStream, legacy::SvxFormatKeep::GetVersion(fileVersion));
831         rStream.WriteUInt16( m_aRepeatHeading ).WriteBool( m_bLayoutSplit ).WriteBool( m_bRowSplit ).WriteBool( m_bCollapsingBorders );
832         legacy::SvxShadow::Store(*m_aShadow, rStream, legacy::SvxShadow::GetVersion(fileVersion));
833     }
834 
835     bool bRet = ERRCODE_NONE == rStream.GetError();
836 
837     for( int i = 0; bRet && i < 16; ++i )
838     {
839         SwBoxAutoFormat* pFormat = m_aBoxAutoFormat[ i ];
840         if( !pFormat )     // if not set -> write default
841         {
842             // If it doesn't exist yet:
843             if( !pDfltBoxAutoFormat )
844                 pDfltBoxAutoFormat = new SwBoxAutoFormat;
845             pFormat = pDfltBoxAutoFormat;
846         }
847         bRet = pFormat->Save( rStream, fileVersion );
848     }
849     return bRet;
850 }
851 
GetTableTemplateCellSubName(const SwBoxAutoFormat & rBoxFormat) const852 OUString SwTableAutoFormat::GetTableTemplateCellSubName(const SwBoxAutoFormat& rBoxFormat) const
853 {
854     sal_Int32 nIndex = 0;
855     for (; nIndex < 16; ++nIndex)
856         if (m_aBoxAutoFormat[nIndex] == &rBoxFormat) break;
857 
858     // box format doesn't belong to this table format
859     if (16 <= nIndex)
860         return OUString();
861 
862     const std::vector<sal_Int32> aTableTemplateMap = GetTableTemplateMap();
863     for (size_t i=0; i < aTableTemplateMap.size(); ++i)
864     {
865         if (aTableTemplateMap[i] == nIndex)
866             return "." + OUString::number(i + 1);
867     }
868 
869     // box format doesn't belong to a table template
870     return OUString();
871 }
872 
873 /*
874  * Mapping schema
875  *          0            1            2           3           4           5
876  *      +-----------------------------------------------------------------------+
877  *   0  |   FRSC    |  FR       |  FREC     |           |           |  FRENC    |
878  *      +-----------------------------------------------------------------------+
879  *   1  |   FC      |  ER       |  EC       |           |           |  LC       |
880  *      +-----------------------------------------------------------------------+
881  *   2  |   OR      |  OC       |  BODY     |           |           |  BCKG     |
882  *      +-----------------------------------------------------------------------+
883  *   3  |           |           |           |           |           |           |
884  *      +-----------------------------------------------------------------------+
885  *   4  |           |           |           |           |           |           |
886  *      +-----------------------------------------------------------------------+
887  *   5  |   LRSC    |  LR       |  LREC     |           |           |  LRENC    |
888  *      +-----------+-----------+-----------+-----------+-----------+-----------+
889  * ODD  = 1, 3, 5, ...
890  * EVEN = 2, 4, 6, ...
891  */
GetTableTemplateMap()892 const std::vector<sal_Int32> & SwTableAutoFormat::GetTableTemplateMap()
893 {
894     static std::vector<sal_Int32> const aTableTemplateMap
895     {
896         1 , // FIRST_ROW              // FR
897         13, // LAST_ROW               // LR
898         4 , // FIRST_COLUMN           // FC
899         7 , // LAST_COLUMN            // LC
900         5 , // EVEN_ROWS              // ER
901         8 , // ODD_ROWS               // OR
902         6 , // EVEN_COLUMNS           // EC
903         9 , // ODD_COLUMNS            // OC
904         10, // BODY
905         11, // BACKGROUND             // BCKG
906         0 , // FIRST_ROW_START_COLUMN // FRSC
907         3 , // FIRST_ROW_END_COLUMN   // FRENC
908         12, // LAST_ROW_START_COLUMN  // LRSC
909         15, // LAST_ROW_END_COLUMN    // LRENC
910         2 , // FIRST_ROW_EVEN_COLUMN  // FREC
911         14, // LAST_ROW_EVEN_COLUMN   // LREC
912     };
913     return aTableTemplateMap;
914 }
915 
CountPos(sal_uInt32 nCol,sal_uInt32 nCols,sal_uInt32 nRow,sal_uInt32 nRows)916 sal_uInt8 SwTableAutoFormat::CountPos(sal_uInt32 nCol, sal_uInt32 nCols, sal_uInt32 nRow,
917                                       sal_uInt32 nRows)
918 {
919     sal_uInt8 nRet = static_cast<sal_uInt8>(
920         !nRow ? 0 : ((nRow + 1 == nRows) ? 12 : (4 * (1 + ((nRow - 1) & 1)))));
921     nRet = nRet
922            + static_cast<sal_uInt8>(!nCol ? 0 : (nCol + 1 == nCols ? 3 : (1 + ((nCol - 1) & 1))));
923     return nRet;
924 }
925 
926 struct SwTableAutoFormatTable::Impl
927 {
928     std::vector<std::unique_ptr<SwTableAutoFormat>> m_AutoFormats;
929 };
930 
size() const931 size_t SwTableAutoFormatTable::size() const
932 {
933     return m_pImpl->m_AutoFormats.size();
934 }
935 
operator [](size_t const i) const936 SwTableAutoFormat const& SwTableAutoFormatTable::operator[](size_t const i) const
937 {
938     return *m_pImpl->m_AutoFormats[i];
939 }
operator [](size_t const i)940 SwTableAutoFormat      & SwTableAutoFormatTable::operator[](size_t const i)
941 {
942     return *m_pImpl->m_AutoFormats[i];
943 }
944 
AddAutoFormat(const SwTableAutoFormat & rTableStyle)945 void SwTableAutoFormatTable::AddAutoFormat(const SwTableAutoFormat& rTableStyle)
946 {
947     // don't insert when we already have style of this name
948     if (FindAutoFormat(rTableStyle.GetName()))
949         return;
950 
951     InsertAutoFormat(size(), std::make_unique<SwTableAutoFormat>(rTableStyle));
952 }
953 
InsertAutoFormat(size_t const i,std::unique_ptr<SwTableAutoFormat> pFormat)954 void SwTableAutoFormatTable::InsertAutoFormat(size_t const i, std::unique_ptr<SwTableAutoFormat> pFormat)
955 {
956     m_pImpl->m_AutoFormats.insert(m_pImpl->m_AutoFormats.begin() + i, std::move(pFormat));
957 }
958 
EraseAutoFormat(size_t const i)959 void SwTableAutoFormatTable::EraseAutoFormat(size_t const i)
960 {
961     m_pImpl->m_AutoFormats.erase(m_pImpl->m_AutoFormats.begin() + i);
962 }
963 
EraseAutoFormat(const OUString & rName)964 void SwTableAutoFormatTable::EraseAutoFormat(const OUString& rName)
965 {
966     auto iter = std::find_if(m_pImpl->m_AutoFormats.begin(), m_pImpl->m_AutoFormats.end(),
967         [&rName](const std::unique_ptr<SwTableAutoFormat>& rpFormat) { return rpFormat->GetName() == rName; });
968     if (iter != m_pImpl->m_AutoFormats.end())
969     {
970         m_pImpl->m_AutoFormats.erase(iter);
971         return;
972     }
973     SAL_INFO("sw.core", "SwTableAutoFormatTable::EraseAutoFormat, SwTableAutoFormat with given name not found");
974 }
975 
ReleaseAutoFormat(size_t const i)976 std::unique_ptr<SwTableAutoFormat> SwTableAutoFormatTable::ReleaseAutoFormat(size_t const i)
977 {
978     auto const iter(m_pImpl->m_AutoFormats.begin() + i);
979     std::unique_ptr<SwTableAutoFormat> pRet(std::move(*iter));
980     m_pImpl->m_AutoFormats.erase(iter);
981     return pRet;
982 }
983 
ReleaseAutoFormat(const OUString & rName)984 std::unique_ptr<SwTableAutoFormat> SwTableAutoFormatTable::ReleaseAutoFormat(const OUString& rName)
985 {
986     std::unique_ptr<SwTableAutoFormat> pRet;
987     auto iter = std::find_if(m_pImpl->m_AutoFormats.begin(), m_pImpl->m_AutoFormats.end(),
988         [&rName](const std::unique_ptr<SwTableAutoFormat>& rpFormat) { return rpFormat->GetName() == rName; });
989     if (iter != m_pImpl->m_AutoFormats.end())
990     {
991         pRet = std::move(*iter);
992         m_pImpl->m_AutoFormats.erase(iter);
993     }
994     return pRet;
995 }
996 
FindAutoFormat(const OUString & rName) const997 SwTableAutoFormat* SwTableAutoFormatTable::FindAutoFormat(const OUString& rName) const
998 {
999     for (const auto &rFormat : m_pImpl->m_AutoFormats)
1000     {
1001         if (rFormat->GetName() == rName)
1002             return rFormat.get();
1003     }
1004 
1005     return nullptr;
1006 }
1007 
~SwTableAutoFormatTable()1008 SwTableAutoFormatTable::~SwTableAutoFormatTable()
1009 {
1010 }
1011 
SwTableAutoFormatTable()1012 SwTableAutoFormatTable::SwTableAutoFormatTable()
1013     : m_pImpl(new Impl)
1014 {
1015     std::unique_ptr<SwTableAutoFormat> pNew(new SwTableAutoFormat(
1016                 SwStyleNameMapper::GetUIName(RES_POOLTABSTYLE_DEFAULT, OUString())));
1017 
1018     sal_uInt8 i;
1019 
1020     Color aColor( COL_BLACK );
1021     SvxBoxItem aBox( RES_BOX );
1022 
1023     aBox.SetAllDistances(55);
1024     SvxBorderLine aLn( &aColor, DEF_LINE_WIDTH_5 );
1025     aBox.SetLine( &aLn, SvxBoxItemLine::LEFT );
1026     aBox.SetLine( &aLn, SvxBoxItemLine::BOTTOM );
1027 
1028     for( i = 0; i <= 15; ++i )
1029     {
1030         aBox.SetLine( i <= 3 ? &aLn : nullptr, SvxBoxItemLine::TOP );
1031         aBox.SetLine( (3 == ( i & 3 )) ? &aLn : nullptr, SvxBoxItemLine::RIGHT );
1032         pNew->GetBoxFormat( i ).SetBox( aBox );
1033     }
1034 
1035     pNew->SetUserDefined(false);
1036     m_pImpl->m_AutoFormats.push_back(std::move(pNew));
1037 }
1038 
Load()1039 void SwTableAutoFormatTable::Load()
1040 {
1041     if (utl::ConfigManager::IsFuzzing())
1042         return;
1043     OUString sNm(AUTOTABLE_FORMAT_NAME);
1044     SvtPathOptions aOpt;
1045     if( aOpt.SearchFile( sNm ))
1046     {
1047         SfxMedium aStream( sNm, StreamMode::STD_READ );
1048         Load( *aStream.GetInStream() );
1049     }
1050 }
1051 
Save() const1052 bool SwTableAutoFormatTable::Save() const
1053 {
1054     if (utl::ConfigManager::IsFuzzing())
1055         return false;
1056     SvtPathOptions aPathOpt;
1057     const OUString sNm( aPathOpt.GetUserConfigPath() + "/" AUTOTABLE_FORMAT_NAME );
1058     SfxMedium aStream(sNm, StreamMode::STD_WRITE );
1059     return Save( *aStream.GetOutStream() ) && aStream.Commit();
1060 }
1061 
Load(SvStream & rStream)1062 bool SwTableAutoFormatTable::Load( SvStream& rStream )
1063 {
1064     bool bRet = ERRCODE_NONE == rStream.GetError();
1065     if (bRet)
1066     {
1067         // Attention: We need to read a general Header here
1068         sal_uInt16 nVal = 0;
1069         rStream.ReadUInt16( nVal );
1070         bRet = ERRCODE_NONE == rStream.GetError();
1071 
1072         if( bRet )
1073         {
1074             SwAfVersions aVersions;
1075 
1076             // Default version is 5.0, unless we detect an old format ID.
1077             sal_uInt16 nFileVers = SOFFICE_FILEFORMAT_50;
1078             if(nVal < AUTOFORMAT_ID_31005)
1079                 nFileVers = SOFFICE_FILEFORMAT_40;
1080 
1081             if( nVal == AUTOFORMAT_ID_358 ||
1082                     (AUTOFORMAT_ID_504 <= nVal && nVal <= AUTOFORMAT_ID) )
1083             {
1084                 sal_uInt8 nChrSet, nCnt;
1085                 long nPos = rStream.Tell();
1086                 rStream.ReadUChar( nCnt ).ReadUChar( nChrSet );
1087                 if( rStream.Tell() != sal_uLong(nPos + nCnt) )
1088                 {
1089                     OSL_ENSURE( false, "The Header contains more or newer Data" );
1090                     rStream.Seek( nPos + nCnt );
1091                 }
1092                 rStream.SetStreamCharSet( static_cast<rtl_TextEncoding>(nChrSet) );
1093                 rStream.SetVersion( nFileVers );
1094             }
1095 
1096             if( nVal == AUTOFORMAT_ID_358 || nVal == AUTOFORMAT_ID_X ||
1097                     (AUTOFORMAT_ID_504 <= nVal && nVal <= AUTOFORMAT_ID) )
1098             {
1099                 aVersions.Load( rStream, nVal );        // Item versions
1100 
1101                 sal_uInt16 nCount = 0;
1102                 rStream.ReadUInt16( nCount );
1103 
1104                 bRet = ERRCODE_NONE== rStream.GetError();
1105                 if (bRet)
1106                 {
1107                     const size_t nMinRecordSize = sizeof(sal_uInt16);
1108                     const size_t nMaxRecords = rStream.remainingSize() / nMinRecordSize;
1109                     if (nCount > nMaxRecords)
1110                     {
1111                         SAL_WARN("sw.core", "Parsing error: " << nMaxRecords <<
1112                                  " max possible entries, but " << nCount << " claimed, truncating");
1113                         nCount = nMaxRecords;
1114                     }
1115                     for (sal_uInt16 i = 0; i < nCount; ++i)
1116                     {
1117                         std::unique_ptr<SwTableAutoFormat> pNew(
1118                             new SwTableAutoFormat( OUString() ));
1119                         bRet = pNew->Load( rStream, aVersions );
1120                         if( bRet )
1121                         {
1122                             m_pImpl->m_AutoFormats.push_back(std::move(pNew));
1123                         }
1124                         else
1125                         {
1126                             break;
1127                         }
1128                     }
1129                 }
1130             }
1131             else
1132             {
1133                 bRet = false;
1134             }
1135         }
1136     }
1137     return bRet;
1138 }
1139 
Save(SvStream & rStream) const1140 bool SwTableAutoFormatTable::Save( SvStream& rStream ) const
1141 {
1142     bool bRet = ERRCODE_NONE == rStream.GetError();
1143     if (bRet)
1144     {
1145         rStream.SetVersion(AUTOFORMAT_FILE_VERSION);
1146 
1147         // Attention: We need to save a general Header here
1148         rStream.WriteUInt16( AUTOFORMAT_ID )
1149                .WriteUChar( 2 ) // Character count of the Header including this value
1150                .WriteUChar( GetStoreCharSet( ::osl_getThreadTextEncoding() ) );
1151 
1152         bRet = ERRCODE_NONE == rStream.GetError();
1153         if (!bRet)
1154             return false;
1155 
1156         // Write this version number for all attributes
1157         SwAfVersions::Write(rStream, AUTOFORMAT_FILE_VERSION);
1158 
1159         rStream.WriteUInt16( m_pImpl->m_AutoFormats.size() - 1 );
1160         bRet = ERRCODE_NONE == rStream.GetError();
1161 
1162         for (size_t i = 1; bRet && i < m_pImpl->m_AutoFormats.size(); ++i)
1163         {
1164             SwTableAutoFormat const& rFormat = *m_pImpl->m_AutoFormats[i];
1165             bRet = rFormat.Save(rStream, AUTOFORMAT_FILE_VERSION);
1166         }
1167     }
1168     rStream.Flush();
1169     return bRet;
1170 }
1171 
SwCellStyleTable()1172 SwCellStyleTable::SwCellStyleTable()
1173 { }
1174 
~SwCellStyleTable()1175 SwCellStyleTable::~SwCellStyleTable()
1176 {
1177 }
1178 
size() const1179 size_t SwCellStyleTable::size() const
1180 {
1181     return m_aCellStyles.size();
1182 }
1183 
clear()1184 void SwCellStyleTable::clear()
1185 {
1186     m_aCellStyles.clear();
1187 }
1188 
operator [](size_t i) const1189 SwCellStyleDescriptor SwCellStyleTable::operator[](size_t i) const
1190 {
1191     return SwCellStyleDescriptor(m_aCellStyles[i]);
1192 }
1193 
AddBoxFormat(const SwBoxAutoFormat & rBoxFormat,const OUString & sName)1194 void SwCellStyleTable::AddBoxFormat(const SwBoxAutoFormat& rBoxFormat, const OUString& sName)
1195 {
1196     m_aCellStyles.emplace_back(sName, std::make_unique<SwBoxAutoFormat>(rBoxFormat));
1197 }
1198 
RemoveBoxFormat(const OUString & sName)1199 void SwCellStyleTable::RemoveBoxFormat(const OUString& sName)
1200 {
1201     auto iter = std::find_if(m_aCellStyles.begin(), m_aCellStyles.end(),
1202         [&sName](const std::pair<OUString, std::unique_ptr<SwBoxAutoFormat>>& rStyle) { return rStyle.first == sName; });
1203     if (iter != m_aCellStyles.end())
1204     {
1205         m_aCellStyles.erase(iter);
1206         return;
1207     }
1208     SAL_INFO("sw.core", "SwCellStyleTable::RemoveBoxFormat, format with given name doesn't exists");
1209 }
1210 
GetBoxFormatName(const SwBoxAutoFormat & rBoxFormat) const1211 OUString SwCellStyleTable::GetBoxFormatName(const SwBoxAutoFormat& rBoxFormat) const
1212 {
1213     for (size_t i=0; i < m_aCellStyles.size(); ++i)
1214     {
1215         if (m_aCellStyles[i].second.get() == &rBoxFormat)
1216             return m_aCellStyles[i].first;
1217     }
1218 
1219     // box format not found
1220     return OUString();
1221 }
1222 
GetBoxFormat(const OUString & sName) const1223 SwBoxAutoFormat* SwCellStyleTable::GetBoxFormat(const OUString& sName) const
1224 {
1225     for (size_t i=0; i < m_aCellStyles.size(); ++i)
1226     {
1227         if (m_aCellStyles[i].first == sName)
1228             return m_aCellStyles[i].second.get();
1229     }
1230 
1231     return nullptr;
1232 }
1233 
ChangeBoxFormatName(const OUString & sFromName,const OUString & sToName)1234 void SwCellStyleTable::ChangeBoxFormatName(const OUString& sFromName, const OUString& sToName)
1235 {
1236     if (!GetBoxFormat(sToName))
1237     {
1238         SAL_INFO("sw.core", "SwCellStyleTable::ChangeBoxName, box with given name already exists");
1239         return;
1240     }
1241     for (size_t i=0; i < m_aCellStyles.size(); ++i)
1242     {
1243         if (m_aCellStyles[i].first == sFromName)
1244         {
1245             m_aCellStyles[i].first = sToName;
1246             // changed successfully
1247             return;
1248         }
1249     }
1250     SAL_INFO("sw.core", "SwCellStyleTable::ChangeBoxName, box with given name not found");
1251 }
1252 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1253