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


Quelle  PresenterHelpView.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/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <utility>
#include <vcl/settings.hxx>
#include "PresenterHelpView.hxx"
#include "PresenterButton.hxx"
#include "PresenterCanvasHelper.hxx"
#include "PresenterGeometryHelper.hxx"
#include <DrawController.hxx>
#include <com/sun/star/awt/XWindowPeer.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/drawing/framework/XConfigurationController.hpp>
#include <com/sun/star/rendering/CompositeOperation.hpp>
#include <com/sun/star/rendering/TextDirection.hpp>
#include <com/sun/star/util/Color.hpp>
#include <algorithm>
#include <numeric>
#include <string_view>
#include <vector>

using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing::framework;
using ::std::vector;

namespace sdext::presenter {

namespace {
    const sal_Int32 gnHorizontalGap (20);
    const sal_Int32 gnVerticalBorder (30);
    const sal_Int32 gnVerticalButtonPadding (12);

    class LineDescriptor
    {
    public:
        LineDescriptor();
        void AddPart (
            std::u16string_view rsLine,
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont);
        bool IsEmpty() const;

        OUString msLine;
        geometry::RealSize2D maSize;
        double mnVerticalOffset;

        void CalculateSize (const css::uno::Reference<css::rendering::XCanvasFont>& rxFont);
    };

    class LineDescriptorList
    {
    public:
        LineDescriptorList (
            OUString sText,
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
            const sal_Int32 nMaximalWidth);

        void Update (
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
            const sal_Int32 nMaximalWidth);

        double Paint(
            const Reference<rendering::XCanvas>& rxCanvas,
            const geometry::RealRectangle2D& rBBox,
            const bool bFlushLeft,
            const rendering::ViewState& rViewState,
            rendering::RenderState& rRenderState,
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const;
        double GetHeight() const;

    private:
        const OUString msText;
        std::shared_ptr<vector<LineDescriptor> > mpLineDescriptors;

        static void SplitText (std::u16string_view rsText, vector<OUString>& rTextParts);
        void FormatText (
            const vector<OUString>& rTextParts,
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
            const sal_Int32 nMaximalWidth);
    };

    class Block
    {
    public:
        Block (
            const OUString& rsLeftText,
            const OUString& rsRightText,
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
            const sal_Int32 nMaximalWidth);
        Block(const Block&) = delete;
        Block& operator=(const Block&) = delete;
        void Update (
            const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
            const sal_Int32 nMaximalWidth);

