/*************************************************************************
 *
 *  $RCSfile: rtfitem.cxx,v $
 *
 *  $Revision: 1.24 $
 *
 *  last change: $Author: vg $ $Date: 2005-02-16 17:56:39 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */

#pragma hdrstop

#define ITEMID_FONTLIST     0
#define ITEMID_FONT         0
#define ITEMID_POSTURE      0
#define ITEMID_WEIGHT       0
#define ITEMID_FONTHEIGHT   0
#define ITEMID_UNDERLINE    0
#define ITEMID_CROSSEDOUT   0
#define ITEMID_SHADOWED     0
#define ITEMID_AUTOKERN     0
#define ITEMID_WORDLINEMODE 0
#define ITEMID_CONTOUR      0
#define ITEMID_PROPSIZE     0
#define ITEMID_COLOR        0
#define ITEMID_CHARSETCOLOR 0
#define ITEMID_KERNING      0
#define ITEMID_CASEMAP      0
#define ITEMID_ESCAPEMENT   0
#define ITEMID_LANGUAGE     0
#define ITEMID_NOLINEBREAK  0
#define ITEMID_NOHYPHENHERE 0
#define ITEMID_BLINK        0
#define ITEMID_PAPERBIN     0
#define ITEMID_SIZE         0
#define ITEMID_LRSPACE      0
#define ITEMID_ULSPACE      0
#define ITEMID_PRINT        0
#define ITEMID_OPAQUE       0
#define ITEMID_PROTECT      0
#define ITEMID_SHADOW       0
#define ITEMID_BOX          0
#define ITEMID_BOXINFO      0
#define TEMID_FMTBREAK      0
#define ITEMID_FMTKEEP      0
#define ITEMID_LINE         0
#define ITEMID_BRUSH        0
#define ITEMID_LINESPACING  0
#define TEMID_ADJUST        0
#define ITEMID_ORPHANS      0
#define ITEMID_WIDOWS       0
#define ITEMID_TABSTOP      0
#define ITEMID_PAGEMODEL    0
#define ITEMID_FMTSPLIT     0
#define ITEMID_HYPHENZONE   0
#define ITEMID_FMTBREAK     0
#define ITEMID_ADJUST       0
#define ITEMID_EMPHASISMARK 0
#define ITEMID_TWOLINES     0
#define ITEMID_CHARSCALE_W  0
#define ITEMID_CHARROTATE   0
#define ITEMID_CHARRELIEF   0
#define ITEMID_PARAVERTALIGN 0
#define ITEMID_FORBIDDENRULE 0
#define ITEMID_SCRIPTSPACE 0
#define ITEMID_HANGINGPUNCTUATION 0
#define ITEMID_FRAMEDIR 0
#define ITEMID_CHARHIDDEN 0

#include "flstitem.hxx"
#include "fontitem.hxx"
#include "postitem.hxx"
#include "wghtitem.hxx"
#include "fhgtitem.hxx"
#include "fwdtitem.hxx"
#include "udlnitem.hxx"
#include "crsditem.hxx"
#include "shdditem.hxx"
#include "akrnitem.hxx"
#include "wrlmitem.hxx"
#include "cntritem.hxx"
#include "prszitem.hxx"
#include "colritem.hxx"
#include "cscoitem.hxx"
#include "kernitem.hxx"
#include "cmapitem.hxx"
#include "escpitem.hxx"
#include "langitem.hxx"
#include "nlbkitem.hxx"
#include "nhypitem.hxx"
#include "lcolitem.hxx"
#include "blnkitem.hxx"
#include "emphitem.hxx"
#include "twolinesitem.hxx"

#include "pbinitem.hxx"
#include "sizeitem.hxx"
#include "lrspitem.hxx"
#include "ulspitem.hxx"
#include "prntitem.hxx"
#include "opaqitem.hxx"
#include "protitem.hxx"
#include "shaditem.hxx"
#include "boxitem.hxx"
#include "brkitem.hxx"
#include "keepitem.hxx"
#include "bolnitem.hxx"
#include "brshitem.hxx"
#include "lspcitem.hxx"
#include "adjitem.hxx"
#include "orphitem.hxx"
#include "widwitem.hxx"
#include "tstpitem.hxx"
#include "pmdlitem.hxx"
#include "spltitem.hxx"
#include "hyznitem.hxx"
#include "charscaleitem.hxx"
#include "charrotateitem.hxx"
#include "charreliefitem.hxx"
#include "paravertalignitem.hxx"
#include "forbiddenruleitem.hxx"
#include "hngpnctitem.hxx"
#include "scriptspaceitem.hxx"
#include "frmdiritem.hxx"
#include "charhiddenitem.hxx"


#ifndef _RTFTOKEN_H
#include <svtools/rtftoken.h>
#endif
#ifndef _SFXITEMPOOL_HXX //autogen
#include <svtools/itempool.hxx>
#endif
#ifndef _SFXITEMITER_HXX
#include <svtools/itemiter.hxx>
#endif

#include "svxrtf.hxx"


#define BRACELEFT   '{'
#define BRACERIGHT  '}'


// einige Hilfs-Funktionen
// char
inline const SvxEscapementItem& GetEscapement(const SfxItemSet& rSet,USHORT nId,BOOL bInP=TRUE)
    { return (const SvxEscapementItem&)rSet.Get( nId,bInP); }
inline const SvxLineSpacingItem& GetLineSpacing(const SfxItemSet& rSet,USHORT nId,BOOL bInP=TRUE)
    { return (const SvxLineSpacingItem&)rSet.Get( nId,bInP); }
inline const SvxUnderlineItem& GetUnderline(const SfxItemSet& rSet,USHORT nId,BOOL bInP=TRUE)
    { return (const SvxUnderlineItem&)rSet.Get( nId,bInP); }
// frm
inline const SvxLRSpaceItem& GetLRSpace(const SfxItemSet& rSet,USHORT nId,BOOL bInP=TRUE)
    { return (const SvxLRSpaceItem&)rSet.Get( nId,bInP); }
inline const SvxULSpaceItem& GetULSpace(const SfxItemSet& rSet,USHORT nId,BOOL bInP=TRUE)
    { return (const SvxULSpaceItem&)rSet.Get( nId,bInP); }

#define PARDID      ((RTFPardAttrMapIds*)aPardMap.GetData())
#define PLAINID     ((RTFPlainAttrMapIds*)aPlainMap.GetData())


enum RTF_CharTypeDef
{
    NOTDEF_CHARTYPE,
    LOW_CHARTYPE,
    HIGH_CHARTYPE,
    DOUBLEBYTE_CHARTYPE
};


void SvxRTFParser::SetScriptAttr( USHORT eType, SfxItemSet& rSet,
                                    SfxPoolItem& rItem )
{
    const USHORT *pNormal = 0, *pCJK = 0, *pCTL = 0;
    const RTFPlainAttrMapIds* pIds = (RTFPlainAttrMapIds*)aPlainMap.GetData();
    switch( rItem.Which() )
    {
    case SID_ATTR_CHAR_FONT:
        pNormal = &pIds->nFont;
        pCJK = &pIds->nCJKFont;
        pCTL = &pIds->nCTLFont;
        break;

    case SID_ATTR_CHAR_FONTHEIGHT:
        pNormal = &pIds->nFontHeight;
        pCJK = &pIds->nCJKFontHeight;
        pCTL = &pIds->nCTLFontHeight;
        break;

    case SID_ATTR_CHAR_POSTURE:
        pNormal = &pIds->nPosture;
        pCJK = &pIds->nCJKPosture;
        pCTL = &pIds->nCTLPosture;
        break;

    case SID_ATTR_CHAR_WEIGHT:
        pNormal = &pIds->nWeight;
        pCJK = &pIds->nCJKWeight;
        pCTL = &pIds->nCTLWeight;
        break;

    case SID_ATTR_CHAR_LANGUAGE:
        pNormal = &pIds->nLanguage;
        pCJK = &pIds->nCJKLanguage;
        pCTL = &pIds->nCTLLanguage;
        break;

    case 0:
        // it exist no WhichId - don't set this item
        break;

    default:
       rSet.Put( rItem );
       break;
    }


    if( DOUBLEBYTE_CHARTYPE == eType )
    {
        if( bIsLeftToRightDef && *pCJK )
        {
            rItem.SetWhich( *pCJK );
            rSet.Put( rItem );
        }
    }
    else if( !bIsLeftToRightDef )
    {
        if( *pCTL )
        {
            rItem.SetWhich( *pCTL );
            rSet.Put( rItem );
        }
    }
    else
    {
        if( LOW_CHARTYPE == eType || HIGH_CHARTYPE == eType )
        {
            if( *pNormal )
            {
                rItem.SetWhich( *pNormal );
                rSet.Put( rItem );
            }
        }
        else
        {
            if( *pCJK )
            {
                rItem.SetWhich( *pCJK );
                rSet.Put( rItem );
            }
            if( *pCTL )
            {
                rItem.SetWhich( *pCTL );
                rSet.Put( rItem );
            }
            if( *pNormal )
            {
                rItem.SetWhich( *pNormal );
                rSet.Put( rItem );
            }
        }
    }
}

