/* -*- 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 .
*/
void SAL_CALL SdrLightEmbeddedClient_Impl::notifyEvent( const document::EventObject& aEvent )
{ // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl
SolarMutexGuard aGuard;
// the code currently makes sense only in case there is no other client if ( !(mpObj && mpObj->GetAspect() != embed::Aspects::MSOLE_ICON && aEvent.EventName == "OnVisAreaChanged"
&& mpObj->GetObjRef().is() && mpObj->GetObjRef()->getClientSite() == uno::Reference< embed::XEmbeddedClient >( this )) ) return;
// react to the change if the difference is bigger than one pixel
Size aPixelDiff =
Application::GetDefaultDevice()->LogicToPixel(
Size( aLogicRect.GetWidth() - aScaledSize.Width(),
aLogicRect.GetHeight() - aScaledSize.Height() ),
MapMode(aContainerMapUnit)); if( aPixelDiff.Width() || aPixelDiff.Height() )
{
mpObj->SetLogicRect( tools::Rectangle( aLogicRect.TopLeft(), aScaledSize ) );
mpObj->BroadcastObjectChange();
} else
mpObj->ActionChanged();
} catch( uno::Exception& )
{
TOOLS_WARN_EXCEPTION("svx.svdraw", "");
}
}
void SAL_CALL SdrLightEmbeddedClient_Impl::saveObject()
{ // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl
uno::Reference< embed::XCommonEmbedPersist > xPersist;
uno::Reference< util::XModifiable > xModifiable;
{
SolarMutexGuard aGuard;
if ( !mpObj ) throw embed::ObjectSaveVetoException();
// the common persistence is supported by objects and links
xPersist.set( mpObj->GetObjRef(), uno::UNO_QUERY_THROW );
xModifiable.set( mpObj->GetParentXModel(), uno::UNO_QUERY );
}
xPersist->storeOwn();
if ( xModifiable.is() )
xModifiable->setModified( true );
}
void SAL_CALL SdrLightEmbeddedClient_Impl::visibilityChanged( sal_Bool /*bVisible*/ )
{ // nothing to do currently // TODO/LATER: when writer uses this implementation the code could be shared with SfxInPlaceClient_Impl if ( mpObj )
{
tools::Rectangle aLogicRect( mpObj->GetLogicRect() );
Size aLogicSize( aLogicRect.GetWidth(), aLogicRect.GetHeight() );
if( mpObj->IsChart() )
{ //charts never should be stretched see #i84323# for example
mpObj->SetLogicRect( tools::Rectangle( aLogicRect.TopLeft(), aLogicSize ) );
mpObj->BroadcastObjectChange();
} // if( mpObj->IsChart() )
}
}
// check if the change is at least one pixel in size
awt::Rectangle aOldRect = getPlacement();
tools::Rectangle aNewPixelRect = vcl::unohelper::ConvertToVCLRect(aPosRect);
tools::Rectangle aOldPixelRect = vcl::unohelper::ConvertToVCLRect(aOldRect); if ( aOldPixelRect == aNewPixelRect ) // nothing has changed return;
// new scaled object area
MapUnit aContainerMapUnit( MapUnit::Map100thMM );
uno::Reference< embed::XVisualObject > xParentVis( mpObj->GetParentXModel(), uno::UNO_QUERY ); if ( xParentVis.is() )
aContainerMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xParentVis->getMapUnit( mpObj->GetAspect() ) );
// the calculation of the object area has not changed the object size // it should be done here then //SfxBooleanFlagGuard aGuard( m_bResizeNoScale, true );
// new size of the object area without scaling
Size aNewObjSize( tools::Long( aNewLogicRect.GetWidth() / m_aScaleWidth ),
tools::Long( aNewLogicRect.GetHeight() / m_aScaleHeight ) );
// now remove scaling from new placement and keep this at the new object area
aNewLogicRect.SetSize( aNewObjSize ); // react to the change if the difference is bigger than one pixel
Size aPixelDiff =
Application::GetDefaultDevice()->LogicToPixel(
Size( aLogicRect.GetWidth() - aNewObjSize.Width(),
aLogicRect.GetHeight() - aNewObjSize.Height() ),
MapMode(aContainerMapUnit)); if( aPixelDiff.Width() || aPixelDiff.Height() )
{
mpObj->SetLogicRect( tools::Rectangle( aLogicRect.TopLeft(), aNewObjSize ) );
mpObj->BroadcastObjectChange();
} else
mpObj->ActionChanged();
} // XWindowSupplier
::sfx2::SvBaseLink::UpdateResult SdrEmbedObjectLink::DataChanged( const OUString& /*rMimeType*/, const css::uno::Any & /*rValue*/ )
{ if ( !m_pObj->UpdateLinkURL_Impl() )
{ // the link URL was not changed
uno::Reference< embed::XEmbeddedObject > xObject = m_pObj->GetObjRef();
OSL_ENSURE( xObject.is(), "The object must exist always!" ); if ( xObject.is() )
{ // let the object reload the link // TODO/LATER: reload call could be used for this case
try
{
sal_Int32 nState = xObject->getCurrentState(); if ( nState != embed::EmbedStates::LOADED )
{ // in some cases the linked file probably is not locked so it could be changed
xObject->changeState( embed::EmbedStates::LOADED );
xObject->changeState( nState );
}
} catch ( uno::Exception& )
{
}
}
}
::sfx2::SvBaseLink::UpdateResult SdrIFrameLink::DataChanged( const OUString&, const uno::Any& )
{
uno::Reference<embed::XEmbeddedObject> xObject = m_pObject->GetObjRef();
uno::Reference<embed::XCommonEmbedPersist> xPersObj(xObject, uno::UNO_QUERY); if (xPersObj.is())
{ // let the IFrameObject reload the link try
{
xPersObj->reload(uno::Sequence<beans::PropertyValue>(), uno::Sequence<beans::PropertyValue>());
} catch (const uno::Exception&)
{
}
m_pObject->SetChanged();
}
return SUCCESS;
}
class SdrOle2ObjImpl
{ public:
svt::EmbeddedObjectRef mxObjRef;
std::optional<Graphic> moGraphic;
OUString maProgName;
OUString aPersistName; // name of object in persist
rtl::Reference<SdrLightEmbeddedClient_Impl> mxLightClient; // must be registered as client only using AddOwnLightClient() call
bool mbFrame:1; // Due to compatibility at SdrTextObj for now bool mbSuppressSetVisAreaSize:1; // #i118524# mutablebool mbTypeAsked:1; mutablebool mbIsChart:1; bool mbLoadingOLEObjectFailed:1; // New local var to avoid repeated loading if load of OLE2 fails bool mbConnected:1; bool mbIgnoreOLEObjectScale : 1 = false; // See SdXMLObjectShapeContext::createFastChildContext
if (mxModifyListener.is())
{
mxModifyListener->invalidate();
}
}
};
// Predicate determining whether the given OLE is an internal math // object staticbool ImplIsMathObj( const uno::Reference < embed::XEmbeddedObject >& rObjRef )
{ if ( !rObjRef.is() ) returnfalse;
void SdrOle2Obj::Init()
{ // Stuff that was done from old SetModel: // #i43086# #i85304 redo the change for charts for the above bugfix, as #i43086# does not occur anymore // so maybe the ImpSetVisAreaSize call can be removed here completely // Nevertheless I leave it in for other objects as I am not sure about the side effects when removing now if(!getSdrModelFromSdrObject().isLocked() && !IsChart())
{
ImpSetVisAreaSize();
}
::comphelper::IEmbeddedHelper* pDestPers(getSdrModelFromSdrObject().GetPersist()); if(pDestPers && !IsEmptyPresObj())
{ // object wasn't connected, now it should be
Connect_Impl();
}
if( mpImpl->mbConnected )
{ // currently there are situations where it seems to be unavoidable to have multiple connects // changing this would need a larger code rewrite, so for now I remove the assertion // OSL_FAIL("Connect() called on connected object!"); return;
}
if ( mpImpl->mpObjectLink )
{
sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
if ( pLinkManager )
{
OUString aNewLinkURL;
sfx2::LinkManager::GetDisplayNames( mpImpl->mpObjectLink, nullptr, &aNewLinkURL ); if ( !aNewLinkURL.equalsIgnoreAsciiCase( mpImpl->maLinkURL ) )
{
GetObjRef_Impl();
uno::Reference<embed::XCommonEmbedPersist> xPersObj( mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY );
OSL_ENSURE( xPersObj.is(), "The object must exist!" ); if ( xPersObj.is() )
{ try
{
sal_Int32 nCurState = mpImpl->mxObjRef->getCurrentState(); if ( nCurState != embed::EmbedStates::LOADED )
mpImpl->mxObjRef->changeState(embed::EmbedStates::LOADED);
// TODO/LATER: there should be possible to get current mediadescriptor settings from the object
uno::Sequence< beans::PropertyValue > aArgs{ comphelper::makePropertyValue(
u"URL"_ustr, aNewLinkURL) };
xPersObj->reload( aArgs, uno::Sequence< beans::PropertyValue >() );
void SdrOle2Obj::CheckFileLink_Impl()
{ if (!mpImpl->mxObjRef.GetObject().is() || mpImpl->mpObjectLink) return;
try
{
uno::Reference<embed::XEmbeddedObject> xObject = mpImpl->mxObjRef.GetObject(); if (!xObject) return;
bool bIFrame = false;
OUString aLinkURL;
uno::Reference<embed::XLinkageSupport> xLinkSupport(xObject, uno::UNO_QUERY); if (xLinkSupport)
{ if (xLinkSupport->isLink())
aLinkURL = xLinkSupport->getLinkURL();
} else
{ // get IFrame (Floating Frames) listed and updatable from the // manage links dialog
SvGlobalName aClassId(xObject->getClassID()); if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID))
{
uno::Reference<beans::XPropertySet> xSet(xObject->getComponent(), uno::UNO_QUERY); if (xSet.is())
xSet->getPropertyValue(u"FrameURL"_ustr) >>= aLinkURL;
bIFrame = true;
}
}
if (!aLinkURL.isEmpty()) // this is a file link so the model link manager should handle it
{
sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager());
if ( pLinkManager )
{
SdrEmbedObjectLink* pEmbedObjectLink = nullptr; if (!bIFrame)
{
pEmbedObjectLink = new SdrEmbedObjectLink(this);
mpImpl->mpObjectLink = pEmbedObjectLink;
} else
mpImpl->mpObjectLink = new SdrIFrameLink(this);
mpImpl->maLinkURL = aLinkURL;
pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL ); if (pEmbedObjectLink)
pEmbedObjectLink->Connect();
}
}
} catch (const css::uno::Exception&)
{
TOOLS_WARN_EXCEPTION("svx", "SdrOle2Obj::CheckFileLink_Impl()");
}
}
void SdrOle2Obj::Disconnect_Impl()
{ try
{ if ( !mpImpl->aPersistName.isEmpty() )
{ if( getSdrModelFromSdrObject().IsInDestruction() )
{ // TODO/LATER: here we must assume that the destruction of the model is enough to make clear that we will not // remove the object from the container, even if the DrawingObject itself is not destroyed (unfortunately this // There is no real need to do the following removing of the object from the container // in case the model has correct persistence, but in case of problems such a removing // would make the behavior of the office more stable
// happens later than the destruction of the model, so we can't assert that). //DBG_ASSERT( bInDestruction, "Model is destroyed, but not me?!" ); //TODO/LATER: should be make sure that the ObjectShell also forgets the object, because we will close it soon? /* uno::Reference < util::XCloseable > xClose( xObjRef, uno::UNO_QUERY ); if ( xClose.is() ) { try { xClose->close( true ); } catch ( util::CloseVetoException& ) { // there's still someone who needs the object! } }
xObjRef = NULL;*/
} elseif ( mpImpl->mxObjRef.is() )
{ if ( getSdrModelFromSdrObject().getUnoModel().is() )
{ // remove object, but don't close it (that's up to someone else)
comphelper::EmbeddedObjectContainer* pContainer = mpImpl->mxObjRef.GetContainer(); if ( pContainer )
{
pContainer->RemoveEmbeddedObject( mpImpl->mxObjRef.GetObject() );
// TODO/LATER: mpImpl->aPersistName contains outdated information, to keep it updated // it should be returned from RemoveEmbeddedObject call. Currently it is no problem, // since no container is adjusted, actually the empty string could be provided as a name here
mpImpl->mxObjRef.AssignToContainer( nullptr, mpImpl->aPersistName );
}
return rtl::Reference<SdrObject>(pClone);
} else
{ // #i100710# pOLEGraphic may be zero (no visualisation available), // so we need to use the OLE replacement graphic
rtl::Reference<SdrRectObj> pClone = new SdrRectObj(
getSdrModelFromSdrObject(),
GetSnapRect());
// the caller of the method is responsible to control the old object, it will not be closed here // Otherwise WW8 import crashes because it transfers control to OLENode by this method if ( mpImpl->mxObjRef.GetObject().is() )
mpImpl->mxObjRef.Lock( false );
// avoid removal of object in Disconnect! It is definitely a HACK to call SetObjRef(0)! // This call will try to close the objects; so if anybody else wants to keep it, it must be locked by a CloseListener
mpImpl->mxObjRef.Clear();
if ( mpImpl->mxObjRef.is() )
{
mpImpl->moGraphic.reset();
if ( mpImpl->mxObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::EMBED_NEVERRESIZE )
SetResizeProtect(true);
// For math objects, set closed state to transparent
SetClosedObj(!ImplIsMathObj( rNewObjRef ));
Connect();
}
SetChanged();
BroadcastObjectChange();
}
void SdrOle2Obj::SetClosedObj( bool bIsClosed )
{ // TODO/LATER: do we still need this hack? // Allow changes to the closed state of OLE objects
m_bClosedObj = bIsClosed;
}
rtl::Reference<SdrObject> SdrOle2Obj::getFullDragClone() const
{ // #i118485# use central replacement generator return createSdrGrafObjReplacement(false);
}
void SdrOle2Obj::ImpSetVisAreaSize()
{ // #i118524# do not again set VisAreaSize when the call comes from OLE client (e.g. ObjectAreaChanged) if (mpImpl->mbSuppressSetVisAreaSize) return;
// currently there is no need to recalculate scaling for iconified objects // TODO/LATER: it might be needed in future when it is possible to change the icon if ( GetAspect() == embed::Aspects::MSOLE_ICON ) return;
// the object area of an embedded object was changed, e.g. by user interaction an a selected object
GetObjRef(); if (!mpImpl->mxObjRef.is()) return;
// the client is required to get access to scaling
SfxInPlaceClient* pClient(
SfxInPlaceClient::GetClient( dynamic_cast<SfxObjectShell*>(
getSdrModelFromSdrObject().GetPersist()),
mpImpl->mxObjRef.GetObject())); constbool bHasOwnClient(
mpImpl->mxLightClient.is() &&
mpImpl->mxObjRef->getClientSite() == uno::Reference< embed::XEmbeddedClient >( mpImpl->mxLightClient ) );
if ( pClient || bHasOwnClient )
{ // TODO: IMHO we need to do similar things when object is UIActive or OutplaceActive?! if ( ((nMiscStatus & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) &&
svt::EmbeddedObjectRef::TryRunningState( mpImpl->mxObjRef.GetObject() ))
|| mpImpl->mxObjRef->getCurrentState() == embed::EmbedStates::INPLACE_ACTIVE
)
{
Fraction aScaleWidth;
Fraction aScaleHeight; if ( pClient )
{
aScaleWidth = pClient->GetScaleWidth();
aScaleHeight = pClient->GetScaleHeight();
} else
{
aScaleWidth = mpImpl->mxLightClient->GetScaleWidth();
aScaleHeight = mpImpl->mxLightClient->GetScaleHeight();
}
// The object wants to resize itself (f.e. Chart wants to recalculate the layout) // or object is inplace active and so has a window that must be resized also // In these cases the change in the object area size will be reflected in a change of the // objects' visual area. The scaling will not change, but it might exist already and must // be used in calculations
MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( mpImpl->mxObjRef->getMapUnit( GetAspect() ) );
Size aVisSize; if (sal_Int32(aScaleWidth) != 0 && sal_Int32(aScaleHeight) != 0) // avoid div by zero
aVisSize = Size( static_cast<tools::Long>( Fraction( getRectangle().GetWidth() ) / aScaleWidth ), static_cast<tools::Long>( Fraction( getRectangle().GetHeight() ) / aScaleHeight ) );
tools::Rectangle aAcceptedVisArea;
aAcceptedVisArea.SetSize( Size( static_cast<tools::Long>( Fraction( tools::Long( aSz.Width ) ) * aScaleWidth ), static_cast<tools::Long>( Fraction( tools::Long( aSz.Height ) ) * aScaleHeight ) ) ); if (aVisSize != aAcceptedVisArea.GetSize())
{ // server changed VisArea to its liking and the VisArea is different than the suggested one // store the new value as given by the object
MapUnit aNewMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( mpImpl->mxObjRef->getMapUnit( GetAspect() ) ); auto aSize = OutputDevice::LogicToLogic(aAcceptedVisArea.GetSize(), MapMode(aNewMapUnit), MapMode(getSdrModelFromSdrObject().GetScaleUnit()));
setRectangleSize(aSize.Width(), aSize.Height());
}
// make the new object area known to the client // compared to the "else" branch aRect might have been changed by the object and no additional scaling was applied // WHY this -> OSL_ASSERT( pClient ); if( pClient )
pClient->SetObjArea(getRectangle());
// we need a new replacement image as the object has resized itself
//#i79578# don't request a new replacement image for charts to often //a chart sends a modified call to the framework if it was changed //thus the replacement update is already handled there if( !IsChart() )
mpImpl->mxObjRef.UpdateReplacement();
} else
{ // The object isn't active and does not want to resize itself so the changed object area size // will be reflected in a changed object scaling
Fraction aScaleWidth;
Fraction aScaleHeight;
Size aObjAreaSize; if ( CalculateNewScaling( aScaleWidth, aScaleHeight, aObjAreaSize ) )
{ if ( pClient )
{
tools::Rectangle aScaleRect(getRectangle().TopLeft(), aObjAreaSize);
pClient->SetObjAreaAndScale( aScaleRect, aScaleWidth, aScaleHeight);
} else
{
mpImpl->mxLightClient->SetSizeScale( aScaleWidth, aScaleHeight );
}
}
}
} elseif( (nMiscStatus & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE) &&
svt::EmbeddedObjectRef::TryRunningState( mpImpl->mxObjRef.GetObject() ) )
{ //also handle not sfx based ole objects e.g. charts //#i83860# resizing charts in impress distorts fonts
uno::Reference< embed::XVisualObject > xVisualObject( getXModel(), uno::UNO_QUERY ); if( xVisualObject.is() )
{ const MapUnit aMapUnit(
VCLUnoHelper::UnoEmbed2VCLMapUnit(
mpImpl->mxObjRef->getMapUnit(GetAspect()))); const Point aTL( getRectangle().TopLeft() ); const Point aBR( getRectangle().BottomRight() ); const Point aTL2(
OutputDevice::LogicToLogic(
aTL,
MapMode(getSdrModelFromSdrObject().GetScaleUnit()),
MapMode(aMapUnit))); const Point aBR2(
OutputDevice::LogicToLogic(
aBR,
MapMode(getSdrModelFromSdrObject().GetScaleUnit()),
MapMode(aMapUnit))); const tools::Rectangle aNewRect(
aTL2,
aBR2);
if ( mpImpl->mxObjRef.is() && ( mpImpl->mxObjRef->getStatus( GetAspect() ) & embed::EmbedMisc::MS_EMBED_RECOMPOSEONRESIZE ) )
{ // if the object needs recompose on resize // the client site should be created before the resize will take place // check whether there is no client site and create it if necessary
AddOwnLightClient();
}
}
if ( mpImpl->mxObjRef.is() && IsChart() )
{ //#i103460# charts do not necessarily have an own size within ODF files, //for this case they need to use the size settings from the surrounding frame, //which is made available with this method as there is no other way
mpImpl->mxObjRef.SetDefaultSizeForChart( Size( rRect.GetWidth(), rRect.GetHeight() ) );
}
}
void SdrOle2Obj::GetObjRef_Impl()
{ if ( !mpImpl->mxObjRef.is() && !mpImpl->aPersistName.isEmpty() && getSdrModelFromSdrObject().GetPersist() )
{ // Only try loading if it did not went wrong up to now if(!mpImpl->mbLoadingOLEObjectFailed)
{
mpImpl->mxObjRef.Assign(
getSdrModelFromSdrObject().GetPersist()->getEmbeddedObjectContainer().GetEmbeddedObject(mpImpl->aPersistName),
GetAspect());
mpImpl->mbTypeAsked = false;
CheckFileLink_Impl();
// If loading of OLE object failed, remember that to not invoke an endless // loop trying to load it again and again. if( mpImpl->mxObjRef.is() )
{
mpImpl->mbLoadingOLEObjectFailed = true;
}
// For math objects, set closed state to transparent
SetClosedObj(!ImplIsMathObj( mpImpl->mxObjRef.GetObject() ));
}
if ( mpImpl->mxObjRef.is() )
{ if( !IsEmptyPresObj() )
{ // remember modified status of model constbool bWasChanged(getSdrModelFromSdrObject().IsChanged());
// perhaps preview not valid anymore // This line changes the modified state of the model
ClearGraphic();
// if status was not set before, force it back // to not set, so that SetGraphic(0) above does not // set the modified state of the model. if(!bWasChanged && getSdrModelFromSdrObject().IsChanged())
{
getSdrModelFromSdrObject().SetChanged( false );
}
}
}
if ( mpImpl->mxObjRef.is() )
Connect();
}
if ( mpImpl->mbConnected )
{ // move object to first position in cache
GetSdrGlobalData().GetOLEObjCache().InsertObj(this);
}
}
void SdrOle2Obj::SetGraphicToObj( const Graphic& aGraphic )
{
mpImpl->mxObjRef.SetGraphic( aGraphic, OUString() ); // if the object isn't valid, e.g. link to something that doesn't exist, set the fallback // graphic as mxGraphic so SdrOle2Obj::GetGraphic will show the fallback if (const Graphic* pObjGraphic = mpImpl->mxObjRef.is() ? nullptr : mpImpl->mxObjRef.GetGraphic())
mpImpl->moGraphic.emplace(*pObjGraphic);
}
void SdrOle2Obj::SetGraphicToObj( const uno::Reference< io::XInputStream >& xGrStream, const OUString& aMediaType )
{
mpImpl->mxObjRef.SetGraphicStream( xGrStream, aMediaType ); // if the object isn't valid, e.g. link to something that doesn't exist, set the fallback // graphic as mxGraphic so SdrOle2Obj::GetGraphic will show the fallback if (const Graphic* pObjGraphic = mpImpl->mxObjRef.is() ? nullptr : mpImpl->mxObjRef.GetGraphic())
mpImpl->moGraphic.emplace(*pObjGraphic);
}
bool SdrOle2Obj::IsCalc() const
{ if ( !mpImpl->mxObjRef.is() ) returnfalse;
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.