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