/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2000, 2010 Oracle and/or its affiliates.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _PARCSS1_HXX
#define _PARCSS1_HXX

// Die Tokens des CSS1-Parsers
enum CSS1Token
{
    CSS1_NULL,
    CSS1_UNKOWN,

    CSS1_IDENT,
    CSS1_STRING,
    CSS1_NUMBER,
    CSS1_PERCENTAGE,
    CSS1_LENGTH,            // eine absolute Groesse in 1/100 MM
    CSS1_PIXLENGTH,         // eine Pixel-Groesse
    CSS1_EMS,
    CSS1_EMX,
    CSS1_HEXCOLOR,

    CSS1_DOT_W_WS,
    CSS1_DOT_WO_WS,
    CSS1_COLON,
    CSS1_SLASH,
    CSS1_PLUS,
    CSS1_MINUS,
    CSS1_OBRACE,
    CSS1_CBRACE,
    CSS1_SEMICOLON,
    CSS1_COMMA,
    CSS1_HASH,

    CSS1_IMPORT_SYM,
// Feature: PrintExt
    CSS1_PAGE_SYM,
// /Feature: PrintExt

    CSS1_IMPORTANT_SYM,

    CSS1_URL,
    CSS1_RGB
};

// die Zustaende des Parsers
enum CSS1ParserState
{
    CSS1_PAR_ACCEPTED = 0,
    CSS1_PAR_WORKING,
    CSS1_PAR_ERROR
};

enum CSS1SelectorType
{
    CSS1_SELTYPE_ELEMENT,
    CSS1_SELTYPE_ELEM_CLASS,
    CSS1_SELTYPE_CLASS,
    CSS1_SELTYPE_ID,
    CSS1_SELTYPE_PSEUDO,
// Feature: PrintExt
    CSS1_SELTYPE_PAGE
// /Feature: PrintExt

};

// Die folegende Klasse beschreibt einen Simple-Selector, also
// - einen HTML-Element-Namen
// - einen HTML-Element-Namen mit Klasse (durch '.' getrennt)
// - eine Klasse (ohne Punkt)
// - eine mit ID=xxx gesetzte ID aus einem HTML-Dokument
// oder
// - ein Pseudo-Element
//
// Die Simple-Sektoren werden in einer Liste zu vollstaendigen
// Selektoren verkettet
class CSS1Selector
{
    CSS1SelectorType eType;     // Art des Selektors
    String aSelector;           // der Selektor selbst
    CSS1Selector *pNext;        // die naechste Komponente

public:

    CSS1Selector( CSS1SelectorType eTyp, const String &rSel )
        : eType(eTyp), aSelector( rSel ), pNext( 0 )
    {}

    ~CSS1Selector();

    CSS1SelectorType GetType() const { return eType; }
    const String& GetString() const { return aSelector; }

    void SetNext( CSS1Selector *pNxt ) { pNext = pNxt; }
    const CSS1Selector *GetNext() const { return pNext; }
};

// Die folegende Klasse beschreibt einen Teil-Ausdruck einer
// CSS1-Deklaration sie besteht aus
//
// - dem Typ des Ausdrucks (entspricht dem Token)
// - dem eigentlichen Wert als String und ggf. double
//   der double-Wert enthaelt das Vorzeichen fuer NUMBER und LENGTH
// - und dem Operator, mit dem er mit dem *Vorganger*-Ausdruck
//   verknuepft ist.
//
struct CSS1Expression
{
    sal_Unicode cOp;        // Art der Verkuepfung mit dem Vorgaenger
    CSS1Token eType;        // der Typ des Wertes
    String aValue;          // und sein Wert als String
    double nValue;          // und als Zahl (TWIPs fuer LENGTH)
    CSS1Expression *pNext;  // die naechste Komponente

public:

    CSS1Expression( CSS1Token eTyp, const String &rVal,
                    double nVal, sal_Unicode cO = 0 )
        : cOp(cO), eType(eTyp), aValue(rVal), nValue(nVal), pNext(0)
    {}

    ~CSS1Expression();

    inline void Set( CSS1Token eTyp, const String &rVal, double nVal,
                     sal_Unicode cO = 0 );

    CSS1Token GetType() const { return eType; }
    const String& GetString() const { return aValue; }
    double GetNumber() const { return nValue; }
    inline sal_uInt32 GetULength() const;
    inline sal_Int32 GetSLength() const;
    sal_Unicode GetOp() const { return cOp; }


    sal_Bool GetURL( String& rURL ) const;
    sal_Bool GetColor( Color &rRGB ) const;

