<commit_before>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_3DCanvasSource.h"

#include "EC_3DCanvas.h"
#include "EC_Mesh.h"
#include "EC_OgreCustomObject.h"
#include "IModule.h"
#include "ModuleManager.h"
#include "Entity.h"
#include "UiProxyWidget.h"
#include "UiServiceInterface.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_3DCanvasSource")

#include <QWebView>
#include <QLineEdit>
#include <QApplication>
#include <QPushButton>
#include <QUiLoader>
#include <QVBoxLayout>
#include <QGraphicsScene>
#include <QPushButton>
#include <QProgressBar>
#include <QSize>

#include "MemoryLeakCheck.h"

EC_3DCanvasSource::EC_3DCanvasSource(IModule *module) :
    IComponent(module->GetFramework()),
    source(this, "Source", ""),
    submesh(this, "Submesh", 0),
    refreshRate(this, "Refresh per sec", 0),
    show2d(this, "Show 2D on click", true),
    sync2dbrowsing(this, "Sync 2D browsing", false),
    pageWidth(this, "Page width", 800),
    pageHeight(this, "Page height", 600),
    widget_(0),
    content_widget_(0),
    placeholder_widget_(0),
    button_refreshstop_(0),
    progress_bar_(0),
    proxy_(0),
    source_edit_(0),
    canvas_started_(false)
{
    static AttributeMetadata size_metadata("", "100", "2000", "50");
    pageWidth.SetMetadata(&size_metadata);
    pageHeight.SetMetadata(&size_metadata);

    connect(this, SIGNAL(OnAttributeChanged(IAttribute*, AttributeChange::Type)), this, SLOT(UpdateWidgetAndCanvas(IAttribute*, AttributeChange::Type)));
    connect(this, SIGNAL(ParentEntitySet()), this, SLOT(RegisterActions()));
    CreateWidget();
}

EC_3DCanvasSource::~EC_3DCanvasSource()
{
    // Note: content widget is inside widget_s layout,
    // no need to do a separate deleteLater for it. This would cause problems on rundown.
    SAFE_DELETE_LATER(widget_);
}

void EC_3DCanvasSource::OnClick()
{
    if ((getshow2d() == true) && (widget_) && (proxy_))
    {
        if (!proxy_->scene())
            return;
        if (!proxy_->scene()->isActive())
            return;
        if (proxy_->isVisible())
            proxy_->AnimatedHide();
        else
            proxy_->show();
    }
}

void EC_3DCanvasSource::SourceEdited()
{
    if (!source_edit_)
        return;

    QString new_source = source_edit_->text();
    if (new_source != getsource())
    {
        if (getsync2dbrowsing())
            setsource(new_source);
        else
            UpdateWidget(new_source);
    }
}

void EC_3DCanvasSource::RefreshStopPressed()
{
    QWebView *webview = GetWebView();
    if (!webview || !progress_bar_)
        return;
    if (progress_bar_->isVisible())
        webview->stop();
    else
        webview->reload();
}

void EC_3DCanvasSource::BackPressed()
{
    QWebView *webview = GetWebView();
    if (!webview)
        return;
    webview->back();
}

void EC_3DCanvasSource::ForwardPressed()
{
    QWebView *webview = GetWebView();
    if (!webview)
        return;
    webview->forward();
}

void EC_3DCanvasSource::HomePressed()
{
    QWebView *webview = GetWebView();
    if (!webview || home_url_.isEmpty())
        return;
    webview->load(QUrl(home_url_));
}

void EC_3DCanvasSource::UpdateWidgetAndCanvas(IAttribute *attribute, AttributeChange::Type type)
{
    EC_3DCanvas *canvas = Get3DCanvas();
    bool update = false;
    if (attribute == &submesh)
    {
        if (canvas)
        {
            int my_submesh = getsubmesh();
            if (my_submesh < 0)
                my_submesh = 0;
            if (!canvas->GetSubMeshes().contains(my_submesh))
            {
                canvas->SetSubmesh(my_submesh);
                update = true;
            }
        }
        else
            UpdateWidget();
    }
    else if (attribute == &source)
    {
        if (last_source_ != getsource())
        {
            UpdateWidget();
            if (!canvas_started_)
                UpdateCanvas();
            else
                update = true;

            if (home_url_.isEmpty())
                home_url_ = getsource();
        }
    }
    else if (attribute == &refreshRate)
    {
        if (canvas)
        {
            int ref_rate_sec = getrefreshRate();
            if (ref_rate_sec > 0)
            {
                int ref_rate_msec = 1000 / ref_rate_sec;
                if (canvas->GetRefreshRate() != ref_rate_msec)
                {
                    canvas->SetRefreshRate(ref_rate_sec);
                    canvas_started_ = false;
                    UpdateCanvas();
                }
            }
            else
                canvas->SetRefreshRate(0);
        }
    }
    else if (attribute == &pageHeight || attribute == &pageWidth)
    {
        QWebView *webview = GetWebView();
        if (webview)
        {
            QSize new_size(getpageWidth(), getpageHeight());
            if (webview->size() != new_size)
            {
                webview->resize(new_size);
                update = true;
            }
        }
    }

    if (update && canvas)
        UpdateCanvas();
}

void EC_3DCanvasSource::WebViewLinkClicked(const QUrl& url)
{
    //! \todo: check here if the link is something we want to open differently (external program etc.)

    // If url is different than the source, update the lineedit & browser & replicate to network
    QString url_str = url.toString();
    if (url_str != getsource())
    {
        QWebView* webwidget = dynamic_cast<QWebView*>(content_widget_);
        if (!webwidget)
            return;
        webwidget->setUrl(url);

        if (source_edit_)
            source_edit_->setText(url_str);

        if (getsync2dbrowsing())
        {
            // Set last_source now so that we won't trigger reload of the page again when the source comes back from network
            last_source_ = url_str;
            setsource(url_str);
        }
    }
}

void EC_3DCanvasSource::WebViewLoadStarted()
{
    if (progress_bar_)
        progress_bar_->show();
    if (button_refreshstop_)
        button_refreshstop_->setStyleSheet("QPushButton#button_refreshstop { background-image: url('./data/ui/images/browser/stop.png'); }");
}

void EC_3DCanvasSource::WebViewLoadProgress(int progress)
{
    if (progress_bar_)
        progress_bar_->setValue(progress);
}

void EC_3DCanvasSource::WebViewLoadCompleted()
{
    // Setup ui
    if (progress_bar_)
        progress_bar_->hide();
    if (button_refreshstop_)
        button_refreshstop_->setStyleSheet("QPushButton#button_refreshstop { background-image: url('./data/ui/images/browser/refresh.png'); }");

    // Update the 2d ui line edit
    QWebView *webview = GetWebView();
    if (webview && source_edit_)
        source_edit_->setText(webview->url().toString());

    // Invoke a delayed repaint of the inworld texture
    QTimer::singleShot(50, this, SLOT(RepaintCanvas()));
}

void EC_3DCanvasSource::RepaintCanvas()
{
    EC_3DCanvas *canvas = Get3DCanvas();
    if (canvas)
        canvas->Update();
}

EC_3DCanvas *EC_3DCanvasSource::Get3DCanvas()
{
    Scene::Entity* entity = GetParentEntity();
    if (!entity)
        return 0;
    ComponentPtr comp = entity->GetComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
        return 0;
    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    return canvas;
}

QWebView *EC_3DCanvasSource::GetWebView()
{
    if (!content_widget_)
        return 0;
    return dynamic_cast<QWebView*>(content_widget_);
}

void EC_3DCanvasSource::UpdateWidget(QString url)
{
    // Prefer inparam over the attribute (if sync 2d browsing is disabled)
    QString source;
    if (url.isEmpty())
        source = getsource();
    else
        source = url;

    if (source.isEmpty())
    {
        QTimer::singleShot(1000, this, SLOT(FetchWebViewUrl()));
        return;
    }

    if (source != last_source_)
    {
        if (source_edit_)
            source_edit_->setText(source);
        last_source_ = source;

        if (!placeholder_widget_)
        {
            LogError("No placeholder widget, cannot create content widget");
            return;
        }

        // See if source looks like an url, and instantiate a QWebView then if it doesn't already exist
        if (source.indexOf("http://") != -1)
        {
            QWebView* webwidget = GetWebView();
            if (!webwidget)
            {
                // If widget exists, but is wrong type, delete and recreate
                if (content_widget_)
                {
                    content_widget_->deleteLater();
                    content_widget_ = 0;
                }

                webwidget = new QWebView(placeholder_widget_);
                QVBoxLayout *layout = placeholder_widget_->findChild<QVBoxLayout*>("widget_placeholder_layout");
                if (layout)
                    layout->addWidget(webwidget);

                // Load current source and resize to attribute set size
                webwidget->load(QUrl(source));
                webwidget->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
                webwidget->resize(getpageWidth(), getpageHeight());

                // Connect webview signals
                connect(webwidget, SIGNAL(loadStarted()), this, SLOT(WebViewLoadStarted()), Qt::UniqueConnection);
                connect(webwidget, SIGNAL(loadProgress(int)), this, SLOT(WebViewLoadProgress(int)), Qt::UniqueConnection);
                connect(webwidget, SIGNAL(loadFinished(bool)), this, SLOT(WebViewLoadCompleted()), Qt::UniqueConnection);
                connect(webwidget, SIGNAL(linkClicked(const QUrl&)), this, SLOT(WebViewLinkClicked(const QUrl &)), Qt::UniqueConnection);
                connect(webwidget->page(), SIGNAL(scrollRequested(int, int, const QRect&)), this, SLOT(RepaintCanvas()), Qt::UniqueConnection);

                // This webview is our new content_widget_
                content_widget_ = webwidget;
            }
            else
            {
                // If source changed, update the webview URL
                webwidget->load(QUrl(source));
            }
        }
    }
}

void EC_3DCanvasSource::UpdateCanvas()
{
    if (!content_widget_)
        return;

    Scene::Entity* entity = GetParentEntity();
    if (!entity)
    {
        LogError("No parent entity, cannot create/update 3DCanvas");
        return;
    }

    ComponentPtr comp = entity->GetOrCreateComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
    {
        LogError("Could not create/get 3DCanvas component");
        return;
    }

    // If entity has no valid mesh or prim yet, start a retry timer and try to set the canvas later
    if ((!entity->GetComponent(EC_Mesh::TypeNameStatic())) &&
        (!entity->GetComponent(EC_OgreCustomObject::TypeNameStatic())))
    {
        //LogInfo("Mesh or prim did not exist yet, retrying");
        QTimer::singleShot(1000, this, SLOT(UpdateCanvas()));
        return;
    }

    // Set widget if different
    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    if (canvas->GetWidget() != content_widget_)
    {
        canvas->SetWidget(content_widget_);
    }

    // Set submesh if different
    int my_submesh = getsubmesh();
    if (my_submesh < 0)
        my_submesh = 0;
    if (!canvas->GetSubMeshes().contains(my_submesh))
        canvas->SetSubmesh(my_submesh);

    // Refresh rate
    int ref_rate_sec = getrefreshRate();
    if (ref_rate_sec > 0)
    {
        int ref_rate_msec = 1000 / ref_rate_sec;
        if (canvas->GetRefreshRate() != ref_rate_msec)
        {
            canvas->SetRefreshRate(ref_rate_sec);
            canvas_started_ = false;
        }
    }
    else
        canvas->SetRefreshRate(0);

    // Start if first run
    if (!canvas_started_)
    {
        canvas->Start();
        canvas_started_ = true;
    }
    // Update otherwise
    else
    {
        canvas->Update();
    }
}

