Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  txtparai.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */


#include <sal/config.h>

#include "txtparai.hxx"

#include <string_view>

#include "XMLFootnoteImportContext.hxx"
#include "XMLTextFrameContext.hxx"
#include "xmlimp.hxx"

#include <sal/log.hxx>

using namespace com::sun::star;

namespace
{
/// Looks for rName in rStyles and fills rPropertyList based on that
/// (rAutomaticStyles and rNamedStyles are a list of possible parents).
void FillStyle(const OUString& rName, std::map<OUString, librevenge::RVNGPropertyList>& rStyles,
               std::map<OUString, librevenge::RVNGPropertyList>& rAutomaticStyles,
               std::map<OUString, librevenge::RVNGPropertyList>& rNamedStyles,
               librevenge::RVNGPropertyList& rPropertyList)
{
    auto itStyle = rStyles.find(rName);
    if (itStyle == rStyles.end())
        return;

    const librevenge::RVNGPropertyList& rStyle = itStyle->second;
    if (rStyle["style:parent-style-name"])
    {
        // The style has a parent.
        OUString aParent = OStringToOUString(rStyle["style:parent-style-name"]->getStr().cstr(),
                                             RTL_TEXTENCODING_UTF8);
        if (!aParent.isEmpty())
            writerperfect::exp::FillStyles(aParent, rAutomaticStyles, rNamedStyles, rPropertyList);
    }

    // Apply properties from named style.
    librevenge::RVNGPropertyList::Iter itProp(rStyle);
    for (itProp.rewind(); itProp.next();)
    {
        if (std::string_view("style:parent-style-name") != itProp.key())
            rPropertyList.insert(itProp.key(), itProp()->clone());
    }
}
}

namespace writerperfect::exp
{
namespace
{
/// Handler for <text:sequence>.
class XMLTextSequenceContext : public XMLImportContext
{
public:
    XMLTextSequenceContext(XMLImport& rImport, const librevenge::RVNGPropertyList&&nbsp;rPropertyList);

    void SAL_CALL characters(const OUString& rChars) override;

private:
    librevenge::RVNGPropertyList m_aPropertyList;
};
}

XMLTextSequenceContext::XMLTextSequenceContext(XMLImport& rImport,
                                               const librevenge::RVNGPropertyList& rPropertyList)
    : XMLImportContext(rImport)
{
    // Inherit properties from parent.
    librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
    for (itProp.rewind(); itProp.next();)
        m_aPropertyList.insert(itProp.key(), itProp()->clone());
}

void XMLTextSequenceContext::characters(const OUString& rChars)
{
    GetImport().GetGenerator().openSpan(m_aPropertyList);

    OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
    GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));

    GetImport().GetGenerator().closeSpan();
}

namespace
{
/// Handler for <text:span>.
class XMLSpanContext : public XMLImportContext
{
public:
    XMLSpanContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);

    rtl::Reference<XMLImportContext>
    CreateChildContext(const OUString& rName,
                       const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;

    void SAL_CALL
    startElement(const OUString& rName,
                 const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
    void SAL_CALL characters(const OUString& rChars) override;

private:
    librevenge::RVNGPropertyList m_aPropertyList;
};
}

XMLSpanContext::XMLSpanContext(XMLImport& rImport,
                               const librevenge::RVNGPropertyList& rPropertyList)
    : XMLImportContext(rImport)
{
    // Inherit properties from parent.
    librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
    for (itProp.rewind(); itProp.next();)
        m_aPropertyList.insert(itProp.key(), itProp()->clone());
}

rtl::Reference<XMLImportContext> XMLSpanContext::CreateChildContext(
    const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>&&nbsp;/*xAttribs*/)
{
    return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
}

void XMLSpanContext::startElement(
    const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
{
    for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
    {
        const OUString aAttributeName = xAttribs->getNameByIndex(i);
        const OUString aAttributeValue = xAttribs->getValueByIndex(i);
        if (aAttributeName == "text:style-name")
            FillStyles(aAttributeValue, GetImport().GetAutomaticTextStyles(),
                       GetImport().GetTextStyles(), m_aPropertyList);
        else
        {
            OString sName = OUStringToOString(aAttributeName, RTL_TEXTENCODING_UTF8);
            OString sValue = OUStringToOString(aAttributeValue, RTL_TEXTENCODING_UTF8);
            m_aPropertyList.insert(sName.getStr(), sValue.getStr());
        }
    }
}

void XMLSpanContext::characters(const OUString& rChars)
{
    GetImport().GetGenerator().openSpan(m_aPropertyList);

    OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
    GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));

