xref: /trunk/main/sw/source/core/text/atrstck.cxx (revision 86e1cf34)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sw.hxx"
26 
27 
28 #include <errhdl.hxx>   // ASSERT
29 #include <atrhndl.hxx>
30 #include <svl/itemiter.hxx>
31 #include <vcl/outdev.hxx>
32 #include <editeng/cmapitem.hxx>
33 #include <editeng/colritem.hxx>
34 #include <editeng/cntritem.hxx>
35 #include <editeng/crsditem.hxx>
36 #include <editeng/escpitem.hxx>
37 #include <editeng/fontitem.hxx>
38 #include <editeng/fhgtitem.hxx>
39 #include <editeng/kernitem.hxx>
40 #include <editeng/charreliefitem.hxx>
41 #include <editeng/langitem.hxx>
42 #include <editeng/postitem.hxx>
43 #include <editeng/shdditem.hxx>
44 #include <editeng/udlnitem.hxx>
45 #include <editeng/wghtitem.hxx>
46 #include <editeng/wrlmitem.hxx>
47 #include <editeng/akrnitem.hxx>
48 #include <editeng/blnkitem.hxx>
49 #include <editeng/charrotateitem.hxx>
50 #include <editeng/emphitem.hxx>
51 #include <editeng/charscaleitem.hxx>
52 #include <editeng/twolinesitem.hxx>
53 #include <editeng/charhiddenitem.hxx>
54 #include <viewopt.hxx>
55 #include <charfmt.hxx>
56 #include <fchrfmt.hxx>
57 #include <fmtautofmt.hxx>
58 #include <editeng/brshitem.hxx>
59 #include <fmtinfmt.hxx>
60 #include <txtinet.hxx>
61 #include <IDocumentSettingAccess.hxx>
62 #include <viewsh.hxx>   // ViewShell
63 #include <viewopt.hxx>  // SwViewOptions
64 
65 #define STACK_INCREMENT 4
66 
67 /*************************************************************************
68  *                      Attribute to Stack Mapping
69  *
70  * Attributes applied to a text are pushed on different stacks. For each
71  * stack, the top most attribute on the stack is valid. Because some
72  * kinds of attributes have to be pushed to the same stacks we map their
73  * ids to stack ids
74  * Attention: The first NUM_DEFAULT_VALUES ( defined in swfntcch.hxx == 35 )
75  * are stored in the defaultitem-cache, if you add one, you have to increase
76  * NUM_DEFAULT_VALUES.
77  * Also adjust NUM_ATTRIBUTE_STACKS in atrhndl.hxx.
78  *************************************************************************/
79 
80 const sal_uInt8 StackPos[ static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) -
81                      static_cast<sal_uInt16>(RES_CHRATR_BEGIN) + 1 ] =
82 {
83      0, //                                       //  0
84      1, // RES_CHRATR_CASEMAP = RES_CHRATR_BEGIN //  1
85      0, // RES_CHRATR_CHARSETCOLOR,              //  2
86      2, // RES_CHRATR_COLOR,                     //  3
87      3, // RES_CHRATR_CONTOUR,                   //  4
88      4, // RES_CHRATR_CROSSEDOUT,                //  5
89      5, // RES_CHRATR_ESCAPEMENT,                //  6
90      6, // RES_CHRATR_FONT,                      //  7
91      7, // RES_CHRATR_FONTSIZE,                  //  8
92      8, // RES_CHRATR_KERNING,                   //  9
93      9, // RES_CHRATR_LANGUAGE,                  // 10
94     10, // RES_CHRATR_POSTURE,                   // 11
95      0, // RES_CHRATR_PROPORTIONALFONTSIZE,      // 12
96     11, // RES_CHRATR_SHADOWED,                  // 13
97     12, // RES_CHRATR_UNDERLINE,                 // 14
98     13, // RES_CHRATR_WEIGHT,                    // 15
99     14, // RES_CHRATR_WORDLINEMODE,              // 16
100     15, // RES_CHRATR_AUTOKERN,                  // 17
101     16, // RES_CHRATR_BLINK,                     // 18
102     17, // RES_CHRATR_NOHYPHEN,                  // 19
103      0, // RES_CHRATR_NOLINEBREAK,               // 20
104     18, // RES_CHRATR_BACKGROUND,                // 21
105     19, // RES_CHRATR_CJK_FONT,                  // 22
106     20, // RES_CHRATR_CJK_FONTSIZE,              // 23
107     21, // RES_CHRATR_CJK_LANGUAGE,              // 24
108     22, // RES_CHRATR_CJK_POSTURE,               // 25
109     23, // RES_CHRATR_CJK_WEIGHT,                // 26
110     24, // RES_CHRATR_CTL_FONT,                  // 27
111     25, // RES_CHRATR_CTL_FONTSIZE,              // 28
112     26, // RES_CHRATR_CTL_LANGUAGE,              // 29
113     27, // RES_CHRATR_CTL_POSTURE,               // 30
114     28, // RES_CHRATR_CTL_WEIGHT,                // 31
115     29, // RES_CHRATR_ROTATE,                    // 32
116     30, // RES_CHRATR_EMPHASIS_MARK,             // 33
117     31, // RES_CHRATR_TWO_LINES,                 // 34
118     32, // RES_CHRATR_SCALEW,                    // 35
119     33, // RES_CHRATR_RELIEF,                    // 36
120     34, // RES_CHRATR_HIDDEN,                    // 37
121     35, // RES_CHRATR_OVERLINE,                  // 38
122      0, // RES_CHRATR_DUMMY1,                    // 39
123      0, // RES_CHRATR_DUMMY2,                    // 40
124 	 0, // RES_CHRATR_BIDIRTL                    // 41
125 	 0, // RES_CHRATR_IDCTHINT                   // 42
126     36, // RES_TXTATR_REFMARK,                   // 43
127     37, // RES_TXTATR_TOXMARK,                   // 44
128     38, // RES_TXTATR_META,                      // 45
129     38, // RES_TXTATR_METAFIELD,                 // 46
130      0, // RES_TXTATR_AUTOFMT,                   // 47
131      0, // RES_TXTATR_INETFMT                    // 48
132      0, // RES_TXTATR_CHARFMT,                   // 49
133     39, // RES_TXTATR_CJK_RUBY,                  // 50
134      0, // RES_TXTATR_UNKNOWN_CONTAINER,         // 51
135     40, // RES_TXTATR_INPUTFIELD                 // 52
136 };
137 
138 /*************************************************************************
139  *                      CharFmt::GetItem
140  * returns the item set associated with an character/inet/auto style
141  *************************************************************************/
142 
143 namespace CharFmt
144 {
145 
GetItemSet(const SfxPoolItem & rAttr)146 const SfxItemSet* GetItemSet( const SfxPoolItem& rAttr )
147 {
148     const SfxItemSet* pSet = 0;
149 
150     if ( RES_TXTATR_AUTOFMT == rAttr.Which() )
151     {
152         pSet = static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle().get();
153     }
154     else
155     {
156         // aus der Vorlage die Attribute holen:
157         SwCharFmt* pFmt = RES_TXTATR_INETFMT == rAttr.Which() ?
158                         ((SwFmtINetFmt&)rAttr).GetTxtINetFmt()->GetCharFmt() :
159                         ((SwFmtCharFmt&)rAttr).GetCharFmt();
160         if( pFmt )
161         {
162             pSet = &pFmt->GetAttrSet();
163         }
164     }
165 
166     return pSet;
167 }
168 
169 /*************************************************************************
170  *                      CharFmt::GetItem
171  * extracts pool item of type nWhich from rAttr
172  *************************************************************************/
173 
GetItem(const SwTxtAttr & rAttr,sal_uInt16 nWhich)174 const SfxPoolItem* GetItem( const SwTxtAttr& rAttr, sal_uInt16 nWhich )
175 {
176     if ( RES_TXTATR_INETFMT == rAttr.Which() ||
177          RES_TXTATR_CHARFMT == rAttr.Which() ||
178          RES_TXTATR_AUTOFMT == rAttr.Which() )
179     {
180         const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
181         if ( !pSet ) return 0;
182 
183        bool bInParent = RES_TXTATR_AUTOFMT != rAttr.Which();
184        const SfxPoolItem* pItem;
185        sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( nWhich, bInParent, &pItem );
186 
187        return bRet ? pItem : 0;
188     }
189 
190     return ( nWhich == rAttr.Which() ) ? &rAttr.GetAttr() : 0;
191 }
192 
193 /*************************************************************************
194  *                      CharFmt::IsItemIncluded
195  * checks if item is included in character/inet/auto style
196  *************************************************************************/
197 
IsItemIncluded(const sal_uInt16 nWhich,const SwTxtAttr * pAttr)198 sal_Bool IsItemIncluded( const sal_uInt16 nWhich, const SwTxtAttr *pAttr )
199 {
200     sal_Bool bRet = sal_False;
201 
202     const SfxItemSet* pItemSet = CharFmt::GetItemSet( pAttr->GetAttr() );
203     if ( pItemSet )
204         bRet = SFX_ITEM_SET == pItemSet->GetItemState( nWhich, sal_True );
205 
206     return bRet;
207 }
208 
209 }
210 
211 /*************************************************************************
212  *                      lcl_ChgHyperLinkColor
213  * The color of hyperlinks is taken from the associated character attribute,
214  * depending on its 'visited' state. There are actually two cases, which
215  * should override the colors from the character attribute:
216  * 1. We never take the 'visited' color during printing/pdf export/preview
217  * 2. The user has chosen to override these colors in the view options
218  *************************************************************************/
219 
lcl_ChgHyperLinkColor(const SwTxtAttr & rAttr,const SfxPoolItem & rItem,const ViewShell * pShell,Color * pColor)220 bool lcl_ChgHyperLinkColor( const SwTxtAttr& rAttr,
221                             const SfxPoolItem& rItem,
222                             const ViewShell* pShell,
223                             Color* pColor )
224 {
225     if ( !pShell ||
226          RES_TXTATR_INETFMT != rAttr.Which() ||
227          RES_CHRATR_COLOR != rItem.Which() )
228         return false;
229 
230     // --> FME 2004-09-13 #i15455#
231     // 1. case:
232     // We do not want to show visited links:
233     // (printing, pdf export, page preview)
234     //
235     if ( pShell->GetOut()->GetOutDevType() == OUTDEV_PRINTER ||
236          pShell->GetViewOptions()->IsPDFExport() ||
237          pShell->GetViewOptions()->IsPagePreview() )
238     {
239         if ( ((SwTxtINetFmt&)rAttr).IsVisited() )
240         {
241             if ( pColor )
242             {
243                 // take color from character format 'unvisited link'
244                 SwTxtINetFmt& rInetAttr( const_cast<SwTxtINetFmt&>(
245                     static_cast<const SwTxtINetFmt&>(rAttr)) );
246                 rInetAttr.SetVisited( false );
247                 const SwCharFmt* pTmpFmt = ((SwTxtINetFmt&)rAttr).GetCharFmt();
248                 const SfxPoolItem* pItem;
249                 pTmpFmt->GetItemState( RES_CHRATR_COLOR, sal_True, &pItem );
250                 *pColor = ((SvxColorItem*)pItem)->GetValue();
251                 rInetAttr.SetVisited( true );
252             }
253             return true;
254         }
255 
256         return false;
257     }
258     // <--
259 
260     //
261     // 2. case:
262     // We do not want to apply the color set in the hyperlink
263     // attribute, instead we take the colors from the view options:
264     //
265     if ( pShell->GetWin() &&
266         (
267           (((SwTxtINetFmt&)rAttr).IsVisited() && SwViewOption::IsVisitedLinks()) ||
268           (!((SwTxtINetFmt&)rAttr).IsVisited() && SwViewOption::IsLinks())
269         )
270        )
271     {
272         if ( pColor )
273         {
274             if ( ((SwTxtINetFmt&)rAttr).IsVisited() )
275             {
276                 // take color from view option 'visited link color'
277                 *pColor = SwViewOption::GetVisitedLinksColor();
278             }
279             else
280             {
281                 // take color from view option 'unvisited link color'
282                 *pColor = SwViewOption::GetLinksColor();
283             }
284         }
285         return true;
286     }
287 
288     return false;
289 }
290 
291 /*************************************************************************
292  *                      SwAttrHandler::SwAttrStack::SwAttrStack()
293  *************************************************************************/
294 
SwAttrStack()295 inline SwAttrHandler::SwAttrStack::SwAttrStack()
296     : nCount( 0 ), nSize( INITIAL_NUM_ATTR )
297 {
298     pArray = pInitialArray;
299 }
300 
301 /*************************************************************************
302  *                      SwAttrHandler::SwAttrStack::Insert()
303  *************************************************************************/
304 
Insert(const SwTxtAttr & rAttr,const sal_uInt16 nPos)305 void SwAttrHandler::SwAttrStack::Insert( const SwTxtAttr& rAttr, const sal_uInt16 nPos )
306 {
307     // do we still have enough space?
308     if ( nCount >= nSize )
309     {
310          // we are still in our initial array
311         if ( INITIAL_NUM_ATTR == nSize )
312         {
313             nSize += STACK_INCREMENT;
314             pArray = new SwTxtAttr*[ nSize ];
315             // copy from pInitArray to new Array
316             memcpy( pArray, pInitialArray,
317                     INITIAL_NUM_ATTR * sizeof(SwTxtAttr*)
318                     );
319         }
320         // we are in new memory
321         else
322         {
323             nSize += STACK_INCREMENT;
324             SwTxtAttr** pTmpArray = new SwTxtAttr*[ nSize ];
325             // copy from pArray to new Array
326             memcpy( pTmpArray, pArray, nCount * sizeof(SwTxtAttr*) );
327             // free old array
328             delete [] pArray;
329             pArray = pTmpArray;
330         }
331     }
332 
333     ASSERT( nPos <= nCount, "wrong position for insert operation");
334 
335     if ( nPos < nCount )
336         memmove( pArray + nPos + 1, pArray + nPos,
337                 ( nCount - nPos ) * sizeof(SwTxtAttr*)
338                 );
339     pArray[ nPos ] = (SwTxtAttr*)&rAttr;
340 
341     nCount++;
342 }
343 
344 /*************************************************************************
345  *                      SwAttrHandler::SwAttrStack::Remove()
346  *************************************************************************/
347 
Remove(const SwTxtAttr & rAttr)348 void SwAttrHandler::SwAttrStack::Remove( const SwTxtAttr& rAttr )
349 {
350     sal_uInt16 nPos = Pos( rAttr );
351     if ( nPos < nCount )
352     {
353         memmove( pArray + nPos, pArray + nPos + 1,
354                 ( nCount - 1 - nPos ) * sizeof(SwTxtAttr*)
355                 );
356         nCount--;
357     }
358 }
359 
360 /*************************************************************************
361  *                      SwAttrHandler::SwAttrStack::Top()
362  *************************************************************************/
363 
Top() const364 const SwTxtAttr* SwAttrHandler::SwAttrStack::Top() const
365 {
366     return nCount ? pArray[ nCount - 1 ] : 0;
367 }
368 
369 /*************************************************************************
370  *                      SwAttrHandler::SwAttrStack::Pos()
371  *************************************************************************/
372 
Pos(const SwTxtAttr & rAttr) const373 sal_uInt16 SwAttrHandler::SwAttrStack::Pos( const SwTxtAttr& rAttr ) const
374 {
375     if ( ! nCount )
376         // empty stack
377         return USHRT_MAX;
378 
379     for ( sal_uInt16 nIdx = nCount; nIdx > 0; )
380     {
381         if ( &rAttr == pArray[ --nIdx ] )
382             return nIdx;
383     }
384 
385     // element not found
386     return USHRT_MAX;
387 }
388 
389 /*************************************************************************
390  *                      SwAttrHandler::SwAttrHandler()
391  *************************************************************************/
392 
SwAttrHandler()393 SwAttrHandler::SwAttrHandler() : mpShell( 0 ), pFnt( 0 ), bVertLayout( sal_False )
394 
395 {
396     memset( pDefaultArray, 0, NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) );
397 }
398 
~SwAttrHandler()399 SwAttrHandler::~SwAttrHandler()
400 {
401     delete pFnt;
402 }
403 
404 /*************************************************************************
405  *                      SwAttrHandler::Init()
406  *************************************************************************/
407 
Init(const SwAttrSet & rAttrSet,const IDocumentSettingAccess & rIDocumentSettingAcces,const ViewShell * pSh)408 void SwAttrHandler::Init( const SwAttrSet& rAttrSet,
409                           const IDocumentSettingAccess& rIDocumentSettingAcces,
410                           const ViewShell* pSh )
411 {
412     mpIDocumentSettingAccess = &rIDocumentSettingAcces;
413     mpShell = pSh;
414 
415     for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++ )
416         pDefaultArray[ StackPos[ i ] ] = &rAttrSet.Get( i, sal_True );
417 }
418 
Init(const SfxPoolItem ** pPoolItem,const SwAttrSet * pAS,const IDocumentSettingAccess & rIDocumentSettingAcces,const ViewShell * pSh,SwFont & rFnt,sal_Bool bVL)419 void SwAttrHandler::Init( const SfxPoolItem** pPoolItem, const SwAttrSet* pAS,
420                           const IDocumentSettingAccess& rIDocumentSettingAcces,
421                           const ViewShell* pSh,
422                           SwFont& rFnt, sal_Bool bVL )
423 {
424     // initialize default array
425     memcpy( pDefaultArray, pPoolItem,
426             NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) );
427 
428     mpIDocumentSettingAccess = &rIDocumentSettingAcces;
429     mpShell = pSh;
430 
431     // do we have to apply additional paragraph attributes?
432     bVertLayout = bVL;
433 
434     if ( pAS && pAS->Count() )
435     {
436         SfxItemIter aIter( *pAS );
437         sal_uInt16 nWhich;
438         const SfxPoolItem* pItem = aIter.GetCurItem();
439         while( sal_True )
440         {
441             nWhich = pItem->Which();
442             if (isCHRATR(nWhich))
443             {
444                 pDefaultArray[ StackPos[ nWhich ] ] = pItem;
445                 FontChg( *pItem, rFnt, sal_True );
446             }
447 
448             if( aIter.IsAtEnd() )
449                 break;
450 
451             pItem = aIter.NextItem();
452         }
453     }
454 
455     // It is possible, that Init is called more than once, e.g., in a
456     // SwTxtFrm::FormatOnceMore situation.
457     delete pFnt;
458     pFnt = new SwFont( rFnt );
459 }
460 
Reset()461 void SwAttrHandler::Reset( )
462 {
463     for ( sal_uInt16 i = 0; i < NUM_ATTRIBUTE_STACKS; i++ )
464         aAttrStack[ i ].Reset();
465 }
466 
467 /*************************************************************************
468  *                      SwAttrHandler::PushAndChg()
469  *************************************************************************/
470 
PushAndChg(const SwTxtAttr & rAttr,SwFont & rFnt)471 void SwAttrHandler::PushAndChg( const SwTxtAttr& rAttr, SwFont& rFnt )
472 {
473     // these special attributes in fact represent a collection of attributes
474     // they have to be pushed to each stack they belong to
475     if ( RES_TXTATR_INETFMT == rAttr.Which() ||
476          RES_TXTATR_CHARFMT == rAttr.Which() ||
477          RES_TXTATR_AUTOFMT == rAttr.Which() )
478     {
479         const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
480         if ( !pSet ) return;
481 
482         for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
483         {
484             const SfxPoolItem* pItem;
485             sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( i, rAttr.Which() != RES_TXTATR_AUTOFMT, &pItem );
486 
487             if ( bRet )
488             {
489                 // we push rAttr onto the appropriate stack
490                 if ( Push( rAttr, *pItem ) )
491                 {
492                     // we let pItem change rFnt
493                     Color aColor;
494                     if ( lcl_ChgHyperLinkColor( rAttr, *pItem, mpShell, &aColor ) )
495                     {
496                         SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR );
497                         FontChg( aItemNext, rFnt, sal_True );
498                     }
499                     else
500                         FontChg( *pItem, rFnt, sal_True );
501                 }
502             }
503         }
504     }
505     // this is the usual case, we have a basic attribute, push it onto the
506     // stack and change the font
507     else
508     {
509         if ( Push( rAttr, rAttr.GetAttr() ) )
510             // we let pItem change rFnt
511             FontChg( rAttr.GetAttr(), rFnt, sal_True );
512     }
513 }
514 
515 /*************************************************************************
516  *                      SwAttrHandler::Push()
517  *************************************************************************/
518 
Push(const SwTxtAttr & rAttr,const SfxPoolItem & rItem)519 sal_Bool SwAttrHandler::Push( const SwTxtAttr& rAttr, const SfxPoolItem& rItem )
520 {
521     ASSERT( rItem.Which() < RES_TXTATR_WITHEND_END,
522             "I do not want this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
523 
524     // robust
525     if ( RES_TXTATR_WITHEND_END <= rItem.Which() )
526         return sal_False;
527 
528     const sal_uInt16 nStack = StackPos[ rItem.Which() ];
529 
530     // attributes originating from redlining have highest priority
531     // second priority are hyperlink attributes, which have a color replacement
532     const SwTxtAttr* pTopAttr = aAttrStack[ nStack ].Top();
533     if ( !pTopAttr
534          || rAttr.IsPriorityAttr()
535          || ( !pTopAttr->IsPriorityAttr()
536               && !lcl_ChgHyperLinkColor( *pTopAttr, rItem, mpShell, 0 ) ) )
537     {
538         aAttrStack[ nStack ].Push( rAttr );
539         return sal_True;
540     }
541 
542     const sal_uInt16 nPos = aAttrStack[ nStack ].Count();
543     ASSERT( nPos, "empty stack?" );
544     aAttrStack[ nStack ].Insert( rAttr, nPos - 1 );
545     return sal_False;
546 }
547 
548 /*************************************************************************
549  *                      SwAttrHandler::PopAndChg()
550  *************************************************************************/
551 
PopAndChg(const SwTxtAttr & rAttr,SwFont & rFnt)552 void SwAttrHandler::PopAndChg( const SwTxtAttr& rAttr, SwFont& rFnt )
553 {
554     if ( RES_TXTATR_WITHEND_END <= rAttr.Which() )
555         return; // robust
556 
557     // these special attributes in fact represent a collection of attributes
558     // they have to be removed from each stack they belong to
559     if ( RES_TXTATR_INETFMT == rAttr.Which() ||
560          RES_TXTATR_CHARFMT == rAttr.Which() ||
561          RES_TXTATR_AUTOFMT == rAttr.Which() )
562     {
563         const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
564         if ( !pSet ) return;
565 
566         for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
567         {
568             const SfxPoolItem* pItem;
569             sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( i, RES_TXTATR_AUTOFMT != rAttr.Which(), &pItem );
570             if ( bRet )
571             {
572                 // we remove rAttr from the appropriate stack
573                 sal_uInt16 nStackPos = StackPos[ i ];
574                 aAttrStack[ nStackPos ].Remove( rAttr );
575                 // reset font according to attribute on top of stack
576                 // or default value
577                 ActivateTop( rFnt, i );
578             }
579         }
580     }
581     // this is the usual case, we have a basic attribute, remove it from the
582     // stack and reset the font
583     else
584     {
585         aAttrStack[ StackPos[ rAttr.Which() ] ].Remove( rAttr );
586         // reset font according to attribute on top of stack
587         // or default value
588         ActivateTop( rFnt, rAttr.Which() );
589     }
590 }
591 
592 /*************************************************************************
593  *                      SwAttrHandler::Pop()
594  *
595  * only used during redlining
596  *************************************************************************/
597 
Pop(const SwTxtAttr & rAttr)598 void SwAttrHandler::Pop( const SwTxtAttr& rAttr )
599 {
600     ASSERT( rAttr.Which() < RES_TXTATR_WITHEND_END,
601             "I do not have this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
602 
603     if ( rAttr.Which() < RES_TXTATR_WITHEND_END )
604     {
605         aAttrStack[ StackPos[ rAttr.Which() ] ].Remove( rAttr );
606     }
607 }
608 
609 /*************************************************************************
610  *                      SwAttrHandler::ActivateTop()
611  *************************************************************************/
ActivateTop(SwFont & rFnt,const sal_uInt16 nAttr)612 void SwAttrHandler::ActivateTop( SwFont& rFnt, const sal_uInt16 nAttr )
613 {
614     ASSERT( nAttr < RES_TXTATR_WITHEND_END,
615             "I cannot activate this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
616 
617     const sal_uInt16 nStackPos = StackPos[ nAttr ];
618     const SwTxtAttr* pTopAt = aAttrStack[ nStackPos ].Top();
619     if ( pTopAt )
620     {
621         // check if top attribute is collection of attributes
622         if ( RES_TXTATR_INETFMT == pTopAt->Which() ||
623              RES_TXTATR_CHARFMT == pTopAt->Which() ||
624              RES_TXTATR_AUTOFMT == pTopAt->Which() )
625         {
626             const SfxItemSet* pSet = CharFmt::GetItemSet( pTopAt->GetAttr() );
627             const SfxPoolItem* pItemNext;
628             pSet->GetItemState( nAttr, RES_TXTATR_AUTOFMT != pTopAt->Which(), &pItemNext );
629 
630             Color aColor;
631             if ( lcl_ChgHyperLinkColor( *pTopAt, *pItemNext, mpShell, &aColor ) )
632             {
633                 SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR );
634                 FontChg( aItemNext, rFnt, sal_False );
635             }
636             else
637                 FontChg( *pItemNext, rFnt, sal_False );
638         }
639         else
640             FontChg( pTopAt->GetAttr(), rFnt, sal_False );
641     }
642 
643     // default value has to be set, we only have default values for char attribs
644     else if ( nStackPos < NUM_DEFAULT_VALUES )
645         FontChg( *pDefaultArray[ nStackPos ], rFnt, sal_False );
646     else if ( RES_TXTATR_REFMARK == nAttr )
647         rFnt.GetRef()--;
648     else if ( RES_TXTATR_TOXMARK == nAttr )
649         rFnt.GetTox()--;
650     else if ( (RES_TXTATR_META == nAttr) || (RES_TXTATR_METAFIELD == nAttr) )
651     {
652         rFnt.GetMeta()--;
653     }
654     else if ( RES_TXTATR_CJK_RUBY == nAttr )
655     {
656         // ruby stack has no more attributes
657         // check, if an rotation attribute has to be applied
658         sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ];
659         sal_Bool bTwoLineAct = sal_False;
660         const SfxPoolItem* pTwoLineItem = 0;
661         const SwTxtAttr* pTwoLineAttr = aAttrStack[ nTwoLineStack ].Top();
662 
663         if ( pTwoLineAttr )
664         {
665              pTwoLineItem = CharFmt::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES );
666              bTwoLineAct = ((SvxTwoLinesItem*)pTwoLineItem)->GetValue();
667         }
668         else
669             bTwoLineAct =
670                 ((SvxTwoLinesItem*)pDefaultArray[ nTwoLineStack ])->GetValue();
671 
672         if ( bTwoLineAct )
673             return;
674 
675         // eventually, an rotate attribute has to be activated
676         sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ];
677         const SfxPoolItem* pRotateItem = 0;
678         const SwTxtAttr* pRotateAttr = aAttrStack[ nRotateStack ].Top();
679 
680         if ( pRotateAttr )
681         {
682             pRotateItem = CharFmt::GetItem( *pRotateAttr, RES_CHRATR_ROTATE );
683             rFnt.SetVertical( ((SvxCharRotateItem*)pRotateItem)->GetValue(),
684                                bVertLayout );
685         }
686         else
687             rFnt.SetVertical(
688                 ((SvxCharRotateItem*)pDefaultArray[ nRotateStack ])->GetValue(),
689                  bVertLayout
690             );
691     }
692     else if ( RES_TXTATR_INPUTFIELD == nAttr )
693         rFnt.GetInputField()--;
694 }
695 
696 /*************************************************************************
697  *                      Font Changing Function
698  *
699  * When popping an attribute from the stack, the top mose remaining
700  * attribute in the stack becomes valid. The following function change
701  * a font depending on the stack id.
702  *************************************************************************/
703 
FontChg(const SfxPoolItem & rItem,SwFont & rFnt,sal_Bool bPush)704 void SwAttrHandler::FontChg(const SfxPoolItem& rItem, SwFont& rFnt, sal_Bool bPush )
705 {
706     switch ( rItem.Which() )
707     {
708         case RES_CHRATR_CASEMAP :
709             rFnt.SetCaseMap( ((SvxCaseMapItem&)rItem).GetCaseMap() );
710             break;
711         case RES_CHRATR_COLOR :
712             rFnt.SetColor( ((SvxColorItem&)rItem).GetValue() );
713             break;
714         case RES_CHRATR_CONTOUR :
715             rFnt.SetOutline( ((SvxContourItem&)rItem).GetValue() );
716             break;
717         case RES_CHRATR_CROSSEDOUT :
718             rFnt.SetStrikeout( ((SvxCrossedOutItem&)rItem).GetStrikeout() );
719             break;
720         case RES_CHRATR_ESCAPEMENT :
721             rFnt.SetEscapement( ((SvxEscapementItem&)rItem).GetEsc() );
722             rFnt.SetProportion( ((SvxEscapementItem&)rItem).GetProp() );
723             break;
724         case RES_CHRATR_FONT :
725             rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_LATIN );
726             rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_LATIN );
727             rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_LATIN );
728             rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_LATIN );
729             rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_LATIN );
730             break;
731         case RES_CHRATR_FONTSIZE :
732             rFnt.SetSize(Size(0,((SvxFontHeightItem&)rItem).GetHeight() ), SW_LATIN );
733             break;
734         case RES_CHRATR_KERNING :
735             rFnt.SetFixKerning( ((SvxKerningItem&)rItem).GetValue() );
736             break;
737         case RES_CHRATR_LANGUAGE :
738             rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_LATIN );
739             break;
740         case RES_CHRATR_POSTURE :
741             rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_LATIN );
742             break;
743         case RES_CHRATR_SHADOWED :
744             rFnt.SetShadow( ((SvxShadowedItem&)rItem).GetValue() );
745             break;
746         case RES_CHRATR_UNDERLINE :
747         {
748             const sal_uInt16 nStackPos = StackPos[ RES_CHRATR_HIDDEN ];
749             const SwTxtAttr* pTopAt = aAttrStack[ nStackPos ].Top();
750 
751             const SfxPoolItem* pTmpItem = pTopAt ?
752                                           CharFmt::GetItem( *pTopAt, RES_CHRATR_HIDDEN ) :
753                                           pDefaultArray[ nStackPos ];
754 
755             if( (mpShell && !mpShell->GetWin()) ||
756                 (pTmpItem && !static_cast<const SvxCharHiddenItem*>(pTmpItem)->GetValue()) )
757             {
758                 rFnt.SetUnderline( ((SvxUnderlineItem&)rItem).GetLineStyle() );
759                 rFnt.SetUnderColor( ((SvxUnderlineItem&)rItem).GetColor() );
760             }
761             break;
762         }
763         case RES_CHRATR_OVERLINE :
764             rFnt.SetOverline( ((SvxOverlineItem&)rItem).GetLineStyle() );
765             rFnt.SetOverColor( ((SvxOverlineItem&)rItem).GetColor() );
766             break;
767         case RES_CHRATR_WEIGHT :
768             rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_LATIN );
769             break;
770         case RES_CHRATR_WORDLINEMODE :
771             rFnt.SetWordLineMode( ((SvxWordLineModeItem&)rItem).GetValue() );
772             break;
773         case RES_CHRATR_AUTOKERN :
774             if( ((SvxAutoKernItem&)rItem).GetValue() )
775             {
776                 rFnt.SetAutoKern( ( !mpIDocumentSettingAccess ||
777                                     !mpIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION) ) ?
778                                      KERNING_FONTSPECIFIC :
779                                      KERNING_ASIAN );
780             }
781 			else
782                 rFnt.SetAutoKern( 0 );
783             break;
784         case RES_CHRATR_BLINK :
785             rFnt.SetBlink( ((SvxBlinkItem&)rItem).GetValue() );
786             break;
787         case RES_CHRATR_BACKGROUND :
788             rFnt.SetBackColor(new Color( ((SvxBrushItem&)rItem).GetColor() ) );
789             break;
790         case RES_CHRATR_CJK_FONT :
791             rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_CJK );
792             rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_CJK );
793             rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_CJK );
794             rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_CJK );
795             rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_CJK );
796             break;
797         case RES_CHRATR_CJK_FONTSIZE :
798             rFnt.SetSize(Size( 0, ((SvxFontHeightItem&)rItem).GetHeight()), SW_CJK);
799             break;
800         case RES_CHRATR_CJK_LANGUAGE :
801             rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_CJK );
802             break;
803         case RES_CHRATR_CJK_POSTURE :
804             rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_CJK );
805             break;
806         case RES_CHRATR_CJK_WEIGHT :
807             rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_CJK );
808             break;
809         case RES_CHRATR_CTL_FONT :
810             rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_CTL );
811             rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_CTL );
812             rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_CTL );
813             rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_CTL );
814             rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_CTL );
815             break;
816         case RES_CHRATR_CTL_FONTSIZE :
817             rFnt.SetSize(Size(0, ((SvxFontHeightItem&)rItem).GetHeight() ), SW_CTL);
818             break;
819         case RES_CHRATR_CTL_LANGUAGE :
820             rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_CTL );
821             break;
822         case RES_CHRATR_CTL_POSTURE :
823             rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_CTL );
824             break;
825         case RES_CHRATR_CTL_WEIGHT :
826             rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_CTL );
827             break;
828         case RES_CHRATR_EMPHASIS_MARK :
829             rFnt.SetEmphasisMark(
830                      ((SvxEmphasisMarkItem&)rItem).GetEmphasisMark()
831                      );
832             break;
833         case RES_CHRATR_SCALEW :
834             rFnt.SetPropWidth( ((SvxCharScaleWidthItem&)rItem).GetValue() );
835             break;
836         case RES_CHRATR_RELIEF :
837             rFnt.SetRelief( (FontRelief)((SvxCharReliefItem&)rItem).GetValue() );
838             break;
839         case RES_CHRATR_HIDDEN :
840             if( mpShell && mpShell->GetWin())
841             {
842                 if ( ((SvxCharHiddenItem&)rItem).GetValue() )
843                     rFnt.SetUnderline( UNDERLINE_DOTTED );
844                 else
845                     ActivateTop( rFnt, RES_CHRATR_UNDERLINE );
846             }
847             break;
848         case RES_CHRATR_ROTATE :
849         {
850             // rotate attribute is applied, when:
851             // 1. ruby stack is empty and
852             // 2. top of two line stack ( or default attribute )is an
853             //    deactivated two line attribute
854             const bool bRuby =
855                 0 != aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].Count();
856 
857             if ( bRuby )
858                 break;
859 
860             sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ];
861             sal_Bool bTwoLineAct = sal_False;
862             const SfxPoolItem* pTwoLineItem = 0;
863             const SwTxtAttr* pTwoLineAttr = aAttrStack[ nTwoLineStack ].Top();
864 
865             if ( pTwoLineAttr )
866             {
867                 pTwoLineItem = CharFmt::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES );
868                 bTwoLineAct = ((SvxTwoLinesItem*)pTwoLineItem)->GetValue();
869             }
870             else
871                 bTwoLineAct =
872                     ((SvxTwoLinesItem*)pDefaultArray[ nTwoLineStack ])->GetValue();
873 
874             if ( !bTwoLineAct )
875                 rFnt.SetVertical( ((SvxCharRotateItem&)rItem).GetValue(),
876                                    bVertLayout );
877 
878             break;
879         }
880         case RES_CHRATR_TWO_LINES :
881         {
882             sal_Bool bRuby = 0 !=
883                     aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].Count();
884             sal_Bool bTwoLineAct = sal_False;
885 
886             // two line is activated, if
887             // 1. no ruby attribute is set and
888             // 2. attribute is active
889             bTwoLineAct = ((SvxTwoLinesItem&)rItem).GetValue();
890 
891             if ( !bRuby && bTwoLineAct )
892             {
893                 rFnt.SetVertical( 0, bVertLayout );
894                 break;
895             }
896 
897             // a deactivating two line attribute is on top of stack,
898             // check if rotate attribute has to be enabled
899             if ( bRuby )
900                 break;
901 
902             sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ];
903             const SfxPoolItem* pRotateItem = 0;
904             const SwTxtAttr* pRotateAttr = aAttrStack[ nRotateStack ].Top();
905 
906             if ( pRotateAttr )
907             {
908                 pRotateItem = CharFmt::GetItem( *pRotateAttr, RES_CHRATR_ROTATE );
909                 rFnt.SetVertical( ((SvxCharRotateItem*)pRotateItem)->GetValue(),
910                                    bVertLayout );
911             }
912             else
913                 rFnt.SetVertical(
914                     ((SvxCharRotateItem*)pDefaultArray[ nRotateStack ])->GetValue(),
915                      bVertLayout
916                 );
917             break;
918         }
919         case RES_TXTATR_CJK_RUBY :
920             rFnt.SetVertical( 0, bVertLayout );
921             break;
922         case RES_TXTATR_REFMARK :
923             if ( bPush )
924                 rFnt.GetRef()++;
925             else
926                 rFnt.GetRef()--;
927             break;
928         case RES_TXTATR_TOXMARK :
929             if ( bPush )
930                 rFnt.GetTox()++;
931             else
932                 rFnt.GetTox()--;
933             break;
934         case RES_TXTATR_META:
935         case RES_TXTATR_METAFIELD:
936             if ( bPush )
937                 rFnt.GetMeta()++;
938             else
939                 rFnt.GetMeta()--;
940             break;
941         case RES_TXTATR_INPUTFIELD :
942             if ( bPush )
943                 rFnt.GetInputField()++;
944             else
945                 rFnt.GetInputField()--;
946             break;
947     }
948 }
949 
950 // Takes the default font and calculated the ascent and height
GetDefaultAscentAndHeight(ViewShell * pShell,OutputDevice & rOut,sal_uInt16 & nAscent,sal_uInt16 & nHeight) const951 void SwAttrHandler::GetDefaultAscentAndHeight( ViewShell* pShell, OutputDevice& rOut,
952                                                sal_uInt16& nAscent, sal_uInt16& nHeight ) const
953 {
954     ASSERT( pFnt, "No font available for GetDefaultAscentAndHeight" )
955 
956     if ( pFnt )
957     {
958         SwFont aFont( *pFnt );
959         nHeight = aFont.GetHeight( pShell, rOut );
960         nAscent = aFont.GetAscent( pShell, rOut );
961     }
962 }
963 
964