void EC_3DCanvasSource::FetchWebViewUrl()
{
    // Workaround on the bug that ec_3canvas->webview()->url() is not valid when this component is created/updated.
    // Somehow its doesent have time to set it before we already come here. So this polls untill the url is valid.

    Scene::Entity* entity = GetParentEntity();
    if (!entity)
    {
        LogError("No parent entity, cannot create/update 3DCanvas");
        return;
    }

    ComponentPtr comp = entity->GetOrCreateComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
    {
        LogError("Could not create/get 3DCanvas component");
        return;
    }

    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    QWidget *canvas_widget = canvas->GetWidget();
    if (!canvas_widget)
        return;
    QWebView *canvas_webview = dynamic_cast<QWebView*>(canvas_widget);
    if (!canvas_webview)
        return;
    QString url = canvas_webview->url().toString();
    if (!url.isEmpty())
    {
        setsource(url);
        if (home_url_.isEmpty())
            home_url_ = url;
    }
    else
        QTimer::singleShot(1000, this, SLOT(FetchWebViewUrl()));
}

void EC_3DCanvasSource::ChangeLanguage()
{
    if (widget_)
    {
        QString title = tr("3DCanvas Controls");
        widget_->setWindowTitle(title);
    }
}

void EC_3DCanvasSource::CreateWidget()
{
    UiServiceInterface *ui = framework_->GetService<UiServiceInterface>();
    if (!ui)
    {
        LogError("Failed to acquire UI service");
        return;
    }

    QUiLoader loader;
    loader.setLanguageChangeEnabled(true);
    QFile file("./data/ui/3dcanvassource.ui");
    file.open(QFile::ReadOnly);
    widget_ = loader.load(&file);
    file.close();

    if (!widget_)
    {
        LogError("Failed to create 3D canvas controls widget");
        return;
    }

    widget_->setWindowTitle(tr("Naali Web Browser"));
    proxy_ = ui->AddWidgetToScene(widget_);
    connect(qApp, SIGNAL(LanguageChanged()), this, SLOT(ChangeLanguage()));

    source_edit_ = widget_->findChild<QLineEdit*>("line_source");
    if (source_edit_)
        connect(source_edit_, SIGNAL(returnPressed()), SLOT(SourceEdited()));

    placeholder_widget_ = widget_->findChild<QWidget*>("widget_placeholder");

    button_refreshstop_ = widget_->findChild<QPushButton*>("button_refreshstop");
    if (button_refreshstop_)
        connect(button_refreshstop_, SIGNAL(clicked()), SLOT(RefreshStopPressed()));

    QPushButton* button = widget_->findChild<QPushButton*>("button_back");
    if (button)
        connect(button, SIGNAL(clicked()), SLOT(BackPressed()));

    button = widget_->findChild<QPushButton*>("button_forward");
    if (button)
        connect(button, SIGNAL(clicked()), SLOT(ForwardPressed()));

    button = widget_->findChild<QPushButton*>("button_home");
    if (button)
        connect(button, SIGNAL(clicked()), SLOT(HomePressed()));

    progress_bar_ = widget_->findChild<QProgressBar*>("progress_bar");
    if (progress_bar_)
        progress_bar_->hide();
}

void EC_3DCanvasSource::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
        entity->ConnectAction("MousePress", this, SLOT(OnClick()));
}

<commit_msg>3DCanvasSource: Was trying to oad widgets and webviews into memory on a headless server, no more.<commit_after>// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "DebugOperatorNew.h"

#include "EC_3DCanvasSource.h"

#include "EC_3DCanvas.h"
#include "EC_Mesh.h"
#include "EC_OgreCustomObject.h"
#include "IModule.h"
#include "ModuleManager.h"
#include "Entity.h"
#include "UiProxyWidget.h"
#include "UiServiceInterface.h"
#include "LoggingFunctions.h"

DEFINE_POCO_LOGGING_FUNCTIONS("EC_3DCanvasSource")

#include <QWebView>
#include <QLineEdit>
#include <QApplication>
#include <QPushButton>
#include <QUiLoader>
#include <QVBoxLayout>
#include <QGraphicsScene>
#include <QPushButton>
#include <QProgressBar>
#include <QSize>

#include "MemoryLeakCheck.h"

EC_3DCanvasSource::EC_3DCanvasSource(IModule *module) :
    IComponent(module->GetFramework()),
    source(this, "Source", ""),
    submesh(this, "Submesh", 0),
    refreshRate(this, "Refresh per sec", 0),
    show2d(this, "Show 2D on click", true),
    sync2dbrowsing(this, "Sync 2D browsing", false),
    pageWidth(this, "Page width", 800),
    pageHeight(this, "Page height", 600),
    widget_(0),
    content_widget_(0),
    placeholder_widget_(0),
    button_refreshstop_(0),
    progress_bar_(0),
    proxy_(0),
    source_edit_(0),
    canvas_started_(false)
{
    static AttributeMetadata size_metadata("", "100", "2000", "50");
    pageWidth.SetMetadata(&size_metadata);
    pageHeight.SetMetadata(&size_metadata);

    connect(this, SIGNAL(OnAttributeChanged(IAttribute*, AttributeChange::Type)), this, SLOT(UpdateWidgetAndCanvas(IAttribute*, AttributeChange::Type)));
    connect(this, SIGNAL(ParentEntitySet()), this, SLOT(RegisterActions()));
    CreateWidget();
}

EC_3DCanvasSource::~EC_3DCanvasSource()
{
    // Note: content widget is inside widget_s layout,
    // no need to do a separate deleteLater for it. This would cause problems on rundown.
    SAFE_DELETE_LATER(widget_);
}

void EC_3DCanvasSource::OnClick()
{
    if ((getshow2d() == true) && (widget_) && (proxy_))
    {
        if (!proxy_->scene())
            return;
        if (!proxy_->scene()->isActive())
            return;
        if (proxy_->isVisible())
            proxy_->AnimatedHide();
        else
            proxy_->show();
    }
}

void EC_3DCanvasSource::SourceEdited()
{
    if (!source_edit_)
        return;

    QString new_source = source_edit_->text();
    if (new_source != getsource())
    {
        if (getsync2dbrowsing())
            setsource(new_source);
        else
            UpdateWidget(new_source);
    }
}

void EC_3DCanvasSource::RefreshStopPressed()
{
    QWebView *webview = GetWebView();
    if (!webview || !progress_bar_)
        return;
    if (progress_bar_->isVisible())
        webview->stop();
    else
        webview->reload();
}

void EC_3DCanvasSource::BackPressed()
{
    QWebView *webview = GetWebView();
    if (!webview)
        return;
    webview->back();
}

void EC_3DCanvasSource::ForwardPressed()
{
    QWebView *webview = GetWebView();
    if (!webview)
        return;
    webview->forward();
}

void EC_3DCanvasSource::HomePressed()
{
    QWebView *webview = GetWebView();
    if (!webview || home_url_.isEmpty())
        return;
    webview->load(QUrl(home_url_));
}

void EC_3DCanvasSource::UpdateWidgetAndCanvas(IAttribute *attribute, AttributeChange::Type type)
{
    EC_3DCanvas *canvas = Get3DCanvas();
    bool update = false;
    if (attribute == &submesh)
    {
        if (canvas)
        {
            int my_submesh = getsubmesh();
            if (my_submesh < 0)
                my_submesh = 0;
            if (!canvas->GetSubMeshes().contains(my_submesh))
            {
                canvas->SetSubmesh(my_submesh);
                update = true;
            }
        }
        else
            UpdateWidget();
    }
    else if (attribute == &source)
    {
        if (last_source_ != getsource())
        {
            UpdateWidget();
            if (!canvas_started_)
                UpdateCanvas();
            else
                update = true;

            if (home_url_.isEmpty())
                home_url_ = getsource();
        }
    }
    else if (attribute == &refreshRate)
    {
        if (canvas)
        {
            int ref_rate_sec = getrefreshRate();
            if (ref_rate_sec > 0)
            {
                int ref_rate_msec = 1000 / ref_rate_sec;
                if (canvas->GetRefreshRate() != ref_rate_msec)
                {
                    canvas->SetRefreshRate(ref_rate_sec);
                    canvas_started_ = false;
                    UpdateCanvas();
                }
            }
            else
                canvas->SetRefreshRate(0);
        }
    }
    else if (attribute == &pageHeight || attribute == &pageWidth)
    {
        QWebView *webview = GetWebView();
        if (webview)
        {
            QSize new_size(getpageWidth(), getpageHeight());
            if (webview->size() != new_size)
            {
                webview->resize(new_size);
                update = true;
            }
        }
    }

    if (update && canvas)
        UpdateCanvas();
}

void EC_3DCanvasSource::WebViewLinkClicked(const QUrl& url)
{
    //! \todo: check here if the link is something we want to open differently (external program etc.)

    // If url is different than the source, update the lineedit & browser & replicate to network
    QString url_str = url.toString();
    if (url_str != getsource())
    {
        QWebView* webwidget = dynamic_cast<QWebView*>(content_widget_);
        if (!webwidget)
            return;
        webwidget->setUrl(url);

        if (source_edit_)
            source_edit_->setText(url_str);

        if (getsync2dbrowsing())
        {
            // Set last_source now so that we won't trigger reload of the page again when the source comes back from network
            last_source_ = url_str;
            setsource(url_str);
        }
    }
}

void EC_3DCanvasSource::WebViewLoadStarted()
{
    if (progress_bar_)
        progress_bar_->show();
    if (button_refreshstop_)
        button_refreshstop_->setStyleSheet("QPushButton#button_refreshstop { background-image: url('./data/ui/images/browser/stop.png'); }");
}

void EC_3DCanvasSource::WebViewLoadProgress(int progress)
{
    if (progress_bar_)
        progress_bar_->setValue(progress);
}

void EC_3DCanvasSource::WebViewLoadCompleted()
{
    // Setup ui
    if (progress_bar_)
        progress_bar_->hide();
    if (button_refreshstop_)
        button_refreshstop_->setStyleSheet("QPushButton#button_refreshstop { background-image: url('./data/ui/images/browser/refresh.png'); }");

    // Update the 2d ui line edit
    QWebView *webview = GetWebView();
    if (webview && source_edit_)
        source_edit_->setText(webview->url().toString());

    // Invoke a delayed repaint of the inworld texture
    QTimer::singleShot(50, this, SLOT(RepaintCanvas()));
}

void EC_3DCanvasSource::RepaintCanvas()
{
    EC_3DCanvas *canvas = Get3DCanvas();
    if (canvas)
        canvas->Update();
}

EC_3DCanvas *EC_3DCanvasSource::Get3DCanvas()
{
    Scene::Entity* entity = GetParentEntity();
    if (!entity)
        return 0;
    ComponentPtr comp = entity->GetComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
        return 0;
    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    return canvas;
}

QWebView *EC_3DCanvasSource::GetWebView()
{
    if (!content_widget_)
        return 0;
    return dynamic_cast<QWebView*>(content_widget_);
}