    GetImport().GetGenerator().closeSpan();
}

namespace
{
/// Handler for <text:ruby>.
class XMLRubyContext : public XMLImportContext
{
public:
    XMLRubyContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);

    rtl::Reference<XMLImportContext>
    CreateChildContext(const OUString& rName,
                       const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;

    void SAL_CALL endElement(const OUString& rName) override;

    void SetRubyText(const OUString& rRubyText) { m_sRubyText = rRubyText; }

    OUString& GetRubyBase() { return m_sRubyBase; }

private:
    OUString m_sRubyText;
    OUString m_sRubyBase;
    librevenge::RVNGPropertyList m_aPropertyList;
};

/// Handler for <text:ruby-text>.
class XMLRubyTextContext : public XMLImportContext
{
public:
    XMLRubyTextContext(XMLImport& rImport, XMLRubyContext& rParent)
        : XMLImportContext(rImport)
        , m_rParent(rParent)
    {
    }

    void SAL_CALL characters(const OUString& rChars) override { m_rParent.SetRubyText(rChars); }

private:
    XMLRubyContext& m_rParent;
};

/// Handler for <text:ruby-base>.
class XMLRubyBaseContext : public XMLImportContext
{
public:
    XMLRubyBaseContext(XMLImport& rImport, XMLRubyContext& rParent)
        : XMLImportContext(rImport)
        , m_rParent(rParent)
    {
    }

    void SAL_CALL characters(const OUString& rChars) override { m_rParent.GetRubyBase() += rChars; }

private:
    XMLRubyContext& m_rParent;
};
}

XMLRubyContext::XMLRubyContext(XMLImport& rImport,
                               const librevenge::RVNGPropertyList& rPropertyList)
    : XMLImportContext(rImport)
{
    // Inherit properties from parent.
    librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
    for (itProp.rewind(); itProp.next();)
        m_aPropertyList.insert(itProp.key(), itProp()->clone());
}

rtl::Reference<XMLImportContext> XMLRubyContext::CreateChildContext(
    const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>&&nbsp;/*xAttribs*/)
{
    if (rName == "text:ruby-base")
        return new XMLRubyBaseContext(GetImport(), *this);
    if (rName == "text:ruby-text")
        return new XMLRubyTextContext(GetImport(), *this);
    return nullptr;
}

void XMLRubyContext::endElement(const OUString& /*rName*/)
{
    OString sRubyText = OUStringToOString(m_sRubyText, RTL_TEXTENCODING_UTF8);
    OString sRubyBase = OUStringToOString(m_sRubyBase, RTL_TEXTENCODING_UTF8);
    if (sRubyText.getLength())
        m_aPropertyList.insert("text:ruby-text", sRubyText.getStr());
    GetImport().GetGenerator().openSpan(m_aPropertyList);
    GetImport().GetGenerator().insertText(sRubyBase.getStr());
    GetImport().GetGenerator().closeSpan();
}

namespace
{
/// Base class for contexts that represent a single character only.
class XMLCharContext : public XMLImportContext
{
public:
    XMLCharContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);

    const librevenge::RVNGPropertyList& GetPropertyList() const { return m_aPropertyList; }

private:
    librevenge::RVNGPropertyList m_aPropertyList;
};
}

XMLCharContext::XMLCharContext(XMLImport& rImport,
                               const librevenge::RVNGPropertyList& rPropertyList)
    : XMLImportContext(rImport)
{
    // Inherit properties from parent.
    librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
    for (itProp.rewind(); itProp.next();)
        m_aPropertyList.insert(itProp.key(), itProp()->clone());
}