        LineDescriptorList maLeft;
        LineDescriptorList maRight;
    };
// end of anonymous namespace

class PresenterHelpView::TextContainer : public vector<std::shared_ptr<Block> >
{
};

PresenterHelpView::PresenterHelpView (
    const Reference<uno::XComponentContext>& rxContext,
    const Reference<XResourceId>& rxViewId,
    const rtl::Reference<::sd::DrawController>& rxController,
    ::rtl::Reference<PresenterController> xPresenterController)
    : PresenterHelpViewInterfaceBase(m_aMutex),
      mxComponentContext(rxContext),
      mxViewId(rxViewId),
      mpPresenterController(std::move(xPresenterController)),
      mnSeparatorY(0),
      mnMaximalWidth(0)
{
    try
    {
        // Get the content window via the pane anchor.
        Reference<XConfigurationController> xCC (
            rxController->getConfigurationController(), UNO_SET_THROW);
        mxPane.set(xCC->getResource(rxViewId->getAnchor()), UNO_QUERY_THROW);

        mxWindow = mxPane->getWindow();
        ProvideCanvas();

        mxWindow->addWindowListener(this);
        mxWindow->addPaintListener(this);
        Reference<awt::XWindowPeer> xPeer (mxWindow, UNO_QUERY);
        if (xPeer.is())
            xPeer->setBackground(util::Color(0xff000000));
        mxWindow->setVisible(true);

        if (mpPresenterController.is())
        {
            mpFont = mpPresenterController->GetViewFont(mxViewId->getResourceURL());
            if (mpFont)
            {
                mpFont->PrepareFont(mxCanvas);
            }
        }

        // Create the close button.
        mpCloseButton = PresenterButton::Create(
            mxComponentContext,
            mpPresenterController,
            mpPresenterController->GetTheme(),
            mxWindow,
            mxCanvas,
            u"HelpViewCloser"_ustr);

        ReadHelpStrings();
        Resize();
    }
    catch (RuntimeException&)
    {
        mxViewId = nullptr;
        mxWindow = nullptr;
        throw;
    }
}

PresenterHelpView::~PresenterHelpView()
{
}

void SAL_CALL PresenterHelpView::disposing()
{
    mxViewId = nullptr;

    if (mpCloseButton.is())
    {
        rtl::Reference<PresenterButton> xComponent = std::move(mpCloseButton);
        if (xComponent.is())
            xComponent->dispose();
    }

    if (mxWindow.is())
    {
        mxWindow->removeWindowListener(this);
        mxWindow->removePaintListener(this);
    }
}

//----- lang::XEventListener --------------------------------------------------

void SAL_CALL PresenterHelpView::disposing (const lang::EventObject& rEventObject)
{
    if (rEventObject.Source == mxCanvas)
    {
        mxCanvas = nullptr;
    }
    else if (rEventObject.Source == mxWindow)
    {
        mxWindow = nullptr;
        dispose();
    }
}

//----- XWindowListener -------------------------------------------------------

void SAL_CALL PresenterHelpView::windowResized (const awt::WindowEvent&)
{
    ThrowIfDisposed();
    Resize();
}

void SAL_CALL PresenterHelpView::windowMoved (const awt::WindowEvent&)
{
    ThrowIfDisposed();
}

void SAL_CALL PresenterHelpView::windowShown (const lang::EventObject&)
{
    ThrowIfDisposed();
    Resize();
}

void SAL_CALL PresenterHelpView::windowHidden (const lang::EventObject&)
{
    ThrowIfDisposed();
}

//----- XPaintListener --------------------------------------------------------

void SAL_CALL PresenterHelpView::windowPaint (const css::awt::PaintEvent& rEvent)
{
    Paint(rEvent.UpdateRect);
}

void PresenterHelpView::Paint (const awt::Rectangle& rUpdateBox)
{
    ProvideCanvas();
    if ( ! mxCanvas.is())
        return;

    // Clear background.
    const awt::Rectangle aWindowBox (mxWindow->getPosSize());
    mpPresenterController->GetCanvasHelper()->Paint(
        mpPresenterController->GetViewBackground(mxViewId->getResourceURL()),
        mxCanvas,
        rUpdateBox,
        awt::Rectangle(0,0,aWindowBox.Width,aWindowBox.Height),
        awt::Rectangle());

    // Paint vertical divider.

    rendering::ViewState aViewState(
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        PresenterGeometryHelper::CreatePolygon(rUpdateBox, mxCanvas->getDevice()));

    rendering::RenderState aRenderState (
        geometry::AffineMatrix2D(1,0,0, 0,1,0),
        nullptr,
        Sequence<double>(4),
        rendering::CompositeOperation::SOURCE);
    PresenterCanvasHelper::SetDeviceColor(aRenderState, mpFont->mnColor);

    mxCanvas->drawLine(
            geometry::RealPoint2D((aWindowBox.Width/2.0), gnVerticalBorder),
            geometry::RealPoint2D((aWindowBox.Width/2.0), mnSeparatorY - gnVerticalBorder),
        aViewState,
        aRenderState);

    // Paint the horizontal separator.
    mxCanvas->drawLine(
        geometry::RealPoint2D(0, mnSeparatorY),
        geometry::RealPoint2D(aWindowBox.Width, mnSeparatorY),
        aViewState,
        aRenderState);

    // Paint text.
    double nY (gnVerticalBorder);
    for (const auto& rxBlock : *mpTextContainer)
    {
        sal_Int32 LeftX1 = gnHorizontalGap;
        sal_Int32 LeftX2 = aWindowBox.Width/2 - gnHorizontalGap;
        sal_Int32 RightX1 = aWindowBox.Width/2 + gnHorizontalGap;
        sal_Int32 RightX2 = aWindowBox.Width - gnHorizontalGap;
        /* check whether RTL interface or not
           then replace the windowbox position */

        if(AllSettings::GetLayoutRTL())
        {
            LeftX1 = aWindowBox.Width/2 + gnHorizontalGap;
            LeftX2 = aWindowBox.Width - gnHorizontalGap;
            RightX1 = gnHorizontalGap;
            RightX2 = aWindowBox.Width/2 - gnHorizontalGap;
        }
        const double nLeftHeight (
            rxBlock->maLeft.Paint(mxCanvas,
                geometry::RealRectangle2D(
                        LeftX1,
                        nY,
                        LeftX2,
                        aWindowBox.Height - gnVerticalBorder),
                false,
                aViewState,
                aRenderState,
                mpFont->mxFont));
        const double nRightHeight (
            rxBlock->maRight.Paint(mxCanvas,
                geometry::RealRectangle2D(
                        RightX1,
                        nY,
                        RightX2,
                        aWindowBox.Height - gnVerticalBorder),
                true,
                aViewState,
                aRenderState,
                mpFont->mxFont));

        nY += ::std::max(nLeftHeight,nRightHeight);
    }

    Reference<rendering::XSpriteCanvas> xSpriteCanvas (mxCanvas, UNO_QUERY);
    if (xSpriteCanvas.is())
        xSpriteCanvas->updateScreen(false);
}

void PresenterHelpView::ReadHelpStrings()
{
    mpTextContainer.reset(new TextContainer);
    PresenterConfigurationAccess aConfiguration (
        mxComponentContext,
        u"/org.openoffice.Office.PresenterScreen/"_ustr,
        PresenterConfigurationAccess::READ_ONLY);
    Reference<container::XNameAccess> xStrings (
        aConfiguration.GetConfigurationNode(u"PresenterScreenSettings/HelpView/HelpStrings"_ustr),
        UNO_QUERY);
    PresenterConfigurationAccess::ForAll(
        xStrings,
        [this](OUString const&, uno::Reference<beans::XPropertySet> const& xProps)
        {
            return this->ProcessString(xProps);
        });
}

void PresenterHelpView::ProcessString (
    const Reference<beans::XPropertySet>& rsProperties)
{
    if ( ! rsProperties.is())
        return;

    OUString sLeftText;
    PresenterConfigurationAccess::GetProperty(rsProperties, u"Left"_ustr) >>= sLeftText;
    OUString sRightText;
    PresenterConfigurationAccess::GetProperty(rsProperties, u"Right"_ustr) >>= sRightText;
    mpTextContainer->push_back(
        std::make_shared<Block>(
            sLeftText, sRightText, mpFont->mxFont, mnMaximalWidth));
}

void PresenterHelpView::CheckFontSize()
{
    if (!mpFont)
        return;

    sal_Int32 nBestSize (6);

    // Scaling down and then reformatting can cause the text to be too large
    // still.  So do this again and again until the text size is
    // small enough.  Restrict the number of loops.
    for (int nLoopCount=0; nLoopCount<5; ++nLoopCount)
    {
        double nY = std::accumulate(mpTextContainer->begin(), mpTextContainer->end(), double(0),
            [](const double& sum, const std::shared_ptr<Block>& rxBlock) {
                return sum + std::max(
                    rxBlock->maLeft.GetHeight(),
                    rxBlock->maRight.GetHeight());
            });

        const double nHeightDifference (nY - (mnSeparatorY-gnVerticalBorder));
        if (nHeightDifference <= 0 && nHeightDifference > -50)
        {
            // We have found a good font size that is large and leaves not
            // too much space below the help text.
            return;
        }

        // Use a simple linear transformation to calculate initial guess of
        // a size that lets all help text to be shown inside the window.
        const double nScale (double(mnSeparatorY-gnVerticalBorder) / nY);
        if (nScale > 1.0 && nScale < 1.05)
            break;

        sal_Int32 nFontSizeGuess (sal_Int32(mpFont->mnSize * nScale));
        if (nHeightDifference<=0 && mpFont->mnSize>nBestSize)
            nBestSize = mpFont->mnSize;
        mpFont->mnSize = nFontSizeGuess;
        mpFont->mxFont = nullptr;
        mpFont->PrepareFont(mxCanvas);

        // Reformat blocks.
        for (auto& rxBlock : *mpTextContainer)
            rxBlock->Update(mpFont->mxFont, mnMaximalWidth);
    }

    if (nBestSize != mpFont->mnSize)
    {
        mpFont->mnSize = nBestSize;
        mpFont->mxFont = nullptr;
        mpFont->PrepareFont(mxCanvas);

        // Reformat blocks.
        for (auto& rxBlock : *mpTextContainer)
        {
            rxBlock->Update(mpFont->mxFont, mnMaximalWidth);
        }
    }
}

//----- XResourceId -----------------------------------------------------------

Reference<XResourceId> SAL_CALL PresenterHelpView::getResourceId()
{
    ThrowIfDisposed();
    return mxViewId;
}

sal_Bool SAL_CALL PresenterHelpView::isAnchorOnly()
{
    return false;
}


void PresenterHelpView::ProvideCanvas()
{
    if ( ! mxCanvas.is() && mxPane.is())
    {
        mxCanvas = mxPane->getCanvas();
        if ( ! mxCanvas.is())
            return;
        Reference<lang::XComponent> xComponent (mxCanvas, UNO_QUERY);
        if (xComponent.is())
            xComponent->addEventListener(static_cast<awt::XPaintListener*>(this));

        if (mpCloseButton.is())
            mpCloseButton->SetCanvas(mxCanvas, mxWindow);
    }
}

void PresenterHelpView::Resize()
{
    if (!(mpCloseButton && mxWindow.is()))
        return;

    const awt::Rectangle aWindowBox (mxWindow->getPosSize());
    mnMaximalWidth = (mxWindow->getPosSize().Width - 4*gnHorizontalGap) / 2;

    // Place vertical separator.
    mnSeparatorY = aWindowBox.Height
        - mpCloseButton->GetSize().Height - gnVerticalButtonPadding;

    mpCloseButton->SetCenter(geometry::RealPoint2D(
        aWindowBox.Width/2.0,
        aWindowBox.Height - mpCloseButton->GetSize().Height/2.0));

    CheckFontSize();
}

void PresenterHelpView::ThrowIfDisposed()
{
    if (rBHelper.bDisposed || rBHelper.bInDispose)
    {
        throw lang::DisposedException (
            u"PresenterHelpView has been already disposed"_ustr,
            static_cast<uno::XWeak*>(this));
    }
}

//===== LineDescriptor =========================================================

namespace {

LineDescriptor::LineDescriptor()
    : maSize(0,0),
      mnVerticalOffset(0)
{
}

void LineDescriptor::AddPart (
    std::u16string_view rsLine,
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont)
{
    msLine += rsLine;

    CalculateSize(rxFont);
}

bool LineDescriptor::IsEmpty() const
{
    return msLine.isEmpty();
}

void LineDescriptor::CalculateSize (
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont)
{
    OSL_ASSERT(rxFont.is());

    rendering::StringContext aContext (msLine, 0, msLine.getLength());
    Reference<rendering::XTextLayout> xLayout (
        rxFont->createTextLayout(aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0));
    const geometry::RealRectangle2D aTextBBox (xLayout->queryTextBounds());
    maSize = css::geometry::RealSize2D(aTextBBox.X2 - aTextBBox.X1, aTextBBox.Y2 - aTextBBox.Y1);
    mnVerticalOffset = aTextBBox.Y2;
}

// end of anonymous namespace

//===== LineDescriptorList ====================================================

namespace {

LineDescriptorList::LineDescriptorList (
    OUString sText,
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
    const sal_Int32 nMaximalWidth)
    : msText(std::move(sText))
{
    Update(rxFont, nMaximalWidth);
}

double LineDescriptorList::Paint(
    const Reference<rendering::XCanvas>& rxCanvas,
    const geometry::RealRectangle2D& rBBox,
    const bool bFlushLeft,
    const rendering::ViewState& rViewState,
    rendering::RenderState& rRenderState,
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont) const
{
    if ( ! rxCanvas.is())
        return 0;

    double nY (rBBox.Y1);
    for (const auto& rLine : *mpLineDescriptors)
    {
        double nX;
        /// check whether RTL interface or not
        if(!AllSettings::GetLayoutRTL())
        {
            nX = rBBox.X1;
            if ( ! bFlushLeft)
                nX = rBBox.X2 - rLine.maSize.Width;
        }
        else
        {
            nX=rBBox.X2 - rLine.maSize.Width;
            if ( ! bFlushLeft)
                nX = rBBox.X1;
        }
        rRenderState.AffineTransform.m02 = nX;
        rRenderState.AffineTransform.m12 = nY + rLine.maSize.Height - rLine.mnVerticalOffset;

        const rendering::StringContext aContext (rLine.msLine, 0, rLine.msLine.getLength());
        Reference<rendering::XTextLayout> xLayout (
        rxFont->createTextLayout(aContext, rendering::TextDirection::WEAK_LEFT_TO_RIGHT, 0));
        rxCanvas->drawTextLayout (
            xLayout,
            rViewState,
            rRenderState);

        nY += rLine.maSize.Height * 1.2;
    }

    return nY - rBBox.Y1;
}

double LineDescriptorList::GetHeight() const
{
    return std::accumulate(mpLineDescriptors->begin(), mpLineDescriptors->end(), double(0),
        [](const double& nHeight, const LineDescriptor& rLine) {
            return nHeight + rLine.maSize.Height * 1.2;
        });
}

void LineDescriptorList::Update (
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
    const sal_Int32 nMaximalWidth)
{
    vector<OUString> aTextParts;
    SplitText(msText, aTextParts);
    FormatText(aTextParts, rxFont, nMaximalWidth);
}

void LineDescriptorList::SplitText (
    std::u16string_view rsText,
    vector<OUString>& rTextParts)
{
    const char cQuote ('\'');
    const char cSeparator (',');

    size_t nIndex (0);
    size_t nStart (0);
    size_t nLength (rsText.size());
    bool bIsQuoted (false);
    while (nIndex < nLength)
    {
        const size_t nQuoteIndex (rsText.find(cQuote, nIndex));
        const size_t nSeparatorIndex (rsText.find(cSeparator, nIndex));
        if (nQuoteIndex != std::u16string_view::npos &&
            (nSeparatorIndex == std::u16string_view::npos || nQuoteIndex<nSeparatorIndex))
        {
            bIsQuoted = !bIsQuoted;
            nIndex = nQuoteIndex+1;
            continue;
        }

        const sal_Int32 nNextIndex = nSeparatorIndex;
        if (nNextIndex < 0)
        {
            break;
        }
        else if ( ! bIsQuoted)
        {
            rTextParts.push_back(OUString(rsText.substr(nStart, nNextIndex-nStart)));
            nStart = nNextIndex + 1;
        }
        nIndex = nNextIndex+1;
    }
    if (nStart < nLength)
        rTextParts.push_back(OUString(rsText.substr(nStart, nLength-nStart)));
}

void LineDescriptorList::FormatText (
    const vector<OUString>& rTextParts,
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
    const sal_Int32 nMaximalWidth)
{
    LineDescriptor aLineDescriptor;

    mpLineDescriptors = std::make_shared<vector<LineDescriptor>>();

    vector<OUString>::const_iterator iPart (rTextParts.begin());
    vector<OUString>::const_iterator iEnd (rTextParts.end());
    while (iPart!=iEnd)
    {
        if (aLineDescriptor.IsEmpty())
        {
            // Avoid empty lines.
            if (PresenterCanvasHelper::GetTextSize(
                rxFont, *iPart).Width > nMaximalWidth)
            {
                const char cSpace (' ');

                sal_Int32 nIndex (0);
                sal_Int32 nStart (0);
                sal_Int32 nLength (iPart->getLength());
                while (nIndex < nLength)
                {
                    sal_Int32  nSpaceIndex (iPart->indexOf(cSpace, nIndex));
                    while (nSpaceIndex >= 0 && PresenterCanvasHelper::GetTextSize(
                        rxFont, iPart->copy(nStart, nSpaceIndex-nStart)).Width <= nMaximalWidth)
                    {
                        nIndex = nSpaceIndex;
                        nSpaceIndex = iPart->indexOf(cSpace, nIndex+1);
                    }

                    if (nSpaceIndex < 0 && PresenterCanvasHelper::GetTextSize(
                        rxFont, iPart->copy(nStart, nLength-nStart)).Width <= nMaximalWidth)
                    {
                        nIndex = nLength;
                    }

                    if (nIndex == nStart)
                    {
                        nIndex = nLength;
                    }

                    aLineDescriptor.AddPart(iPart->subView(nStart, nIndex-nStart), rxFont);
                    if (nIndex != nLength)
                    {
                        mpLineDescriptors->push_back(aLineDescriptor);
                        aLineDescriptor = LineDescriptor();
                    }
                    nStart = nIndex;
                }
            }
            else
            {
                aLineDescriptor.AddPart(*iPart, rxFont);
            }
        }
        else if (PresenterCanvasHelper::GetTextSize(
            rxFont, aLineDescriptor.msLine+", "+*iPart).Width > nMaximalWidth)
        {
            aLineDescriptor.AddPart(u",", rxFont);
            mpLineDescriptors->push_back(aLineDescriptor);
            aLineDescriptor = LineDescriptor();
            continue;
        }
        else
        {
            aLineDescriptor.AddPart(Concat2View(", "+*iPart), rxFont);
        }
        ++iPart;
    }
    if ( ! aLineDescriptor.IsEmpty())
    {
        mpLineDescriptors->push_back(aLineDescriptor);
    }
}

// end of anonymous namespace

//===== Block =================================================================

namespace {

Block::Block (
    const OUString& rsLeftText,
    const OUString& rsRightText,
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
    const sal_Int32 nMaximalWidth)
    : maLeft(rsLeftText, rxFont, nMaximalWidth),
      maRight(rsRightText, rxFont, nMaximalWidth)
{
}

void Block::Update (
    const css::uno::Reference<css::rendering::XCanvasFont>& rxFont,
    const sal_Int32 nMaximalWidth)
{
    maLeft.Update(rxFont, nMaximalWidth);
    maRight.Update(rxFont, nMaximalWidth);
}

// end of anonymous namespace

// end of namespace ::sdext::presenter

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

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

¤ Dauer der Verarbeitung: 0.21 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