void EC_3DCanvasSource::UpdateWidget(QString url)
{
    // Don't load QWebViews into memory if headless
    if (GetFramework()->IsHeadless())
        return;

    // Prefer inparam over the attribute (if sync 2d browsing is disabled)
    QString source;
    if (url.isEmpty())
        source = getsource();
    else
        source = url;

    if (source.isEmpty())
    {
        QTimer::singleShot(1000, this, SLOT(FetchWebViewUrl()));
        return;
    }

    if (source != last_source_)
    {
        if (source_edit_)
            source_edit_->setText(source);
        last_source_ = source;

        if (!placeholder_widget_)
        {
            LogError("No placeholder widget, cannot create content widget");
            return;
        }

        // See if source looks like an url, and instantiate a QWebView then if it doesn't already exist
        if (source.indexOf("http://") != -1)
        {
            QWebView* webwidget = GetWebView();
            if (!webwidget)
            {
                // If widget exists, but is wrong type, delete and recreate
                if (content_widget_)
                {
                    content_widget_->deleteLater();
                    content_widget_ = 0;
                }

                webwidget = new QWebView(placeholder_widget_);
                QVBoxLayout *layout = placeholder_widget_->findChild<QVBoxLayout*>("widget_placeholder_layout");
                if (layout)
                    layout->addWidget(webwidget);

                // Load current source and resize to attribute set size
                webwidget->load(QUrl(source));
                webwidget->page()->setLinkDelegationPolicy(QWebPage::DelegateAllLinks);
                webwidget->resize(getpageWidth(), getpageHeight());

                // Connect webview signals
                connect(webwidget, SIGNAL(loadStarted()), this, SLOT(WebViewLoadStarted()), Qt::UniqueConnection);
                connect(webwidget, SIGNAL(loadProgress(int)), this, SLOT(WebViewLoadProgress(int)), Qt::UniqueConnection);
                connect(webwidget, SIGNAL(loadFinished(bool)), this, SLOT(WebViewLoadCompleted()), Qt::UniqueConnection);
                connect(webwidget, SIGNAL(linkClicked(const QUrl&)), this, SLOT(WebViewLinkClicked(const QUrl &)), Qt::UniqueConnection);
                connect(webwidget->page(), SIGNAL(scrollRequested(int, int, const QRect&)), this, SLOT(RepaintCanvas()), Qt::UniqueConnection);

                // This webview is our new content_widget_
                content_widget_ = webwidget;
            }
            else
            {
                // If source changed, update the webview URL
                webwidget->load(QUrl(source));
            }
        }
    }
}

void EC_3DCanvasSource::UpdateCanvas()
{
    if (!content_widget_)
        return;

    Scene::Entity* entity = GetParentEntity();
    if (!entity)
    {
        LogError("No parent entity, cannot create/update 3DCanvas");
        return;
    }

    ComponentPtr comp = entity->GetOrCreateComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
    {
        LogError("Could not create/get 3DCanvas component");
        return;
    }

    // If entity has no valid mesh or prim yet, start a retry timer and try to set the canvas later
    if ((!entity->GetComponent(EC_Mesh::TypeNameStatic())) &&
        (!entity->GetComponent(EC_OgreCustomObject::TypeNameStatic())))
    {
        //LogInfo("Mesh or prim did not exist yet, retrying");
        QTimer::singleShot(1000, this, SLOT(UpdateCanvas()));
        return;
    }

    // Set widget if different
    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    if (canvas->GetWidget() != content_widget_)
    {
        canvas->SetWidget(content_widget_);
    }

    // Set submesh if different
    int my_submesh = getsubmesh();
    if (my_submesh < 0)
        my_submesh = 0;
    if (!canvas->GetSubMeshes().contains(my_submesh))
        canvas->SetSubmesh(my_submesh);

    // Refresh rate
    int ref_rate_sec = getrefreshRate();
    if (ref_rate_sec > 0)
    {
        int ref_rate_msec = 1000 / ref_rate_sec;
        if (canvas->GetRefreshRate() != ref_rate_msec)
        {
            canvas->SetRefreshRate(ref_rate_sec);
            canvas_started_ = false;
        }
    }
    else
        canvas->SetRefreshRate(0);

    // Start if first run
    if (!canvas_started_)
    {
        canvas->Start();
        canvas_started_ = true;
    }
    // Update otherwise
    else
    {
        canvas->Update();
    }
}

void EC_3DCanvasSource::FetchWebViewUrl()
{
    // Workaround on the bug that ec_3canvas->webview()->url() is not valid when this component is created/updated.
    // Somehow its doesent have time to set it before we already come here. So this polls untill the url is valid.

    Scene::Entity* entity = GetParentEntity();
    if (!entity)
    {
        LogError("No parent entity, cannot create/update 3DCanvas");
        return;
    }

    ComponentPtr comp = entity->GetOrCreateComponent(EC_3DCanvas::TypeNameStatic());
    if (!comp)
    {
        LogError("Could not create/get 3DCanvas component");
        return;
    }

    EC_3DCanvas* canvas = checked_static_cast<EC_3DCanvas*>(comp.get());
    QWidget *canvas_widget = canvas->GetWidget();
    if (!canvas_widget)
        return;
    QWebView *canvas_webview = dynamic_cast<QWebView*>(canvas_widget);
    if (!canvas_webview)
        return;
    QString url = canvas_webview->url().toString();
    if (!url.isEmpty())
    {
        setsource(url);
        if (home_url_.isEmpty())
            home_url_ = url;
    }
    else
        QTimer::singleShot(1000, this, SLOT(FetchWebViewUrl()));
}

void EC_3DCanvasSource::ChangeLanguage()
{
    if (widget_)
    {
        QString title = tr("3DCanvas Controls");
        widget_->setWindowTitle(title);
    }
}

void EC_3DCanvasSource::CreateWidget()
{
    if (GetFramework()->IsHeadless())
        return;

    UiServiceInterface *ui = framework_->GetService<UiServiceInterface>();
    if (!ui)
    {
        LogError("Failed to acquire UI service");
        return;
    }

    QUiLoader loader;
    loader.setLanguageChangeEnabled(true);
    QFile file("./data/ui/3dcanvassource.ui");
    file.open(QFile::ReadOnly);
    widget_ = loader.load(&file);
    file.close();

    if (!widget_)
    {
        LogError("Failed to create 3D canvas controls widget");
        return;
    }

    widget_->setWindowTitle(tr("Naali Web Browser"));
    proxy_ = ui->AddWidgetToScene(widget_);
    connect(qApp, SIGNAL(LanguageChanged()), this, SLOT(ChangeLanguage()));

    source_edit_ = widget_->findChild<QLineEdit*>("line_source");
    if (source_edit_)
        connect(source_edit_, SIGNAL(returnPressed()), SLOT(SourceEdited()));

    placeholder_widget_ = widget_->findChild<QWidget*>("widget_placeholder");

    button_refreshstop_ = widget_->findChild<QPushButton*>("button_refreshstop");
    if (button_refreshstop_)
        connect(button_refreshstop_, SIGNAL(clicked()), SLOT(RefreshStopPressed()));

    QPushButton* button = widget_->findChild<QPushButton*>("button_back");
    if (button)
        connect(button, SIGNAL(clicked()), SLOT(BackPressed()));

    button = widget_->findChild<QPushButton*>("button_forward");
    if (button)
        connect(button, SIGNAL(clicked()), SLOT(ForwardPressed()));

    button = widget_->findChild<QPushButton*>("button_home");
    if (button)
        connect(button, SIGNAL(clicked()), SLOT(HomePressed()));

    progress_bar_ = widget_->findChild<QProgressBar*>("progress_bar");
    if (progress_bar_)
        progress_bar_->hide();
}

void EC_3DCanvasSource::RegisterActions()
{
    Scene::Entity *entity = GetParentEntity();
    assert(entity);
    if (entity)
        entity->ConnectAction("MousePress", this, SLOT(OnClick()));
}

<|endoftext|>


<commit_before>// CsScripts.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "CsScripts.h"
#include "SafeArray.h"
#include <iostream>
#include <sstream>
#include <vector>

// CLR headers
#include <metahost.h>
#include <CorError.h>

#pragma comment(lib, "mscoree.lib")

// Import mscorlib.tlb (Microsoft Common Language Runtime Class Library).
#import "mscorlib.tlb" raw_interfaces_only				\
    high_property_prefixes("_get","_put","_putref")		\
    rename("ReportEvent", "InteropServices_ReportEvent")

#import "CsScriptManaged.tlb" raw_interfaces_only

// Debugging engine headers
#define KDEXT_64BIT
#include <wdbgexts.h>
#include <Dbgeng.h>

using namespace std;
using namespace mscorlib;

// Checks HRESULT expression and throws ComException if fails.
//
#define CHECKCOM(expr) \
    { \
        HRESULT _temp_hr = (expr); \
        if (FAILED(_temp_hr)) \
        { \
            WriteComException(_temp_hr, #expr); \
            return _temp_hr; \
        } \
    }

void WriteComException(HRESULT hr, const char* expression)
{
    CAutoComPtr<IErrorInfo> errorInfo;

    cout << "COM Exception!!!" << endl;
    cout << "HRESULT: " << hex << showbase << hr << noshowbase << dec << endl;
    cout << "Expression: " << expression << endl;
    if (SUCCEEDED(GetErrorInfo(0, &errorInfo)) && errorInfo != nullptr)
    {
        BSTR description = nullptr;

        errorInfo->GetDescription(&description);
        if (description != nullptr)
        {
            wcout << "Description: " << description << endl;
        }

        CAutoComPtr<_Exception> exception;

        if (SUCCEEDED(errorInfo->QueryInterface(IID_PPV_ARGS(&exception))))
        {
        	BSTR toString = nullptr, stackTrace = nullptr;

        	exception->get_ToString(&toString);
        	if (toString != nullptr)
        	{
        		wcout << "Exception.ToString(): " << toString << endl;
        	}
        }
    }
}

class HostControl : public IHostControl
{
public:
	HostControl()
		: counter(1)
	{
	}

	virtual HRESULT STDMETHODCALLTYPE QueryInterface(
		REFIID riid,
		void ** ppvObject)
	{
		if (riid == __uuidof(IHostControl))
		{
			AddRef();
			*ppvObject = this;
			return S_OK;
		}

		return E_NOINTERFACE;
	}

	virtual ULONG STDMETHODCALLTYPE AddRef()
	{
		return ++counter;
	}

	virtual ULONG STDMETHODCALLTYPE Release()
	{
		ULONG result = --counter;

		if (result == 0)
			delete this;
		return result;
	}

	HRESULT STDMETHODCALLTYPE GetHostManager(
		_In_ REFIID riid,
		_Outptr_result_maybenull_ void **ppv)
	{
		return E_NOINTERFACE;
	}

	HRESULT STDMETHODCALLTYPE SetAppDomainManager(
		_In_ DWORD dwAppDomainID,
		_In_ IUnknown *pUnkAppDomainManager)
	{
		return pUnkAppDomainManager->QueryInterface(__uuidof(CsScriptManaged::IExecutor), (PVOID*)&m_appDomainManager);
	}

	CsScriptManaged::IExecutor* GetAppDomainManager() const
	{
		return m_appDomainManager;
	}

private:
	CAutoComPtr<CsScriptManaged::IExecutor> m_appDomainManager;
	ULONG counter;
};

wstring GetCurrentDllDirectory()
{
    wchar_t dllpath[8000];
    HMODULE hm = NULL;

    if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
        GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
        (LPCSTR)&GetCurrentDllDirectory,
        &hm))
    {
        int ret = GetLastError();
        fprintf(stderr, "GetModuleHandle returned %d\n", ret);
    }

    GetModuleFileNameW(hm, dllpath, ARRAYSIZE(dllpath));

    wstring path = dllpath;
    size_t pos = path.find_last_of('\\');

    if (pos != wstring::npos)
        path.resize(pos + 1);
    return path;
}

wstring GetWorkingDirectory()
{
	wchar_t dllpath[8000];

	GetCurrentDirectoryW(ARRAYSIZE(dllpath), dllpath);
	return dllpath;
}