namespace
{
/// Handler for <text:line-break>.
class XMLLineBreakContext : public XMLCharContext
{
public:
    XMLLineBreakContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);

    void SAL_CALL
    startElement(const OUString& rName,
                 const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
};
}

XMLLineBreakContext::XMLLineBreakContext(XMLImport& rImport,
                                         const librevenge::RVNGPropertyList& rPropertyList)
    : XMLCharContext(rImport, rPropertyList)
{
}

void XMLLineBreakContext::startElement(
    const OUString& /*rName*/,
    const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
    GetImport().GetGenerator().openSpan(GetPropertyList());
    GetImport().GetGenerator().insertLineBreak();
    GetImport().GetGenerator().closeSpan();
}

namespace
{
/// Handler for <text:s>.
class XMLSpaceContext : public XMLCharContext
{
public:
    XMLSpaceContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);

    void SAL_CALL
    startElement(const OUString& rName,
                 const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
};
}

XMLSpaceContext::XMLSpaceContext(XMLImport& rImport,
                                 const librevenge::RVNGPropertyList& rPropertyList)
    : XMLCharContext(rImport, rPropertyList)
{
}

void XMLSpaceContext::startElement(
    const OUString& /*rName*/,
    const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
    GetImport().GetGenerator().openSpan(GetPropertyList());
    GetImport().GetGenerator().insertSpace();
    GetImport().GetGenerator().closeSpan();
}

namespace
{
/// Handler for <text:tab>.
class XMLTabContext : public XMLCharContext
{
public:
    XMLTabContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);

    void SAL_CALL
    startElement(const OUString& rName,
                 const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
};
}

XMLTabContext::XMLTabContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList)
    : XMLCharContext(rImport, rPropertyList)
{
}

void XMLTabContext::startElement(
    const OUString& /*rName*/,
    const css::uno::Reference<css::xml::sax::XAttributeList>& /*xAttribs*/)
{
    GetImport().GetGenerator().openSpan(GetPropertyList());
    GetImport().GetGenerator().insertTab();
    GetImport().GetGenerator().closeSpan();
}

namespace
{
/// Handler for <draw:a>.
class XMLTextFrameHyperlinkContext : public XMLImportContext
{
public:
    XMLTextFrameHyperlinkContext(XMLImport& rImport,
                                 const librevenge::RVNGPropertyList& rPropertyList);
    rtl::Reference<XMLImportContext>
    CreateChildContext(const OUString& rName,
                       const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;

    void SAL_CALL
    startElement(const OUString& rName,
                 const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
    void SAL_CALL endElement(const OUString& rName) override;
    void SAL_CALL characters(const OUString& rChars) override;

private:
    librevenge::RVNGPropertyList m_aPropertyList;
    PopupState m_ePopupState = PopupState::NONE;
};
}

XMLTextFrameHyperlinkContext::XMLTextFrameHyperlinkContext(
    XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList)
    : XMLImportContext(rImport)
{
    // Inherit properties from parent.
    librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
    for (itProp.rewind(); itProp.next();)
        m_aPropertyList.insert(itProp.key(), itProp()->clone());
}

rtl::Reference<XMLImportContext> XMLTextFrameHyperlinkContext::CreateChildContext(
    const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>&&nbsp;/*xAttribs*/)
{
    return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
}

void XMLTextFrameHyperlinkContext::startElement(
    const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
{
    librevenge::RVNGPropertyList aPropertyList;
    for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
    {
        const OUString aAttributeName = xAttribs->getNameByIndex(i);
        const OUString aAttributeValue = xAttribs->getValueByIndex(i);
        if (aAttributeName == "text:style-name")
            // This affects the nested span's properties.
            FillStyles(aAttributeValue, GetImport().GetAutomaticTextStyles(),
                       GetImport().GetTextStyles(), m_aPropertyList);
        else
        {
            if (aAttributeName == "xlink:href")
            {
                m_ePopupState = GetImport().FillPopupData(aAttributeValue, aPropertyList);
                if (m_ePopupState != PopupState::NotConsumed)
                    continue;
            }

            // This affects the link's properties.
            OString sName = OUStringToOString(aAttributeName, RTL_TEXTENCODING_UTF8);
            OString sValue = OUStringToOString(aAttributeValue, RTL_TEXTENCODING_UTF8);
            aPropertyList.insert(sName.getStr(), sValue.getStr());
        }
    }

    if (m_ePopupState != PopupState::Ignore)
        GetImport().GetGenerator().openLink(aPropertyList);
}

void XMLTextFrameHyperlinkContext::endElement(const OUString& /*rName*/)
{
    if (m_ePopupState != PopupState::Ignore)
        GetImport().GetGenerator().closeLink();
}

void XMLTextFrameHyperlinkContext::characters(const OUString& rChars)
{
    GetImport().GetGenerator().openSpan(m_aPropertyList);

    OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
    GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));