    void SetNext( CSS1Expression *pNxt ) { pNext = pNxt; }
    const CSS1Expression *GetNext() const { return pNext; }
};

inline void CSS1Expression::Set( CSS1Token eTyp, const String &rVal,
                                 double nVal, sal_Unicode cO )
{
    cOp = cO; eType = eTyp; aValue = rVal; nValue = nVal; pNext = 0;
}

inline sal_uInt32 CSS1Expression::GetULength() const
{
    return nValue < 0. ? 0UL : (sal_uInt32)(nValue + .5);
}

inline sal_Int32 CSS1Expression::GetSLength() const
{
    return (sal_Int32)(nValue + (nValue < 0. ? -.5 : .5 ));
}

// Diese Klasse parst den Inhalt eines Style-Elements oder eine Style-Option
// und bereitet ihn ein wenig auf.
//
// Das Ergebnis des Parsers wird durch die Mehtoden SelectorParsed()
// und DeclarationParsed() an abgeleitete Parser uebergeben. Bsp:
//
// H1, H2 { font-weight: bold; text-align: right }
//  |  |                    |                  |
//  |  |                    |                  DeclP( 'text-align', 'right' )
//  |  |                    DeclP( 'font-weight', 'bold' )
//  |  SelP( 'H2', sal_False )
//  SelP( 'H1', sal_True )
//
class CSS1Parser
{
    sal_Bool bWhiteSpace : 1;           // White-Space gelesen?
    sal_Bool bEOF : 1;                  // Ende des "Files" ?

    sal_Unicode cNextCh;                // naechstes Zeichen

    xub_StrLen nInPos;                  // aktuelle Position im Input-String

    sal_uInt32 nlLineNr;                    // akt. Zeilen Nummer
    sal_uInt32 nlLinePos;               // akt. Spalten Nummer

    double nValue;                  // der Wert des Tokens als Zahl

    CSS1ParserState eState;         // der akteulle Zustand der Parsers
    CSS1Token nToken;               // das aktuelle Token

    String aIn;                     // der zu parsende String
    String aToken;                  // das Token als String

    // Parsen vorbereiten
    void InitRead( const String& rIn );

    // das naechste Zeichen holen
    sal_Unicode GetNextChar();

    // das naechste Token holen
    CSS1Token GetNextToken();

    // arbeitet der Parser noch?
    sal_Bool IsParserWorking() const { return CSS1_PAR_WORKING == eState; }

    sal_Bool IsEOF() const { return bEOF; }

    sal_uInt32 IncLineNr() { return ++nlLineNr; }
    sal_uInt32 IncLinePos() { return ++nlLinePos; }
    inline sal_uInt32 SetLinePos( sal_uInt32 nlPos );           // inline unten

    // Parsen von Teilen der Grammatik
    void ParseRule();
    CSS1Selector *ParseSelector();
    CSS1Expression *ParseDeclaration( String& rProperty );

protected:

    void ParseStyleSheet();

    // Den Inhalt eines HTML-Style-Elements parsen.
    // Fuer jeden Selektor und jede Deklaration wird
    // SelectorParsed() bzw. DeclarationParsed() aufgerufen.
    sal_Bool ParseStyleSheet( const String& rIn );

    // Den Inhalt einer HTML-Style-Option parsen.
    // F�r jede Deklaration wird DeclarationParsed() aufgerufen.
    sal_Bool ParseStyleOption( const String& rIn );

    // Diese Methode wird aufgerufen, wenn ein Selektor geparsed wurde
    // Wenn 'bFirst' gesetzt ist, beginnt mit dem Selektor eine neue
    // Deklaration. Wird sal_True zurueckgegeben, wird der Selektor
    // geloscht, sonst nicht.
    // Die Implementierung dieser Methode gibt nur sal_True zuruck.
    virtual bool SelectorParsed( CSS1Selector* pSelector, bool bFirst );

    // Diese Methode wird fuer jede geparsete Property aufgerufen. Wird
    // sal_True zurueckgegeben wird der Selektor geloscht, sonst nicht.
    // Die Implementierung dieser Methode gibt nur sal_True zuruck.
    virtual sal_Bool DeclarationParsed( const String& rProperty,
                                    const CSS1Expression *pExpr );

public:

    CSS1Parser();
    virtual ~CSS1Parser();

    inline sal_uInt32   GetLineNr() const       { return nlLineNr; }
    inline sal_uInt32   GetLinePos() const      { return nlLinePos; }
};

inline sal_uInt32 CSS1Parser::SetLinePos( sal_uInt32 nlPos )
{
    sal_uInt32 nlOld = nlLinePos;
    nlLinePos = nlPos;
    return nlOld;
}


#endif


/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