class ClrInitializator
{
public:
	HRESULT Initialize(const wchar_t* csScriptsManaged, IDebugClient* client)
	{
		// We should figure out needed runtime version
		//
		CAutoComPtr<ICLRMetaHostPolicy> pClrHostPolicy;

		CHECKCOM(CLRCreateInstance(
			CLSID_CLRMetaHostPolicy,
			IID_ICLRMetaHostPolicy,
			(LPVOID*)&pClrHostPolicy));

		wstring runtimeVersion;
		wchar_t queriedRuntimeVersion[100] = { 0 };
		DWORD length = sizeof(queriedRuntimeVersion) / sizeof(wchar_t);

		CHECKCOM(pClrHostPolicy->GetRequestedRuntime(
			METAHOST_POLICY_HIGHCOMPAT,
			csScriptsManaged,
			nullptr,
			queriedRuntimeVersion,
			&length,
			nullptr,
			nullptr,
			nullptr,
			IID_PPV_ARGS(&runtimeInfo)));
		runtimeVersion = queriedRuntimeVersion;

		// Set custom memory manager and start CLR
		//
		hostControl = new HostControl();
		CHECKCOM(runtimeInfo->BindAsLegacyV2Runtime());
		//CHECKCOM(runtimeInfo->SetDefaultStartupFlags(clrStartupFlags, nullptr));
		CHECKCOM(runtimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&clrRuntimeHost)));
		CHECKCOM(clrRuntimeHost->GetCLRControl(&clrControl));
		//CHECKCOM(clrControl->SetAppDomainManagerType(L"CsScriptManaged", L"CsScriptManaged.CustomAppDomainManager"));
		CHECKCOM(clrRuntimeHost->SetHostControl(hostControl));
		CHECKCOM(clrRuntimeHost->Start());

		// Create a new AppDomain that will contain application configuration.
		//
		CAutoComPtr<IUnknown> appDomainSetupThunk;
		CAutoComPtr<IAppDomainSetup> appDomainSetup;
		CAutoComPtr<IUnknown> appDomainThunk;
		CAutoComPtr<_AppDomain> appDomain;

		CHECKCOM(runtimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(&corRuntimeHost)));
		CHECKCOM(corRuntimeHost->CreateDomainSetup(&appDomainSetupThunk));
		CHECKCOM(appDomainSetupThunk->QueryInterface(IID_PPV_ARGS(&appDomainSetup)));
		CHECKCOM(corRuntimeHost->CreateDomainEx(L"MyDomain", appDomainSetup, nullptr, &appDomainThunk));
		CHECKCOM(appDomainThunk->QueryInterface(IID_PPV_ARGS(&appDomain)));

		// Load our assembly
		//
		CAutoComPtr<_Assembly> mscorlibAssembly;
		CAutoComPtr<_Type> reflectionAssemblyType;
		SafeArray loadFromArguments;
		variant_t loadFromResult;
		variant_t arg1(csScriptsManaged);

		loadFromArguments.CreateVector(VT_VARIANT, 0, 1);
		loadFromArguments.PutElement(0, &arg1);

		CHECKCOM(GetAssemblyFromAppDomain(appDomain, L"mscorlib", &mscorlibAssembly));
		CHECKCOM(mscorlibAssembly->GetType_2(bstr_t(L"System.Reflection.Assembly"), &reflectionAssemblyType));
		CHECKCOM(reflectionAssemblyType->InvokeMember_3(bstr_t(L"LoadFrom"), (BindingFlags)(BindingFlags_InvokeMethod | BindingFlags_Public | BindingFlags_Static), nullptr, variant_t(), loadFromArguments, &loadFromResult));

		// Create our extension CLR instance
		//
		CAutoComPtr<_Assembly> assembly = (_Assembly*)(IDispatch*)loadFromResult;
		variant_t variant;

		CHECKCOM(assembly->CreateInstance_2(bstr_t(L"CsScriptManaged.Executor"), true, &variant));
		CHECKCOM(variant.punkVal->QueryInterface(&instance));

		CHECKCOM(InitializeContext(client));
		return S_OK;
	}

	HRESULT InitializeContext(IDebugClient* client)
	{
		CHECKCOM(instance->InitializeContext(client));
		return S_OK;
	}

	HRESULT ExecuteScript(const wchar_t* scriptPath, const vector<wstring>& arguments)
	{
		// Transfer all arguments to CLR
		//
		SafeArray safeArray;
		bstr_t bstrScriptPath = scriptPath;

		safeArray.CreateVector(VT_BSTR, 0, (ULONG)arguments.size());
		for (size_t i = 0; i < arguments.size(); i++)
		{
			// Intentionally allocating string because SafeArray will automatically dispose of it.
			//
			safeArray.PutElement((LONG)i, SysAllocString(arguments[i].c_str()));
		}

		// Execute script function
		//
		CHECKCOM(instance->ExecuteScript(bstrScriptPath, safeArray));
		return S_OK;
	}

	HRESULT ExecuteScript(const wchar_t* arguments)
	{
		// Execute script function
		//
		bstr_t bstrArguments = arguments;

		CHECKCOM(instance->ExecuteScript_2(bstrArguments));
		return S_OK;
	}

	void Uninitialize()
	{
		clrRuntimeHost->Stop();
		corRuntimeHost = nullptr;
		clrControl = nullptr;
		clrRuntimeHost = nullptr;
		runtimeInfo = nullptr;
		hostControl = nullptr;
		instance = nullptr;
	}

private:
	HRESULT GetAssemblyFromAppDomain(_AppDomain* appDomain, const wchar_t* assemblyName, _Assembly **assembly)
	{
		SAFEARRAY* safearray;
		CComSafeArray<IUnknown*> assemblies;

		CHECKCOM(appDomain->GetAssemblies(&safearray));
		assemblies.Attach(safearray);
		for (int i = 0, n = assemblies.GetCount(); i < n; i++)
		{
			CComPtr<_Assembly> a;

			a = assemblies[i];
			if (a == nullptr)
				continue;
			CComBSTR assemblyFullName;
			CHECKCOM(a->get_FullName(&assemblyFullName));
			if (assemblyFullName != nullptr && _wcsnicmp(assemblyFullName, assemblyName, wcslen(assemblyName)) == 0)
			{
				*assembly = a.Detach();
				return S_OK;
			}
		}

		return E_FAIL;
	}

	CAutoComPtr<ICLRRuntimeInfo> runtimeInfo;
	CAutoComPtr<ICLRRuntimeHost> clrRuntimeHost;
	CAutoComPtr<ICLRControl> clrControl;
	CAutoComPtr<HostControl> hostControl;
	CAutoComPtr<ICorRuntimeHost> corRuntimeHost;
	CAutoComPtr<CsScriptManaged::IExecutor> instance;
} clr;

CSSCRIPTS_API HRESULT DebugExtensionInitialize(
    _Out_ PULONG Version,
    _Out_ PULONG Flags)
{
    wstring currentDirectory = GetCurrentDllDirectory();
    wstring csScriptsManaged = currentDirectory + L"CsScriptManaged.dll";

    // Return parameters
    if (Version != nullptr)
        *Version = DEBUG_EXTENSION_VERSION(0, 1);
    if (Flags != nullptr)
        *Flags = 0;

	// Initialize CRL and CsScriptManaged library
	CAutoComPtr<IDebugClient> debugClient;

	CHECKCOM(DebugCreate(IID_PPV_ARGS(&debugClient)));

	HRESULT hr = clr.Initialize(csScriptsManaged.c_str(), debugClient);

	return hr;
}

CSSCRIPTS_API void CALLBACK DebugExtensionUninitialize()
{
	clr.Uninitialize();
}

HRESULT CALLBACK execute(
	_In_     IDebugClient* Client,
	_In_opt_ PCSTR         Args)
{
	wstringstream ss;

	ss << Args;
	clr.InitializeContext(Client);
	return clr.ExecuteScript(ss.str().c_str());
}
<commit_msg>Removing unused code from CsScripts native code...<commit_after>// CsScripts.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"
#include "CsScripts.h"
#include "SafeArray.h"
#include <iostream>
#include <sstream>
#include <vector>

// CLR headers
#include <metahost.h>
#include <CorError.h>

#pragma comment(lib, "mscoree.lib")

// Import mscorlib.tlb (Microsoft Common Language Runtime Class Library).
#import "mscorlib.tlb" raw_interfaces_only				\
    high_property_prefixes("_get","_put","_putref")		\
    rename("ReportEvent", "InteropServices_ReportEvent")

#import "CsScriptManaged.tlb" raw_interfaces_only

// Debugging engine headers
#define KDEXT_64BIT
#include <wdbgexts.h>
#include <Dbgeng.h>

using namespace std;
using namespace mscorlib;