    GetImport().GetGenerator().closeSpan();
}

namespace
{
/// Handler for <text:a>.
class XMLHyperlinkContext : public XMLImportContext
{
public:
    XMLHyperlinkContext(XMLImport& rImport, const librevenge::RVNGPropertyList& rPropertyList);
    rtl::Reference<XMLImportContext>
    CreateChildContext(const OUString& rName,
                       const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;

    void SAL_CALL
    startElement(const OUString& rName,
                 const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs) override;
    void SAL_CALL endElement(const OUString& rName) override;
    void SAL_CALL characters(const OUString& rChars) override;

private:
    librevenge::RVNGPropertyList m_aPropertyList;
    PopupState m_ePopupState = PopupState::NONE;
};
}

XMLHyperlinkContext::XMLHyperlinkContext(XMLImport& rImport,
                                         const librevenge::RVNGPropertyList& rPropertyList)
    : XMLImportContext(rImport)
{
    // Inherit properties from parent.
    librevenge::RVNGPropertyList::Iter itProp(rPropertyList);
    for (itProp.rewind(); itProp.next();)
        m_aPropertyList.insert(itProp.key(), itProp()->clone());
}

rtl::Reference<XMLImportContext> XMLHyperlinkContext::CreateChildContext(
    const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>&&nbsp;/*xAttribs*/)
{
    return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aPropertyList);
}

void XMLHyperlinkContext::startElement(
    const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
{
    librevenge::RVNGPropertyList aPropertyList;
    for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
    {
        const OUString aAttributeName = xAttribs->getNameByIndex(i);
        const OUString aAttributeValue = xAttribs->getValueByIndex(i);
        if (aAttributeName == "text:style-name")
            // This affects the nested span's properties.
            FillStyles(aAttributeValue, GetImport().GetAutomaticTextStyles(),
                       GetImport().GetTextStyles(), m_aPropertyList);
        else
        {
            if (aAttributeName == "xlink:href")
            {
                m_ePopupState = GetImport().FillPopupData(aAttributeValue, aPropertyList);
                if (m_ePopupState != PopupState::NotConsumed)
                    continue;
            }

            // This affects the link's properties.
            OString sName = OUStringToOString(aAttributeName, RTL_TEXTENCODING_UTF8);
            OString sValue = OUStringToOString(aAttributeValue, RTL_TEXTENCODING_UTF8);
            aPropertyList.insert(sName.getStr(), sValue.getStr());
        }
    }

    if (m_ePopupState != PopupState::Ignore)
        GetImport().GetGenerator().openLink(aPropertyList);
}

void XMLHyperlinkContext::endElement(const OUString& /*rName*/)
{
    if (m_ePopupState != PopupState::Ignore)
        GetImport().GetGenerator().closeLink();
}

void XMLHyperlinkContext::characters(const OUString& rChars)
{
    GetImport().GetGenerator().openSpan(m_aPropertyList);

    OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
    GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));

    GetImport().GetGenerator().closeSpan();
}

XMLParaContext::XMLParaContext(XMLImport& rImport, bool bTopLevel)
    : XMLImportContext(rImport)
    , m_bTopLevel(bTopLevel)
{
}