// --------------------

void SvxRTFParser::ReadAttr( int nToken, SfxItemSet* pSet )
{
    DBG_ASSERT( pSet, "Es muss ein SfxItemSet uebergeben werden!" );
    int bFirstToken = TRUE, bWeiter = TRUE;
    USHORT nStyleNo = 0;        // default
    FontUnderline eUnderline;
    FontEmphasisMark eEmphasis;
    bPardTokenRead = FALSE;
    RTF_CharTypeDef eCharType = NOTDEF_CHARTYPE;
    USHORT nFontAlign;

    int bChkStkPos = !bNewGroup && aAttrStack.Top();

    while( bWeiter && IsParserWorking() )           // solange bekannte Attribute erkannt werden
    {
        switch( nToken )
        {
        case RTF_PARD:
            RTFPardPlain( TRUE, &pSet );
            ResetPard();
            nStyleNo = 0;
            bPardTokenRead = TRUE;
            break;

        case RTF_PLAIN:
            RTFPardPlain( FALSE, &pSet );
            break;

        default:
            do {        // middle checked loop
                if( !bChkStkPos )
                    break;

                SvxRTFItemStackType* pAkt = aAttrStack.Top();
                if( !pAkt || (pAkt->pSttNd->GetIdx() == pInsPos->GetNodeIdx() &&
                    pAkt->nSttCnt == pInsPos->GetCntIdx() ))
                    break;

                int nLastToken = GetStackPtr(-1)->nTokenId;
                if( RTF_PARD == nLastToken || RTF_PLAIN == nLastToken )
                    break;

                if( pAkt->aAttrSet.Count() || pAkt->pChildList ||
                    pAkt->nStyleNo )
                {
                    // eine neue Gruppe aufmachen
                    SvxRTFItemStackType* pNew = new SvxRTFItemStackType(
                                                *pAkt, *pInsPos, TRUE );
                    pNew->SetRTFDefaults( GetRTFDefaults() );

                    // alle bis hierher gueltigen Attribute "setzen"
                    AttrGroupEnd();
                    pAkt = aAttrStack.Top();  // can be changed after AttrGroupEnd!
                    pNew->aAttrSet.SetParent( pAkt ? &pAkt->aAttrSet : 0 );

                    aAttrStack.Push( pNew );
                    pAkt = pNew;
                }
                else
                    // diesen Eintrag als neuen weiterbenutzen
                    pAkt->SetStartPos( *pInsPos );

                pSet = &pAkt->aAttrSet;
            } while( FALSE );

            switch( nToken )
            {
            case RTF_INTBL:
            case RTF_PAGEBB:
            case RTF_SBYS:
            case RTF_CS:
            case RTF_LS:
            case RTF_ILVL:
                    UnknownAttrToken( nToken, pSet );
                    break;

            case RTF_S:
                if( bIsInReadStyleTab )
                {
                    if( !bFirstToken )
                        SkipToken( -1 );
                    bWeiter = FALSE;
                }
                else
                {
                    nStyleNo = -1 == nTokenValue ? 0 : USHORT(nTokenValue);
                    // setze am akt. auf dem AttrStack stehenden Style die
                    // StyleNummer
                    SvxRTFItemStackType* pAkt = aAttrStack.Top();
                    if( !pAkt )
                        break;

                    pAkt->nStyleNo = USHORT( nStyleNo );

#if 0
// JP 05.09.95: zuruecksetzen der Style-Attribute fuehrt nur zu Problemen.
//              Es muss reichen, wenn das ueber pard/plain erfolgt
//  ansonsten Bugdoc 15304.rtf - nach nur "\pard" falscher Font !!

                    SvxRTFStyleType* pStyle = aStyleTbl.Get( pAkt->nStyleNo );
                    if( pStyle && pStyle->aAttrSet.Count() )
                    {
                        //JP 07.07.95:
                        // alle Attribute, die in der Vorlage gesetzt werden
                        // auf defaults setzen. In RTF werden die Attribute
                        // der Vorlage danach ja wiederholt.
                        // WICHTIG: Attribute die in der Vorlage definiert
                        //          sind, werden zurueckgesetzt !!!!
                        // pAkt->aAttrSet.Put( pStyle->aAttrSet );

                        SfxItemIter aIter( pStyle->aAttrSet );
                        SfxItemPool* pPool = pStyle->aAttrSet.GetPool();
                        USHORT nWh = aIter.GetCurItem()->Which();
                        while( TRUE )
                        {
                            pAkt->aAttrSet.Put( pPool->GetDefaultItem( nWh ));
                            if( aIter.IsAtEnd() )
                                break;
                            nWh = aIter.NextItem()->Which();
                        }
                    }
#endif
                }
                break;

            case RTF_KEEP:
                if( PARDID->nSplit )
                {
                    pSet->Put( SvxFmtSplitItem( FALSE, PARDID->nSplit ));
                }
                break;

            case RTF_KEEPN:
                if( PARDID->nKeep )
                {
                    pSet->Put( SvxFmtKeepItem( TRUE, PARDID->nKeep ));
                }
                break;

            case RTF_LEVEL:
                if( PARDID->nOutlineLvl )
                {
                    pSet->Put( SfxUInt16Item( PARDID->nOutlineLvl,
                                                (UINT16)nTokenValue ));
                }
                break;

            case RTF_QL:
                if( PARDID->nAdjust )
                {
                    pSet->Put( SvxAdjustItem( SVX_ADJUST_LEFT, PARDID->nAdjust ));
                }
                break;
            case RTF_QR:
                if( PARDID->nAdjust )
                {
                    pSet->Put( SvxAdjustItem( SVX_ADJUST_RIGHT, PARDID->nAdjust ));
                }
                break;
            case RTF_QJ:
                if( PARDID->nAdjust )
                {
                    pSet->Put( SvxAdjustItem( SVX_ADJUST_BLOCK, PARDID->nAdjust ));
                }
                break;
            case RTF_QC:
                if( PARDID->nAdjust )
                {
                    pSet->Put( SvxAdjustItem( SVX_ADJUST_CENTER, PARDID->nAdjust ));
                }
                break;

            case RTF_FI:
                if( PARDID->nLRSpace )
                {
                    SvxLRSpaceItem aLR( GetLRSpace(*pSet, PARDID->nLRSpace ));
                    USHORT nSz = 0;
                    if( -1 != nTokenValue )
                    {
                        if( IsCalcValue() )
                            CalcValue();
                        nSz = USHORT(nTokenValue);
                    }
                    aLR.SetTxtFirstLineOfst( nSz );
                    pSet->Put( aLR );
                }
                break;

            case RTF_LI:
            case RTF_LIN:
                if( PARDID->nLRSpace )
                {
                    SvxLRSpaceItem aLR( GetLRSpace(*pSet, PARDID->nLRSpace ));
                    USHORT nSz = 0;
                    if( 0 < nTokenValue )
                    {
                        if( IsCalcValue() )
                            CalcValue();
                        nSz = USHORT(nTokenValue);
                    }
                    aLR.SetTxtLeft( nSz );
                    pSet->Put( aLR );
                }
                break;

            case RTF_RI:
            case RTF_RIN:
                if( PARDID->nLRSpace )
                {
                    SvxLRSpaceItem aLR( GetLRSpace(*pSet, PARDID->nLRSpace ));
                    USHORT nSz = 0;
                    if( 0 < nTokenValue )
                    {
                        if( IsCalcValue() )
                            CalcValue();
                        nSz = USHORT(nTokenValue);
                    }
                    aLR.SetRight( nSz );
                    pSet->Put( aLR );
                }
                break;

            case RTF_SB:
                if( PARDID->nULSpace )
                {
                    SvxULSpaceItem aUL( GetULSpace(*pSet, PARDID->nULSpace ));
                    USHORT nSz = 0;
                    if( 0 < nTokenValue )
                    {
                        if( IsCalcValue() )
                            CalcValue();
                        nSz = USHORT(nTokenValue);
                    }
                    aUL.SetUpper( nSz );
                    pSet->Put( aUL );
                }
                break;

            case RTF_SA:
                if( PARDID->nULSpace )
                {
                    SvxULSpaceItem aUL( GetULSpace(*pSet, PARDID->nULSpace ));
                    USHORT nSz = 0;
                    if( 0 < nTokenValue )
                    {
                        if( IsCalcValue() )
                            CalcValue();
                        nSz = USHORT(nTokenValue);
                    }
                    aUL.SetLower( nSz );
                    pSet->Put( aUL );
                }
                break;

            case RTF_SLMULT:
                if( PARDID->nLinespacing && 1 == nTokenValue )
                {
                    // dann wird auf mehrzeilig umgeschaltet!
                    SvxLineSpacingItem aLSpace( GetLineSpacing( *pSet,
                                                PARDID->nLinespacing, FALSE ));

                    // wieviel bekommt man aus dem LineHeight Wert heraus

                    // Proportionale-Groesse:
                    // D.H. das Verhaeltnis ergibt sich aus ( n / 240 ) Twips

                    nTokenValue = 240;
                    if( IsCalcValue() )
                        CalcValue();

                    nTokenValue = short( 100L * aLSpace.GetLineHeight()
                                            / long( nTokenValue ) );

                    if( nTokenValue > 200 )     // Datenwert fuer PropLnSp
                        nTokenValue = 200;      // ist ein BYTE !!!

                    aLSpace.SetPropLineSpace( (const BYTE)nTokenValue );
                    aLSpace.GetLineSpaceRule() = SVX_LINE_SPACE_AUTO;

                    pSet->Put( aLSpace );
                }
                break;

            case RTF_SL:
                if( PARDID->nLinespacing )
                {
                    // errechne das Verhaeltnis aus dem default Font zu der
                    // Size Angabe. Der Abstand besteht aus der Zeilenhoehe
                    // (100%) und dem Leerraum ueber der Zeile (20%).
                    SvxLineSpacingItem aLSpace(0, PARDID->nLinespacing);

                    nTokenValue = !bTokenHasValue ? 0 : nTokenValue;
                    if (1000 == nTokenValue )
                        nTokenValue = 240;

                    SvxLineSpace eLnSpc;
                    if (nTokenValue < 0)
                    {
                        eLnSpc = SVX_LINE_SPACE_FIX;
                        nTokenValue = -nTokenValue;
                    }
                    else if (nTokenValue == 0)
                    {
                        //if \sl0 is used, the line spacing is automatically
                        //determined
                        eLnSpc = SVX_LINE_SPACE_AUTO;
                    }
                    else
                        eLnSpc = SVX_LINE_SPACE_MIN;

                    if (IsCalcValue())
                        CalcValue();

                    if (eLnSpc != SVX_LINE_SPACE_AUTO)
                        aLSpace.SetLineHeight( (const USHORT)nTokenValue );

                    aLSpace.GetLineSpaceRule() = eLnSpc;
                    pSet->Put(aLSpace);
                }
                break;

            case RTF_NOCWRAP:
                if( PARDID->nForbRule )
                {
                    pSet->Put( SvxForbiddenRuleItem( FALSE,
                                                    PARDID->nForbRule ));
                }
                break;
            case RTF_NOOVERFLOW:
                if( PARDID->nHangPunct )
                {
                    pSet->Put( SvxHangingPunctuationItem( FALSE,
                                                    PARDID->nHangPunct ));
                }
                break;

            case RTF_ASPALPHA:
                if( PARDID->nScriptSpace )
                {
                    pSet->Put( SvxScriptSpaceItem( TRUE,
                                                PARDID->nScriptSpace ));
                }
                break;

            case RTF_FAFIXED:
            case RTF_FAAUTO:    nFontAlign = SvxParaVertAlignItem::AUTOMATIC;
                                goto SET_FONTALIGNMENT;
            case RTF_FAHANG:    nFontAlign = SvxParaVertAlignItem::TOP;
                                goto SET_FONTALIGNMENT;
            case RTF_FAVAR:     nFontAlign = SvxParaVertAlignItem::BOTTOM;
                                goto SET_FONTALIGNMENT;
            case RTF_FACENTER:  nFontAlign = SvxParaVertAlignItem::CENTER;
                                goto SET_FONTALIGNMENT;
            case RTF_FAROMAN:   nFontAlign = SvxParaVertAlignItem::BASELINE;
                                goto SET_FONTALIGNMENT;
SET_FONTALIGNMENT:
            if( PARDID->nFontAlign )
            {
                pSet->Put( SvxParaVertAlignItem( nFontAlign,
                                                PARDID->nFontAlign ));
            }
            break;

/*  */
            case RTF_B:
            case RTF_AB:
                if( IsAttrSttPos() )    // nicht im Textfluss ?
                {

                    SvxWeightItem aTmpItem(
                                    nTokenValue ? WEIGHT_BOLD : WEIGHT_NORMAL,
                                    SID_ATTR_CHAR_WEIGHT );
                    SetScriptAttr( eCharType, *pSet, aTmpItem);
                }
                break;

            case RTF_CAPS:
            case RTF_SCAPS:
                if( PLAINID->nCaseMap &&
                    IsAttrSttPos() )        // nicht im Textfluss ?
                {
                    SvxCaseMap eCaseMap;
                    if( !nTokenValue )
                        eCaseMap = SVX_CASEMAP_NOT_MAPPED;
                    else if( RTF_CAPS == nToken )
                        eCaseMap = SVX_CASEMAP_VERSALIEN;
                    else
                        eCaseMap = SVX_CASEMAP_KAPITAELCHEN;

                    pSet->Put( SvxCaseMapItem( eCaseMap, PLAINID->nCaseMap ));
                }
                break;

            case RTF_DN:
            case RTF_SUB:
                if( PLAINID->nEscapement )
                {
                    const USHORT nEsc = PLAINID->nEscapement;
                    if( -1 == nTokenValue || RTF_SUB == nToken )
                        nTokenValue = 6;
                    if( IsCalcValue() )
                        CalcValue();
                    const SvxEscapementItem& rOld = GetEscapement( *pSet, nEsc, FALSE );
                    short nEs;
                    BYTE nProp;
                    if( DFLT_ESC_AUTO_SUPER == rOld.GetEsc() )
                    {
                        nEs = DFLT_ESC_AUTO_SUB;
                        nProp = rOld.GetProp();
                    }
                    else
                    {
                        nEs = (short)-nTokenValue;
                        nProp = (nToken == RTF_SUB) ? DFLT_ESC_PROP : 100;
                    }
                    pSet->Put( SvxEscapementItem( nEs, nProp, nEsc ));
                }
                break;

            case RTF_NOSUPERSUB:
                if( PLAINID->nEscapement )
                {
                    const USHORT nEsc = PLAINID->nEscapement;
                    pSet->Put( SvxEscapementItem( nEsc ));
                }
                break;

            case RTF_EXPND:
                if( PLAINID->nKering )
                {
                    if( -1 == nTokenValue )
                        nTokenValue = 0;
                    else
                        nTokenValue *= 5;
                    if( IsCalcValue() )
                        CalcValue();
                    pSet->Put( SvxKerningItem( (short)nTokenValue, PLAINID->nKering ));
                }
                break;

            case RTF_KERNING:
                if( PLAINID->nAutoKerning )
                {
                    if( -1 == nTokenValue )
                        nTokenValue = 0;
                    else
                        nTokenValue *= 10;
                    if( IsCalcValue() )
                        CalcValue();
                    pSet->Put( SvxAutoKernItem( 0 != nTokenValue,
                                                PLAINID->nAutoKerning ));
                }
                break;

            case RTF_EXPNDTW:
                if( PLAINID->nKering )
                {
                    if( -1 == nTokenValue )
                        nTokenValue = 0;
                    if( IsCalcValue() )
                        CalcValue();
                    pSet->Put( SvxKerningItem( (short)nTokenValue, PLAINID->nKering ));
                }
                break;

            case RTF_F:
            case RTF_AF:
                {
                    const Font& rSVFont = GetFont( USHORT(nTokenValue) );
                    SvxFontItem aTmpItem( rSVFont.GetFamily(),
                                    rSVFont.GetName(), rSVFont.GetStyleName(),
                                    rSVFont.GetPitch(), rSVFont.GetCharSet(),
                                    SID_ATTR_CHAR_FONT );
                    SetScriptAttr( eCharType, *pSet, aTmpItem );
                    if( RTF_F == nToken )
                    {
                        SetEncoding( rSVFont.GetCharSet() );
                        RereadLookahead();
                    }
                }
                break;

            case RTF_FS:
            case RTF_AFS:
                {
                    if( -1 == nTokenValue )
                        nTokenValue = 240;
                    else
                        nTokenValue *= 10;
                    if( IsCalcValue() )
                        CalcValue();
                    SvxFontHeightItem aTmpItem(
                            (const USHORT)nTokenValue, 100,
                            SID_ATTR_CHAR_FONTHEIGHT );
                    SetScriptAttr( eCharType, *pSet, aTmpItem );
                }
                break;

            case RTF_I:
            case RTF_AI:
                if( IsAttrSttPos() )        // nicht im Textfluss ?
                {
                    SvxPostureItem aTmpItem(
                                    nTokenValue ? ITALIC_NORMAL : ITALIC_NONE,
                                    SID_ATTR_CHAR_POSTURE );
                    SetScriptAttr( eCharType, *pSet, aTmpItem );
                }
                break;

            case RTF_OUTL:
                if( PLAINID->nContour &&
                    IsAttrSttPos() )        // nicht im Textfluss ?
                {
                    pSet->Put( SvxContourItem( nTokenValue ? TRUE : FALSE,
                                PLAINID->nContour ));
                }
                break;

            case RTF_SHAD:
                if( PLAINID->nShadowed &&
                    IsAttrSttPos() )        // nicht im Textfluss ?
                {
                    pSet->Put( SvxShadowedItem( nTokenValue ? TRUE : FALSE,
                                PLAINID->nShadowed ));
                }
                break;

            case RTF_STRIKE:
                if( PLAINID->nCrossedOut &&
                    IsAttrSttPos() )        // nicht im Textfluss ?
                {
                    pSet->Put( SvxCrossedOutItem(
                        nTokenValue ? STRIKEOUT_SINGLE : STRIKEOUT_NONE,
                        PLAINID->nCrossedOut ));
                }
                break;

            case RTF_STRIKED:
                if( PLAINID->nCrossedOut )      // nicht im Textfluss ?
                {
                    pSet->Put( SvxCrossedOutItem(
                        nTokenValue ? STRIKEOUT_DOUBLE : STRIKEOUT_NONE,
                        PLAINID->nCrossedOut ));
                }
                break;

            case RTF_UL:
                if( !IsAttrSttPos() )
                    break;
                eUnderline = nTokenValue ? UNDERLINE_SINGLE : UNDERLINE_NONE;
                goto ATTR_SETUNDERLINE;

            case RTF_ULD:
                eUnderline = UNDERLINE_DOTTED;
                goto ATTR_SETUNDERLINE;
            case RTF_ULDASH:
                eUnderline = UNDERLINE_DASH;
                goto ATTR_SETUNDERLINE;
            case RTF_ULDASHD:
                eUnderline = UNDERLINE_DASHDOT;
                goto ATTR_SETUNDERLINE;
            case RTF_ULDASHDD:
                eUnderline = UNDERLINE_DASHDOTDOT;
                goto ATTR_SETUNDERLINE;
            case RTF_ULDB:
                eUnderline = UNDERLINE_DOUBLE;
                goto ATTR_SETUNDERLINE;
            case RTF_ULNONE:
                eUnderline = UNDERLINE_NONE;
                goto ATTR_SETUNDERLINE;
            case RTF_ULTH:
                eUnderline = UNDERLINE_BOLD;
                goto ATTR_SETUNDERLINE;
            case RTF_ULWAVE:
                eUnderline = UNDERLINE_WAVE;
                goto ATTR_SETUNDERLINE;
            case RTF_ULTHD:
                eUnderline = UNDERLINE_BOLDDOTTED;
                goto ATTR_SETUNDERLINE;
            case RTF_ULTHDASH:
                eUnderline = UNDERLINE_BOLDDASH;
                goto ATTR_SETUNDERLINE;
            case RTF_ULLDASH:
                eUnderline = UNDERLINE_LONGDASH;
                goto ATTR_SETUNDERLINE;
            case RTF_ULTHLDASH:
                eUnderline = UNDERLINE_BOLDLONGDASH;
                goto ATTR_SETUNDERLINE;
            case RTF_ULTHDASHD:
                eUnderline = UNDERLINE_BOLDDASHDOT;
                goto ATTR_SETUNDERLINE;
            case RTF_ULTHDASHDD:
                eUnderline = UNDERLINE_BOLDDASHDOTDOT;
                goto ATTR_SETUNDERLINE;
            case RTF_ULHWAVE:
                eUnderline = UNDERLINE_BOLDWAVE;
                goto ATTR_SETUNDERLINE;
            case RTF_ULULDBWAVE:
                eUnderline = UNDERLINE_DOUBLEWAVE;
                goto ATTR_SETUNDERLINE;

            case RTF_ULW:
                eUnderline = UNDERLINE_SINGLE;

                if( PLAINID->nWordlineMode )
                {
                    pSet->Put( SvxWordLineModeItem( TRUE, PLAINID->nWordlineMode ));
                }
                goto ATTR_SETUNDERLINE;

ATTR_SETUNDERLINE:
                if( PLAINID->nUnderline )
                {
                    pSet->Put( SvxUnderlineItem( eUnderline, PLAINID->nUnderline ));
                }
                break;

            case RTF_ULC:
                if( PLAINID->nUnderline )
                {
                    SvxUnderlineItem aUL( UNDERLINE_SINGLE,
                                            PLAINID->nUnderline );
                    const SfxPoolItem* pItem;
                    if( SFX_ITEM_SET == pSet->GetItemState(
                        PLAINID->nUnderline, FALSE, &pItem ) )
                    {
                        // is switched off ?
                        if( UNDERLINE_NONE ==
                            ((SvxUnderlineItem*)pItem)->GetUnderline() )
                            break;
                        aUL = *(SvxUnderlineItem*)pItem;
                    }
                    else
                        aUL = GetUnderline( *pSet, PLAINID->nUnderline, FALSE );

                    if( UNDERLINE_NONE == aUL.GetUnderline() )
                        aUL.SetUnderline( UNDERLINE_SINGLE );
                    aUL.SetColor( GetColor( USHORT(nTokenValue) ));
                    pSet->Put( aUL );
                }
                break;

            case RTF_UP:
            case RTF_SUPER:
                if( PLAINID->nEscapement )
                {
                    const USHORT nEsc = PLAINID->nEscapement;
                    if( -1 == nTokenValue || RTF_SUPER == nToken )
                        nTokenValue = 6;
                    if( IsCalcValue() )
                        CalcValue();
                    const SvxEscapementItem& rOld = GetEscapement( *pSet, nEsc, FALSE );
                    short nEs;
                    BYTE nProp;
                    if( DFLT_ESC_AUTO_SUB == rOld.GetEsc() )
                    {
                        nEs = DFLT_ESC_AUTO_SUPER;
                        nProp = rOld.GetProp();
                    }
                    else
                    {
                        nEs = (short)nTokenValue;
                        nProp = (nToken == RTF_SUPER) ? DFLT_ESC_PROP : 100;
                    }
                    pSet->Put( SvxEscapementItem( nEs, nProp, nEsc ));
                }
                break;

            case RTF_CF:
                if( PLAINID->nColor )
                {
                    pSet->Put( SvxColorItem( GetColor( USHORT(nTokenValue) ),
                                PLAINID->nColor ));
                }
                break;
#if 0
            //#i12501# While cb is clearly documented in the rtf spec, word
            //doesn't accept it at all
            case RTF_CB:
                if( PLAINID->nBgColor )
                {
                    pSet->Put( SvxBrushItem( GetColor( USHORT(nTokenValue) ),
                                PLAINID->nBgColor ));
                }
                break;
#endif
            case RTF_LANG:
                if( PLAINID->nLanguage )
                {
                    pSet->Put( SvxLanguageItem( (LanguageType)nTokenValue,
                                PLAINID->nLanguage ));
                }
                break;

            case RTF_LANGFE:
                if( PLAINID->nCJKLanguage )
                {
                    pSet->Put( SvxLanguageItem( (LanguageType)nTokenValue,
                                                PLAINID->nCJKLanguage ));
                }
                break;
            case RTF_ALANG:
                {
                    SvxLanguageItem aTmpItem( (LanguageType)nTokenValue,
                                    SID_ATTR_CHAR_LANGUAGE );
                    SetScriptAttr( eCharType, *pSet, aTmpItem );
                }
                break;

            case RTF_RTLCH:
                bIsLeftToRightDef = FALSE;
                break;
            case RTF_LTRCH:
                bIsLeftToRightDef = TRUE;
                break;
            case RTF_RTLPAR:
                if (PARDID->nDirection)
                {
                    pSet->Put(SvxFrameDirectionItem(FRMDIR_HORI_RIGHT_TOP,
                        PARDID->nDirection));
                }
                break;
            case RTF_LTRPAR:
                if (PARDID->nDirection)
                {
                    pSet->Put(SvxFrameDirectionItem(FRMDIR_HORI_LEFT_TOP,
                        PARDID->nDirection));
                }
                break;
            case RTF_LOCH:      eCharType = LOW_CHARTYPE;           break;
            case RTF_HICH:      eCharType = HIGH_CHARTYPE;          break;
            case RTF_DBCH:      eCharType = DOUBLEBYTE_CHARTYPE;    break;


            case RTF_ACCNONE:
                eEmphasis = EMPHASISMARK_NONE;
                goto ATTR_SETEMPHASIS;
            case RTF_ACCDOT:
                eEmphasis = EMPHASISMARK_DOTS_ABOVE;
                goto ATTR_SETEMPHASIS;

            case RTF_ACCCOMMA:
                eEmphasis = EMPHASISMARK_SIDE_DOTS;
ATTR_SETEMPHASIS:
                if( PLAINID->nEmphasis )
                {
                    pSet->Put( SvxEmphasisMarkItem( eEmphasis,
                                                       PLAINID->nEmphasis ));
                }
                break;

            case RTF_TWOINONE:
                if( PLAINID->nTwoLines )
                {
                    sal_Unicode cStt, cEnd;
                    switch ( nTokenValue )
                    {
                    case 1: cStt = '(', cEnd = ')'; break;
                    case 2: cStt = '[', cEnd = ']'; break;
                    case 3: cStt = '<', cEnd = '>'; break;
                    case 4: cStt = '{', cEnd = '}'; break;
                    default: cStt = 0, cEnd = 0; break;
                    }

                    pSet->Put( SvxTwoLinesItem( TRUE, cStt, cEnd,
                                                       PLAINID->nTwoLines ));
                }
                break;

            case RTF_CHARSCALEX :
                if (PLAINID->nCharScaleX)
                {
                    //i21372
                    if (nTokenValue < 1 || nTokenValue > 600)
                        nTokenValue = 100;
                    pSet->Put( SvxCharScaleWidthItem( USHORT(nTokenValue),
                                                       PLAINID->nCharScaleX ));
                }
                break;

            case RTF_HORZVERT:
                if( PLAINID->nHorzVert )
                {
                    // RTF knows only 90deg
                    pSet->Put( SvxCharRotateItem( 900, 1 == nTokenValue,
                                                       PLAINID->nHorzVert ));
                }
                break;

            case RTF_EMBO:
                if (PLAINID->nRelief)
                {
                    pSet->Put(SvxCharReliefItem(RELIEF_EMBOSSED,
                        PLAINID->nRelief));
                }
                break;
            case RTF_IMPR:
                if (PLAINID->nRelief)
                {
                    pSet->Put(SvxCharReliefItem(RELIEF_ENGRAVED,
                        PLAINID->nRelief));
                }
                break;
            case RTF_V:
                if (PLAINID->nHidden)
                {
                    pSet->Put(SvxCharHiddenItem(nTokenValue != 0,
                        PLAINID->nHidden));
                }
                break;
            case RTF_CHBGFDIAG:
            case RTF_CHBGDKVERT:
            case RTF_CHBGDKHORIZ:
            case RTF_CHBGVERT:
            case RTF_CHBGHORIZ:
            case RTF_CHBGDKFDIAG:
            case RTF_CHBGDCROSS:
            case RTF_CHBGCROSS:
            case RTF_CHBGBDIAG:
            case RTF_CHBGDKDCROSS:
            case RTF_CHBGDKCROSS:
            case RTF_CHBGDKBDIAG:
            case RTF_CHCBPAT:
            case RTF_CHCFPAT:
            case RTF_CHSHDNG:
                if( PLAINID->nBgColor )
                    ReadBackgroundAttr( nToken, *pSet );
                break;


/*  */

            case BRACELEFT:
                {
                    // teste auf Swg-Interne Tokens
                    bool bHandled = false;
                    short nSkip = 0;
                    if( RTF_IGNOREFLAG != GetNextToken())
                        nSkip = -1;
                    else if( (nToken = GetNextToken() ) & RTF_SWGDEFS )
                    {
                        bHandled = true;
                        switch( nToken )
                        {
                        case RTF_PGDSCNO:
                        case RTF_PGBRK:
                        case RTF_SOUTLVL:
                            UnknownAttrToken( nToken, pSet );
                            // ueberlese die schliessende Klammer
                            break;

                        case RTF_SWG_ESCPROP:
                            {
                                // prozentuale Veraenderung speichern !
                                BYTE nProp = BYTE( nTokenValue / 100 );
                                short nEsc = 0;
                                if( 1 == ( nTokenValue % 100 ))
                                    // Erkennung unseres AutoFlags!
                                    nEsc = DFLT_ESC_AUTO_SUPER;

                                if( PLAINID->nEscapement )
                                    pSet->Put( SvxEscapementItem( nEsc, nProp,
                                                       PLAINID->nEscapement ));
                            }
                            break;

                        case RTF_HYPHEN:
                            {
                                SvxHyphenZoneItem aHypenZone(
                                            (nTokenValue & 1) ? TRUE : FALSE,
                                                PARDID->nHyphenzone );
                                aHypenZone.SetPageEnd(
                                            (nTokenValue & 2) ? TRUE : FALSE );

                                if( PARDID->nHyphenzone &&
                                    RTF_HYPHLEAD == GetNextToken() &&
                                    RTF_HYPHTRAIL == GetNextToken() &&
                                    RTF_HYPHMAX == GetNextToken() )
                                {
                                    aHypenZone.GetMinLead() =
                                        BYTE(GetStackPtr( -2 )->nTokenValue);
                                    aHypenZone.GetMinTrail() =
                                            BYTE(GetStackPtr( -1 )->nTokenValue);
                                    aHypenZone.GetMaxHyphens() =
                                            BYTE(nTokenValue);

                                    pSet->Put( aHypenZone );
                                }
                                else
                                    SkipGroup();        // ans Ende der Gruppe
                            }
                            break;

                        case RTF_SHADOW:
                            {
                                int bSkip = TRUE;
                                do {    // middle check loop
                                    SvxShadowLocation eSL = SvxShadowLocation( nTokenValue );
                                    if( RTF_SHDW_DIST != GetNextToken() )
                                        break;
                                    USHORT nDist = USHORT( nTokenValue );

                                    if( RTF_SHDW_STYLE != GetNextToken() )
                                        break;
                                    //! (pb) class Brush removed -> obsolete
                                    //! BrushStyle eStyle = BrushStyle( nTokenValue );

                                    if( RTF_SHDW_COL != GetNextToken() )
                                        break;
                                    USHORT nCol = USHORT( nTokenValue );

                                    if( RTF_SHDW_FCOL != GetNextToken() )
                                        break;
                                    USHORT nFillCol = USHORT( nTokenValue );

                                    Color aColor = GetColor( nCol );

                                    if( PARDID->nShadow )
                                        pSet->Put( SvxShadowItem( PARDID->nShadow,
                                                                  &aColor, nDist, eSL ) );

                                    bSkip = FALSE;
                                } while( FALSE );

                                if( bSkip )
                                    SkipGroup();        // ans Ende der Gruppe
                            }
                            break;

                        default:
                            bHandled = false;
                            if( (nToken & ~(0xff | RTF_SWGDEFS)) == RTF_TABSTOPDEF )
                            {
                                nToken = SkipToken( -2 );
                                ReadTabAttr( nToken, *pSet );
                            }
                            else if( (nToken & ~(0xff| RTF_SWGDEFS)) == RTF_BRDRDEF)
                            {
                                nToken = SkipToken( -2 );
                                ReadBorderAttr( nToken, *pSet );
                            }
                            else        // also kein Attribut mehr
                                nSkip = -2;
                            break;
                        }

#if 1
                        /*
                        cmc: #i4727# / #i12713# Who owns this closing bracket?
                        If we read the opening one, we must read this one, if
                        other is counting the brackets so as to push/pop off
                        the correct environment then we will have pushed a new
                        environment for the start { of this, but will not see
                        the } and so is out of sync for the rest of the
                        document.
                        */
                        if (bHandled && !bFirstToken)
                            GetNextToken();
#endif
                    }
                    else
                        nSkip = -2;

                    if( nSkip )             // alles voellig unbekannt
                    {
                        if (!bFirstToken)
                            --nSkip;    // BRACELEFT: ist das naechste Token
                        SkipToken( nSkip );
                        bWeiter = FALSE;
                    }
                }
                break;
            default:
                if( (nToken & ~0xff ) == RTF_TABSTOPDEF )
                    ReadTabAttr( nToken, *pSet );
                else if( (nToken & ~0xff ) == RTF_BRDRDEF )
                    ReadBorderAttr( nToken, *pSet );
                else if( (nToken & ~0xff ) == RTF_SHADINGDEF )
                    ReadBackgroundAttr( nToken, *pSet );
                else
                {
                    // kenne das Token nicht also das Token "in den Parser zurueck"
                    if( !bFirstToken )
                        SkipToken( -1 );
                    bWeiter = FALSE;
                }
            }
        }
        if( bWeiter )
        {
            nToken = GetNextToken();
        }
        bFirstToken = FALSE;
    }

/*
    // teste Attribute gegen ihre Styles
    if( IsChkStyleAttr() && pSet->Count() && !pInsPos->GetCntIdx() )
    {
        SvxRTFStyleType* pStyle = aStyleTbl.Get( nStyleNo );
        if( pStyle && pStyle->aAttrSet.Count() )
        {
            // alle Attribute, die schon vom Style definiert sind, aus dem
            // akt. Set entfernen
            const SfxPoolItem* pItem;
            SfxItemIter aIter( *pSet );
            USHORT nWhich = aIter.GetCurItem()->Which();
            while( TRUE )
            {
                if( SFX_ITEM_SET == pStyle->aAttrSet.GetItemState(
                    nWhich, FALSE, &pItem ) && *pItem == *aIter.GetCurItem())
                    pSet->ClearItem( nWhich );      // loeschen

                if( aIter.IsAtEnd() )
                    break;
                nWhich = aIter.NextItem()->Which();
            }
        }
    }
*/
}

void SvxRTFParser::ReadTabAttr( int nToken, SfxItemSet& rSet )
{
    // dann lese doch mal alle TabStops ein
    SvxTabStop aTabStop;
    SvxTabStopItem aAttr( 0, 0, SVX_TAB_ADJUST_DEFAULT, PARDID->nTabStop );
    int bWeiter = TRUE;
    do {
        switch( nToken )
        {
        case RTF_TB:        // BarTab ???
        case RTF_TX:
            {
                if( IsCalcValue() )
                    CalcValue();
                aTabStop.GetTabPos() = nTokenValue;
                aAttr.Insert( aTabStop );
                aTabStop = SvxTabStop();    // alle Werte default
            }
            break;

        case RTF_TQL:
            aTabStop.GetAdjustment() = SVX_TAB_ADJUST_LEFT;
            break;
        case RTF_TQR:
            aTabStop.GetAdjustment() = SVX_TAB_ADJUST_RIGHT;
            break;
        case RTF_TQC:
            aTabStop.GetAdjustment() = SVX_TAB_ADJUST_CENTER;
            break;
        case RTF_TQDEC:
            aTabStop.GetAdjustment() = SVX_TAB_ADJUST_DECIMAL;
            break;

        case RTF_TLDOT:     aTabStop.GetFill() = '.';   break;
        case RTF_TLHYPH:    aTabStop.GetFill() = ' ';   break;
        case RTF_TLUL:      aTabStop.GetFill() = '_';   break;
        case RTF_TLTH:      aTabStop.GetFill() = '-';   break;
        case RTF_TLEQ:      aTabStop.GetFill() = '=';   break;

        case BRACELEFT:
            {
                // Swg - Kontrol BRACELEFT RTF_IGNOREFLAG RTF_TLSWG BRACERIGHT
                short nSkip = 0;
                if( RTF_IGNOREFLAG != GetNextToken() )
                    nSkip = -1;
                else if( RTF_TLSWG != ( nToken = GetNextToken() ))
                    nSkip = -2;
                else
                {
                    aTabStop.GetDecimal() = BYTE(nTokenValue & 0xff);
                    aTabStop.GetFill() = BYTE((nTokenValue >> 8) & 0xff);
                    // ueberlese noch die schliessende Klammer
                    GetNextToken();
                }
                if( nSkip )
                {
                    SkipToken( nSkip );     // Ignore wieder zurueck
                    bWeiter = FALSE;
                }
            }
            break;

        default:
            bWeiter = FALSE;
        }
        if( bWeiter )
            nToken = GetNextToken();
    } while( bWeiter );

    // mit Defaults aufuellen fehlt noch !!!
    rSet.Put( aAttr );
    SkipToken( -1 );
}

static void SetBorderLine( int nBorderTyp, SvxBoxItem& rItem,
                            const SvxBorderLine& rBorder )
{
    switch( nBorderTyp )
    {
    case RTF_BOX:           // alle Stufen durchlaufen

    case RTF_BRDRT:
        rItem.SetLine( &rBorder, BOX_LINE_TOP );
        if( RTF_BOX != nBorderTyp )
            return;

    case RTF_BRDRB:
        rItem.SetLine( &rBorder, BOX_LINE_BOTTOM );
        if( RTF_BOX != nBorderTyp )
            return;

    case RTF_BRDRL:
        rItem.SetLine( &rBorder, BOX_LINE_LEFT );
        if( RTF_BOX != nBorderTyp )
            return;

    case RTF_BRDRR:
        rItem.SetLine( &rBorder, BOX_LINE_RIGHT );
        if( RTF_BOX != nBorderTyp )
            return;
    }
}

void SvxRTFParser::ReadBorderAttr( int nToken, SfxItemSet& rSet,
                                    int bTableDef )
{
    // dann lese doch mal das BoderAttribut ein
    SvxBoxItem aAttr( PARDID->nBox );
    const SfxPoolItem* pItem;
    if( SFX_ITEM_SET == rSet.GetItemState( PARDID->nBox, FALSE, &pItem ) )
        aAttr = *(SvxBoxItem*)pItem;

    SvxBorderLine aBrd( 0, DEF_LINE_WIDTH_0, 0, 0 );    // einfache Linien
    int bWeiter = TRUE, nBorderTyp = 0;

    do {
        switch( nToken )
        {
        case RTF_BOX:
        case RTF_BRDRT:
        case RTF_BRDRB:
        case RTF_BRDRL:
        case RTF_BRDRR:
            nBorderTyp = nToken;
            goto SETBORDER;

        case RTF_CLBRDRT:
            if( !bTableDef )
                break;
            nBorderTyp = RTF_BRDRT;
            goto SETBORDER;
        case RTF_CLBRDRB:
            if( !bTableDef )
                break;
            nBorderTyp = RTF_BRDRB;
            goto SETBORDER;
        case RTF_CLBRDRL:
            if( !bTableDef )
                break;
            nBorderTyp = RTF_BRDRL;
            goto SETBORDER;
        case RTF_CLBRDRR:
            if( !bTableDef )
                break;
            nBorderTyp = RTF_BRDRR;
            goto SETBORDER;

SETBORDER:
            {
                // auf defaults setzen
                aBrd.SetOutWidth( DEF_LINE_WIDTH_0 );
                aBrd.SetInWidth( 0 );
                aBrd.SetDistance( 0 );
                aBrd.SetColor( Color( COL_BLACK ) );
            }
            break;


// werden noch nicht ausgewertet
        case RTF_BRSP:
            {
                switch( nBorderTyp )
                {
                case RTF_BRDRB:
                    aAttr.SetDistance( (USHORT)nTokenValue, BOX_LINE_BOTTOM );
                    break;

                case RTF_BRDRT:
                    aAttr.SetDistance( (USHORT)nTokenValue, BOX_LINE_TOP );
                    break;

                case RTF_BRDRL:
                    aAttr.SetDistance( (USHORT)nTokenValue, BOX_LINE_LEFT );
                    break;

                case RTF_BRDRR:
                    aAttr.SetDistance( (USHORT)nTokenValue, BOX_LINE_RIGHT );
                    break;

                case RTF_BOX:
                    aAttr.SetDistance( (USHORT)nTokenValue );
                    break;
                }
            }
            break;

case RTF_BRDRBTW:
case RTF_BRDRBAR:           break;


        case RTF_BRDRCF:
            {
                aBrd.SetColor( GetColor( USHORT(nTokenValue) ) );
                SetBorderLine( nBorderTyp, aAttr, aBrd );
            }
            break;

        case RTF_BRDRTH:
            aBrd.SetOutWidth( DEF_LINE_WIDTH_1 );
            aBrd.SetInWidth( 0 );
            aBrd.SetDistance( 0 );
            goto SETBORDERLINE;
            break;

        case RTF_BRDRDB:
            aBrd.SetOutWidth( DEF_DOUBLE_LINE0_OUT );
            aBrd.SetInWidth( DEF_DOUBLE_LINE0_IN );
            aBrd.SetDistance( DEF_DOUBLE_LINE0_DIST );
            goto SETBORDERLINE;
            break;

        case RTF_BRDRSH:
            // schattierte Box
            {
                rSet.Put( SvxShadowItem( PARDID->nShadow, (Color*) 0, 60 /*3pt*/,
                                        SVX_SHADOW_BOTTOMRIGHT ) );
            }
            break;

        case RTF_BRDRW:
            if( -1 != nTokenValue )
            {
                // sollte es eine "dicke" Linie sein ?
                if( DEF_LINE_WIDTH_0 != aBrd.GetOutWidth() )
                    nTokenValue *= 2;

                // eine Doppelline?
                if( aBrd.GetInWidth() )
                {
                    // WinWord - Werte an StarOffice anpassen
                    if( nTokenValue < DEF_LINE_WIDTH_1 - (DEF_LINE_WIDTH_1/10))
                    {
                        aBrd.SetOutWidth( DEF_DOUBLE_LINE0_OUT );
                        aBrd.SetInWidth( DEF_DOUBLE_LINE0_IN );
                        aBrd.SetDistance( DEF_DOUBLE_LINE0_DIST );
                    }
                    else
                    if( nTokenValue < DEF_LINE_WIDTH_2 - (DEF_LINE_WIDTH_2/10))
                    {
                        aBrd.SetOutWidth( DEF_DOUBLE_LINE1_OUT );
                        aBrd.SetInWidth( DEF_DOUBLE_LINE1_IN );
                        aBrd.SetDistance( DEF_DOUBLE_LINE1_DIST );
                    }
                    else
                    {
                        aBrd.SetOutWidth( DEF_DOUBLE_LINE2_OUT );
                        aBrd.SetInWidth( DEF_DOUBLE_LINE2_IN );
                        aBrd.SetDistance( DEF_DOUBLE_LINE2_DIST );
                    }
                }
                else
                {
                    // WinWord - Werte an StarOffice anpassen
                    if( nTokenValue < DEF_LINE_WIDTH_1 - (DEF_LINE_WIDTH_1/10))
                        aBrd.SetOutWidth( DEF_LINE_WIDTH_0 );
                    else
                    if( nTokenValue < DEF_LINE_WIDTH_2 - (DEF_LINE_WIDTH_2/10))
                        aBrd.SetOutWidth( DEF_LINE_WIDTH_1 );
                    else
                    if( nTokenValue < DEF_LINE_WIDTH_3 - (DEF_LINE_WIDTH_3/10))
                        aBrd.SetOutWidth( DEF_LINE_WIDTH_2 );
                    else
                    if( nTokenValue < DEF_LINE_WIDTH_4 )
                        aBrd.SetOutWidth( DEF_LINE_WIDTH_3 );
                    else
                        aBrd.SetOutWidth( DEF_LINE_WIDTH_4 );
                }
            }
            goto SETBORDERLINE;

        case RTF_BRDRS:
        case RTF_BRDRDOT:
        case RTF_BRDRHAIR:
        case RTF_BRDRDASH:
SETBORDERLINE:
            SetBorderLine( nBorderTyp, aAttr, aBrd );
            break;

        case BRACELEFT:
            {
                short nSkip = 0;
                if( RTF_IGNOREFLAG != GetNextToken() )
                    nSkip = -1;
                else
                {
                    int bSwgControl = TRUE, bFirstToken = TRUE;
                    nToken = GetNextToken();
                    do {
                        switch( nToken )
                        {
                        case RTF_BRDBOX:
                            aAttr.SetDistance( USHORT(nTokenValue) );
                            break;

                        case RTF_BRDRT:
                        case RTF_BRDRB:
                        case RTF_BRDRR:
                        case RTF_BRDRL:
                            nBorderTyp = nToken;
                            bFirstToken = FALSE;
                            if( RTF_BRDLINE_COL != GetNextToken() )
                            {
                                bSwgControl = FALSE;
                                break;
                            }
                            aBrd.SetColor( GetColor( USHORT(nTokenValue) ));

                            if( RTF_BRDLINE_IN != GetNextToken() )
                            {
                                bSwgControl = FALSE;
                                break;
                            }
                            aBrd.SetInWidth( USHORT(nTokenValue));

                            if( RTF_BRDLINE_OUT != GetNextToken() )
                            {
                                bSwgControl = FALSE;
                                break;
                            }
                            aBrd.SetOutWidth( USHORT(nTokenValue));

                            if( RTF_BRDLINE_DIST != GetNextToken() )
                            {
                                bSwgControl = FALSE;
                                break;
                            }
                            aBrd.SetDistance( USHORT(nTokenValue));
                            SetBorderLine( nBorderTyp, aAttr, aBrd );
                            break;

                        default:
                            bSwgControl = FALSE;
                            break;
                        }

                        if( bSwgControl )
                        {
                            nToken = GetNextToken();
                            bFirstToken = FALSE;
                        }
                    } while( bSwgControl );

                    // Ende der Swg-Gruppe
                    // -> lese noch die schliessende Klammer
                    if( BRACERIGHT == nToken )
                        ;
                    else if( !bFirstToken )
                    {
                        // es ist ein Parser-Fehler, springe zum
                        // Ende der Gruppe
                        SkipGroup();
                        // schliessende BRACERIGHT ueberspringen
                        GetNextToken();
                    }
                    else
                        nSkip = -2;
                }

                if( nSkip )
                {
                    SkipToken( nSkip );     // Ignore wieder zurueck
                    bWeiter = FALSE;
                }
            }
            break;

        default:
            bWeiter = (nToken & ~(0xff| RTF_SWGDEFS)) == RTF_BRDRDEF;
        }
        if( bWeiter )
            nToken = GetNextToken();
    } while( bWeiter );
    rSet.Put( aAttr );
    SkipToken( -1 );
}

inline ULONG CalcShading( ULONG nColor, ULONG nFillColor, BYTE nShading )
{
    nColor = (nColor * nShading) / 100;
    nFillColor = (nFillColor * ( 100 - nShading )) / 100;
    return nColor + nFillColor;
}

void SvxRTFParser::ReadBackgroundAttr( int nToken, SfxItemSet& rSet,
                                        int bTableDef )
{
    // dann lese doch mal das BoderAttribut ein
    int bWeiter = TRUE;
    USHORT nColor = USHRT_MAX, nFillColor = USHRT_MAX;
    BYTE nFillValue = 0;

    USHORT nWh = ( nToken & ~0xff ) == RTF_CHRFMT
                    ? PLAINID->nBgColor
                    : PARDID->nBrush;

    do {
        switch( nToken )
        {
        case RTF_CLCBPAT:
        case RTF_CHCBPAT:
        case RTF_CBPAT:
            nFillColor = USHORT( nTokenValue );
            break;

        case RTF_CLCFPAT:
        case RTF_CHCFPAT:
        case RTF_CFPAT:
            nColor = USHORT( nTokenValue );
            break;

        case RTF_CLSHDNG:
        case RTF_CHSHDNG:
        case RTF_SHADING:
            nFillValue = (BYTE)( nTokenValue / 100 );
            break;

        case RTF_CLBGDKHOR:
        case RTF_CHBGDKHORIZ:
        case RTF_BGDKHORIZ:
        case RTF_CLBGDKVERT:
        case RTF_CHBGDKVERT:
        case RTF_BGDKVERT:
        case RTF_CLBGDKBDIAG:
        case RTF_CHBGDKBDIAG:
        case RTF_BGDKBDIAG:
        case RTF_CLBGDKFDIAG:
        case RTF_CHBGDKFDIAG:
        case RTF_BGDKFDIAG:
        case RTF_CLBGDKCROSS:
        case RTF_CHBGDKCROSS:
        case RTF_BGDKCROSS:
        case RTF_CLBGDKDCROSS:
        case RTF_CHBGDKDCROSS:
        case RTF_BGDKDCROSS:
            // dark -> 60%
            nFillValue = 60;
            break;

        case RTF_CLBGHORIZ:
        case RTF_CHBGHORIZ:
        case RTF_BGHORIZ:
        case RTF_CLBGVERT:
        case RTF_CHBGVERT:
        case RTF_BGVERT:
        case RTF_CLBGBDIAG:
        case RTF_CHBGBDIAG:
        case RTF_BGBDIAG:
        case RTF_CLBGFDIAG:
        case RTF_CHBGFDIAG:
        case RTF_BGFDIAG:
        case RTF_CLBGCROSS:
        case RTF_CHBGCROSS:
        case RTF_BGCROSS:
        case RTF_CLBGDCROSS:
        case RTF_CHBGDCROSS:
        case RTF_BGDCROSS:
            // light -> 20%
            nFillValue = 20;
            break;

        default:
            if( bTableDef )
                bWeiter = (nToken & ~(0xff | RTF_TABLEDEF) ) == RTF_SHADINGDEF;
            else
                bWeiter = (nToken & ~0xff) == RTF_SHADINGDEF;
        }
        if( bWeiter )
            nToken = GetNextToken();
    } while( bWeiter );

    Color aCol( COL_WHITE ), aFCol;
    if( !nFillValue )
    {
        // es wurde nur eine von beiden Farben angegeben oder kein BrushTyp
        if( USHRT_MAX != nFillColor )
        {
            nFillValue = 100;
            aCol = GetColor( nFillColor );
        }
        else if( USHRT_MAX != nColor )
            aFCol = GetColor( nColor );
    }
    else
    {
        if( USHRT_MAX != nColor )
            aCol = GetColor( nColor );
        else
            aCol = Color( COL_BLACK );

        if( USHRT_MAX != nFillColor )
            aFCol = GetColor( nFillColor );
        else
            aFCol = Color( COL_WHITE );
    }

    Color aColor;
    if( 0 == nFillValue || 100 == nFillValue )
        aColor = aCol;
    else
        aColor = Color(
            (BYTE)CalcShading( aCol.GetRed(), aFCol.GetRed(), nFillValue ),
            (BYTE)CalcShading( aCol.GetGreen(), aFCol.GetGreen(), nFillValue ),
            (BYTE)CalcShading( aCol.GetBlue(), aFCol.GetBlue(), nFillValue ) );

    rSet.Put( SvxBrushItem( aColor, nWh ) );
    SkipToken( -1 );
}


// pard / plain abarbeiten
void SvxRTFParser::RTFPardPlain( int bPard, SfxItemSet** ppSet )
{
    if( !bNewGroup && aAttrStack.Top() )    // nicht am Anfang einer neuen Gruppe
    {
        SvxRTFItemStackType* pAkt = aAttrStack.Top();

        int nLastToken = GetStackPtr(-1)->nTokenId;
        int bNewStkEntry = TRUE;
        if( RTF_PARD != nLastToken &&
            RTF_PLAIN != nLastToken &&
            BRACELEFT != nLastToken )
        {
            if( pAkt->aAttrSet.Count() || pAkt->pChildList || pAkt->nStyleNo )
            {
                // eine neue Gruppe aufmachen
                SvxRTFItemStackType* pNew = new SvxRTFItemStackType( *pAkt, *pInsPos, TRUE );
                pNew->SetRTFDefaults( GetRTFDefaults() );

                // alle bis hierher gueltigen Attribute "setzen"
                AttrGroupEnd();
                pAkt = aAttrStack.Top();  // can be changed after AttrGroupEnd!
                pNew->aAttrSet.SetParent( pAkt ? &pAkt->aAttrSet : 0 );
                aAttrStack.Push( pNew );
                pAkt = pNew;
            }
            else
            {
                // diesen Eintrag als neuen weiterbenutzen
                pAkt->SetStartPos( *pInsPos );
                bNewStkEntry = FALSE;
            }
        }

        // jetzt noch alle auf default zuruecksetzen
        if( bNewStkEntry &&
            ( pAkt->aAttrSet.GetParent() || pAkt->aAttrSet.Count() ))
        {
            const SfxPoolItem *pItem, *pDef;
            const USHORT* pPtr;
            USHORT nCnt;
            const SfxItemSet* pDfltSet = &GetRTFDefaults();
            if( bPard )
            {
                pAkt->nStyleNo = 0;
                pPtr = aPardMap.GetData();
                nCnt = aPardMap.Count();
            }
            else
            {
                pPtr = aPlainMap.GetData();
                nCnt = aPlainMap.Count();
            }

            for( USHORT n = 0; n < nCnt; ++n, ++pPtr )
            {
                // Item gesetzt und unterschiedlich -> das Pooldefault setzen
                //JP 06.04.98: bei Items die nur SlotItems sind, darf nicht
                //              auf das Default zugefriffen werden. Diese
                //              werden gecleart
                if( !*pPtr )
                    ;
                else if( SFX_WHICH_MAX < *pPtr )
                    pAkt->aAttrSet.ClearItem( *pPtr );
                else if( IsChkStyleAttr() )
                    pAkt->aAttrSet.Put( pDfltSet->Get( *pPtr ) );
                else if( !pAkt->aAttrSet.GetParent() )
                {
                    if( SFX_ITEM_SET ==
                        pDfltSet->GetItemState( *pPtr, FALSE, &pDef ))
                        pAkt->aAttrSet.Put( *pDef );
                    else
                        pAkt->aAttrSet.ClearItem( *pPtr );
                }
                else if( SFX_ITEM_SET == pAkt->aAttrSet.GetParent()->
                            GetItemState( *pPtr, TRUE, &pItem ) &&
                        *( pDef = &pDfltSet->Get( *pPtr )) != *pItem )
                    pAkt->aAttrSet.Put( *pDef );
                else
                {
                    if( SFX_ITEM_SET ==
                        pDfltSet->GetItemState( *pPtr, FALSE, &pDef ))
                        pAkt->aAttrSet.Put( *pDef );
                    else
                        pAkt->aAttrSet.ClearItem( *pPtr );
                }
            }
        }
        else if( bPard )
            pAkt->nStyleNo = 0;     // Style-Nummer zuruecksetzen

        *ppSet = &pAkt->aAttrSet;

        if (!bPard)
        {
            //Once we have a default font, then any text without a font specifier is
            //in the default font, and thus has the default font charset, otherwise
            //we can fall back to the ansicpg set codeset
            if (nDfltFont != -1)
            {
                const Font& rSVFont = GetFont(USHORT(nDfltFont));
                SetEncoding(rSVFont.GetCharSet());
            }
            else
                SetEncoding(GetCodeSet());
        }
    }
}