// Checks HRESULT expression and throws ComException if fails.
//
#define CHECKCOM(expr) \
    { \
        HRESULT _temp_hr = (expr); \
        if (FAILED(_temp_hr)) \
        { \
            WriteComException(_temp_hr, #expr); \
            return _temp_hr; \
        } \
    }

void WriteComException(HRESULT hr, const char* expression)
{
    CAutoComPtr<IErrorInfo> errorInfo;

    cout << "COM Exception!!!" << endl;
    cout << "HRESULT: " << hex << showbase << hr << noshowbase << dec << endl;
    cout << "Expression: " << expression << endl;
    if (SUCCEEDED(GetErrorInfo(0, &errorInfo)) && errorInfo != nullptr)
    {
        BSTR description = nullptr;

        errorInfo->GetDescription(&description);
        if (description != nullptr)
        {
            wcout << "Description: " << description << endl;
        }

        CAutoComPtr<_Exception> exception;

        if (SUCCEEDED(errorInfo->QueryInterface(IID_PPV_ARGS(&exception))))
        {
        	BSTR toString = nullptr, stackTrace = nullptr;

        	exception->get_ToString(&toString);
        	if (toString != nullptr)
        	{
        		wcout << "Exception.ToString(): " << toString << endl;
        	}
        }
    }
}

wstring GetCurrentDllDirectory()
{
    wchar_t dllpath[8000];
    HMODULE hm = NULL;

    if (!GetModuleHandleExA(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
        GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
        (LPCSTR)&GetCurrentDllDirectory,
        &hm))
    {
        int ret = GetLastError();
        fprintf(stderr, "GetModuleHandle returned %d\n", ret);
    }

    GetModuleFileNameW(hm, dllpath, ARRAYSIZE(dllpath));

    wstring path = dllpath;
    size_t pos = path.find_last_of('\\');

    if (pos != wstring::npos)
        path.resize(pos + 1);
    return path;
}

wstring GetWorkingDirectory()
{
	wchar_t dllpath[8000];

	GetCurrentDirectoryW(ARRAYSIZE(dllpath), dllpath);
	return dllpath;
}

class ClrInitializator
{
public:
	HRESULT Initialize(const wchar_t* csScriptsManaged, IDebugClient* client)
	{
		// We should figure out needed runtime version
		//
		CAutoComPtr<ICLRMetaHostPolicy> pClrHostPolicy;

		CHECKCOM(CLRCreateInstance(
			CLSID_CLRMetaHostPolicy,
			IID_ICLRMetaHostPolicy,
			(LPVOID*)&pClrHostPolicy));

		wstring runtimeVersion;
		wchar_t queriedRuntimeVersion[100] = { 0 };
		DWORD length = sizeof(queriedRuntimeVersion) / sizeof(wchar_t);

		CHECKCOM(pClrHostPolicy->GetRequestedRuntime(
			METAHOST_POLICY_HIGHCOMPAT,
			csScriptsManaged,
			nullptr,
			queriedRuntimeVersion,
			&length,
			nullptr,
			nullptr,
			nullptr,
			IID_PPV_ARGS(&runtimeInfo)));
		runtimeVersion = queriedRuntimeVersion;

		// Set custom memory manager and start CLR
		//
		CHECKCOM(runtimeInfo->BindAsLegacyV2Runtime());
		//CHECKCOM(runtimeInfo->SetDefaultStartupFlags(clrStartupFlags, nullptr));
		CHECKCOM(runtimeInfo->GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS(&clrRuntimeHost)));
		CHECKCOM(clrRuntimeHost->GetCLRControl(&clrControl));
		CHECKCOM(clrRuntimeHost->Start());

		// Create a new AppDomain that will contain application configuration.
		//
		CAutoComPtr<IUnknown> appDomainSetupThunk;
		CAutoComPtr<IAppDomainSetup> appDomainSetup;
		CAutoComPtr<IUnknown> appDomainThunk;
		CAutoComPtr<_AppDomain> appDomain;

		CHECKCOM(runtimeInfo->GetInterface(CLSID_CorRuntimeHost, IID_PPV_ARGS(&corRuntimeHost)));
		CHECKCOM(corRuntimeHost->CreateDomainSetup(&appDomainSetupThunk));
		CHECKCOM(appDomainSetupThunk->QueryInterface(IID_PPV_ARGS(&appDomainSetup)));
		CHECKCOM(corRuntimeHost->CreateDomainEx(L"MyDomain", appDomainSetup, nullptr, &appDomainThunk));
		CHECKCOM(appDomainThunk->QueryInterface(IID_PPV_ARGS(&appDomain)));

		// Load our assembly
		//
		CAutoComPtr<_Assembly> mscorlibAssembly;
		CAutoComPtr<_Type> reflectionAssemblyType;
		SafeArray loadFromArguments;
		variant_t loadFromResult;
		variant_t arg1(csScriptsManaged);

		loadFromArguments.CreateVector(VT_VARIANT, 0, 1);
		loadFromArguments.PutElement(0, &arg1);

		CHECKCOM(GetAssemblyFromAppDomain(appDomain, L"mscorlib", &mscorlibAssembly));
		CHECKCOM(mscorlibAssembly->GetType_2(bstr_t(L"System.Reflection.Assembly"), &reflectionAssemblyType));
		CHECKCOM(reflectionAssemblyType->InvokeMember_3(bstr_t(L"LoadFrom"), (BindingFlags)(BindingFlags_InvokeMethod | BindingFlags_Public | BindingFlags_Static), nullptr, variant_t(), loadFromArguments, &loadFromResult));

		// Create our extension CLR instance
		//
		CAutoComPtr<_Assembly> assembly = (_Assembly*)(IDispatch*)loadFromResult;
		variant_t variant;

		CHECKCOM(assembly->CreateInstance_2(bstr_t(L"CsScriptManaged.Executor"), true, &variant));
		CHECKCOM(variant.punkVal->QueryInterface(&instance));

		CHECKCOM(InitializeContext(client));
		return S_OK;
	}

	HRESULT InitializeContext(IDebugClient* client)
	{
		CHECKCOM(instance->InitializeContext(client));
		return S_OK;
	}

	HRESULT ExecuteScript(const wchar_t* scriptPath, const vector<wstring>& arguments)
	{
		// Transfer all arguments to CLR
		//
		SafeArray safeArray;
		bstr_t bstrScriptPath = scriptPath;

		safeArray.CreateVector(VT_BSTR, 0, (ULONG)arguments.size());
		for (size_t i = 0; i < arguments.size(); i++)
		{
			// Intentionally allocating string because SafeArray will automatically dispose of it.
			//
			safeArray.PutElement((LONG)i, SysAllocString(arguments[i].c_str()));
		}

		// Execute script function
		//
		CHECKCOM(instance->ExecuteScript(bstrScriptPath, safeArray));
		return S_OK;
	}

	HRESULT ExecuteScript(const wchar_t* arguments)
	{
		// Execute script function
		//
		bstr_t bstrArguments = arguments;

		CHECKCOM(instance->ExecuteScript_2(bstrArguments));
		return S_OK;
	}

	void Uninitialize()
	{
		clrRuntimeHost->Stop();
		corRuntimeHost = nullptr;
		clrControl = nullptr;
		clrRuntimeHost = nullptr;
		runtimeInfo = nullptr;
		instance = nullptr;
	}

private:
	HRESULT GetAssemblyFromAppDomain(_AppDomain* appDomain, const wchar_t* assemblyName, _Assembly **assembly)
	{
		SAFEARRAY* safearray;
		CComSafeArray<IUnknown*> assemblies;

		CHECKCOM(appDomain->GetAssemblies(&safearray));
		assemblies.Attach(safearray);
		for (int i = 0, n = assemblies.GetCount(); i < n; i++)
		{
			CComPtr<_Assembly> a;

			a = assemblies[i];
			if (a == nullptr)
				continue;
			CComBSTR assemblyFullName;
			CHECKCOM(a->get_FullName(&assemblyFullName));
			if (assemblyFullName != nullptr && _wcsnicmp(assemblyFullName, assemblyName, wcslen(assemblyName)) == 0)
			{
				*assembly = a.Detach();
				return S_OK;
			}
		}

		return E_FAIL;
	}

	CAutoComPtr<ICLRRuntimeInfo> runtimeInfo;
	CAutoComPtr<ICLRRuntimeHost> clrRuntimeHost;
	CAutoComPtr<ICLRControl> clrControl;
	CAutoComPtr<ICorRuntimeHost> corRuntimeHost;
	CAutoComPtr<CsScriptManaged::IExecutor> instance;
} clr;

CSSCRIPTS_API HRESULT DebugExtensionInitialize(
    _Out_ PULONG Version,
    _Out_ PULONG Flags)
{
    wstring currentDirectory = GetCurrentDllDirectory();
    wstring csScriptsManaged = currentDirectory + L"CsScriptManaged.dll";

    // Return parameters
    if (Version != nullptr)
        *Version = DEBUG_EXTENSION_VERSION(0, 1);
    if (Flags != nullptr)
        *Flags = 0;

	// Initialize CRL and CsScriptManaged library
	CAutoComPtr<IDebugClient> debugClient;

	CHECKCOM(DebugCreate(IID_PPV_ARGS(&debugClient)));

	HRESULT hr = clr.Initialize(csScriptsManaged.c_str(), debugClient);

	return hr;
}

CSSCRIPTS_API void CALLBACK DebugExtensionUninitialize()
{
	clr.Uninitialize();
}