rtl::Reference<XMLImportContext> XMLParaContext::CreateChildContext(
    const OUString& rName, const css::uno::Reference<css::xml::sax::XAttributeList>&&nbsp;/*xAttribs*/)
{
    if (rName == "text:a")
        return new XMLHyperlinkContext(GetImport(), m_aTextPropertyList);
    if (rName == "draw:a")
        return new XMLTextFrameHyperlinkContext(GetImport(), m_aTextPropertyList);
    if (rName == "text:ruby")
        return new XMLRubyContext(GetImport(), m_aTextPropertyList);
    return CreateParagraphOrSpanChildContext(GetImport(), rName, m_aTextPropertyList);
}

void XMLParaContext::startElement(
    const OUString& /*rName*/, const css::uno::Reference<css::xml::sax::XAttributeList>& xAttribs)
{
    librevenge::RVNGPropertyList aPropertyList;
    for (sal_Int16 i = 0; i < xAttribs->getLength(); ++i)
    {
        const OUString aAttributeName = xAttribs->getNameByIndex(i);
        const OUString aAttributeValue = xAttribs->getValueByIndex(i);
        if (aAttributeName == "text:style-name")
        {
            m_aStyleName = aAttributeValue;
            FillStyles(m_aStyleName, GetImport().GetAutomaticParagraphStyles(),
                       GetImport().GetParagraphStyles(), aPropertyList);
            FillStyles(m_aStyleName, GetImport().GetAutomaticTextStyles(),
                       GetImport().GetTextStyles(), m_aTextPropertyList);
            if (m_bTopLevel)
                GetImport().HandlePageSpan(aPropertyList);
        }
        else
        {
            OString sName = OUStringToOString(aAttributeName, RTL_TEXTENCODING_UTF8);
            OString sValue = OUStringToOString(aAttributeValue, RTL_TEXTENCODING_UTF8);
            aPropertyList.insert(sName.getStr(), sValue.getStr());
        }
    }

    GetImport().GetGenerator().openParagraph(aPropertyList);
}

void XMLParaContext::endElement(const OUString& /*rName*/)
{
    GetImport().GetGenerator().closeParagraph();
}

void XMLParaContext::characters(const OUString& rChars)
{
    librevenge::RVNGPropertyList aPropertyList;
    if (!m_aStyleName.isEmpty())
        FillStyles(m_aStyleName, GetImport().GetAutomaticTextStyles(), GetImport().GetTextStyles(),
                   aPropertyList);
    GetImport().GetGenerator().openSpan(aPropertyList);

    OString sCharU8 = OUStringToOString(rChars, RTL_TEXTENCODING_UTF8);
    GetImport().GetGenerator().insertText(librevenge::RVNGString(sCharU8.getStr()));

    GetImport().GetGenerator().closeSpan();
}

rtl::Reference<XMLImportContext>
CreateParagraphOrSpanChildContext(XMLImport& rImport, const OUString& rName,
                                  const librevenge::RVNGPropertyList& rTextPropertyList)
{
    if (rName == "text:span")
        return new XMLSpanContext(rImport, rTextPropertyList);
    if (rName == "text:line-break")
        return new XMLLineBreakContext(rImport, rTextPropertyList);
    if (rName == "text:s")
        return new XMLSpaceContext(rImport, rTextPropertyList);
    if (rName == "text:tab")
        return new XMLTabContext(rImport, rTextPropertyList);
    if (rName == "draw:frame")
        return new XMLTextFrameContext(rImport);
    if (rName == "text:sequence")
        return new XMLTextSequenceContext(rImport, rTextPropertyList);
    if (rName == "text:note")
        return new XMLFootnoteImportContext(rImport);
    SAL_WARN("writerperfect""CreateParagraphOrSpanChildContext: unhandled " << rName);
    return nullptr;
}

void FillStyles(const OUString& rName,
                std::map<OUString, librevenge::RVNGPropertyList>& rAutomaticStyles,
                std::map<OUString, librevenge::RVNGPropertyList>& rNamedStyles,
                librevenge::RVNGPropertyList& rPropertyList)
{
    FillStyle(rName, rAutomaticStyles, rAutomaticStyles, rNamedStyles, rPropertyList);
    FillStyle(rName, rNamedStyles, rAutomaticStyles, rNamedStyles, rPropertyList);
}

// namespace writerperfect

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

Messung V0.5
C=97 H=96 G=96

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge