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