HRESULT CALLBACK execute(
	_In_     IDebugClient* Client,
	_In_opt_ PCSTR         Args)
{
	wstringstream ss;

	ss << Args;
	clr.InitializeContext(Client);
	return clr.ExecuteScript(ss.str().c_str());
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkHyperTreeGridToUnstructuredGrid.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkHyperTreeGridToUnstructuredGrid.h"

#include "vtkBitArray.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkHyperTreeGrid.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkUnstructuredGrid.h"

vtkStandardNewMacro(vtkHyperTreeGridToUnstructuredGrid);

//-----------------------------------------------------------------------------
vtkHyperTreeGridToUnstructuredGrid::vtkHyperTreeGridToUnstructuredGrid()
{
  this->Points = 0;
  this->Cells = 0;
  this->Input = 0;
  this->Output = 0;

  this->Dimension = 0;
  this->CellSize = 0;
  this->Coefficients = 0;
}

//-----------------------------------------------------------------------------
vtkHyperTreeGridToUnstructuredGrid::~vtkHyperTreeGridToUnstructuredGrid()
{
  if ( this->Points )
    {
    this->Points->Delete();
    this->Points = 0;
    }
  if ( this->Cells )
    {
    this->Cells->Delete();
    this->Cells = 0;
    }
  if ( this->Coefficients )
    {
    delete [] this->Coefficients;
    this->Coefficients = 0;
    }
}

//----------------------------------------------------------------------------
void vtkHyperTreeGridToUnstructuredGrid::PrintSelf( ostream& os, vtkIndent indent )
{
  this->Superclass::PrintSelf( os, indent );

  if( this->Input )
    {
    os << indent << "Input:\n";
    this->Input->PrintSelf( os, indent.GetNextIndent() );
    }
  else
    {
    os << indent << "Input: ( none )\n";
    }
  if( this->Output )
    {
    os << indent << "Output:\n";
    this->Output->PrintSelf( os, indent.GetNextIndent() );
    }
  else
    {
    os << indent << "Output: ( none )\n";
    }
  if( this->Points )
    {
    os << indent << "Points:\n";
    this->Points->PrintSelf( os, indent.GetNextIndent() );
    }
  else
    {
    os << indent << "Points: ( none )\n";
    }
  if( this->Cells )
    {
    os << indent << "Cells:\n";
    this->Cells->PrintSelf( os, indent.GetNextIndent() );
    }
  else
    {
    os << indent << "Cells: ( none )\n";
    }

  os << indent << "Dimension : " << this->Dimension << endl;
  os << indent << "CellSize : " << this->CellSize << endl;
  os << indent << "Coefficients : " << endl;
  for ( unsigned int i = 0; i < this->CellSize; ++ i )
    {
    os << indent;
    for ( unsigned int j = 0; j < this->Dimension; ++ j )
      {
      os << " " << this->Coefficients[i * this->Dimension + j];
      }
    os << endl;
    }
}

//-----------------------------------------------------------------------------
int vtkHyperTreeGridToUnstructuredGrid::FillInputPortInformation( int, vtkInformation *info )
{
  info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkHyperTreeGrid" );
  return 1;
}

//----------------------------------------------------------------------------
int vtkHyperTreeGridToUnstructuredGrid::RequestData( vtkInformation*,
                                          vtkInformationVector** inputVector,
                                          vtkInformationVector* outputVector )
{
  // Get the info objects
  vtkInformation *inInfo = inputVector[0]->GetInformationObject( 0 );
  vtkInformation *outInfo = outputVector->GetInformationObject( 0 );

  // Retrieve input and output
  this->Input = vtkHyperTreeGrid::SafeDownCast( inInfo->Get( vtkDataObject::DATA_OBJECT() ) );
  this->Output= vtkUnstructuredGrid::SafeDownCast( outInfo->Get( vtkDataObject::DATA_OBJECT() ) );

  // Set instance variables needed for this conversion
  this->Dimension = this->Input->GetDimension();
  switch ( this->Dimension )
    {
    case 1:
      this->CellSize = 2;
      this->Coefficients = new unsigned int[2];
      for ( unsigned int i = 0; i < 2; ++ i )
        {
        this->Coefficients[i] = i;
        }
      break;
    case 2 :
      this->CellSize = 4;
      this->Coefficients = new unsigned int[8];
      for ( unsigned int i = 0; i < 4; ++ i )
        {
        div_t r = div( i, 2 );
        this->Coefficients[2 * i] = r.rem;
        this->Coefficients[2 * i + 1] = r.quot;
        }
      break;
    case 3 :
      this->CellSize = 8;
      this->Coefficients = new unsigned int[24];
      for ( unsigned int i = 0; i < 8; ++ i )
        {
        div_t r1 = div( i, 2 );
        div_t r2 = div( r1.quot, 2 );
        this->Coefficients[3 * i] = r1.rem;
        this->Coefficients[3 * i + 1] = r2.quot;
        this->Coefficients[3 * i + 2] = r2.rem;
        }
      break;
    default:
      vtkErrorMacro( "Incorrect tree dimension: "
                     << this->Dimension
                     << "." );
      return 0;
    }

  // Ensure that primal grid API is used for hyper trees
  int inputDualFlagIsOn = this->Input->GetUseDualGrid();
  if ( inputDualFlagIsOn )
    {
    this->Input->SetUseDualGrid( 0 );
    }

  // Initialize output cell data
  vtkCellData *outCD = this->Output->GetCellData();
  vtkCellData *inCD = this->Input->GetCellData();
  outCD->CopyAllocate( inCD );

  // Cut through hyper tree grid
  this->ProcessTrees();

  // Return duality flag of input to its original state
  if ( inputDualFlagIsOn )
    {
    this->Input->SetUseDualGrid( 1 );
    }

  // Clean up
  this->Input = 0;
  this->Output = 0;

  this->UpdateProgress ( 1. );

  return 1;
}

//-----------------------------------------------------------------------------
void vtkHyperTreeGridToUnstructuredGrid::ProcessTrees()
{
  // TODO: MTime on generation of this table.
  this->Input->GenerateSuperCursorTraversalTable();

  // Primal corner points
  this->Points = vtkPoints::New();
  this->Cells = vtkCellArray::New();

  // Iterate over all hyper trees
  unsigned int* gridSize = this->Input->GetGridSize();
  for ( unsigned int k = 0; k < gridSize[2]; ++ k )
    {
    for ( unsigned int j = 0; j < gridSize[1]; ++ j )
      {
        for ( unsigned int i = 0; i < gridSize[0]; ++ i )
        {
        // Storage for super cursors
        vtkHyperTreeGridSuperCursor superCursor;

        // Initialize center cursor
        this->Input->InitializeSuperCursor(&superCursor, i, j, k );

        // Traverse and populate dual recursively
        this->RecursiveProcessTree( &superCursor );
        } // i
      } // j
    } // k

  // Set output geometry and topology
  this->Output->SetPoints( this->Points );
  switch ( this->Dimension )
    {
    case 1:
      this->Output->SetCells( VTK_LINE, this->Cells );
      break;
    case 2:
      this->Output->SetCells( VTK_QUAD, this->Cells );
      break;
    case 3:
      this->Output->SetCells( VTK_VOXEL, this->Cells );
      break;
    }
}

//----------------------------------------------------------------------------
void vtkHyperTreeGridToUnstructuredGrid::AddCell( vtkIdType inId,
                                                  double* origin,
                                                  double* size )
{
  // Storage for cell IDs
  vtkIdType ids[8];

  // Generate 2^d points
  double pt[3];
  pt[0] = origin[0];
  pt[1] = origin[1];
  pt[2] = origin[2];
  ids[0] = this->Points->InsertNextPoint( pt );
  for ( unsigned int i = 1; i < this->CellSize; ++ i )
    {
    for ( unsigned int j = 0; j < this->Dimension; ++ j )
      {
      pt[j] = origin[j] + this->Coefficients[i * this->Dimension + j] * size[j];
      }
    ids[i] = this->Points->InsertNextPoint( pt );
    }

  vtkIdType outId = this->Cells->InsertNextCell( this->CellSize, ids );
  this->Output->GetCellData()->CopyData( this->Input->GetCellData(), inId, outId );
}

//----------------------------------------------------------------------------
void vtkHyperTreeGridToUnstructuredGrid::RecursiveProcessTree( vtkHyperTreeGridSuperCursor* superCursor )
{
  // Get cursor at super cursor center
  vtkHyperTreeGridCursor* cursor = superCursor->GetCursor( 0 );

  // If cursor is not at leaf, recurse to all children
  if ( ! cursor->IsLeaf() )
    {
    int numChildren = this->Input->GetNumberOfChildren();
    for ( int child = 0; child < numChildren; ++ child )
      {
      vtkHyperTreeGridSuperCursor newSuperCursor;
      this->Input->InitializeSuperCursorChild( superCursor,&newSuperCursor, child );
      this->RecursiveProcessTree( &newSuperCursor );
      }
    return;
    }

  // Cursor is a leaf, retrieve its global index
  vtkIdType inId = cursor->GetGlobalLeafIndex();

  // If leaf is masked, skip it
  if ( ! this->Input->GetMaskedLeafIds()->GetTuple1( inId ) )
    {
    return;
    }

  // Create cell
  this->AddCell( inId, superCursor->Origin, superCursor->Size );
}
<commit_msg>whitespace cleanup<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkHyperTreeGridToUnstructuredGrid.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkHyperTreeGridToUnstructuredGrid.h"

#include "vtkBitArray.h"
#include "vtkCellArray.h"
#include "vtkCellData.h"
#include "vtkHyperTreeGrid.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkUnstructuredGrid.h"

vtkStandardNewMacro(vtkHyperTreeGridToUnstructuredGrid);

//-----------------------------------------------------------------------------
vtkHyperTreeGridToUnstructuredGrid::vtkHyperTreeGridToUnstructuredGrid()
{
  this->Points = 0;
  this->Cells = 0;
  this->Input = 0;
  this->Output = 0;

  this->Dimension = 0;
  this->CellSize = 0;
  this->Coefficients = 0;
}

//-----------------------------------------------------------------------------
vtkHyperTreeGridToUnstructuredGrid::~vtkHyperTreeGridToUnstructuredGrid()
{
  if ( this->Points )
    {
    this->Points->Delete();
    this->Points = 0;
    }
  if ( this->Cells )
    {
    this->Cells->Delete();
    this->Cells = 0;
    }
  if ( this->Coefficients )
    {
    delete [] this->Coefficients;
    this->Coefficients = 0;
    }
}

//----------------------------------------------------------------------------
void vtkHyperTreeGridToUnstructuredGrid::PrintSelf( ostream& os, vtkIndent indent )
{
  this->Superclass::PrintSelf( os, indent );

  if( this->Input )
    {
    os << indent << "Input:\n";
    this->Input->PrintSelf( os, indent.GetNextIndent() );
    }
  else
    {
    os << indent << "Input: ( none )\n";
    }
  if( this->Output )
    {
    os << indent << "Output:\n";
    this->Output->PrintSelf( os, indent.GetNextIndent() );
    }
  else
    {
    os << indent << "Output: ( none )\n";
    }
  if( this->Points )
    {
    os << indent << "Points:\n";
    this->Points->PrintSelf( os, indent.GetNextIndent() );
    }
  else
    {
    os << indent << "Points: ( none )\n";
    }
  if( this->Cells )
    {
    os << indent << "Cells:\n";
    this->Cells->PrintSelf( os, indent.GetNextIndent() );
    }
  else
    {
    os << indent << "Cells: ( none )\n";
    }

  os << indent << "Dimension : " << this->Dimension << endl;
  os << indent << "CellSize : " << this->CellSize << endl;
  os << indent << "Coefficients : " << endl;
  for ( unsigned int i = 0; i < this->CellSize; ++ i )
    {
    os << indent;
    for ( unsigned int j = 0; j < this->Dimension; ++ j )
      {
      os << " " << this->Coefficients[i * this->Dimension + j];
      }
    os << endl;
    }
}

//-----------------------------------------------------------------------------
int vtkHyperTreeGridToUnstructuredGrid::FillInputPortInformation( int, vtkInformation *info )
{
  info->Set( vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkHyperTreeGrid" );
  return 1;
}

//----------------------------------------------------------------------------
int vtkHyperTreeGridToUnstructuredGrid::RequestData( vtkInformation*,
                                          vtkInformationVector** inputVector,
                                          vtkInformationVector* outputVector )
{
  // Get the info objects
  vtkInformation *inInfo = inputVector[0]->GetInformationObject( 0 );
  vtkInformation *outInfo = outputVector->GetInformationObject( 0 );

  // Retrieve input and output
  this->Input = vtkHyperTreeGrid::SafeDownCast( inInfo->Get( vtkDataObject::DATA_OBJECT() ) );
  this->Output= vtkUnstructuredGrid::SafeDownCast( outInfo->Get( vtkDataObject::DATA_OBJECT() ) );

  // Set instance variables needed for this conversion
  this->Dimension = this->Input->GetDimension();
  switch ( this->Dimension )
    {
    case 1:
      this->CellSize = 2;
      this->Coefficients = new unsigned int[2];
      for ( unsigned int i = 0; i < 2; ++ i )
        {
        this->Coefficients[i] = i;
        }
      break;
    case 2 :
      this->CellSize = 4;
      this->Coefficients = new unsigned int[8];
      for ( unsigned int i = 0; i < 4; ++ i )
        {
        div_t r = div( i, 2 );
        this->Coefficients[2 * i] = r.rem;
        this->Coefficients[2 * i + 1] = r.quot;
        }
      break;
    case 3 :
      this->CellSize = 8;
      this->Coefficients = new unsigned int[24];
      for ( unsigned int i = 0; i < 8; ++ i )
        {
        div_t r1 = div( i, 2 );
        div_t r2 = div( r1.quot, 2 );
        this->Coefficients[3 * i] = r1.rem;
        this->Coefficients[3 * i + 1] = r2.quot;
        this->Coefficients[3 * i + 2] = r2.rem;
        }
      break;
    default:
      vtkErrorMacro( "Incorrect tree dimension: "
                     << this->Dimension
                     << "." );
      return 0;
    }

  // Ensure that primal grid API is used for hyper trees
  int inputDualFlagIsOn = this->Input->GetUseDualGrid();
  if ( inputDualFlagIsOn )
    {
    this->Input->SetUseDualGrid( 0 );
    }

  // Initialize output cell data
  vtkCellData *outCD = this->Output->GetCellData();
  vtkCellData *inCD = this->Input->GetCellData();
  outCD->CopyAllocate( inCD );

  // Cut through hyper tree grid
  this->ProcessTrees();

  // Return duality flag of input to its original state
  if ( inputDualFlagIsOn )
    {
    this->Input->SetUseDualGrid( 1 );
    }

  // Clean up
  this->Input = 0;
  this->Output = 0;

  this->UpdateProgress ( 1. );

  return 1;
}

//-----------------------------------------------------------------------------
void vtkHyperTreeGridToUnstructuredGrid::ProcessTrees()
{
  // TODO: MTime on generation of this table.
  this->Input->GenerateSuperCursorTraversalTable();

  // Primal corner points
  this->Points = vtkPoints::New();
  this->Cells = vtkCellArray::New();

  // Iterate over all hyper trees
  unsigned int* gridSize = this->Input->GetGridSize();
  for ( unsigned int k = 0; k < gridSize[2]; ++ k )
    {
    for ( unsigned int j = 0; j < gridSize[1]; ++ j )
      {
        for ( unsigned int i = 0; i < gridSize[0]; ++ i )
        {
        // Storage for super cursors
        vtkHyperTreeGridSuperCursor superCursor;

        // Initialize center cursor
        this->Input->InitializeSuperCursor(&superCursor, i, j, k );

        // Traverse and populate dual recursively
        this->RecursiveProcessTree( &superCursor );
        } // i
      } // j
    } // k

  // Set output geometry and topology
  this->Output->SetPoints( this->Points );
  switch ( this->Dimension )
    {
    case 1:
      this->Output->SetCells( VTK_LINE, this->Cells );
      break;
    case 2:
      this->Output->SetCells( VTK_QUAD, this->Cells );
      break;
    case 3:
      this->Output->SetCells( VTK_VOXEL, this->Cells );
      break;
    }
}

//----------------------------------------------------------------------------
void vtkHyperTreeGridToUnstructuredGrid::AddCell( vtkIdType inId,
                                                  double* origin,
                                                  double* size )
{
  // Storage for cell IDs
  vtkIdType ids[8];

  // Generate 2^d points
  double pt[3];
  pt[0] = origin[0];
  pt[1] = origin[1];
  pt[2] = origin[2];
  ids[0] = this->Points->InsertNextPoint( pt );
  for ( unsigned int i = 1; i < this->CellSize; ++ i )
    {
    for ( unsigned int j = 0; j < this->Dimension; ++ j )
      {
      pt[j] = origin[j] + this->Coefficients[i * this->Dimension + j] * size[j];
      }
    ids[i] = this->Points->InsertNextPoint( pt );
    }

  vtkIdType outId = this->Cells->InsertNextCell( this->CellSize, ids );
  this->Output->GetCellData()->CopyData( this->Input->GetCellData(), inId, outId );
}

//----------------------------------------------------------------------------
void vtkHyperTreeGridToUnstructuredGrid::RecursiveProcessTree( vtkHyperTreeGridSuperCursor* superCursor )
{
  // Get cursor at super cursor center
  vtkHyperTreeGridCursor* cursor = superCursor->GetCursor( 0 );

  // If cursor is not at leaf, recurse to all children
  if ( ! cursor->IsLeaf() )
    {
    int numChildren = this->Input->GetNumberOfChildren();
    for ( int child = 0; child < numChildren; ++ child )
      {
      vtkHyperTreeGridSuperCursor newSuperCursor;
      this->Input->InitializeSuperCursorChild( superCursor,&newSuperCursor, child );
      this->RecursiveProcessTree( &newSuperCursor );
      }
    return;
    }

  // Cursor is a leaf, retrieve its global index
  vtkIdType inId = cursor->GetGlobalLeafIndex();

  // If leaf is masked, skip it
  if ( ! this->Input->GetMaskedLeafIds()->GetTuple1( inId ) )
    {
    return;
    }

  // Create cell
  this->AddCell( inId, superCursor->Origin, superCursor->Size );
}
<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  START raw data conversion class                                            //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <Riostream.h>
#include <TTree.h>

#include "AliSTART.h"
#include "AliSTARTRawData.h"
#include "AliSTARTdigit.h"
#include "AliBitPacking.h"
#include "AliRawDataHeader.h"
#include "AliBitPacking.h"

ClassImp(AliSTARTRawData)

//_____________________________________________________________________________
AliSTARTRawData::AliSTARTRawData():TObject()
{
  /*
-  48 channels (2 words each as in TOF DDL) for :
word 1 :0-5bit number of PMT; word 2: 0-7 error sign, 8-31 TDC
and the same but for amplified signal. Now I wrote the same time because
CDF are not ready and differences didn't measured yet.

-  48 channel for amplitude: very preliminary, QTC features are not
known now, preliminary i put as T1 time signal for this PMT in first
channel and T1+A in second, where A=Log(Amplitude);
and the same for amplified but A=Log(10*Amplitude).

- T0-A and T0-C 2 channels
- T0A-T0C vertex information
- Time Meaner where T0C TOF increase to the T0A TOF distance
- 6 multiplicity signals the same way as amplitude and with the same
uncertances
  */

  fIndex=-1;
  fDigits = NULL;

  fTimeCFD = new TArrayI(24);
  fADC = new TArrayI(24);
  fTimeLED = new TArrayI(24);
  fADC0 = new TArrayI(24);
   //   this->Dump();

}

//_____________________________________________________________________________
AliSTARTRawData::AliSTARTRawData(const AliSTARTRawData &r):TObject()
{
  //
  // AliSTARTrawData copy constructor
  //

  ((AliSTARTRawData &) r).Copy(*this);

}

//_____________________________________________________________________________
AliSTARTRawData::~AliSTARTRawData()
{
  //
  // Destructor
  //
  if (fDigits) {
    delete fDigits;
    fDigits = NULL;
  }
  delete fTimeCFD;
  delete fADC;
  delete fTimeLED;
  delete fADC0;
}

//_____________________________________________________________________________
AliSTARTRawData &AliSTARTRawData::operator=(const AliSTARTRawData &r)
{
  //
  // Assignment operator
  //

  if (this != &r) ((AliSTARTRawData &) r).Copy(*this);
  return *this;

}

//_____________________________________________________________________________
void AliSTARTRawData::GetDigits(AliSTARTdigit *fDigits, UInt_t *buf)
{

  //This method packs the START digits in a proper 32 bits structure

  //read START digits and fill TDC and ADC arrays

  UInt_t word;
  UInt_t baseWord=0;
  Int_t error=0;

    // Get the digits array

  fDigits->GetTime(*fTimeCFD);
  fDigits->GetADC(*fADC);
  fDigits->GetTimeAmp(*fTimeLED);
  fDigits->GetADCAmp(*fADC0);

  // Loop through all PMT

  for (Int_t det = 0; det < 24; det++) {
    Int_t timeLED=fTimeLED->At(det);
    //   if( timeLED > 0){
      // DDL 1 0-5 -#PMT, 6-31 - empty
      //LED
      word=det;;
      PackWord(baseWord,word, 0, 8);
      fIndex++;
      buf[fIndex]=baseWord;

      word=0;
      baseWord=0;
      word=error;
      PackWord(baseWord,word,0, 7); // Error flag
      word=timeLED;
      PackWord(baseWord,word,8,31); // time-of-flight
      fIndex++;
      buf[fIndex]=baseWord;
      word=0;
      baseWord=0;
      //  }
  }
   for (Int_t det = 0; det < 24; det++) {
    //CDF
     Int_t timeCFD=fTimeCFD->At(det);
     //   if ( timeCFD >0 ) {
       // DDL2 2 0-5 -#PMT, 6-31 - empty
       word=0;
       baseWord=0;
       word=det+24;
       PackWord(baseWord,word, 0, 8); // number of PMT on the right side
       fIndex++;
       buf[fIndex]=baseWord;
       word=0;
       baseWord=0;
       word=error;
       PackWord(baseWord,word,0, 7); // Error flag
       word=timeCFD;
       PackWord(baseWord,word,8,31); // time-of-flight
       fIndex++;
       buf[fIndex]=baseWord;
        word=0;
       baseWord=0;
       //  }
   }
  for (Int_t det = 0; det < 24; det++) {
    //conver ADC to time (preliminary algorithm)
    Int_t qtc=fADC->At(det);
    //    if ( qtc > 0 )
    //  {
	word=det+48;
	PackWord(baseWord,word, 0, 8); // number of PMT on the right side
	fIndex++;
	buf[fIndex]=baseWord;
	baseWord=0;
	word=error;
	PackWord(baseWord,word,0, 7); // Error flag
	word=qtc;
	PackWord(baseWord,word,8,31); // Q->Time
	fIndex++;
	buf[fIndex]=baseWord;
 	word=0;
	baseWord=0;
	//     }
  }

  for (Int_t det = 0; det < 24; det++) {
    Int_t qtcAmp=fADC0->At(det);

    // DDL 4 amplified QTC charge * 10

     //Amplified  ADC -> TDC

    word=det+72;
    PackWord(baseWord,word, 0, 8); // number of PMT on the right side
    fIndex++;
    buf[fIndex]=baseWord;
    baseWord=0;
    word=error;
    PackWord(baseWord,word,0, 7); // Error flag
    word=qtcAmp;
    PackWord(baseWord,word,8,31); // Q->T amplified
    fIndex++;
    buf[fIndex]=baseWord;

    word=0;
    baseWord=0;
  }

  word=0;
  baseWord=0;
  fIndex++;
  word=97;
  PackWord(baseWord,word, 0, 8); // ?????????????????
  buf[fIndex]=baseWord;
  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->MeanTime();
  PackWord(baseWord,word,8,31); // MEANER

  fIndex++;
  buf[fIndex]=baseWord;

  // besttime right & left
  word=98;
  PackWord(baseWord,word, 0, 8); // T0-A sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->BestTimeRight();
  PackWord(baseWord,word,8,31); // time-of-flight T0-A
  fIndex++;
  buf[fIndex]=baseWord;

  word=99;
  PackWord(baseWord,word, 0, 8); // T0-C sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->BestTimeLeft();
  PackWord(baseWord,word,8,31); // time-of-flight T0-C
  fIndex++;
  buf[fIndex]=baseWord;

  // time difference
  word=100;
  PackWord(baseWord,word, 0, 8); // TVDS sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;

  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->TimeDiff();
  PackWord(baseWord,word,8,31); // T0verex
  fIndex++;
  buf[fIndex]=baseWord;

  // multiplicity

  Int_t mult=fDigits->SumMult();
  word=101;
  PackWord(baseWord,word, 0, 8);
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=mult;
  PackWord(baseWord,word,8,31); // time amplitude
  fIndex++;
  buf[fIndex]=baseWord;

  // trigger channels
   // besttime right & left
  word=102;
  PackWord(baseWord,word, 0, 8); // T0-A sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->BestTimeRight();
  PackWord(baseWord,word,8,31); // time-of-flight T0-A
  fIndex++;
  buf[fIndex]=baseWord;

  word=103;
  PackWord(baseWord,word, 0, 8); // T0-C sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;

  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->BestTimeLeft();
  PackWord(baseWord,word,8,31); // time-of-flight T0-C
  fIndex++;
  buf[fIndex]=baseWord;

  // time difference
  word=104;
  PackWord(baseWord,word, 0, 8); // TVDS sign
  word=fDigits->TimeDiff();
   PackWord(baseWord,word, 6, 31); // T0 vertex
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;

  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->TimeDiff();
  PackWord(baseWord,word,8,31); // T0verex
  fIndex++;
  buf[fIndex]=baseWord;

  // multiplicity

  mult=fDigits->SumMult();
  word=105;
  PackWord(baseWord,word, 0, 8);
  word=mult;
  PackWord(baseWord,word, 6, 31); // sum amplitude
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
 PackWord(baseWord,word,0, 7); // Error flag
  word=mult;
 PackWord(baseWord,word,8,31); // time amplitude
  fIndex++;
  buf[fIndex]=baseWord;

  // multiplicity

   mult=fDigits->SumMult();
  word=106;
  PackWord(baseWord,word, 0, 8);
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=mult;
  PackWord(baseWord,word,8,31); // time amplitude
  fIndex++;
  buf[fIndex]=baseWord;
  cout<<endl;
}

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

void AliSTARTRawData::PackWord(UInt_t &BaseWord, UInt_t Word, Int_t StartBit, Int_t StopBit)
{
  //This method packs a word into the Baseword buffer starting form the "StartBit"
  //and tacking StopBit-StartBit+1 bits
  UInt_t dummyWord,offSet;
  Int_t  length;
  UInt_t sum;
  //The BaseWord is being filled with 1 from StartBit to StopBit
  length=StopBit-StartBit+1;
  sum=(UInt_t)TMath::Power(2,length)-1;

  if(Word > sum){
    Error("PackWord", "Word to be filled is not within desired length\n"
          "Word:%d Start bit:%d Stop Bit:%d",Word,StartBit,StopBit);
    return;
  }
  offSet=sum;
  offSet<<=StartBit;
  BaseWord=BaseWord|offSet;

  //The Word to be filled is shifted to the position StartBit
  //and the remaining  Left and Right bits are filled with 1
  sum=(UInt_t)TMath::Power(2,StartBit)-1;
  dummyWord=0xFFFFFFFF<<length;
  dummyWord +=Word;
  dummyWord<<=StartBit;
  dummyWord+=sum;
  BaseWord=BaseWord&dummyWord;
  return;
}

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

Int_t AliSTARTRawData::RawDataSTART(AliSTARTdigit *fDigits)
{
   //This method creates the Raw data files for START detector

  const Int_t kSize=512; //2*AliTOFGeometry::NpadXSector()
                          //max number of digits per DDL file times 2
  UInt_t buf[kSize];
  UInt_t baseWord;
  UInt_t word;

  fIndex=-1;

  char fileName[15];
  ofstream outfile;         // logical name of the output file
  AliRawDataHeader header;
  AliBitPacking *pack ;
  //loop over TOF DDL files
  sprintf(fileName,"START_%d.ddl", 0xd00);
  //   sprintf(fileName,"START_0xd00.ddl"); //The name of the output file
#ifndef __DECCXX
    outfile.open(fileName,ios::binary);
#else
    outfile.open(fileName);
#endif
    //write Dummy DATA HEADER
    UInt_t dataHeaderPosition=outfile.tellp();
    outfile.write((char*)(&header),sizeof(header));

    baseWord=0;
    word=0;
    pack-> PackWord(baseWord,word,0, 31); // Number of DDL file

    fIndex++;
    buf[fIndex]=baseWord;
    GetDigits(fDigits,buf);

    outfile.write((char *)buf,((fIndex+1)*sizeof(UInt_t)));
    for(Int_t ii=0;ii<(fIndex+1);ii++) buf[ii]=0;
    fIndex=-1;

    //Write REAL DATA HEADER
    UInt_t currentFilePosition=outfile.tellp();
    outfile.seekp(dataHeaderPosition);
    header.fSize=currentFilePosition-dataHeaderPosition;
    header.SetAttribute(0);  // valid data
    outfile.write((char*)(&header),sizeof(header));
    outfile.close();

 //end for

  return 0;

}
<commit_msg>Bug fixes (Alla)<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
//  START raw data conversion class                                            //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include <Riostream.h>
#include <TTree.h>

#include "AliSTART.h"
#include "AliSTARTRawData.h"
#include "AliSTARTdigit.h"
#include "AliBitPacking.h"
#include "AliRawDataHeader.h"
#include "AliBitPacking.h"

ClassImp(AliSTARTRawData)

//_____________________________________________________________________________
AliSTARTRawData::AliSTARTRawData():TObject()
{
  /*
-  48 channels (2 words each as in TOF DDL) for :
word 1 :0-5bit number of PMT; word 2: 0-7 error sign, 8-31 TDC
and the same but for amplified signal. Now I wrote the same time because
CDF are not ready and differences didn't measured yet.

-  48 channel for amplitude: very preliminary, QTC features are not
known now, preliminary i put as T1 time signal for this PMT in first
channel and T1+A in second, where A=Log(Amplitude);
and the same for amplified but A=Log(10*Amplitude).

- T0-A and T0-C 2 channels
- T0A-T0C vertex information
- Time Meaner where T0C TOF increase to the T0A TOF distance
- 6 multiplicity signals the same way as amplitude and with the same
uncertances
  */

  fIndex=-1;
  fDigits = NULL;

  fTimeCFD = new TArrayI(24);
  fADC = new TArrayI(24);
  fTimeLED = new TArrayI(24);
  fADC0 = new TArrayI(24);
   //   this->Dump();

}

//_____________________________________________________________________________
AliSTARTRawData::AliSTARTRawData(const AliSTARTRawData &r):TObject()
{
  //
  // AliSTARTrawData copy constructor
  //

  ((AliSTARTRawData &) r).Copy(*this);

}

//_____________________________________________________________________________
AliSTARTRawData::~AliSTARTRawData()
{
  //
  // Destructor
  //
  if (fDigits) {
    delete fDigits;
    fDigits = NULL;
  }
  delete fTimeCFD;
  delete fADC;
  delete fTimeLED;
  delete fADC0;
}

//_____________________________________________________________________________
AliSTARTRawData &AliSTARTRawData::operator=(const AliSTARTRawData &r)
{
  //
  // Assignment operator
  //

  if (this != &r) ((AliSTARTRawData &) r).Copy(*this);
  return *this;

}

//_____________________________________________________________________________
void AliSTARTRawData::GetDigits(AliSTARTdigit *fDigits, UInt_t *buf)
{

  //This method packs the START digits in a proper 32 bits structure

  //read START digits and fill TDC and ADC arrays

  UInt_t word;
  UInt_t baseWord=0;
  Int_t error=0;

    // Get the digits array

  fDigits->GetTime(*fTimeCFD);
  fDigits->GetADC(*fADC);
  fDigits->GetTimeAmp(*fTimeLED);
  fDigits->GetADCAmp(*fADC0);

  // Loop through all PMT

  for (Int_t det = 0; det < 24; det++) {
    Int_t timeLED=fTimeLED->At(det);
    //   if( timeLED > 0){
      // DDL 1 0-5 -#PMT, 6-31 - empty
      //LED
      word=det;;
      PackWord(baseWord,word, 0, 8);
      fIndex++;
      buf[fIndex]=baseWord;

      word=0;
      baseWord=0;
      word=error;
      PackWord(baseWord,word,0, 7); // Error flag
      word=timeLED;
      PackWord(baseWord,word,8,31); // time-of-flight
      fIndex++;
      buf[fIndex]=baseWord;
      word=0;
      baseWord=0;
      //  }
  }
   for (Int_t det = 0; det < 24; det++) {
    //CDF
     Int_t timeCFD=fTimeCFD->At(det);
     //   if ( timeCFD >0 ) {
       // DDL2 2 0-5 -#PMT, 6-31 - empty
       word=0;
       baseWord=0;
       word=det+24;
       PackWord(baseWord,word, 0, 8); // number of PMT on the right side
       fIndex++;
       buf[fIndex]=baseWord;
       word=0;
       baseWord=0;
       word=error;
       PackWord(baseWord,word,0, 7); // Error flag
       word=timeCFD;
       PackWord(baseWord,word,8,31); // time-of-flight
       fIndex++;
       buf[fIndex]=baseWord;
        word=0;
       baseWord=0;
       //  }
   }
  for (Int_t det = 0; det < 24; det++) {
    //conver ADC to time (preliminary algorithm)
    Int_t qtc=fADC->At(det);
    //    if ( qtc > 0 )
    //  {
	word=det+48;
	PackWord(baseWord,word, 0, 8); // number of PMT on the right side
	fIndex++;
	buf[fIndex]=baseWord;
	baseWord=0;
	word=error;
	PackWord(baseWord,word,0, 7); // Error flag
	word=qtc;
	PackWord(baseWord,word,8,31); // Q->Time
	fIndex++;
	buf[fIndex]=baseWord;
 	word=0;
	baseWord=0;
	//     }
  }

  for (Int_t det = 0; det < 24; det++) {
    Int_t qtcAmp=fADC0->At(det);

    // DDL 4 amplified QTC charge * 10

     //Amplified  ADC -> TDC

    word=det+72;
    PackWord(baseWord,word, 0, 8); // number of PMT on the right side
    fIndex++;
    buf[fIndex]=baseWord;
    baseWord=0;
    word=error;
    PackWord(baseWord,word,0, 7); // Error flag
    word=qtcAmp;
    PackWord(baseWord,word,8,31); // Q->T amplified
    fIndex++;
    buf[fIndex]=baseWord;

    word=0;
    baseWord=0;
  }

  word=0;
  baseWord=0;
  fIndex++;
  word=97;
  PackWord(baseWord,word, 0, 8); // ?????????????????
  buf[fIndex]=baseWord;
  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->MeanTime();
  PackWord(baseWord,word,8,31); // MEANER

  fIndex++;
  buf[fIndex]=baseWord;

  // besttime right & left
  word=98;
  PackWord(baseWord,word, 0, 8); // T0-A sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->BestTimeRight();
  PackWord(baseWord,word,8,31); // time-of-flight T0-A
  fIndex++;
  buf[fIndex]=baseWord;

  word=99;
  PackWord(baseWord,word, 0, 8); // T0-C sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->BestTimeLeft();
  PackWord(baseWord,word,8,31); // time-of-flight T0-C
  fIndex++;
  buf[fIndex]=baseWord;

  // time difference
  word=100;
  PackWord(baseWord,word, 0, 8); // TVDS sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;

  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->TimeDiff();
  PackWord(baseWord,word,8,31); // T0verex
  fIndex++;
  buf[fIndex]=baseWord;

  // multiplicity

  Int_t mult=fDigits->SumMult();
  word=101;
  PackWord(baseWord,word, 0, 8);
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=mult;
  PackWord(baseWord,word,8,31); // time amplitude
  fIndex++;
  buf[fIndex]=baseWord;

  // trigger channels
   // besttime right & left
  word=102;
  PackWord(baseWord,word, 0, 8); // T0-A sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->BestTimeRight();
  PackWord(baseWord,word,8,31); // time-of-flight T0-A
  fIndex++;
  buf[fIndex]=baseWord;

  word=103;
  PackWord(baseWord,word, 0, 8); // T0-C sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;

  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->BestTimeLeft();
  PackWord(baseWord,word,8,31); // time-of-flight T0-C
  fIndex++;
  buf[fIndex]=baseWord;

  // time difference
  word=104;
  PackWord(baseWord,word, 0, 8); // TVDS sign
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;

  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=fDigits->TimeDiff();
  PackWord(baseWord,word,8,31); // T0verex
  fIndex++;
  buf[fIndex]=baseWord;

  // multiplicity

  mult=fDigits->SumMult();
  word=105;
  PackWord(baseWord,word, 0, 8);
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=mult;
  PackWord(baseWord,word,8,31); // time amplitude
  fIndex++;
  buf[fIndex]=baseWord;

  // multiplicity

  mult=fDigits->SumMult();
  word=106;
  PackWord(baseWord,word, 0, 8);
  fIndex++;
  buf[fIndex]=baseWord;

  baseWord=0;
  word=error;
  PackWord(baseWord,word,0, 7); // Error flag
  word=mult;
  PackWord(baseWord,word,8,31); // time amplitude
  fIndex++;
  buf[fIndex]=baseWord;
  cout<<endl;
}

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

void AliSTARTRawData::PackWord(UInt_t &BaseWord, UInt_t Word, Int_t StartBit, Int_t StopBit)
{
  //This method packs a word into the Baseword buffer starting form the "StartBit"
  //and tacking StopBit-StartBit+1 bits
  UInt_t dummyWord,offSet;
  Int_t  length;
  UInt_t sum;
  //The BaseWord is being filled with 1 from StartBit to StopBit
  length=StopBit-StartBit+1;
  sum=(UInt_t)TMath::Power(2,length)-1;

  if(Word > sum){
    Error("PackWord", "Word to be filled is not within desired length\n"
          "Word:%d Start bit:%d Stop Bit:%d",Word,StartBit,StopBit);
    return;
  }
  offSet=sum;
  offSet<<=StartBit;
  BaseWord=BaseWord|offSet;

  //The Word to be filled is shifted to the position StartBit
  //and the remaining  Left and Right bits are filled with 1
  sum=(UInt_t)TMath::Power(2,StartBit)-1;
  dummyWord=0xFFFFFFFF<<length;
  dummyWord +=Word;
  dummyWord<<=StartBit;
  dummyWord+=sum;
  BaseWord=BaseWord&dummyWord;
  return;
}

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

Int_t AliSTARTRawData::RawDataSTART(AliSTARTdigit *fDigits)
{
   //This method creates the Raw data files for START detector

  const Int_t kSize=512; //2*AliTOFGeometry::NpadXSector()
                          //max number of digits per DDL file times 2
  UInt_t buf[kSize];
  UInt_t baseWord;
  UInt_t word;

  fIndex=-1;

  char fileName[15];
  ofstream outfile;         // logical name of the output file
  AliRawDataHeader header;
  //loop over TOF DDL files
  sprintf(fileName,"START_%d.ddl", 0xd00);
  //   sprintf(fileName,"START_0xd00.ddl"); //The name of the output file
#ifndef __DECCXX
    outfile.open(fileName,ios::binary);
#else
    outfile.open(fileName);
#endif
    //write Dummy DATA HEADER
    UInt_t dataHeaderPosition=outfile.tellp();
    outfile.write((char*)(&header),sizeof(header));

    baseWord=0;
    word=0;
    PackWord(baseWord,word,0, 31); // Number of DDL file

    fIndex++;
    buf[fIndex]=baseWord;
    GetDigits(fDigits,buf);

    outfile.write((char *)buf,((fIndex+1)*sizeof(UInt_t)));
    for(Int_t ii=0;ii<(fIndex+1);ii++) buf[ii]=0;
    fIndex=-1;

    //Write REAL DATA HEADER
    UInt_t currentFilePosition=outfile.tellp();
    outfile.seekp(dataHeaderPosition);
    header.fSize=currentFilePosition-dataHeaderPosition;
    header.SetAttribute(0);  // valid data
    outfile.write((char*)(&header),sizeof(header));
    outfile.close();

 //end for

  return 0;

}
<|endoftext|>


<commit_before><commit_msg>Change a DCHECK to a DCHECK_LT so we can see the failing values.<commit_after><|endoftext|>