void SvxRTFParser::SetDefault( int nToken, short nValue )
{
    if( !bNewDoc )
        return;

    SfxItemSet aTmp( *pAttrPool, aWhichMap.GetData() );
    BOOL bOldFlag = bIsLeftToRightDef;
    bIsLeftToRightDef = TRUE;
    switch( nToken )
    {
    case RTF_ADEFF: bIsLeftToRightDef = FALSE;  // no break!
    case RTF_DEFF:
        {
            if( -1 == nValue )
                nValue = 0;
            const Font& rSVFont = GetFont( USHORT(nValue) );
            SvxFontItem aTmpItem(
                                rSVFont.GetFamily(), rSVFont.GetName(),
                                rSVFont.GetStyleName(), rSVFont.GetPitch(),
                                rSVFont.GetCharSet(), SID_ATTR_CHAR_FONT );
            SetScriptAttr( 0, aTmp, aTmpItem );
        }
        break;

    case RTF_ADEFLANG:  bIsLeftToRightDef = FALSE;  // no break!
    case RTF_DEFLANG:
        // default Language merken
        if( -1 != nValue )
        {
            SvxLanguageItem aTmpItem( (const LanguageType)nValue,
                                        SID_ATTR_CHAR_LANGUAGE );
            SetScriptAttr( 0, aTmp, aTmpItem );
        }
        break;

    case RTF_DEFTAB:
        if( PARDID->nTabStop )
        {
            // RTF definiert 720 twips als default
            bIsSetDfltTab = TRUE;
            if( -1 == nValue || !nValue )
                nValue = 720;

            // wer keine Twips haben moechte ...
            if( IsCalcValue() )
            {
                nTokenValue = nValue;
                CalcValue();
                nValue = (short)nTokenValue;
            }
#if 1
            /*
            cmc:
             This stuff looks a little hairy indeed, this should be totally
             unnecessary where default tabstops are understood. Just make one
             tabstop and stick the value in there, the first one is all that
             matters.

             e.g.

            SvxTabStopItem aNewTab(1, USHORT(nValue), SVX_TAB_ADJUST_DEFAULT,
                PARDID->nTabStop);
            ((SvxTabStop&)aNewTab[0]).GetAdjustment() = SVX_TAB_ADJUST_DEFAULT;


             It must exist as a foul hack to support somebody that does not
             have a true concept of default tabstops by making a tabsetting
             result from the default tabstop, creating a lot of them all at
             the default locations to give the effect of the first real
             default tabstop being in use just in case the receiving
             application doesn't do that for itself.
             */
#endif

            // Verhaeltnis der def. TabWidth / Tabs errechnen und
            // enstsprechend die neue Anzahl errechnen.
/*-----------------14.12.94 19:32-------------------
 ?? wie kommt man auf die 13 ??
--------------------------------------------------*/
            USHORT nAnzTabs = (SVX_TAB_DEFDIST * 13 ) / USHORT(nValue);
            /*
             cmc, make sure we have at least one, or all hell breaks loose in
             everybodies exporters, #i8247#
            */
            if (nAnzTabs < 1)
                nAnzTabs = 1;

            // wir wollen Defaulttabs
            SvxTabStopItem aNewTab( nAnzTabs, USHORT(nValue),
                                SVX_TAB_ADJUST_DEFAULT, PARDID->nTabStop );
            while( nAnzTabs )
                ((SvxTabStop&)aNewTab[ --nAnzTabs ]).GetAdjustment() = SVX_TAB_ADJUST_DEFAULT;

            pAttrPool->SetPoolDefaultItem( aNewTab );
        }
        break;
    }
    bIsLeftToRightDef = bOldFlag;

    if( aTmp.Count() )
    {
        SfxItemIter aIter( aTmp );
        const SfxPoolItem* pItem = aIter.GetCurItem();
        while( TRUE )
        {
            pAttrPool->SetPoolDefaultItem( *pItem );
            if( aIter.IsAtEnd() )
                break;
            pItem = aIter.NextItem();
        }
    }
}

// default: keine Umrechnung, alles bei Twips lassen.
void SvxRTFParser::CalcValue()
{
}

    // fuer Tokens, die im ReadAttr nicht ausgewertet werden
void SvxRTFParser::UnknownAttrToken( int nToken, SfxItemSet* pSet )
{
}

/* vi:set tabstop=4 shiftwidth=4 expandtab: */
