blob: b435361a26d7705d4292668b646d56933dfd3b01 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
#include <errhdl.hxx> // ASSERT
#include <atrhndl.hxx>
#include <svl/itemiter.hxx>
#include <vcl/outdev.hxx>
#include <editeng/cmapitem.hxx>
#include <editeng/colritem.hxx>
#include <editeng/cntritem.hxx>
#include <editeng/crsditem.hxx>
#include <editeng/escpitem.hxx>
#include <editeng/fontitem.hxx>
#include <editeng/fhgtitem.hxx>
#include <editeng/kernitem.hxx>
#include <editeng/charreliefitem.hxx>
#include <editeng/langitem.hxx>
#include <editeng/postitem.hxx>
#include <editeng/shdditem.hxx>
#include <editeng/udlnitem.hxx>
#include <editeng/wghtitem.hxx>
#include <editeng/wrlmitem.hxx>
#include <editeng/akrnitem.hxx>
#include <editeng/blnkitem.hxx>
#include <editeng/charrotateitem.hxx>
#include <editeng/emphitem.hxx>
#include <editeng/charscaleitem.hxx>
#include <editeng/twolinesitem.hxx>
#include <editeng/charhiddenitem.hxx>
#include <viewopt.hxx>
#include <charfmt.hxx>
#include <fchrfmt.hxx>
#include <fmtautofmt.hxx>
#include <editeng/brshitem.hxx>
#include <fmtinfmt.hxx>
#include <txtinet.hxx>
#include <IDocumentSettingAccess.hxx>
#include <viewsh.hxx> // ViewShell
#include <viewopt.hxx> // SwViewOptions
#define STACK_INCREMENT 4
/*************************************************************************
* Attribute to Stack Mapping
*
* Attributes applied to a text are pushed on different stacks. For each
* stack, the top most attribute on the stack is valid. Because some
* kinds of attributes have to be pushed to the same stacks we map their
* ids to stack ids
* Attention: The first NUM_DEFAULT_VALUES ( defined in swfntcch.hxx == 35 )
* are stored in the defaultitem-cache, if you add one, you have to increase
* NUM_DEFAULT_VALUES.
* Also adjust NUM_ATTRIBUTE_STACKS in atrhndl.hxx.
*************************************************************************/
const sal_uInt8 StackPos[ static_cast<sal_uInt16>(RES_TXTATR_WITHEND_END) -
static_cast<sal_uInt16>(RES_CHRATR_BEGIN) + 1 ] =
{
0, // // 0
1, // RES_CHRATR_CASEMAP = RES_CHRATR_BEGIN // 1
0, // RES_CHRATR_CHARSETCOLOR, // 2
2, // RES_CHRATR_COLOR, // 3
3, // RES_CHRATR_CONTOUR, // 4
4, // RES_CHRATR_CROSSEDOUT, // 5
5, // RES_CHRATR_ESCAPEMENT, // 6
6, // RES_CHRATR_FONT, // 7
7, // RES_CHRATR_FONTSIZE, // 8
8, // RES_CHRATR_KERNING, // 9
9, // RES_CHRATR_LANGUAGE, // 10
10, // RES_CHRATR_POSTURE, // 11
0, // RES_CHRATR_PROPORTIONALFONTSIZE, // 12
11, // RES_CHRATR_SHADOWED, // 13
12, // RES_CHRATR_UNDERLINE, // 14
13, // RES_CHRATR_WEIGHT, // 15
14, // RES_CHRATR_WORDLINEMODE, // 16
15, // RES_CHRATR_AUTOKERN, // 17
16, // RES_CHRATR_BLINK, // 18
17, // RES_CHRATR_NOHYPHEN, // 19
0, // RES_CHRATR_NOLINEBREAK, // 20
18, // RES_CHRATR_BACKGROUND, // 21
19, // RES_CHRATR_CJK_FONT, // 22
20, // RES_CHRATR_CJK_FONTSIZE, // 23
21, // RES_CHRATR_CJK_LANGUAGE, // 24
22, // RES_CHRATR_CJK_POSTURE, // 25
23, // RES_CHRATR_CJK_WEIGHT, // 26
24, // RES_CHRATR_CTL_FONT, // 27
25, // RES_CHRATR_CTL_FONTSIZE, // 28
26, // RES_CHRATR_CTL_LANGUAGE, // 29
27, // RES_CHRATR_CTL_POSTURE, // 30
28, // RES_CHRATR_CTL_WEIGHT, // 31
29, // RES_CHRATR_ROTATE, // 32
30, // RES_CHRATR_EMPHASIS_MARK, // 33
31, // RES_CHRATR_TWO_LINES, // 34
32, // RES_CHRATR_SCALEW, // 35
33, // RES_CHRATR_RELIEF, // 36
34, // RES_CHRATR_HIDDEN, // 37
35, // RES_CHRATR_OVERLINE, // 38
0, // RES_CHRATR_DUMMY1, // 39
0, // RES_CHRATR_DUMMY2, // 40
0, // RES_CHRATR_BIDIRTL // 41
0, // RES_CHRATR_IDCTHINT // 42
36, // RES_TXTATR_REFMARK, // 43
37, // RES_TXTATR_TOXMARK, // 44
38, // RES_TXTATR_META, // 45
38, // RES_TXTATR_METAFIELD, // 46
0, // RES_TXTATR_AUTOFMT, // 47
0, // RES_TXTATR_INETFMT // 48
0, // RES_TXTATR_CHARFMT, // 49
39, // RES_TXTATR_CJK_RUBY, // 50
0, // RES_TXTATR_UNKNOWN_CONTAINER, // 51
40, // RES_TXTATR_INPUTFIELD // 52
};
/*************************************************************************
* CharFmt::GetItem
* returns the item set associated with an character/inet/auto style
*************************************************************************/
namespace CharFmt
{
const SfxItemSet* GetItemSet( const SfxPoolItem& rAttr )
{
const SfxItemSet* pSet = 0;
if ( RES_TXTATR_AUTOFMT == rAttr.Which() )
{
pSet = static_cast<const SwFmtAutoFmt&>(rAttr).GetStyleHandle().get();
}
else
{
// aus der Vorlage die Attribute holen:
SwCharFmt* pFmt = RES_TXTATR_INETFMT == rAttr.Which() ?
((SwFmtINetFmt&)rAttr).GetTxtINetFmt()->GetCharFmt() :
((SwFmtCharFmt&)rAttr).GetCharFmt();
if( pFmt )
{
pSet = &pFmt->GetAttrSet();
}
}
return pSet;
}
/*************************************************************************
* CharFmt::GetItem
* extracts pool item of type nWhich from rAttr
*************************************************************************/
const SfxPoolItem* GetItem( const SwTxtAttr& rAttr, sal_uInt16 nWhich )
{
if ( RES_TXTATR_INETFMT == rAttr.Which() ||
RES_TXTATR_CHARFMT == rAttr.Which() ||
RES_TXTATR_AUTOFMT == rAttr.Which() )
{
const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
if ( !pSet ) return 0;
bool bInParent = RES_TXTATR_AUTOFMT != rAttr.Which();
const SfxPoolItem* pItem;
sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( nWhich, bInParent, &pItem );
return bRet ? pItem : 0;
}
return ( nWhich == rAttr.Which() ) ? &rAttr.GetAttr() : 0;
}
/*************************************************************************
* CharFmt::IsItemIncluded
* checks if item is included in character/inet/auto style
*************************************************************************/
sal_Bool IsItemIncluded( const sal_uInt16 nWhich, const SwTxtAttr *pAttr )
{
sal_Bool bRet = sal_False;
const SfxItemSet* pItemSet = CharFmt::GetItemSet( pAttr->GetAttr() );
if ( pItemSet )
bRet = SFX_ITEM_SET == pItemSet->GetItemState( nWhich, sal_True );
return bRet;
}
}
/*************************************************************************
* lcl_ChgHyperLinkColor
* The color of hyperlinks is taken from the associated character attribute,
* depending on its 'visited' state. There are actually two cases, which
* should override the colors from the character attribute:
* 1. We never take the 'visited' color during printing/pdf export/preview
* 2. The user has choosen to override these colors in the view options
*************************************************************************/
bool lcl_ChgHyperLinkColor( const SwTxtAttr& rAttr,
const SfxPoolItem& rItem,
const ViewShell* pShell,
Color* pColor )
{
if ( !pShell ||
RES_TXTATR_INETFMT != rAttr.Which() ||
RES_CHRATR_COLOR != rItem.Which() )
return false;
// --> FME 2004-09-13 #i15455#
// 1. case:
// We do not want to show visited links:
// (printing, pdf export, page preview)
//
if ( pShell->GetOut()->GetOutDevType() == OUTDEV_PRINTER ||
pShell->GetViewOptions()->IsPDFExport() ||
pShell->GetViewOptions()->IsPagePreview() )
{
if ( ((SwTxtINetFmt&)rAttr).IsVisited() )
{
if ( pColor )
{
// take color from character format 'unvisited link'
SwTxtINetFmt& rInetAttr( const_cast<SwTxtINetFmt&>(
static_cast<const SwTxtINetFmt&>(rAttr)) );
rInetAttr.SetVisited( false );
const SwCharFmt* pTmpFmt = ((SwTxtINetFmt&)rAttr).GetCharFmt();
const SfxPoolItem* pItem;
pTmpFmt->GetItemState( RES_CHRATR_COLOR, sal_True, &pItem );
*pColor = ((SvxColorItem*)pItem)->GetValue();
rInetAttr.SetVisited( true );
}
return true;
}
return false;
}
// <--
//
// 2. case:
// We do not want to apply the color set in the hyperlink
// attribute, instead we take the colors from the view options:
//
if ( pShell->GetWin() &&
(
(((SwTxtINetFmt&)rAttr).IsVisited() && SwViewOption::IsVisitedLinks()) ||
(!((SwTxtINetFmt&)rAttr).IsVisited() && SwViewOption::IsLinks())
)
)
{
if ( pColor )
{
if ( ((SwTxtINetFmt&)rAttr).IsVisited() )
{
// take color from view option 'visited link color'
*pColor = SwViewOption::GetVisitedLinksColor();
}
else
{
// take color from view option 'unvisited link color'
*pColor = SwViewOption::GetLinksColor();
}
}
return true;
}
return false;
}
/*************************************************************************
* SwAttrHandler::SwAttrStack::SwAttrStack()
*************************************************************************/
inline SwAttrHandler::SwAttrStack::SwAttrStack()
: nCount( 0 ), nSize( INITIAL_NUM_ATTR )
{
pArray = pInitialArray;
}
/*************************************************************************
* SwAttrHandler::SwAttrStack::Insert()
*************************************************************************/
void SwAttrHandler::SwAttrStack::Insert( const SwTxtAttr& rAttr, const sal_uInt16 nPos )
{
// do we still have enough space?
if ( nCount >= nSize )
{
// we are still in our initial array
if ( INITIAL_NUM_ATTR == nSize )
{
nSize += STACK_INCREMENT;
pArray = new SwTxtAttr*[ nSize ];
// copy from pInitArray to new Array
memcpy( pArray, pInitialArray,
INITIAL_NUM_ATTR * sizeof(SwTxtAttr*)
);
}
// we are in new memory
else
{
nSize += STACK_INCREMENT;
SwTxtAttr** pTmpArray = new SwTxtAttr*[ nSize ];
// copy from pArray to new Array
memcpy( pTmpArray, pArray, nCount * sizeof(SwTxtAttr*) );
// free old array
delete [] pArray;
pArray = pTmpArray;
}
}
ASSERT( nPos <= nCount, "wrong position for insert operation");
if ( nPos < nCount )
memmove( pArray + nPos + 1, pArray + nPos,
( nCount - nPos ) * sizeof(SwTxtAttr*)
);
pArray[ nPos ] = (SwTxtAttr*)&rAttr;
nCount++;
}
/*************************************************************************
* SwAttrHandler::SwAttrStack::Remove()
*************************************************************************/
void SwAttrHandler::SwAttrStack::Remove( const SwTxtAttr& rAttr )
{
sal_uInt16 nPos = Pos( rAttr );
if ( nPos < nCount )
{
memmove( pArray + nPos, pArray + nPos + 1,
( nCount - 1 - nPos ) * sizeof(SwTxtAttr*)
);
nCount--;
}
}
/*************************************************************************
* SwAttrHandler::SwAttrStack::Top()
*************************************************************************/
const SwTxtAttr* SwAttrHandler::SwAttrStack::Top() const
{
return nCount ? pArray[ nCount - 1 ] : 0;
}
/*************************************************************************
* SwAttrHandler::SwAttrStack::Pos()
*************************************************************************/
sal_uInt16 SwAttrHandler::SwAttrStack::Pos( const SwTxtAttr& rAttr ) const
{
if ( ! nCount )
// empty stack
return USHRT_MAX;
for ( sal_uInt16 nIdx = nCount; nIdx > 0; )
{
if ( &rAttr == pArray[ --nIdx ] )
return nIdx;
}
// element not found
return USHRT_MAX;
}
/*************************************************************************
* SwAttrHandler::SwAttrHandler()
*************************************************************************/
SwAttrHandler::SwAttrHandler() : mpShell( 0 ), pFnt( 0 ), bVertLayout( sal_False )
{
memset( pDefaultArray, 0, NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) );
}
SwAttrHandler::~SwAttrHandler()
{
delete pFnt;
}
/*************************************************************************
* SwAttrHandler::Init()
*************************************************************************/
void SwAttrHandler::Init( const SwAttrSet& rAttrSet,
const IDocumentSettingAccess& rIDocumentSettingAcces,
const ViewShell* pSh )
{
mpIDocumentSettingAccess = &rIDocumentSettingAcces;
mpShell = pSh;
for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++ )
pDefaultArray[ StackPos[ i ] ] = &rAttrSet.Get( i, sal_True );
}
void SwAttrHandler::Init( const SfxPoolItem** pPoolItem, const SwAttrSet* pAS,
const IDocumentSettingAccess& rIDocumentSettingAcces,
const ViewShell* pSh,
SwFont& rFnt, sal_Bool bVL )
{
// initialize default array
memcpy( pDefaultArray, pPoolItem,
NUM_DEFAULT_VALUES * sizeof(SfxPoolItem*) );
mpIDocumentSettingAccess = &rIDocumentSettingAcces;
mpShell = pSh;
// do we have to apply additional paragraph attributes?
bVertLayout = bVL;
if ( pAS && pAS->Count() )
{
SfxItemIter aIter( *pAS );
sal_uInt16 nWhich;
const SfxPoolItem* pItem = aIter.GetCurItem();
while( sal_True )
{
nWhich = pItem->Which();
if (isCHRATR(nWhich))
{
pDefaultArray[ StackPos[ nWhich ] ] = pItem;
FontChg( *pItem, rFnt, sal_True );
}
if( aIter.IsAtEnd() )
break;
pItem = aIter.NextItem();
}
}
// It is possible, that Init is called more than once, e.g., in a
// SwTxtFrm::FormatOnceMore situation.
delete pFnt;
pFnt = new SwFont( rFnt );
}
void SwAttrHandler::Reset( )
{
for ( sal_uInt16 i = 0; i < NUM_ATTRIBUTE_STACKS; i++ )
aAttrStack[ i ].Reset();
}
/*************************************************************************
* SwAttrHandler::PushAndChg()
*************************************************************************/
void SwAttrHandler::PushAndChg( const SwTxtAttr& rAttr, SwFont& rFnt )
{
// these special attributes in fact represent a collection of attributes
// they have to be pushed to each stack they belong to
if ( RES_TXTATR_INETFMT == rAttr.Which() ||
RES_TXTATR_CHARFMT == rAttr.Which() ||
RES_TXTATR_AUTOFMT == rAttr.Which() )
{
const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
if ( !pSet ) return;
for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
{
const SfxPoolItem* pItem;
sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( i, rAttr.Which() != RES_TXTATR_AUTOFMT, &pItem );
if ( bRet )
{
// we push rAttr onto the appropriate stack
if ( Push( rAttr, *pItem ) )
{
// we let pItem change rFnt
Color aColor;
if ( lcl_ChgHyperLinkColor( rAttr, *pItem, mpShell, &aColor ) )
{
SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR );
FontChg( aItemNext, rFnt, sal_True );
}
else
FontChg( *pItem, rFnt, sal_True );
}
}
}
}
// this is the usual case, we have a basic attribute, push it onto the
// stack and change the font
else
{
if ( Push( rAttr, rAttr.GetAttr() ) )
// we let pItem change rFnt
FontChg( rAttr.GetAttr(), rFnt, sal_True );
}
}
/*************************************************************************
* SwAttrHandler::Push()
*************************************************************************/
sal_Bool SwAttrHandler::Push( const SwTxtAttr& rAttr, const SfxPoolItem& rItem )
{
ASSERT( rItem.Which() < RES_TXTATR_WITHEND_END,
"I do not want this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
// robust
if ( RES_TXTATR_WITHEND_END <= rItem.Which() )
return sal_False;
const sal_uInt16 nStack = StackPos[ rItem.Which() ];
// attributes originating from redlining have highest priority
// second priority are hyperlink attributes, which have a color replacement
const SwTxtAttr* pTopAttr = aAttrStack[ nStack ].Top();
if ( !pTopAttr
|| rAttr.IsPriorityAttr()
|| ( !pTopAttr->IsPriorityAttr()
&& !lcl_ChgHyperLinkColor( *pTopAttr, rItem, mpShell, 0 ) ) )
{
aAttrStack[ nStack ].Push( rAttr );
return sal_True;
}
const sal_uInt16 nPos = aAttrStack[ nStack ].Count();
ASSERT( nPos, "empty stack?" );
aAttrStack[ nStack ].Insert( rAttr, nPos - 1 );
return sal_False;
}
/*************************************************************************
* SwAttrHandler::PopAndChg()
*************************************************************************/
void SwAttrHandler::PopAndChg( const SwTxtAttr& rAttr, SwFont& rFnt )
{
if ( RES_TXTATR_WITHEND_END <= rAttr.Which() )
return; // robust
// these special attributes in fact represent a collection of attributes
// they have to be removed from each stack they belong to
if ( RES_TXTATR_INETFMT == rAttr.Which() ||
RES_TXTATR_CHARFMT == rAttr.Which() ||
RES_TXTATR_AUTOFMT == rAttr.Which() )
{
const SfxItemSet* pSet = CharFmt::GetItemSet( rAttr.GetAttr() );
if ( !pSet ) return;
for ( sal_uInt16 i = RES_CHRATR_BEGIN; i < RES_CHRATR_END; i++)
{
const SfxPoolItem* pItem;
sal_Bool bRet = SFX_ITEM_SET == pSet->GetItemState( i, RES_TXTATR_AUTOFMT != rAttr.Which(), &pItem );
if ( bRet )
{
// we remove rAttr from the appropriate stack
sal_uInt16 nStackPos = StackPos[ i ];
aAttrStack[ nStackPos ].Remove( rAttr );
// reset font according to attribute on top of stack
// or default value
ActivateTop( rFnt, i );
}
}
}
// this is the usual case, we have a basic attribute, remove it from the
// stack and reset the font
else
{
aAttrStack[ StackPos[ rAttr.Which() ] ].Remove( rAttr );
// reset font according to attribute on top of stack
// or default value
ActivateTop( rFnt, rAttr.Which() );
}
}
/*************************************************************************
* SwAttrHandler::Pop()
*
* only used during redlining
*************************************************************************/
void SwAttrHandler::Pop( const SwTxtAttr& rAttr )
{
ASSERT( rAttr.Which() < RES_TXTATR_WITHEND_END,
"I do not have this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
if ( rAttr.Which() < RES_TXTATR_WITHEND_END )
{
aAttrStack[ StackPos[ rAttr.Which() ] ].Remove( rAttr );
}
}
/*************************************************************************
* SwAttrHandler::ActivateTop()
*************************************************************************/
void SwAttrHandler::ActivateTop( SwFont& rFnt, const sal_uInt16 nAttr )
{
ASSERT( nAttr < RES_TXTATR_WITHEND_END,
"I cannot activate this attribute, nWhich >= RES_TXTATR_WITHEND_END" );
const sal_uInt16 nStackPos = StackPos[ nAttr ];
const SwTxtAttr* pTopAt = aAttrStack[ nStackPos ].Top();
if ( pTopAt )
{
// check if top attribute is collection of attributes
if ( RES_TXTATR_INETFMT == pTopAt->Which() ||
RES_TXTATR_CHARFMT == pTopAt->Which() ||
RES_TXTATR_AUTOFMT == pTopAt->Which() )
{
const SfxItemSet* pSet = CharFmt::GetItemSet( pTopAt->GetAttr() );
const SfxPoolItem* pItemNext;
pSet->GetItemState( nAttr, RES_TXTATR_AUTOFMT != pTopAt->Which(), &pItemNext );
Color aColor;
if ( lcl_ChgHyperLinkColor( *pTopAt, *pItemNext, mpShell, &aColor ) )
{
SvxColorItem aItemNext( aColor, RES_CHRATR_COLOR );
FontChg( aItemNext, rFnt, sal_False );
}
else
FontChg( *pItemNext, rFnt, sal_False );
}
else
FontChg( pTopAt->GetAttr(), rFnt, sal_False );
}
// default value has to be set, we only have default values for char attribs
else if ( nStackPos < NUM_DEFAULT_VALUES )
FontChg( *pDefaultArray[ nStackPos ], rFnt, sal_False );
else if ( RES_TXTATR_REFMARK == nAttr )
rFnt.GetRef()--;
else if ( RES_TXTATR_TOXMARK == nAttr )
rFnt.GetTox()--;
else if ( (RES_TXTATR_META == nAttr) || (RES_TXTATR_METAFIELD == nAttr) )
{
rFnt.GetMeta()--;
}
else if ( RES_TXTATR_CJK_RUBY == nAttr )
{
// ruby stack has no more attributes
// check, if an rotation attribute has to be applied
sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ];
sal_Bool bTwoLineAct = sal_False;
const SfxPoolItem* pTwoLineItem = 0;
const SwTxtAttr* pTwoLineAttr = aAttrStack[ nTwoLineStack ].Top();
if ( pTwoLineAttr )
{
pTwoLineItem = CharFmt::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES );
bTwoLineAct = ((SvxTwoLinesItem*)pTwoLineItem)->GetValue();
}
else
bTwoLineAct =
((SvxTwoLinesItem*)pDefaultArray[ nTwoLineStack ])->GetValue();
if ( bTwoLineAct )
return;
// eventually, an rotate attribute has to be activated
sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ];
const SfxPoolItem* pRotateItem = 0;
const SwTxtAttr* pRotateAttr = aAttrStack[ nRotateStack ].Top();
if ( pRotateAttr )
{
pRotateItem = CharFmt::GetItem( *pRotateAttr, RES_CHRATR_ROTATE );
rFnt.SetVertical( ((SvxCharRotateItem*)pRotateItem)->GetValue(),
bVertLayout );
}
else
rFnt.SetVertical(
((SvxCharRotateItem*)pDefaultArray[ nRotateStack ])->GetValue(),
bVertLayout
);
}
else if ( RES_TXTATR_INPUTFIELD == nAttr )
rFnt.GetInputField()--;
}
/*************************************************************************
* Font Changing Function
*
* When popping an attribute from the stack, the top mose remaining
* attribute in the stack becomes valid. The following function change
* a font depending on the stack id.
*************************************************************************/
void SwAttrHandler::FontChg(const SfxPoolItem& rItem, SwFont& rFnt, sal_Bool bPush )
{
switch ( rItem.Which() )
{
case RES_CHRATR_CASEMAP :
rFnt.SetCaseMap( ((SvxCaseMapItem&)rItem).GetCaseMap() );
break;
case RES_CHRATR_COLOR :
rFnt.SetColor( ((SvxColorItem&)rItem).GetValue() );
break;
case RES_CHRATR_CONTOUR :
rFnt.SetOutline( ((SvxContourItem&)rItem).GetValue() );
break;
case RES_CHRATR_CROSSEDOUT :
rFnt.SetStrikeout( ((SvxCrossedOutItem&)rItem).GetStrikeout() );
break;
case RES_CHRATR_ESCAPEMENT :
rFnt.SetEscapement( ((SvxEscapementItem&)rItem).GetEsc() );
rFnt.SetProportion( ((SvxEscapementItem&)rItem).GetProp() );
break;
case RES_CHRATR_FONT :
rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_LATIN );
rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_LATIN );
rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_LATIN );
rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_LATIN );
rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_LATIN );
break;
case RES_CHRATR_FONTSIZE :
rFnt.SetSize(Size(0,((SvxFontHeightItem&)rItem).GetHeight() ), SW_LATIN );
break;
case RES_CHRATR_KERNING :
rFnt.SetFixKerning( ((SvxKerningItem&)rItem).GetValue() );
break;
case RES_CHRATR_LANGUAGE :
rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_LATIN );
break;
case RES_CHRATR_POSTURE :
rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_LATIN );
break;
case RES_CHRATR_SHADOWED :
rFnt.SetShadow( ((SvxShadowedItem&)rItem).GetValue() );
break;
case RES_CHRATR_UNDERLINE :
{
const sal_uInt16 nStackPos = StackPos[ RES_CHRATR_HIDDEN ];
const SwTxtAttr* pTopAt = aAttrStack[ nStackPos ].Top();
const SfxPoolItem* pTmpItem = pTopAt ?
CharFmt::GetItem( *pTopAt, RES_CHRATR_HIDDEN ) :
pDefaultArray[ nStackPos ];
if( (mpShell && !mpShell->GetWin()) ||
(pTmpItem && !static_cast<const SvxCharHiddenItem*>(pTmpItem)->GetValue()) )
{
rFnt.SetUnderline( ((SvxUnderlineItem&)rItem).GetLineStyle() );
rFnt.SetUnderColor( ((SvxUnderlineItem&)rItem).GetColor() );
}
break;
}
case RES_CHRATR_OVERLINE :
rFnt.SetOverline( ((SvxOverlineItem&)rItem).GetLineStyle() );
rFnt.SetOverColor( ((SvxOverlineItem&)rItem).GetColor() );
break;
case RES_CHRATR_WEIGHT :
rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_LATIN );
break;
case RES_CHRATR_WORDLINEMODE :
rFnt.SetWordLineMode( ((SvxWordLineModeItem&)rItem).GetValue() );
break;
case RES_CHRATR_AUTOKERN :
if( ((SvxAutoKernItem&)rItem).GetValue() )
{
rFnt.SetAutoKern( ( !mpIDocumentSettingAccess ||
!mpIDocumentSettingAccess->get(IDocumentSettingAccess::KERN_ASIAN_PUNCTUATION) ) ?
KERNING_FONTSPECIFIC :
KERNING_ASIAN );
}
else
rFnt.SetAutoKern( 0 );
break;
case RES_CHRATR_BLINK :
rFnt.SetBlink( ((SvxBlinkItem&)rItem).GetValue() );
break;
case RES_CHRATR_BACKGROUND :
rFnt.SetBackColor(new Color( ((SvxBrushItem&)rItem).GetColor() ) );
break;
case RES_CHRATR_CJK_FONT :
rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_CJK );
rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_CJK );
rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_CJK );
rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_CJK );
rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_CJK );
break;
case RES_CHRATR_CJK_FONTSIZE :
rFnt.SetSize(Size( 0, ((SvxFontHeightItem&)rItem).GetHeight()), SW_CJK);
break;
case RES_CHRATR_CJK_LANGUAGE :
rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_CJK );
break;
case RES_CHRATR_CJK_POSTURE :
rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_CJK );
break;
case RES_CHRATR_CJK_WEIGHT :
rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_CJK );
break;
case RES_CHRATR_CTL_FONT :
rFnt.SetName( ((SvxFontItem&)rItem).GetFamilyName(), SW_CTL );
rFnt.SetStyleName( ((SvxFontItem&)rItem).GetStyleName(), SW_CTL );
rFnt.SetFamily( ((SvxFontItem&)rItem).GetFamily(), SW_CTL );
rFnt.SetPitch( ((SvxFontItem&)rItem).GetPitch(), SW_CTL );
rFnt.SetCharSet( ((SvxFontItem&)rItem).GetCharSet(), SW_CTL );
break;
case RES_CHRATR_CTL_FONTSIZE :
rFnt.SetSize(Size(0, ((SvxFontHeightItem&)rItem).GetHeight() ), SW_CTL);
break;
case RES_CHRATR_CTL_LANGUAGE :
rFnt.SetLanguage( ((SvxLanguageItem&)rItem).GetLanguage(), SW_CTL );
break;
case RES_CHRATR_CTL_POSTURE :
rFnt.SetItalic( ((SvxPostureItem&)rItem).GetPosture(), SW_CTL );
break;
case RES_CHRATR_CTL_WEIGHT :
rFnt.SetWeight( ((SvxWeightItem&)rItem).GetWeight(), SW_CTL );
break;
case RES_CHRATR_EMPHASIS_MARK :
rFnt.SetEmphasisMark(
((SvxEmphasisMarkItem&)rItem).GetEmphasisMark()
);
break;
case RES_CHRATR_SCALEW :
rFnt.SetPropWidth( ((SvxCharScaleWidthItem&)rItem).GetValue() );
break;
case RES_CHRATR_RELIEF :
rFnt.SetRelief( (FontRelief)((SvxCharReliefItem&)rItem).GetValue() );
break;
case RES_CHRATR_HIDDEN :
if( mpShell && mpShell->GetWin())
{
if ( ((SvxCharHiddenItem&)rItem).GetValue() )
rFnt.SetUnderline( UNDERLINE_DOTTED );
else
ActivateTop( rFnt, RES_CHRATR_UNDERLINE );
}
break;
case RES_CHRATR_ROTATE :
{
// rotate attribute is applied, when:
// 1. ruby stack is empty and
// 2. top of two line stack ( or default attribute )is an
// deactivated two line attribute
const bool bRuby =
0 != aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].Count();
if ( bRuby )
break;
sal_uInt16 nTwoLineStack = StackPos[ RES_CHRATR_TWO_LINES ];
sal_Bool bTwoLineAct = sal_False;
const SfxPoolItem* pTwoLineItem = 0;
const SwTxtAttr* pTwoLineAttr = aAttrStack[ nTwoLineStack ].Top();
if ( pTwoLineAttr )
{
pTwoLineItem = CharFmt::GetItem( *pTwoLineAttr, RES_CHRATR_TWO_LINES );
bTwoLineAct = ((SvxTwoLinesItem*)pTwoLineItem)->GetValue();
}
else
bTwoLineAct =
((SvxTwoLinesItem*)pDefaultArray[ nTwoLineStack ])->GetValue();
if ( !bTwoLineAct )
rFnt.SetVertical( ((SvxCharRotateItem&)rItem).GetValue(),
bVertLayout );
break;
}
case RES_CHRATR_TWO_LINES :
{
sal_Bool bRuby = 0 !=
aAttrStack[ StackPos[ RES_TXTATR_CJK_RUBY ] ].Count();
sal_Bool bTwoLineAct = sal_False;
// two line is activated, if
// 1. no ruby attribute is set and
// 2. attribute is active
bTwoLineAct = ((SvxTwoLinesItem&)rItem).GetValue();
if ( !bRuby && bTwoLineAct )
{
rFnt.SetVertical( 0, bVertLayout );
break;
}
// a deactivating two line attribute is on top of stack,
// check if rotate attribute has to be enabled
if ( bRuby )
break;
sal_uInt16 nRotateStack = StackPos[ RES_CHRATR_ROTATE ];
const SfxPoolItem* pRotateItem = 0;
const SwTxtAttr* pRotateAttr = aAttrStack[ nRotateStack ].Top();
if ( pRotateAttr )
{
pRotateItem = CharFmt::GetItem( *pRotateAttr, RES_CHRATR_ROTATE );
rFnt.SetVertical( ((SvxCharRotateItem*)pRotateItem)->GetValue(),
bVertLayout );
}
else
rFnt.SetVertical(
((SvxCharRotateItem*)pDefaultArray[ nRotateStack ])->GetValue(),
bVertLayout
);
break;
}
case RES_TXTATR_CJK_RUBY :
rFnt.SetVertical( 0, bVertLayout );
break;
case RES_TXTATR_REFMARK :
if ( bPush )
rFnt.GetRef()++;
else
rFnt.GetRef()--;
break;
case RES_TXTATR_TOXMARK :
if ( bPush )
rFnt.GetTox()++;
else
rFnt.GetTox()--;
break;
case RES_TXTATR_META:
case RES_TXTATR_METAFIELD:
if ( bPush )
rFnt.GetMeta()++;
else
rFnt.GetMeta()--;
break;
case RES_TXTATR_INPUTFIELD :
if ( bPush )
rFnt.GetInputField()++;
else
rFnt.GetInputField()--;
break;
}
}
// Takes the default font and calculated the ascent and height
void SwAttrHandler::GetDefaultAscentAndHeight( ViewShell* pShell, OutputDevice& rOut,
sal_uInt16& nAscent, sal_uInt16& nHeight ) const
{
ASSERT( pFnt, "No font available for GetDefaultAscentAndHeight" )
if ( pFnt )
{
SwFont aFont( *pFnt );
nHeight = aFont.GetHeight( pShell, rOut );
nAscent = aFont.GetAscent( pShell, rOut );
}
}