xref: /core/editeng/source/items/paraitem.cxx (revision 8fe85c24)
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 <com/sun/star/style/TabStop.hpp>
21 #include <com/sun/star/style/LineSpacing.hpp>
22 #include <com/sun/star/style/LineSpacingMode.hpp>
23 #include <com/sun/star/uno/Sequence.hxx>
24 #include <libxml/xmlwriter.h>
25 #include <comphelper/fileformat.h>
26 #include <comphelper/extract.hxx>
27 #include <osl/diagnose.h>
28 #include <unotools/localedatawrapper.hxx>
29 #include <unotools/syslocale.hxx>
30 #include <tools/mapunit.hxx>
31 #include <svl/itempool.hxx>
32 #include <svl/memberid.h>
33 #include <editeng/editrids.hrc>
34 #include <editeng/lspcitem.hxx>
35 #include <editeng/adjustitem.hxx>
36 #include <editeng/orphitem.hxx>
37 #include <editeng/widwitem.hxx>
38 #include <editeng/tstpitem.hxx>
39 #include <editeng/pmdlitem.hxx>
40 #include <editeng/spltitem.hxx>
41 #include <editeng/hyphenzoneitem.hxx>
42 #include <editeng/scriptspaceitem.hxx>
43 #include <editeng/hngpnctitem.hxx>
44 #include <editeng/forbiddenruleitem.hxx>
45 #include <editeng/paravertalignitem.hxx>
46 #include <editeng/pgrditem.hxx>
47 #include <rtl/ustring.hxx>
48 #include <sal/log.hxx>
49 #include <editeng/memberids.h>
50 #include <editeng/editids.hrc>
51 #include <editeng/itemtype.hxx>
52 #include <editeng/eerdll.hxx>
53 #include <editeng/paperinf.hxx>
54 #include <vcl/svapp.hxx>
55 #include <algorithm>
56 
57 using namespace ::com::sun::star;
58 
59 
60 SfxPoolItem* SvxLineSpacingItem::CreateDefault() { return new  SvxLineSpacingItem(LINE_SPACE_DEFAULT_HEIGHT, 0);}
61 SfxPoolItem* SvxAdjustItem::CreateDefault() { return new  SvxAdjustItem(SvxAdjust::Left, 0);}
62 SfxPoolItem* SvxWidowsItem::CreateDefault() { return new  SvxWidowsItem(0, 0);}
63 SfxPoolItem* SvxOrphansItem::CreateDefault() { return new  SvxOrphansItem(0, 0);}
64 SfxPoolItem* SvxHyphenZoneItem::CreateDefault() { return new  SvxHyphenZoneItem(false, 0);}
65 SfxPoolItem* SvxTabStopItem::CreateDefault() { return new  SvxTabStopItem(0);}
66 SfxPoolItem* SvxFormatSplitItem::CreateDefault() { return new  SvxFormatSplitItem(false, 0);}
67 SfxPoolItem* SvxPageModelItem::CreateDefault() { return new  SvxPageModelItem(0);}
68 SfxPoolItem* SvxParaVertAlignItem::CreateDefault() { return new  SvxParaVertAlignItem(Align::Automatic, 0);}
69 
70 
71 enum class SvxSpecialLineSpace
72 {
73     User,
74     OneLine,
75     OnePointFiveLines,
76     TwoLines,
77     End
78 };
79 
80 
81 SvxLineSpacingItem::SvxLineSpacingItem( sal_uInt16 nHeight, const sal_uInt16 nId )
82     : SfxEnumItemInterface( nId )
83 {
84     nPropLineSpace = 100;
85     nInterLineSpace = 0;
86     nLineHeight = nHeight;
87     eLineSpaceRule = SvxLineSpaceRule::Auto;
88     eInterLineSpaceRule = SvxInterLineSpaceRule::Off;
89 }
90 
91 
92 bool SvxLineSpacingItem::operator==( const SfxPoolItem& rAttr ) const
93 {
94     assert(SfxPoolItem::operator==(rAttr));
95 
96     const SvxLineSpacingItem& rLineSpace = static_cast<const SvxLineSpacingItem&>(rAttr);
97     return
98         // Same Linespacing Rule?
99         (eLineSpaceRule == rLineSpace.eLineSpaceRule)
100         // For maximum and minimum Linespacing be the size must coincide.
101         && (eLineSpaceRule == SvxLineSpaceRule::Auto ||
102             nLineHeight == rLineSpace.nLineHeight)
103         // Same Linespacing Rule?
104         && ( eInterLineSpaceRule == rLineSpace.eInterLineSpaceRule )
105         // Either set proportional or additive.
106         && (( eInterLineSpaceRule == SvxInterLineSpaceRule::Off)
107             || (eInterLineSpaceRule == SvxInterLineSpaceRule::Prop
108                 && nPropLineSpace == rLineSpace.nPropLineSpace)
109             || (eInterLineSpaceRule == SvxInterLineSpaceRule::Fix
110                 && (nInterLineSpace == rLineSpace.nInterLineSpace)));
111 }
112 
113 /* Who does still know why the LineSpacingItem is so complicated?
114    We can not use it for UNO since there are only two values:
115       - a sal_uInt16 for the mode
116       - a sal_uInt32 for all values (distance, height, rel. detail)
117 */
118 bool SvxLineSpacingItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
119 {
120     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
121     nMemberId &= ~CONVERT_TWIPS;
122 
123     style::LineSpacing aLSp;
124     switch( eLineSpaceRule )
125     {
126         case SvxLineSpaceRule::Auto:
127             if(eInterLineSpaceRule == SvxInterLineSpaceRule::Fix)
128             {
129                 aLSp.Mode = style::LineSpacingMode::LEADING;
130                 aLSp.Height = ( bConvert ? static_cast<short>(convertTwipToMm100(nInterLineSpace)) : nInterLineSpace);
131             }
132             else if(eInterLineSpaceRule == SvxInterLineSpaceRule::Off)
133             {
134                 aLSp.Mode = style::LineSpacingMode::PROP;
135                 aLSp.Height = 100;
136             }
137             else
138             {
139                 aLSp.Mode = style::LineSpacingMode::PROP;
140                 aLSp.Height = nPropLineSpace;
141             }
142         break;
143         case SvxLineSpaceRule::Fix :
144         case SvxLineSpaceRule::Min :
145             aLSp.Mode = eLineSpaceRule == SvxLineSpaceRule::Fix ? style::LineSpacingMode::FIX : style::LineSpacingMode::MINIMUM;
146             aLSp.Height = ( bConvert ? static_cast<short>(convertTwipToMm100(nLineHeight)) : nLineHeight );
147         break;
148         default:
149             ;//prevent warning about SvxLineSpaceRule::End
150     }
151 
152     switch ( nMemberId )
153     {
154         case 0 :                rVal <<= aLSp; break;
155         case MID_LINESPACE :    rVal <<= aLSp.Mode; break;
156         case MID_HEIGHT :       rVal <<= aLSp.Height; break;
157         default: OSL_FAIL("Wrong MemberId!"); break;
158     }
159 
160     return true;
161 }
162 
163 bool SvxLineSpacingItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
164 {
165     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
166     nMemberId &= ~CONVERT_TWIPS;
167 
168     // fill with current data
169     style::LineSpacing aLSp;
170     uno::Any aAny;
171     bool bRet = QueryValue( aAny, bConvert ? CONVERT_TWIPS : 0 ) && ( aAny >>= aLSp );
172 
173     // get new data
174     switch ( nMemberId )
175     {
176         case 0 :                bRet = (rVal >>= aLSp); break;
177         case MID_LINESPACE :    bRet = (rVal >>= aLSp.Mode); break;
178         case MID_HEIGHT :       bRet = (rVal >>= aLSp.Height); break;
179         default: OSL_FAIL("Wrong MemberId!"); break;
180     }
181 
182     if( bRet )
183     {
184         nLineHeight = aLSp.Height;
185         switch( aLSp.Mode )
186         {
187             case style::LineSpacingMode::LEADING:
188             {
189                 eInterLineSpaceRule = SvxInterLineSpaceRule::Fix;
190                 eLineSpaceRule = SvxLineSpaceRule::Auto;
191                 nInterLineSpace = aLSp.Height;
192                 if(bConvert)
193                     nInterLineSpace = static_cast<short>(convertMm100ToTwip(nInterLineSpace));
194 
195             }
196             break;
197             case style::LineSpacingMode::PROP:
198             {
199                 eLineSpaceRule = SvxLineSpaceRule::Auto;
200                 nPropLineSpace = static_cast<sal_Int16>(aLSp.Height);
201                 if(100 == aLSp.Height)
202                     eInterLineSpaceRule = SvxInterLineSpaceRule::Off;
203                 else
204                     eInterLineSpaceRule = SvxInterLineSpaceRule::Prop;
205             }
206             break;
207             case style::LineSpacingMode::FIX:
208             case style::LineSpacingMode::MINIMUM:
209             {
210                 eInterLineSpaceRule =  SvxInterLineSpaceRule::Off;
211                 eLineSpaceRule = aLSp.Mode == style::LineSpacingMode::FIX ? SvxLineSpaceRule::Fix : SvxLineSpaceRule::Min;
212                 nLineHeight = aLSp.Height;
213                 if(bConvert)
214                     nLineHeight = static_cast<sal_uInt16>(convertMm100ToTwip(nLineHeight));
215             }
216             break;
217         }
218     }
219 
220     return bRet;
221 }
222 
223 
224 SfxPoolItem* SvxLineSpacingItem::Clone( SfxItemPool * ) const
225 {
226     return new SvxLineSpacingItem( *this );
227 }
228 
229 bool SvxLineSpacingItem::GetPresentation
230 (
231     SfxItemPresentation ePres,
232     MapUnit             eCoreUnit,
233     MapUnit             ePresUnit,
234     OUString&           rText, const IntlWrapper& rIntl
235 )   const
236 {
237     switch ( ePres )
238     {
239         case SfxItemPresentation::Nameless:
240         case SfxItemPresentation::Complete:
241         {
242             switch( GetLineSpaceRule() )
243             {
244                 case SvxLineSpaceRule::Auto:
245                 {
246                     SvxInterLineSpaceRule eInter = GetInterLineSpaceRule();
247 
248                     switch( eInter )
249                     {
250                         // Default single line spacing
251                         case SvxInterLineSpaceRule::Off:
252                             rText = EditResId(RID_SVXITEMS_LINESPACING_SINGLE);
253                             break;
254 
255                         // Default single line spacing
256                         case SvxInterLineSpaceRule::Prop:
257                             if ( 100 == GetPropLineSpace() )
258                             {
259                                 rText = EditResId(RID_SVXITEMS_LINESPACING_SINGLE);
260                                 break;
261                             }
262                             // 1.15 line spacing
263                             if ( 115 == GetPropLineSpace() )
264                             {
265                                 rText = EditResId(RID_SVXITEMS_LINESPACING_115);
266                                 break;
267                             }
268                             // 1.5 line spacing
269                             if ( 150 == GetPropLineSpace() )
270                             {
271                                 rText = EditResId(RID_SVXITEMS_LINESPACING_15);
272                                 break;
273                             }
274                             // double line spacing
275                             if ( 200 == GetPropLineSpace() )
276                             {
277                                 rText = EditResId(RID_SVXITEMS_LINESPACING_DOUBLE);
278                                 break;
279                             }
280                             // the set per cent value
281                             rText = EditResId(RID_SVXITEMS_LINESPACING_PROPORTIONAL) + " " + OUString::number(GetPropLineSpace()) + "%";
282                             break;
283 
284                         case SvxInterLineSpaceRule::Fix:
285                             rText = EditResId(RID_SVXITEMS_LINESPACING_LEADING)  +
286                                     " " + GetMetricText(GetInterLineSpace(), eCoreUnit, ePresUnit, &rIntl) +
287                                     " " + EditResId(GetMetricId(ePresUnit));
288                             break;
289                         default: ;//prevent warning
290                     }
291                 }
292                 break;
293                 case SvxLineSpaceRule::Fix:
294                     rText = EditResId(RID_SVXITEMS_LINESPACING_FIXED)  +
295                             " " + GetMetricText(GetLineHeight(), eCoreUnit, ePresUnit, &rIntl) +
296                             " " + EditResId(GetMetricId(ePresUnit));
297                     break;
298 
299                 case SvxLineSpaceRule::Min:
300                     rText = EditResId(RID_SVXITEMS_LINESPACING_MIN) +
301                             " " + GetMetricText(GetLineHeight(), eCoreUnit, ePresUnit, &rIntl) +
302                             " " + EditResId(GetMetricId(ePresUnit));
303                     break;
304                 default: ;//prevent warning
305             }
306         }
307     }
308     return true;
309 }
310 
311 sal_uInt16 SvxLineSpacingItem::GetValueCount() const
312 {
313     return sal_uInt16(SvxSpecialLineSpace::End);   // SvxSpecialLineSpace::TwoLines + 1
314 }
315 
316 
317 sal_uInt16 SvxLineSpacingItem::GetEnumValue() const
318 {
319     SvxSpecialLineSpace nVal;
320     switch ( nPropLineSpace )
321     {
322         case 100:   nVal = SvxSpecialLineSpace::OneLine;            break;
323         case 150:   nVal = SvxSpecialLineSpace::OnePointFiveLines;  break;
324         case 200:   nVal = SvxSpecialLineSpace::TwoLines;           break;
325         default:    nVal = SvxSpecialLineSpace::User;               break;
326     }
327     return static_cast<sal_uInt16>(nVal);
328 }
329 
330 
331 void SvxLineSpacingItem::SetEnumValue( sal_uInt16 nVal )
332 {
333     switch ( static_cast<SvxSpecialLineSpace>(nVal) )
334     {
335         case SvxSpecialLineSpace::OneLine:           nPropLineSpace = 100; break;
336         case SvxSpecialLineSpace::OnePointFiveLines: nPropLineSpace = 150; break;
337         case SvxSpecialLineSpace::TwoLines:          nPropLineSpace = 200; break;
338         default: break;
339     }
340 }
341 
342 // class SvxAdjustItem ---------------------------------------------------
343 
344 SvxAdjustItem::SvxAdjustItem(const SvxAdjust eAdjst, const sal_uInt16 nId )
345     : SfxEnumItemInterface( nId ),
346     bOneBlock( false ), bLastCenter( false ), bLastBlock( false )
347 {
348     SetAdjust( eAdjst );
349 }
350 
351 
352 bool SvxAdjustItem::operator==( const SfxPoolItem& rAttr ) const
353 {
354     assert(SfxPoolItem::operator==(rAttr));
355 
356     const SvxAdjustItem& rItem = static_cast<const SvxAdjustItem&>(rAttr);
357     return GetAdjust() == rItem.GetAdjust() &&
358            bOneBlock == rItem.bOneBlock &&
359            bLastCenter == rItem.bLastCenter &&
360            bLastBlock == rItem.bLastBlock;
361 }
362 
363 bool SvxAdjustItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
364 {
365     nMemberId &= ~CONVERT_TWIPS;
366     switch( nMemberId )
367     {
368         case MID_PARA_ADJUST      : rVal <<= static_cast<sal_Int16>(GetAdjust()); break;
369         case MID_LAST_LINE_ADJUST : rVal <<= static_cast<sal_Int16>(GetLastBlock()); break;
370         case MID_EXPAND_SINGLE    :
371         {
372             rVal <<= bOneBlock;
373             break;
374         }
375         default: ;//prevent warning
376     }
377     return true;
378 }
379 
380 bool SvxAdjustItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
381 {
382     nMemberId &= ~CONVERT_TWIPS;
383     switch( nMemberId )
384     {
385         case MID_PARA_ADJUST              :
386         case MID_LAST_LINE_ADJUST :
387         {
388             sal_Int32 eVal = - 1;
389             ::cppu::enum2int(eVal,rVal);
390             if(eVal >= 0 && eVal <= 4)
391             {
392                 SvxAdjust eAdjust = static_cast<SvxAdjust>(eVal);
393                 if(MID_LAST_LINE_ADJUST == nMemberId &&
394                     eAdjust != SvxAdjust::Left &&
395                     eAdjust != SvxAdjust::Block &&
396                     eAdjust != SvxAdjust::Center)
397                         return false;
398                 nMemberId == MID_PARA_ADJUST ? SetAdjust(eAdjust) : SetLastBlock(eAdjust);
399             }
400         }
401         break;
402         case MID_EXPAND_SINGLE :
403             bOneBlock = Any2Bool(rVal);
404             break;
405     }
406     return true;
407 }
408 
409 
410 SfxPoolItem* SvxAdjustItem::Clone( SfxItemPool * ) const
411 {
412     return new SvxAdjustItem( *this );
413 }
414 
415 
416 bool SvxAdjustItem::GetPresentation
417 (
418     SfxItemPresentation ePres,
419     MapUnit             /*eCoreUnit*/,
420     MapUnit             /*ePresUnit*/,
421     OUString&           rText, const IntlWrapper&
422 )   const
423 {
424     switch ( ePres )
425     {
426         case SfxItemPresentation::Nameless:
427         case SfxItemPresentation::Complete:
428             rText = GetValueTextByPos( static_cast<sal_uInt16>(GetAdjust()) );
429             return true;
430         default: ;//prevent warning
431     }
432     return false;
433 }
434 
435 
436 sal_uInt16 SvxAdjustItem::GetValueCount() const
437 {
438     return sal_uInt16(SvxAdjust::End);  // SvxAdjust::BlockLine + 1
439 }
440 
441 OUString SvxAdjustItem::GetValueTextByPos( sal_uInt16 nPos )
442 {
443     static const char* RID_SVXITEMS_ADJUST[] =
444     {
445         RID_SVXITEMS_ADJUST_LEFT,
446         RID_SVXITEMS_ADJUST_RIGHT,
447         RID_SVXITEMS_ADJUST_BLOCK,
448         RID_SVXITEMS_ADJUST_CENTER,
449         RID_SVXITEMS_ADJUST_BLOCKLINE
450     };
451     static_assert(SAL_N_ELEMENTS(RID_SVXITEMS_ADJUST) - 1 == size_t(SvxAdjust::BlockLine), "unexpected size");
452     assert(nPos <= sal_uInt16(SvxAdjust::BlockLine) && "enum overflow!");
453     return EditResId(RID_SVXITEMS_ADJUST[nPos]);
454 }
455 
456 sal_uInt16 SvxAdjustItem::GetEnumValue() const
457 {
458     return static_cast<sal_uInt16>(GetAdjust());
459 }
460 
461 
462 void SvxAdjustItem::SetEnumValue( sal_uInt16 nVal )
463 {
464     SetAdjust( static_cast<SvxAdjust>(nVal) );
465 }
466 
467 
468 // class SvxWidowsItem ---------------------------------------------------
469 
470 SvxWidowsItem::SvxWidowsItem(const sal_uInt8 nL, const sal_uInt16 nId ) :
471     SfxByteItem( nId, nL )
472 {
473 }
474 
475 
476 SfxPoolItem* SvxWidowsItem::Clone( SfxItemPool * ) const
477 {
478     return new SvxWidowsItem( *this );
479 }
480 
481 
482 bool SvxWidowsItem::GetPresentation
483 (
484     SfxItemPresentation ePres,
485     MapUnit             /*eCoreUnit*/,
486     MapUnit             /*ePresUnit*/,
487     OUString&           rText, const IntlWrapper&
488 )   const
489 {
490     switch ( ePres )
491     {
492         case SfxItemPresentation::Nameless:
493         {
494             rText = EditResId(RID_SVXITEMS_LINES);
495             break;
496         }
497 
498         case SfxItemPresentation::Complete:
499         {
500             rText = EditResId(RID_SVXITEMS_WIDOWS_COMPLETE) + " " + EditResId(RID_SVXITEMS_LINES);
501             break;
502         }
503 
504         default:
505         {
506             SAL_WARN( "editeng.items", "SvxWidowsItem::GetPresentation(): unknown SfxItemPresentation" );
507         }
508     }
509 
510     rText = rText.replaceFirst( "%1", OUString::number( GetValue() ) );
511     return true;
512 }
513 
514 // class SvxOrphansItem --------------------------------------------------
515 
516 SvxOrphansItem::SvxOrphansItem(const sal_uInt8 nL, const sal_uInt16 nId ) :
517     SfxByteItem( nId, nL )
518 {
519 }
520 
521 
522 SfxPoolItem* SvxOrphansItem::Clone( SfxItemPool * ) const
523 {
524     return new SvxOrphansItem( *this );
525 }
526 
527 
528 bool SvxOrphansItem::GetPresentation
529 (
530     SfxItemPresentation ePres,
531     MapUnit             /*eCoreUnit*/,
532     MapUnit             /*ePresUnit*/,
533     OUString&           rText, const IntlWrapper&
534 )   const
535 {
536     switch ( ePres )
537     {
538         case SfxItemPresentation::Nameless:
539         {
540             rText = EditResId(RID_SVXITEMS_LINES);
541             break;
542         }
543 
544         case SfxItemPresentation::Complete:
545         {
546             rText = EditResId(RID_SVXITEMS_ORPHANS_COMPLETE) + " " + EditResId(RID_SVXITEMS_LINES);
547             break;
548         }
549 
550         default:
551         {
552             SAL_WARN( "editeng.items", "SvxOrphansItem::GetPresentation(): unknown SfxItemPresentation" );
553         }
554     }
555 
556     rText = rText.replaceFirst( "%1", OUString::number( GetValue() ) );
557     return true;
558 }
559 
560 // class SvxHyphenZoneItem -----------------------------------------------
561 
562 SvxHyphenZoneItem::SvxHyphenZoneItem( const bool bHyph, const sal_uInt16 nId ) :
563     SfxPoolItem( nId ),
564     bHyphen(bHyph),
565     bPageEnd(true),
566     nMinLead(0),
567     nMinTrail(0),
568     nMaxHyphens(255)
569 {
570 }
571 
572 
573 bool    SvxHyphenZoneItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
574 {
575     nMemberId &= ~CONVERT_TWIPS;
576     switch(nMemberId)
577     {
578         case  MID_IS_HYPHEN:
579             rVal <<= bHyphen;
580         break;
581         case MID_HYPHEN_MIN_LEAD:
582             rVal <<= static_cast<sal_Int16>(nMinLead);
583         break;
584         case MID_HYPHEN_MIN_TRAIL:
585             rVal <<= static_cast<sal_Int16>(nMinTrail);
586         break;
587         case MID_HYPHEN_MAX_HYPHENS:
588             rVal <<= static_cast<sal_Int16>(nMaxHyphens);
589         break;
590     }
591     return true;
592 }
593 
594 bool SvxHyphenZoneItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
595 {
596     nMemberId &= ~CONVERT_TWIPS;
597     sal_Int16 nNewVal = 0;
598 
599     if( nMemberId != MID_IS_HYPHEN )
600         if(!(rVal >>= nNewVal))
601             return false;
602 
603     switch(nMemberId)
604     {
605         case  MID_IS_HYPHEN:
606             bHyphen = Any2Bool(rVal);
607         break;
608         case MID_HYPHEN_MIN_LEAD:
609             nMinLead = static_cast<sal_uInt8>(nNewVal);
610         break;
611         case MID_HYPHEN_MIN_TRAIL:
612             nMinTrail = static_cast<sal_uInt8>(nNewVal);
613         break;
614         case MID_HYPHEN_MAX_HYPHENS:
615             nMaxHyphens = static_cast<sal_uInt8>(nNewVal);
616         break;
617     }
618     return true;
619 }
620 
621 
622 bool SvxHyphenZoneItem::operator==( const SfxPoolItem& rAttr ) const
623 {
624     assert(SfxPoolItem::operator==(rAttr));
625 
626     const SvxHyphenZoneItem& rItem = static_cast<const SvxHyphenZoneItem&>(rAttr);
627     return ( rItem.bHyphen == bHyphen
628             && rItem.bPageEnd == bPageEnd
629             && rItem.nMinLead == nMinLead
630             && rItem.nMinTrail == nMinTrail
631             && rItem.nMaxHyphens == nMaxHyphens );
632 }
633 
634 
635 SfxPoolItem* SvxHyphenZoneItem::Clone( SfxItemPool * ) const
636 {
637     return new SvxHyphenZoneItem( *this );
638 }
639 
640 
641 bool SvxHyphenZoneItem::GetPresentation
642 (
643     SfxItemPresentation ePres,
644     MapUnit             /*eCoreUnit*/,
645     MapUnit             /*ePresUnit*/,
646     OUString&           rText, const IntlWrapper&
647 )   const
648 {
649     OUString cpDelimTmp(cpDelim);
650     switch ( ePres )
651     {
652         case SfxItemPresentation::Nameless:
653         {
654             const char* pId = RID_SVXITEMS_HYPHEN_FALSE;
655 
656             if ( bHyphen )
657                 pId = RID_SVXITEMS_HYPHEN_TRUE;
658             rText = EditResId(pId) + cpDelimTmp;
659             pId = RID_SVXITEMS_PAGE_END_FALSE;
660 
661             if ( bPageEnd )
662                 pId = RID_SVXITEMS_PAGE_END_TRUE;
663             rText = rText + EditResId(pId) + cpDelimTmp +
664                     OUString::number( nMinLead ) + cpDelimTmp +
665                     OUString::number( nMinTrail ) + cpDelimTmp +
666                     OUString::number( nMaxHyphens );
667             return true;
668         }
669         case SfxItemPresentation::Complete:
670         {
671             const char* pId = RID_SVXITEMS_HYPHEN_FALSE;
672 
673             if ( bHyphen )
674                 pId = RID_SVXITEMS_HYPHEN_TRUE;
675             rText = EditResId(pId) + cpDelimTmp;
676             pId = RID_SVXITEMS_PAGE_END_FALSE;
677 
678             if ( bPageEnd )
679                 pId = RID_SVXITEMS_PAGE_END_TRUE;
680             rText = rText +
681                     EditResId(pId) +
682                     cpDelimTmp +
683                     EditResId(RID_SVXITEMS_HYPHEN_MINLEAD).replaceAll("%1", OUString::number(nMinLead)) +
684                     cpDelimTmp +
685                     EditResId(RID_SVXITEMS_HYPHEN_MINTRAIL).replaceAll("%1", OUString::number(nMinTrail)) +
686                     cpDelimTmp +
687                     EditResId(RID_SVXITEMS_HYPHEN_MAX).replaceAll("%1", OUString::number(nMaxHyphens));
688             return true;
689         }
690         default: ;//prevent warning
691     }
692     return false;
693 }
694 
695 
696 // class SvxTabStop ------------------------------------------------------
697 
698 SvxTabStop::SvxTabStop()
699 {
700     nTabPos = 0;
701     eAdjustment = SvxTabAdjust::Left;
702     m_cDecimal = cDfltDecimalChar;
703     cFill = cDfltFillChar;
704 }
705 
706 
707 SvxTabStop::SvxTabStop( const sal_Int32 nPos, const SvxTabAdjust eAdjst,
708                         const sal_Unicode cDec, const sal_Unicode cFil )
709 {
710     nTabPos = nPos;
711     eAdjustment = eAdjst;
712     m_cDecimal = cDec;
713     cFill = cFil;
714 }
715 
716 void SvxTabStop::fillDecimal() const
717 {
718     if ( cDfltDecimalChar == m_cDecimal )
719         m_cDecimal = SvtSysLocale().GetLocaleData().getNumDecimalSep()[0];
720 }
721 
722 void SvxTabStop::dumpAsXml(xmlTextWriterPtr pWriter) const
723 {
724     xmlTextWriterStartElement(pWriter, BAD_CAST("SvxTabStop"));
725     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("nTabPos"),
726                                 BAD_CAST(OString::number(nTabPos).getStr()));
727     xmlTextWriterWriteAttribute(pWriter, BAD_CAST("eAdjustment"),
728                                 BAD_CAST(OString::number(static_cast<int>(eAdjustment)).getStr()));
729     xmlTextWriterEndElement(pWriter);
730 }
731 
732 // class SvxTabStopItem --------------------------------------------------
733 
734 SvxTabStopItem::SvxTabStopItem( sal_uInt16 _nWhich ) :
735     SfxPoolItem( _nWhich ),
736     maTabStops()
737 {
738     const sal_uInt16 nTabs = SVX_TAB_DEFCOUNT, nDist = SVX_TAB_DEFDIST;
739     const SvxTabAdjust eAdjst= SvxTabAdjust::Default;
740 
741     for (sal_uInt16 i = 0; i < nTabs; ++i)
742     {
743         SvxTabStop aTab( (i + 1) * nDist, eAdjst );
744         maTabStops.insert( aTab );
745     }
746 }
747 
748 
749 SvxTabStopItem::SvxTabStopItem( const sal_uInt16 nTabs,
750                                 const sal_uInt16 nDist,
751                                 const SvxTabAdjust eAdjst,
752                                 sal_uInt16 _nWhich ) :
753     SfxPoolItem( _nWhich ),
754     maTabStops()
755 {
756     for ( sal_uInt16 i = 0; i < nTabs; ++i )
757     {
758         SvxTabStop aTab( (i + 1) * nDist, eAdjst );
759         maTabStops.insert( aTab );
760     }
761 }
762 
763 
764 sal_uInt16 SvxTabStopItem::GetPos( const SvxTabStop& rTab ) const
765 {
766     SvxTabStopArr::const_iterator it = maTabStops.find( rTab );
767     return it != maTabStops.end() ? it - maTabStops.begin() : SVX_TAB_NOTFOUND;
768 }
769 
770 
771 sal_uInt16 SvxTabStopItem::GetPos( const sal_Int32 nPos ) const
772 {
773     SvxTabStopArr::const_iterator it = maTabStops.find( SvxTabStop( nPos ) );
774     return it != maTabStops.end() ? it - maTabStops.begin() : SVX_TAB_NOTFOUND;
775 }
776 
777 
778 bool SvxTabStopItem::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const
779 {
780     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
781     nMemberId &= ~CONVERT_TWIPS;
782     switch ( nMemberId )
783     {
784         case MID_TABSTOPS:
785         {
786             sal_uInt16 nCount = Count();
787             uno::Sequence< style::TabStop> aSeq(nCount);
788             style::TabStop* pArr = aSeq.getArray();
789             for(sal_uInt16 i = 0; i < nCount; i++)
790             {
791                 const SvxTabStop& rTab = (*this)[i];
792                 pArr[i].Position        = bConvert ? convertTwipToMm100(rTab.GetTabPos()) : rTab.GetTabPos();
793                 switch(rTab.GetAdjustment())
794                 {
795                 case  SvxTabAdjust::Left   : pArr[i].Alignment = style::TabAlign_LEFT; break;
796                 case  SvxTabAdjust::Right  : pArr[i].Alignment = style::TabAlign_RIGHT; break;
797                 case  SvxTabAdjust::Decimal: pArr[i].Alignment = style::TabAlign_DECIMAL; break;
798                 case  SvxTabAdjust::Center : pArr[i].Alignment = style::TabAlign_CENTER; break;
799                     default: //SvxTabAdjust::Default
800                         pArr[i].Alignment = style::TabAlign_DEFAULT;
801 
802                 }
803                 pArr[i].DecimalChar     = rTab.GetDecimal();
804                 pArr[i].FillChar        = rTab.GetFill();
805             }
806             rVal <<= aSeq;
807             break;
808         }
809         case MID_STD_TAB:
810         {
811             const SvxTabStop &rTab = maTabStops.front();
812             rVal <<= static_cast<sal_Int32>(bConvert ? convertTwipToMm100(rTab.GetTabPos()) : rTab.GetTabPos());
813             break;
814         }
815     }
816     return true;
817 }
818 
819 bool SvxTabStopItem::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId )
820 {
821     bool bConvert = 0!=(nMemberId&CONVERT_TWIPS);
822     nMemberId &= ~CONVERT_TWIPS;
823     switch ( nMemberId )
824     {
825         case MID_TABSTOPS:
826         {
827             uno::Sequence< style::TabStop> aSeq;
828             if(!(rVal >>= aSeq))
829             {
830                 uno::Sequence < uno::Sequence < uno::Any >  > aAnySeq;
831                 if (!(rVal >>= aAnySeq))
832                     return false;
833                 sal_Int32 nLength = aAnySeq.getLength();
834                 aSeq.realloc( nLength );
835                 for ( sal_Int32 n=0; n<nLength; n++ )
836                 {
837                     uno::Sequence < uno::Any >& rAnySeq = aAnySeq[n];
838                     if ( rAnySeq.getLength() == 4 )
839                     {
840                         if (!(rAnySeq[0] >>= aSeq[n].Position)) return false;
841                         if (!(rAnySeq[1] >>= aSeq[n].Alignment))
842                         {
843                             sal_Int32 nVal = 0;
844                             if (rAnySeq[1] >>= nVal)
845                                 aSeq[n].Alignment = static_cast<css::style::TabAlign>(nVal);
846                             else
847                                 return false;
848                         }
849                         if (!(rAnySeq[2] >>= aSeq[n].DecimalChar))
850                         {
851                             OUString aVal;
852                             if ( (rAnySeq[2] >>= aVal) && aVal.getLength() == 1 )
853                                 aSeq[n].DecimalChar = aVal.toChar();
854                             else
855                                 return false;
856                         }
857                         if (!(rAnySeq[3] >>= aSeq[n].FillChar))
858                         {
859                             OUString aVal;
860                             if ( (rAnySeq[3] >>= aVal) && aVal.getLength() == 1 )
861                                 aSeq[n].FillChar = aVal.toChar();
862                             else
863                                 return false;
864                         }
865                     }
866                     else
867                         return false;
868                 }
869             }
870 
871             maTabStops.clear();
872             const style::TabStop* pArr = aSeq.getConstArray();
873             const sal_uInt16 nCount = static_cast<sal_uInt16>(aSeq.getLength());
874             for(sal_uInt16 i = 0; i < nCount ; i++)
875             {
876                 SvxTabAdjust eAdjust = SvxTabAdjust::Default;
877                 switch(pArr[i].Alignment)
878                 {
879                 case style::TabAlign_LEFT   : eAdjust = SvxTabAdjust::Left; break;
880                 case style::TabAlign_CENTER : eAdjust = SvxTabAdjust::Center; break;
881                 case style::TabAlign_RIGHT  : eAdjust = SvxTabAdjust::Right; break;
882                 case style::TabAlign_DECIMAL: eAdjust = SvxTabAdjust::Decimal; break;
883                 default: ;//prevent warning
884                 }
885                 sal_Unicode cFill = pArr[i].FillChar;
886                 sal_Unicode cDecimal = pArr[i].DecimalChar;
887                 SvxTabStop aTab( bConvert ? convertMm100ToTwip(pArr[i].Position) : pArr[i].Position,
888                                     eAdjust,
889                                     cDecimal,
890                                     cFill );
891                 Insert(aTab);
892             }
893             break;
894         }
895         case MID_STD_TAB:
896         {
897             sal_Int32 nNewPos = 0;
898             if (!(rVal >>= nNewPos) )
899                 return false;
900             if (bConvert)
901                 nNewPos = convertMm100ToTwip ( nNewPos );
902             if (nNewPos <= 0)
903                 return false;
904             const SvxTabStop& rTab = maTabStops.front();
905             SvxTabStop aNewTab ( nNewPos, rTab.GetAdjustment(), rTab.GetDecimal(), rTab.GetFill() );
906             Remove( 0 );
907             Insert( aNewTab );
908             break;
909         }
910     }
911     return true;
912 }
913 
914 
915 bool SvxTabStopItem::operator==( const SfxPoolItem& rAttr ) const
916 {
917     assert(SfxPoolItem::operator==(rAttr));
918 
919     const SvxTabStopItem& rTSI = static_cast<const SvxTabStopItem&>(rAttr);
920 
921     if ( Count() != rTSI.Count() )
922         return false;
923 
924     for ( sal_uInt16 i = 0; i < Count(); ++i )
925         if( (*this)[i] != rTSI[i] )
926             return false;
927     return true;
928 }
929 
930 
931 SfxPoolItem* SvxTabStopItem::Clone( SfxItemPool * ) const
932 {
933     return new SvxTabStopItem( *this );
934 }
935 
936 
937 bool SvxTabStopItem::GetPresentation
938 (
939     SfxItemPresentation ePres,
940     MapUnit             eCoreUnit,
941     MapUnit             ePresUnit,
942     OUString&           rText, const IntlWrapper& rIntl
943 )   const
944 {
945     rText.clear();
946 
947     bool bComma = false;
948 
949     for ( sal_uInt16 i = 0; i < Count(); ++i )
950     {
951         if ( SvxTabAdjust::Default != ((*this)[i]).GetAdjustment() )
952         {
953             if ( bComma )
954                 rText += ",";
955             rText += GetMetricText(
956                 ((*this)[i]).GetTabPos(), eCoreUnit, ePresUnit, &rIntl );
957             if ( SfxItemPresentation::Complete == ePres )
958             {
959                 rText += " " + EditResId(GetMetricId(ePresUnit));
960             }
961             bComma = true;
962         }
963     }
964     return true;
965 }
966 
967 
968 bool SvxTabStopItem::Insert( const SvxTabStop& rTab )
969 {
970     sal_uInt16 nTabPos = GetPos(rTab);
971     if(SVX_TAB_NOTFOUND != nTabPos )
972         Remove(nTabPos);
973     return maTabStops.insert( rTab ).second;
974 }
975 
976 void SvxTabStopItem::Insert( const SvxTabStopItem* pTabs )
977 {
978     for( sal_uInt16 i = 0; i < pTabs->Count(); i++ )
979     {
980         const SvxTabStop& rTab = (*pTabs)[i];
981         sal_uInt16 nTabPos = GetPos(rTab);
982         if(SVX_TAB_NOTFOUND != nTabPos)
983             Remove(nTabPos);
984     }
985     for( sal_uInt16 i = 0; i < pTabs->Count(); i++ )
986     {
987         maTabStops.insert( (*pTabs)[i] );
988     }
989 }
990 
991 void SvxTabStopItem::dumpAsXml(xmlTextWriterPtr pWriter) const
992 {
993     xmlTextWriterStartElement(pWriter, BAD_CAST("SvxTabStopItem"));
994     for (const auto& rTabStop : maTabStops)
995         rTabStop.dumpAsXml(pWriter);
996     xmlTextWriterEndElement(pWriter);
997 }
998 
999 // class SvxFormatSplitItem -------------------------------------------------
1000 SvxFormatSplitItem::~SvxFormatSplitItem()
1001 {
1002 }
1003 
1004 SfxPoolItem* SvxFormatSplitItem::Clone( SfxItemPool * ) const
1005 {
1006     return new SvxFormatSplitItem( *this );
1007 }
1008 
1009 
1010 bool SvxFormatSplitItem::GetPresentation
1011 (
1012     SfxItemPresentation /*ePres*/,
1013     MapUnit             /*eCoreUnit*/,
1014     MapUnit             /*ePresUnit*/,
1015     OUString&           rText, const IntlWrapper&
1016 )   const
1017 {
1018     const char* pId = RID_SVXITEMS_FMTSPLIT_FALSE;
1019 
1020     if ( GetValue() )
1021         pId = RID_SVXITEMS_FMTSPLIT_TRUE;
1022     rText = EditResId(pId);
1023     return true;
1024 }
1025 
1026 
1027 SfxPoolItem* SvxPageModelItem::Clone( SfxItemPool* ) const
1028 {
1029     return new SvxPageModelItem( *this );
1030 }
1031 
1032 
1033 bool SvxPageModelItem::QueryValue( css::uno::Any& rVal, sal_uInt8 nMemberId ) const
1034 {
1035     nMemberId &= ~CONVERT_TWIPS;
1036 
1037     switch ( nMemberId )
1038     {
1039         case MID_AUTO: rVal <<= bAuto; break;
1040         case MID_NAME: rVal <<= GetValue(); break;
1041         default: OSL_FAIL("Wrong MemberId!"); return false;
1042     }
1043 
1044     return true;
1045 }
1046 
1047 bool SvxPageModelItem::PutValue( const css::uno::Any& rVal, sal_uInt8 nMemberId )
1048 {
1049     nMemberId &= ~CONVERT_TWIPS;
1050     bool bRet;
1051     OUString aStr;
1052     switch ( nMemberId )
1053     {
1054         case MID_AUTO: bRet = ( rVal >>= bAuto ); break;
1055         case MID_NAME: bRet = ( rVal >>= aStr ); if ( bRet ) SetValue(aStr); break;
1056         default: OSL_FAIL("Wrong MemberId!"); return false;
1057     }
1058 
1059     return bRet;
1060 }
1061 
1062 bool SvxPageModelItem::operator==( const SfxPoolItem& rAttr ) const
1063 {
1064     assert(SfxPoolItem::operator==(rAttr));
1065 
1066     return SfxStringItem::operator==(rAttr) &&
1067            bAuto == static_cast<const SvxPageModelItem&>( rAttr ).bAuto;
1068 }
1069 
1070 bool SvxPageModelItem::GetPresentation
1071 (
1072     SfxItemPresentation ePres,
1073     MapUnit             /*eCoreUnit*/,
1074     MapUnit             /*ePresUnit*/,
1075     OUString&           rText, const IntlWrapper&
1076 )   const
1077 {
1078     rText.clear();
1079     bool bSet = !GetValue().isEmpty();
1080 
1081     switch ( ePres )
1082     {
1083         case SfxItemPresentation::Nameless:
1084             if ( bSet )
1085                 rText = GetValue();
1086             return true;
1087 
1088         case SfxItemPresentation::Complete:
1089             if ( bSet )
1090             {
1091                 rText = EditResId(RID_SVXITEMS_PAGEMODEL_COMPLETE) + GetValue();
1092             }
1093             return true;
1094         default: ;//prevent warning
1095     }
1096     return false;
1097 }
1098 
1099 
1100 SvxScriptSpaceItem::SvxScriptSpaceItem( bool bOn, const sal_uInt16 nId )
1101     : SfxBoolItem( nId, bOn )
1102 {
1103 }
1104 
1105 SfxPoolItem* SvxScriptSpaceItem::Clone( SfxItemPool * ) const
1106 {
1107     return new SvxScriptSpaceItem( *this );
1108 }
1109 
1110 bool SvxScriptSpaceItem::GetPresentation(
1111         SfxItemPresentation /*ePres*/,
1112         MapUnit /*eCoreMetric*/, MapUnit /*ePresMetric*/,
1113         OUString &rText, const IntlWrapper& /*rIntl*/ ) const
1114 {
1115     rText = EditResId( !GetValue()
1116                             ? RID_SVXITEMS_SCRPTSPC_OFF
1117                             : RID_SVXITEMS_SCRPTSPC_ON );
1118     return true;
1119 }
1120 
1121 
1122 SvxHangingPunctuationItem::SvxHangingPunctuationItem(
1123                                     bool bOn, const sal_uInt16 nId )
1124     : SfxBoolItem( nId, bOn )
1125 {
1126 }
1127 
1128 SfxPoolItem* SvxHangingPunctuationItem::Clone( SfxItemPool * ) const
1129 {
1130     return new SvxHangingPunctuationItem( *this );
1131 }
1132 
1133 bool SvxHangingPunctuationItem::GetPresentation(
1134         SfxItemPresentation /*ePres*/,
1135         MapUnit /*eCoreMetric*/, MapUnit /*ePresMetric*/,
1136         OUString &rText, const IntlWrapper& /*rIntl*/ ) const
1137 {
1138     rText = EditResId( !GetValue()
1139                             ? RID_SVXITEMS_HNGPNCT_OFF
1140                             : RID_SVXITEMS_HNGPNCT_ON );
1141     return true;
1142 }
1143 
1144 
1145 SvxForbiddenRuleItem::SvxForbiddenRuleItem(
1146                                     bool bOn, const sal_uInt16 nId )
1147     : SfxBoolItem( nId, bOn )
1148 {
1149 }
1150 
1151 SfxPoolItem* SvxForbiddenRuleItem::Clone( SfxItemPool * ) const
1152 {
1153     return new SvxForbiddenRuleItem( *this );
1154 }
1155 
1156 bool SvxForbiddenRuleItem::GetPresentation(
1157         SfxItemPresentation /*ePres*/,
1158         MapUnit /*eCoreMetric*/, MapUnit /*ePresMetric*/,
1159         OUString &rText, const IntlWrapper& /*rIntl*/ ) const
1160 {
1161     rText = EditResId( !GetValue()
1162                             ? RID_SVXITEMS_FORBIDDEN_RULE_OFF
1163                             : RID_SVXITEMS_FORBIDDEN_RULE_ON );
1164     return true;
1165 }
1166 
1167 /*************************************************************************
1168 |*    class SvxParaVertAlignItem
1169 *************************************************************************/
1170 
1171 SvxParaVertAlignItem::SvxParaVertAlignItem( Align nValue,
1172     const sal_uInt16 nW )
1173     : SfxUInt16Item( nW, static_cast<sal_uInt16>(nValue) )
1174 {
1175 }
1176 
1177 SfxPoolItem* SvxParaVertAlignItem::Clone( SfxItemPool* ) const
1178 {
1179     return new SvxParaVertAlignItem( *this );
1180 }
1181 
1182 bool SvxParaVertAlignItem::GetPresentation(
1183         SfxItemPresentation /*ePres*/,
1184         MapUnit /*eCoreMetric*/, MapUnit /*ePresMetric*/,
1185         OUString &rText, const IntlWrapper& ) const
1186 {
1187     const char* pTmp;
1188     switch( GetValue() )
1189     {
1190         case Align::Automatic: pTmp = RID_SVXITEMS_PARAVERTALIGN_AUTO; break;
1191         case Align::Top:       pTmp = RID_SVXITEMS_PARAVERTALIGN_TOP; break;
1192         case Align::Center:    pTmp = RID_SVXITEMS_PARAVERTALIGN_CENTER; break;
1193         case Align::Bottom:    pTmp = RID_SVXITEMS_PARAVERTALIGN_BOTTOM; break;
1194         default:    pTmp = RID_SVXITEMS_PARAVERTALIGN_BASELINE; break;
1195     }
1196     rText = EditResId(pTmp);
1197     return true;
1198 }
1199 
1200 bool SvxParaVertAlignItem::QueryValue( css::uno::Any& rVal,
1201                                            sal_uInt8 /*nMemberId*/ ) const
1202 {
1203     rVal <<= static_cast<sal_Int16>(GetValue());
1204     return true;
1205 }
1206 
1207 bool SvxParaVertAlignItem::PutValue( const css::uno::Any& rVal,
1208                                          sal_uInt8 /*nMemberId*/ )
1209 {
1210     sal_Int16 nVal = sal_Int16();
1211     if((rVal >>= nVal) && nVal >=0 && nVal <= sal_uInt16(Align::Bottom) )
1212     {
1213         SetValue( static_cast<Align>(nVal) );
1214         return true;
1215     }
1216     else
1217         return false;
1218 }
1219 
1220 bool SvxParaVertAlignItem::operator==( const SfxPoolItem& rItem ) const
1221 {
1222     assert(SfxPoolItem::operator==(rItem));
1223     return SfxUInt16Item::operator==( rItem );
1224 }
1225 
1226 
1227 SvxParaGridItem::SvxParaGridItem( bool bOn, const sal_uInt16 nId )
1228     : SfxBoolItem( nId, bOn )
1229 {
1230 }
1231 
1232 SfxPoolItem* SvxParaGridItem::Clone( SfxItemPool * ) const
1233 {
1234     return new SvxParaGridItem( *this );
1235 }
1236 
1237 bool SvxParaGridItem::GetPresentation(
1238         SfxItemPresentation /*ePres*/,
1239         MapUnit /*eCoreMetric*/, MapUnit /*ePresMetric*/,
1240         OUString &rText, const IntlWrapper& /*rIntl*/ ) const
1241 {
1242     rText = GetValue() ?
1243             EditResId( RID_SVXITEMS_PARASNAPTOGRID_ON ) :
1244             EditResId( RID_SVXITEMS_PARASNAPTOGRID_OFF );
1245 
1246     return true;
1247 }
1248 
1249 
1250 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1251