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 choosen 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