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

BlueBerry Platform

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "berryHelpPluginActivator.h"

#include "berryHelpContentView.h"
#include "berryHelpIndexView.h"
#include "berryHelpSearchView.h"
#include "berryHelpEditor.h"
#include "berryHelpEditorInput.h"
#include "berryHelpPerspective.h"

#include "berryQHelpEngineConfiguration.h"
#include "berryQHelpEngineWrapper.h"

#include <berryPlatformUI.h>

#include <service/event/ctkEventConstants.h>

#include <QtPlugin>
#include <QDir>
#include <QDateTime>

namespace berry {

class HelpPerspectiveListener : public IPerspectiveListener
{
public:

  Events::Types GetPerspectiveEventTypes() const;

  void PerspectiveOpened(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective);
  void PerspectiveChanged(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective, const std::string &changeId);
};

class HelpWindowListener : public IWindowListener
{
public:

  HelpWindowListener();
  ~HelpWindowListener();

  void WindowClosed(IWorkbenchWindow::Pointer window);
  void WindowOpened(IWorkbenchWindow::Pointer window);

private:

  // We use the same perspective listener for every window
  IPerspectiveListener::Pointer perspListener;
};

HelpPluginActivator* HelpPluginActivator::instance = 0;

HelpPluginActivator::HelpPluginActivator()
  : pluginListener(0)
{
  this->instance = this;
}

HelpPluginActivator::~HelpPluginActivator()
{
  instance = 0;
}

void
HelpPluginActivator::start(ctkPluginContext* context)
{
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpContentView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpIndexView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpSearchView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpEditor, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpPerspective, context)

  QFileInfo qhcInfo = context->getDataFile("qthelpcollection.qhc");
  helpEngine.reset(new QHelpEngineWrapper(qhcInfo.absoluteFilePath()));
  if (!helpEngine->setupData())
  {
    BERRY_ERROR << "QHelpEngine set-up failed: " << helpEngine->error().toStdString();
    return;
  }

  helpEngineConfiguration.reset(new QHelpEngineConfiguration(context, *helpEngine.data()));

  delete pluginListener;
  pluginListener = new QCHPluginListener(context, helpEngine.data());
  context->connectPluginListener(pluginListener, SLOT(pluginChanged(ctkPluginEvent)));

  // register all QCH files from all the currently installed plugins
  pluginListener->processPlugins();

  helpEngine->initialDocSetupDone();

  // Register a wnd listener which registers a perspective listener for each
  // new window. The perspective listener opens the help home page in the window
  // if no other help page is opened yet.
  wndListener = IWindowListener::Pointer(new HelpWindowListener());
  PlatformUI::GetWorkbench()->AddWindowListener(wndListener);

  // Register an event handler for CONTEXTHELP_REQUESTED events
  helpContextHandler.reset(new HelpContextHandler);
  ctkDictionary helpHandlerProps;
  helpHandlerProps.insert(ctkEventConstants::EVENT_TOPIC, "org/blueberry/ui/help/CONTEXTHELP_REQUESTED");
  context->registerService<ctkEventHandler>(helpContextHandler.data(), helpHandlerProps);
}

void
HelpPluginActivator::stop(ctkPluginContext* /*context*/)
{
  delete pluginListener;
  pluginListener = 0;

  if (PlatformUI::IsWorkbenchRunning())
  {
    PlatformUI::GetWorkbench()->RemoveWindowListener(wndListener);
  }
  wndListener = 0;
}

HelpPluginActivator *HelpPluginActivator::getInstance()
{
  return instance;
}

QHelpEngineWrapper& HelpPluginActivator::getQHelpEngine()
{
  return *helpEngine;
}

void HelpPluginActivator::linkActivated(IWorkbenchPage::Pointer page, const QUrl &link)
{
  IEditorInput::Pointer input(new HelpEditorInput(link));

  // see if an editor with the same input is already open
  IEditorPart::Pointer reuseEditor = page->FindEditor(input);
  if (reuseEditor)
  {
    // just activate it
    page->Activate(reuseEditor);
  }
  else
  {
    // reuse the currently active editor, if it is a HelpEditor
    reuseEditor = page->GetActiveEditor();
    if (reuseEditor.IsNotNull() && page->GetReference(reuseEditor)->GetId() == HelpEditor::EDITOR_ID)
    {
      page->ReuseEditor(reuseEditor.Cast<IReusableEditor>(), input);
      page->Activate(reuseEditor);
    }
    else
    {
      // get the last used HelpEditor instance
      std::vector<IEditorReference::Pointer> editors =
          page->FindEditors(IEditorInput::Pointer(0), HelpEditor::EDITOR_ID, IWorkbenchPage::MATCH_ID);
      if (editors.empty())
      {
        // no HelpEditor is currently open, create a new one
        page->OpenEditor(input, HelpEditor::EDITOR_ID);
      }
      else
      {
        // reuse an existing editor
        reuseEditor = editors.front()->GetEditor(false);
        page->ReuseEditor(reuseEditor.Cast<IReusableEditor>(), input);
        page->Activate(reuseEditor);
      }
    }
  }
}

QCHPluginListener::QCHPluginListener(ctkPluginContext* context, QHelpEngine* helpEngine)
  : delayRegistration(true), context(context), helpEngine(helpEngine)
{}

void QCHPluginListener::processPlugins()
{
  QMutexLocker lock(&mutex);
  processPlugins_unlocked();
}

void QCHPluginListener::pluginChanged(const ctkPluginEvent& event)
{
  QMutexLocker lock(&mutex);
  if (delayRegistration)
  {
    this->processPlugins_unlocked();
    return;
  }

  /* Only should listen for RESOLVED and UNRESOLVED events.
   *
   * When a plugin is updated the Framework will publish an UNRESOLVED and
   * then a RESOLVED event which should cause the plugin to be removed
   * and then added back into the registry.
   *
   * When a plugin is uninstalled the Framework should publish an UNRESOLVED
   * event and then an UNINSTALLED event so the plugin will have been removed
   * by the UNRESOLVED event before the UNINSTALLED event is published.
   */
  QSharedPointer<ctkPlugin> plugin = event.getPlugin();
  switch (event.getType())
  {
    case ctkPluginEvent::RESOLVED :
      addPlugin(plugin);
      break;
    case ctkPluginEvent::UNRESOLVED :
      removePlugin(plugin);
      break;
  }
}

void QCHPluginListener::processPlugins_unlocked()
{
  if (!delayRegistration) return;

  foreach (QSharedPointer<ctkPlugin> plugin, context->getPlugins())
  {
    if (isPluginResolved(plugin))
      addPlugin(plugin);
    else
      removePlugin(plugin);
  }

  delayRegistration = false;
}

bool QCHPluginListener::isPluginResolved(QSharedPointer<ctkPlugin> plugin)
{
  return (plugin->getState() & (ctkPlugin::RESOLVED | ctkPlugin::ACTIVE | ctkPlugin::STARTING | ctkPlugin::STOPPING)) != 0;
}

void QCHPluginListener::removePlugin(QSharedPointer<ctkPlugin> plugin)
{
  // bail out if system plugin
  if (plugin->getPluginId() == 0) return;

  QFileInfo qchDirInfo = context->getDataFile("qch_files/" + QString::number(plugin->getPluginId()));
  if (qchDirInfo.exists())
  {
    QDir qchDir(qchDirInfo.absoluteFilePath());
    QStringList qchEntries = qchDir.entryList(QStringList("*.qch"));
    QStringList qchFiles;
    foreach(QString qchEntry, qchEntries)
    {
      qchFiles << qchDir.absoluteFilePath(qchEntry);
    }
    // unregister the cached qch files
    foreach(QString qchFile, qchFiles)
    {
      QString namespaceName = QHelpEngineCore::namespaceName(qchFile);
      if (namespaceName.isEmpty())
      {
        BERRY_ERROR << "Could not get the namespace for qch file " << qchFile.toStdString();
        continue;
      }
      else
      {
        if (!helpEngine->unregisterDocumentation(namespaceName))
        {
          BERRY_ERROR << "Unregistering qch namespace " << namespaceName.toStdString() << " failed: " << helpEngine->error().toStdString();
        }
      }
    }
    // clean the directory
    foreach(QString qchEntry, qchEntries)
    {
      qchDir.remove(qchEntry);
    }
  }
}

void QCHPluginListener::addPlugin(QSharedPointer<ctkPlugin> plugin)
{
  // bail out if system plugin
  if (plugin->getPluginId() == 0) return;

  QFileInfo qchDirInfo = context->getDataFile("qch_files/" + QString::number(plugin->getPluginId()));
  QUrl location(plugin->getLocation());
  QFileInfo pluginFileInfo(location.toLocalFile());

  if (!qchDirInfo.exists() || qchDirInfo.lastModified() < pluginFileInfo.lastModified())
  {
    removePlugin(plugin);

    if (!qchDirInfo.exists())
    {
      QDir().mkpath(qchDirInfo.absoluteFilePath());
    }

    QStringList localQCHFiles;
    QStringList resourceList = plugin->findResources("/", "*.qch", true);
    foreach(QString resource, resourceList)
    {
      QByteArray content = plugin->getResource(resource);
      QFile localFile(qchDirInfo.absoluteFilePath() + "/" + resource.section('/', -1));
      localFile.open(QIODevice::WriteOnly);
      localFile.write(content);
      localFile.close();
      if (localFile.error() != QFile::NoError)
      {
        BERRY_WARN << "Error writing " << localFile.fileName().toStdString()
                   << ": " << localFile.errorString().toStdString();
      }
      else
      {
        localQCHFiles << localFile.fileName();
      }
    }

    foreach(QString qchFile, localQCHFiles)
    {
      if (!helpEngine->registerDocumentation(qchFile))
      {
        BERRY_ERROR << "Registering qch file " << qchFile.toStdString() << " failed: " << helpEngine->error().toStdString();
      }
    }
  }

}

IPerspectiveListener::Events::Types HelpPerspectiveListener::GetPerspectiveEventTypes() const
{
  return Events::OPENED | Events::CHANGED;
}

void HelpPerspectiveListener::PerspectiveOpened(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective)
{
  // if no help editor is opened, open one showing the home page
  if (perspective->GetId() == HelpPerspective::ID &&
      page->FindEditors(IEditorInput::Pointer(0), HelpEditor::EDITOR_ID, IWorkbenchPage::MATCH_ID).empty())
  {
    IEditorInput::Pointer input(new HelpEditorInput());
    page->OpenEditor(input, HelpEditor::EDITOR_ID);
  }
}

void HelpPerspectiveListener::PerspectiveChanged(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective, const std::string &changeId)
{
  if (perspective->GetId() == HelpPerspective::ID && changeId == IWorkbenchPage::CHANGE_RESET)
  {
    PerspectiveOpened(page, perspective);
  }
}

HelpWindowListener::HelpWindowListener()
  : perspListener(new HelpPerspectiveListener())
{
  // Register perspective listener for already opened windows
  typedef std::vector<IWorkbenchWindow::Pointer> WndVec;
  WndVec windows = PlatformUI::GetWorkbench()->GetWorkbenchWindows();
  for (WndVec::iterator i = windows.begin(); i != windows.end(); ++i)
  {
    (*i)->AddPerspectiveListener(perspListener);
  }
}

HelpWindowListener::~HelpWindowListener()
{
  typedef std::vector<IWorkbenchWindow::Pointer> WndVec;
  WndVec windows = PlatformUI::GetWorkbench()->GetWorkbenchWindows();
  for (WndVec::iterator i = windows.begin(); i != windows.end(); ++i)
  {
    (*i)->RemovePerspectiveListener(perspListener);
  }
}

void HelpWindowListener::WindowClosed(IWorkbenchWindow::Pointer window)
{
  window->RemovePerspectiveListener(perspListener);
}

void HelpWindowListener::WindowOpened(IWorkbenchWindow::Pointer window)
{
  window->AddPerspectiveListener(perspListener);
}

void HelpContextHandler::handleEvent(const ctkEvent &event)
{
  struct _runner : public Poco::Runnable
  {
    _runner(const ctkEvent& ev) : ev(ev) {}

    void run()
    {
      QUrl helpUrl;
      if (ev.containsProperty("url"))
      {
        helpUrl = QUrl(ev.getProperty("url").toString());
      }
      else
      {
        helpUrl = contextUrl();
      }

      HelpPluginActivator::linkActivated(PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage(),
                                         helpUrl);
      delete this;
    }

    QUrl contextUrl() const
    {
      berry::IWorkbench* currentWorkbench = berry::PlatformUI::GetWorkbench();
      if (currentWorkbench)
      {
        berry::IWorkbenchWindow::Pointer currentWorkbenchWindow = currentWorkbench->GetActiveWorkbenchWindow();
        if (currentWorkbenchWindow)
        {
          berry::IWorkbenchPage::Pointer currentPage = currentWorkbenchWindow->GetActivePage();
          if (currentPage)
          {
            berry::IWorkbenchPart::Pointer currentPart = currentPage->GetActivePart();
            if (currentPart)
            {
              QString pluginID = QString::fromStdString(currentPart->GetSite()->GetPluginId());
              QString viewID = QString::fromStdString(currentPart->GetSite()->GetId());
              QString loc = "qthelp://" + pluginID + "/bundle/%1.html";

              QHelpEngineWrapper& helpEngine = HelpPluginActivator::getInstance()->getQHelpEngine();
              QUrl contextUrl(loc.arg(viewID.replace(".", "_")));
              QUrl url = helpEngine.findFile(contextUrl);
              if (url.isValid()) return url;
              else
              {
                BERRY_INFO << "Context help url invalid: " << contextUrl.toString().toStdString();
              }
              // Try to get the index.html file of the plug-in contributing the
              // currently active part.
              QUrl pluginIndexUrl(loc.arg("index"));
              url = helpEngine.findFile(pluginIndexUrl);
              if (url != pluginIndexUrl)
              {
                // Use the default page instead of another index.html
                // (merged via the virtual folder property).
                url = QUrl();
              }
              return url;
            }
          }
        }
      }
      return QUrl();
    }

    ctkEvent ev;
  };
  // sync with GUI thread
  Display::GetDefault()->AsyncExec(new _runner(event));
}

}

Q_EXPORT_PLUGIN2(org_blueberry_ui_qt_help, berry::HelpPluginActivator)
<commit_msg>Look first for view id, then plugin id, then index.html<commit_after>/*===================================================================

BlueBerry Platform

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "berryHelpPluginActivator.h"

#include "berryHelpContentView.h"
#include "berryHelpIndexView.h"
#include "berryHelpSearchView.h"
#include "berryHelpEditor.h"
#include "berryHelpEditorInput.h"
#include "berryHelpPerspective.h"

#include "berryQHelpEngineConfiguration.h"
#include "berryQHelpEngineWrapper.h"

#include <berryPlatformUI.h>

#include <service/event/ctkEventConstants.h>

#include <QtPlugin>
#include <QDir>
#include <QDateTime>

namespace berry {

class HelpPerspectiveListener : public IPerspectiveListener
{
public:

  Events::Types GetPerspectiveEventTypes() const;

  void PerspectiveOpened(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective);
  void PerspectiveChanged(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective, const std::string &changeId);
};

class HelpWindowListener : public IWindowListener
{
public:

  HelpWindowListener();
  ~HelpWindowListener();

  void WindowClosed(IWorkbenchWindow::Pointer window);
  void WindowOpened(IWorkbenchWindow::Pointer window);

private:

  // We use the same perspective listener for every window
  IPerspectiveListener::Pointer perspListener;
};

HelpPluginActivator* HelpPluginActivator::instance = 0;

HelpPluginActivator::HelpPluginActivator()
  : pluginListener(0)
{
  this->instance = this;
}

HelpPluginActivator::~HelpPluginActivator()
{
  instance = 0;
}

void
HelpPluginActivator::start(ctkPluginContext* context)
{
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpContentView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpIndexView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpSearchView, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpEditor, context)
  BERRY_REGISTER_EXTENSION_CLASS(berry::HelpPerspective, context)

  QFileInfo qhcInfo = context->getDataFile("qthelpcollection.qhc");
  helpEngine.reset(new QHelpEngineWrapper(qhcInfo.absoluteFilePath()));
  if (!helpEngine->setupData())
  {
    BERRY_ERROR << "QHelpEngine set-up failed: " << helpEngine->error().toStdString();
    return;
  }

  helpEngineConfiguration.reset(new QHelpEngineConfiguration(context, *helpEngine.data()));

  delete pluginListener;
  pluginListener = new QCHPluginListener(context, helpEngine.data());
  context->connectPluginListener(pluginListener, SLOT(pluginChanged(ctkPluginEvent)));

  // register all QCH files from all the currently installed plugins
  pluginListener->processPlugins();

  helpEngine->initialDocSetupDone();

  // Register a wnd listener which registers a perspective listener for each
  // new window. The perspective listener opens the help home page in the window
  // if no other help page is opened yet.
  wndListener = IWindowListener::Pointer(new HelpWindowListener());
  PlatformUI::GetWorkbench()->AddWindowListener(wndListener);

  // Register an event handler for CONTEXTHELP_REQUESTED events
  helpContextHandler.reset(new HelpContextHandler);
  ctkDictionary helpHandlerProps;
  helpHandlerProps.insert(ctkEventConstants::EVENT_TOPIC, "org/blueberry/ui/help/CONTEXTHELP_REQUESTED");
  context->registerService<ctkEventHandler>(helpContextHandler.data(), helpHandlerProps);
}

void
HelpPluginActivator::stop(ctkPluginContext* /*context*/)
{
  delete pluginListener;
  pluginListener = 0;

  if (PlatformUI::IsWorkbenchRunning())
  {
    PlatformUI::GetWorkbench()->RemoveWindowListener(wndListener);
  }
  wndListener = 0;
}

HelpPluginActivator *HelpPluginActivator::getInstance()
{
  return instance;
}

QHelpEngineWrapper& HelpPluginActivator::getQHelpEngine()
{
  return *helpEngine;
}

void HelpPluginActivator::linkActivated(IWorkbenchPage::Pointer page, const QUrl &link)
{
  IEditorInput::Pointer input(new HelpEditorInput(link));

  // see if an editor with the same input is already open
  IEditorPart::Pointer reuseEditor = page->FindEditor(input);
  if (reuseEditor)
  {
    // just activate it
    page->Activate(reuseEditor);
  }
  else
  {
    // reuse the currently active editor, if it is a HelpEditor
    reuseEditor = page->GetActiveEditor();
    if (reuseEditor.IsNotNull() && page->GetReference(reuseEditor)->GetId() == HelpEditor::EDITOR_ID)
    {
      page->ReuseEditor(reuseEditor.Cast<IReusableEditor>(), input);
      page->Activate(reuseEditor);
    }
    else
    {
      // get the last used HelpEditor instance
      std::vector<IEditorReference::Pointer> editors =
          page->FindEditors(IEditorInput::Pointer(0), HelpEditor::EDITOR_ID, IWorkbenchPage::MATCH_ID);
      if (editors.empty())
      {
        // no HelpEditor is currently open, create a new one
        page->OpenEditor(input, HelpEditor::EDITOR_ID);
      }
      else
      {
        // reuse an existing editor
        reuseEditor = editors.front()->GetEditor(false);
        page->ReuseEditor(reuseEditor.Cast<IReusableEditor>(), input);
        page->Activate(reuseEditor);
      }
    }
  }
}

QCHPluginListener::QCHPluginListener(ctkPluginContext* context, QHelpEngine* helpEngine)
  : delayRegistration(true), context(context), helpEngine(helpEngine)
{}

void QCHPluginListener::processPlugins()
{
  QMutexLocker lock(&mutex);
  processPlugins_unlocked();
}

void QCHPluginListener::pluginChanged(const ctkPluginEvent& event)
{
  QMutexLocker lock(&mutex);
  if (delayRegistration)
  {
    this->processPlugins_unlocked();
    return;
  }

  /* Only should listen for RESOLVED and UNRESOLVED events.
   *
   * When a plugin is updated the Framework will publish an UNRESOLVED and
   * then a RESOLVED event which should cause the plugin to be removed
   * and then added back into the registry.
   *
   * When a plugin is uninstalled the Framework should publish an UNRESOLVED
   * event and then an UNINSTALLED event so the plugin will have been removed
   * by the UNRESOLVED event before the UNINSTALLED event is published.
   */
  QSharedPointer<ctkPlugin> plugin = event.getPlugin();
  switch (event.getType())
  {
    case ctkPluginEvent::RESOLVED :
      addPlugin(plugin);
      break;
    case ctkPluginEvent::UNRESOLVED :
      removePlugin(plugin);
      break;
  }
}

void QCHPluginListener::processPlugins_unlocked()
{
  if (!delayRegistration) return;

  foreach (QSharedPointer<ctkPlugin> plugin, context->getPlugins())
  {
    if (isPluginResolved(plugin))
      addPlugin(plugin);
    else
      removePlugin(plugin);
  }

  delayRegistration = false;
}

bool QCHPluginListener::isPluginResolved(QSharedPointer<ctkPlugin> plugin)
{
  return (plugin->getState() & (ctkPlugin::RESOLVED | ctkPlugin::ACTIVE | ctkPlugin::STARTING | ctkPlugin::STOPPING)) != 0;
}

void QCHPluginListener::removePlugin(QSharedPointer<ctkPlugin> plugin)
{
  // bail out if system plugin
  if (plugin->getPluginId() == 0) return;

  QFileInfo qchDirInfo = context->getDataFile("qch_files/" + QString::number(plugin->getPluginId()));
  if (qchDirInfo.exists())
  {
    QDir qchDir(qchDirInfo.absoluteFilePath());
    QStringList qchEntries = qchDir.entryList(QStringList("*.qch"));
    QStringList qchFiles;
    foreach(QString qchEntry, qchEntries)
    {
      qchFiles << qchDir.absoluteFilePath(qchEntry);
    }
    // unregister the cached qch files
    foreach(QString qchFile, qchFiles)
    {
      QString namespaceName = QHelpEngineCore::namespaceName(qchFile);
      if (namespaceName.isEmpty())
      {
        BERRY_ERROR << "Could not get the namespace for qch file " << qchFile.toStdString();
        continue;
      }
      else
      {
        if (!helpEngine->unregisterDocumentation(namespaceName))
        {
          BERRY_ERROR << "Unregistering qch namespace " << namespaceName.toStdString() << " failed: " << helpEngine->error().toStdString();
        }
      }
    }
    // clean the directory
    foreach(QString qchEntry, qchEntries)
    {
      qchDir.remove(qchEntry);
    }
  }
}

void QCHPluginListener::addPlugin(QSharedPointer<ctkPlugin> plugin)
{
  // bail out if system plugin
  if (plugin->getPluginId() == 0) return;

  QFileInfo qchDirInfo = context->getDataFile("qch_files/" + QString::number(plugin->getPluginId()));
  QUrl location(plugin->getLocation());
  QFileInfo pluginFileInfo(location.toLocalFile());

  if (!qchDirInfo.exists() || qchDirInfo.lastModified() < pluginFileInfo.lastModified())
  {
    removePlugin(plugin);

    if (!qchDirInfo.exists())
    {
      QDir().mkpath(qchDirInfo.absoluteFilePath());
    }

    QStringList localQCHFiles;
    QStringList resourceList = plugin->findResources("/", "*.qch", true);
    foreach(QString resource, resourceList)
    {
      QByteArray content = plugin->getResource(resource);
      QFile localFile(qchDirInfo.absoluteFilePath() + "/" + resource.section('/', -1));
      localFile.open(QIODevice::WriteOnly);
      localFile.write(content);
      localFile.close();
      if (localFile.error() != QFile::NoError)
      {
        BERRY_WARN << "Error writing " << localFile.fileName().toStdString()
                   << ": " << localFile.errorString().toStdString();
      }
      else
      {
        localQCHFiles << localFile.fileName();
      }
    }

    foreach(QString qchFile, localQCHFiles)
    {
      if (!helpEngine->registerDocumentation(qchFile))
      {
        BERRY_ERROR << "Registering qch file " << qchFile.toStdString() << " failed: " << helpEngine->error().toStdString();
      }
    }
  }

}

IPerspectiveListener::Events::Types HelpPerspectiveListener::GetPerspectiveEventTypes() const
{
  return Events::OPENED | Events::CHANGED;
}

void HelpPerspectiveListener::PerspectiveOpened(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective)
{
  // if no help editor is opened, open one showing the home page
  if (perspective->GetId() == HelpPerspective::ID &&
      page->FindEditors(IEditorInput::Pointer(0), HelpEditor::EDITOR_ID, IWorkbenchPage::MATCH_ID).empty())
  {
    IEditorInput::Pointer input(new HelpEditorInput());
    page->OpenEditor(input, HelpEditor::EDITOR_ID);
  }
}

void HelpPerspectiveListener::PerspectiveChanged(SmartPointer<IWorkbenchPage> page, IPerspectiveDescriptor::Pointer perspective, const std::string &changeId)
{
  if (perspective->GetId() == HelpPerspective::ID && changeId == IWorkbenchPage::CHANGE_RESET)
  {
    PerspectiveOpened(page, perspective);
  }
}

HelpWindowListener::HelpWindowListener()
  : perspListener(new HelpPerspectiveListener())
{
  // Register perspective listener for already opened windows
  typedef std::vector<IWorkbenchWindow::Pointer> WndVec;
  WndVec windows = PlatformUI::GetWorkbench()->GetWorkbenchWindows();
  for (WndVec::iterator i = windows.begin(); i != windows.end(); ++i)
  {
    (*i)->AddPerspectiveListener(perspListener);
  }
}

HelpWindowListener::~HelpWindowListener()
{
  typedef std::vector<IWorkbenchWindow::Pointer> WndVec;
  WndVec windows = PlatformUI::GetWorkbench()->GetWorkbenchWindows();
  for (WndVec::iterator i = windows.begin(); i != windows.end(); ++i)
  {
    (*i)->RemovePerspectiveListener(perspListener);
  }
}

void HelpWindowListener::WindowClosed(IWorkbenchWindow::Pointer window)
{
  window->RemovePerspectiveListener(perspListener);
}

void HelpWindowListener::WindowOpened(IWorkbenchWindow::Pointer window)
{
  window->AddPerspectiveListener(perspListener);
}

void HelpContextHandler::handleEvent(const ctkEvent &event)
{
  struct _runner : public Poco::Runnable
  {
    _runner(const ctkEvent& ev) : ev(ev) {}

    void run()
    {
      QUrl helpUrl;
      if (ev.containsProperty("url"))
      {
        helpUrl = QUrl(ev.getProperty("url").toString());
      }
      else
      {
        helpUrl = contextUrl();
      }

      HelpPluginActivator::linkActivated(PlatformUI::GetWorkbench()->GetActiveWorkbenchWindow()->GetActivePage(),
                                         helpUrl);
      delete this;
    }

    QUrl contextUrl() const
    {
      berry::IWorkbench* currentWorkbench = berry::PlatformUI::GetWorkbench();
      if (currentWorkbench)
      {
        berry::IWorkbenchWindow::Pointer currentWorkbenchWindow = currentWorkbench->GetActiveWorkbenchWindow();
        if (currentWorkbenchWindow)
        {
          berry::IWorkbenchPage::Pointer currentPage = currentWorkbenchWindow->GetActivePage();
          if (currentPage)
          {
            berry::IWorkbenchPart::Pointer currentPart = currentPage->GetActivePart();
            if (currentPart)
            {
              QString pluginID = QString::fromStdString(currentPart->GetSite()->GetPluginId());
              QString viewID = QString::fromStdString(currentPart->GetSite()->GetId());
              QString loc = "qthelp://" + pluginID + "/bundle/%1.html";

              QHelpEngineWrapper& helpEngine = HelpPluginActivator::getInstance()->getQHelpEngine();
              // Get view help page if available
              QUrl contextUrl(loc.arg(viewID.replace(".", "_")));
              QUrl url = helpEngine.findFile(contextUrl);
              if (url.isValid()) return url;
              else
              {
                BERRY_INFO << "Context help url invalid: " << contextUrl.toString().toStdString();
              }
              // If no view help exists get plugin help if available
              QUrl pluginContextUrl(pluginID.replace(".", "_"));
              url = helpEngine.findFile(pluginContextUrl);
              if (url.isValid()) return url;
              // Try to get the index.html file of the plug-in contributing the
              // currently active part.
              QUrl pluginIndexUrl(loc.arg("index"));
              url = helpEngine.findFile(pluginIndexUrl);
              if (url != pluginIndexUrl)
              {
                // Use the default page instead of another index.html
                // (merged via the virtual folder property).
                url = QUrl();
              }
              return url;
            }
          }
        }
      }
      return QUrl();
    }

    ctkEvent ev;
  };
  // sync with GUI thread
  Display::GetDefault()->AsyncExec(new _runner(event));
}

}

Q_EXPORT_PLUGIN2(org_blueberry_ui_qt_help, berry::HelpPluginActivator)
<|endoftext|>


<commit_before>// DXGL
// Copyright (C) 2012 William Feely

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "common.h"
#include "fog.h"

static DWORD fogcolor = 0;
static GLfloat fogstart = 0;
static GLfloat fogend = 1;
static GLfloat fogdensity = 1;

void SetFogColor(DWORD color)
{
	if(color == fogcolor) return;
	fogcolor = color;
	GLfloat colors[4];
	colors[0] = (color >> 16) & 255;
	colors[1] = (color >> 8) & 255;
	colors[2] = color & 255;
	colors[3] = (color >> 24) & 255;
	glFogfv(GL_FOG_COLOR,colors);
}

void SetFogStart(GLfloat start)
{
	if(start == fogstart) return;
	fogstart = start;
	glFogf(GL_FOG_START,start);
}

void SetFogEnd(GLfloat end)
{
	if(end == fogend) return;
	fogend = end;
	glFogf(GL_FOG_END,end);
}

void SetFogDensity(GLfloat density)
{
	if(density == fogdensity) return;
	fogdensity = density;
	glFogf(GL_FOG_DENSITY,density);
}<commit_msg>Scale fog color channels to 0.0-1.0 range.<commit_after>// DXGL
// Copyright (C) 2012 William Feely

// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "common.h"
#include "fog.h"

static DWORD fogcolor = 0;
static GLfloat fogstart = 0;
static GLfloat fogend = 1;
static GLfloat fogdensity = 1;

void SetFogColor(DWORD color)
{
	if(color == fogcolor) return;
	fogcolor = color;
	GLfloat colors[4];
	colors[0] = (GLfloat)((color >> 16) & 255)/255.0f;
	colors[1] = (GLfloat)((color >> 8) & 255)/255.0f;
	colors[2] = (GLfloat)(color & 255)/255.0f;
	colors[3] = (GLfloat)((color >> 24) & 255)/255.0f;
	glFogfv(GL_FOG_COLOR,colors);
}

void SetFogStart(GLfloat start)
{
	if(start == fogstart) return;
	fogstart = start;
	glFogf(GL_FOG_START,start);
}

void SetFogEnd(GLfloat end)
{
	if(end == fogend) return;
	fogend = end;
	glFogf(GL_FOG_END,end);
}

void SetFogDensity(GLfloat density)
{
	if(density == fogdensity) return;
	fogdensity = density;
	glFogf(GL_FOG_DENSITY,density);
}<|endoftext|>


<commit_before>#include <cstring> // memcpy strdup

#include <shoveler.h>

#include "material.h"

extern "C" {
#include <shoveler/view/material.h>
#include <shoveler/log.h>
}

using shoveler::Material;
using shoveler::MaterialType;
using shoveler::Vector2;
using shoveler::Vector3;

static ShovelerComponentMaterialType convertMaterialType(MaterialType type);

void registerMaterialCallbacks(worker::Dispatcher& dispatcher, ShovelerView *view)
{
	dispatcher.OnAddComponent<Material>([&, view](const worker::AddComponentOp<Material>& op) {
		ShovelerViewEntity *entity = shovelerViewGetEntity(view, op.EntityId);

		ShovelerViewMaterialConfiguration configuration;
		configuration.type = convertMaterialType(op.Data.type());

		switch(op.Data.type()) {
            case MaterialType::COLOR: {
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_COLOR;
                Vector3 color = op.Data.color().value_or(Vector3{0, 0, 0});
                configuration.color = shovelerVector3(color.x(), color.y(), color.z());
            } break;
            case MaterialType::TEXTURE:
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_TEXTURE;
                configuration.textureEntityId = *op.Data.texture();
                configuration.textureSamplerEntityId = *op.Data.texture_sampler();
                break;
            case MaterialType::PARTICLE: {
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_PARTICLE;
                Vector3 color = op.Data.color().value_or(Vector3{0, 0, 0});
                configuration.color = shovelerVector3(color.x(), color.y(), color.z());
            } break;
            case MaterialType::TILEMAP:
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_TILEMAP;
                configuration.tilemapEntityId = *op.Data.tilemap();
                break;
            case MaterialType::CANVAS: {
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_CANVAS;
                configuration.canvasEntityId = *op.Data.canvas();

                Vector2 position = op.Data.canvas_region_position().value_or(Vector2{0.0f, 0.0f});
                configuration.canvasRegionPosition = shovelerVector2(position.x(), position.y());
                Vector2 size = op.Data.canvas_region_size().value_or(Vector2{0.0f, 0.0f});
                configuration.canvasRegionSize = shovelerVector2(size.x(), size.y());
            } break;
            case MaterialType::CHUNK:
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_CHUNK;
                configuration.chunkEntityId = *op.Data.chunk();
                break;
		}

		shovelerViewEntityAddMaterial(entity, &configuration);
	});

	dispatcher.OnComponentUpdate<Material>([&, view](const worker::ComponentUpdateOp<Material>& op) {
		ShovelerViewEntity *entity = shovelerViewGetEntity(view, op.EntityId);

		ShovelerViewMaterialConfiguration configuration;
		shovelerViewEntityGetMaterialConfiguration(entity, &configuration);

		if(op.Update.type()) {
			configuration.type = convertMaterialType(*op.Update.type());
		}

        if(op.Update.texture()) {
            configuration.textureEntityId = **op.Update.texture();
        }

        if(op.Update.texture_sampler()) {
            configuration.textureSamplerEntityId = **op.Update.texture_sampler();
        }

        if(op.Update.tilemap()) {
            configuration.tilemapEntityId = **op.Update.tilemap();
        }

        if(op.Update.canvas()) {
            configuration.canvasEntityId = **op.Update.canvas();
        }

        if(op.Update.chunk()) {
            configuration.chunkEntityId = **op.Update.chunk();
        }

		if(op.Update.color()) {
			Vector3 color = op.Update.color()->value_or(Vector3{0, 0, 0});
			configuration.color = shovelerVector3(color.x(), color.y(), color.z());
		}

		if(op.Update.canvas_region_position()) {
			Vector2 position = op.Update.canvas_region_position()->value_or(Vector2{0.0f, 0.0f});
			configuration.canvasRegionPosition = shovelerVector2(position.x(), position.y());
		}

		if(op.Update.canvas_region_size()) {
			Vector2 size = op.Update.canvas_region_size()->value_or(Vector2{0.0f, 0.0f});
			configuration.canvasRegionSize = shovelerVector2(size.x(), size.y());
		}

		shovelerViewEntityUpdateMaterial(entity, &configuration);
	});

	dispatcher.OnRemoveComponent<Material>([&, view](const worker::RemoveComponentOp& op) {
		ShovelerViewEntity *entity = shovelerViewGetEntity(view, op.EntityId);
		shovelerViewEntityRemoveMaterial(entity);
	});
}

static ShovelerComponentMaterialType convertMaterialType(MaterialType type)
{
	switch(type) {
		case MaterialType::COLOR:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_COLOR;
		case MaterialType::TEXTURE:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_TEXTURE;
		case MaterialType::PARTICLE:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_PARTICLE;
		case MaterialType::TILEMAP:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_TILEMAP;
		case MaterialType::CANVAS:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_CANVAS;
		case MaterialType::CHUNK:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_CHUNK;
	}
}
<commit_msg>fixed C++ client material creation<commit_after>#include <cstring> // memcpy strdup

#include <shoveler.h>

#include "material.h"

extern "C" {
#include <shoveler/view/material.h>
#include <shoveler/log.h>
}

using shoveler::Material;
using shoveler::MaterialType;
using shoveler::Vector2;
using shoveler::Vector3;

static ShovelerComponentMaterialType convertMaterialType(MaterialType type);

void registerMaterialCallbacks(worker::Dispatcher& dispatcher, ShovelerView *view)
{
	dispatcher.OnAddComponent<Material>([&, view](const worker::AddComponentOp<Material>& op) {
		ShovelerViewEntity *entity = shovelerViewGetEntity(view, op.EntityId);

		ShovelerViewMaterialConfiguration configuration;
		configuration.type = convertMaterialType(op.Data.type());

		switch(op.Data.type()) {
            case MaterialType::COLOR: {
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_COLOR;
                Vector3 color = op.Data.color().value_or(Vector3{0, 0, 0});
                configuration.color = shovelerVector3(color.x(), color.y(), color.z());
            } break;
            case MaterialType::TEXTURE:
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_TEXTURE;
                configuration.textureEntityId = *op.Data.texture();
                configuration.textureSamplerEntityId = *op.Data.texture_sampler();
                break;
            case MaterialType::PARTICLE: {
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_PARTICLE;
                Vector3 color = op.Data.color().value_or(Vector3{0, 0, 0});
                configuration.color = shovelerVector3(color.x(), color.y(), color.z());
            } break;
            case MaterialType::TILEMAP:
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_TILEMAP;
                configuration.tilemapEntityId = *op.Data.tilemap();
                break;
            case MaterialType::CANVAS: {
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_CANVAS;
                configuration.canvasEntityId = *op.Data.canvas();

                Vector2 position = op.Data.canvas_region_position().value_or(Vector2{0.0f, 0.0f});
                configuration.canvasRegionPosition = shovelerVector2(position.x(), position.y());
                Vector2 size = op.Data.canvas_region_size().value_or(Vector2{0.0f, 0.0f});
                configuration.canvasRegionSize = shovelerVector2(size.x(), size.y());
            } break;
            case MaterialType::CHUNK:
                configuration.type = SHOVELER_COMPONENT_MATERIAL_TYPE_CHUNK;
                configuration.chunkEntityId = *op.Data.chunk();
                break;
		}

		shovelerViewEntityAddMaterial(entity, &configuration);
	});

	dispatcher.OnComponentUpdate<Material>([&, view](const worker::ComponentUpdateOp<Material>& op) {
		ShovelerViewEntity *entity = shovelerViewGetEntity(view, op.EntityId);

		ShovelerViewMaterialConfiguration configuration;
		shovelerViewEntityGetMaterialConfiguration(entity, &configuration);

		if(op.Update.type()) {
			configuration.type = convertMaterialType(*op.Update.type());
		}

        if(op.Update.texture()) {
            configuration.textureEntityId = **op.Update.texture();
        }

        if(op.Update.texture_sampler()) {
            configuration.textureSamplerEntityId = **op.Update.texture_sampler();
        }

        if(op.Update.tilemap()) {
            configuration.tilemapEntityId = **op.Update.tilemap();
        }

        if(op.Update.canvas()) {
            configuration.canvasEntityId = **op.Update.canvas();
        }

        if(op.Update.chunk()) {
            configuration.chunkEntityId = **op.Update.chunk();
        }

		if(op.Update.color()) {
			Vector3 color = op.Update.color()->value_or(Vector3{0, 0, 0});
			configuration.color = shovelerVector3(color.x(), color.y(), color.z());
		}

		if(op.Update.canvas_region_position()) {
			Vector2 position = op.Update.canvas_region_position()->value_or(Vector2{0.0f, 0.0f});
			configuration.canvasRegionPosition = shovelerVector2(position.x(), position.y());
		}

		if(op.Update.canvas_region_size()) {
			Vector2 size = op.Update.canvas_region_size()->value_or(Vector2{0.0f, 0.0f});
			configuration.canvasRegionSize = shovelerVector2(size.x(), size.y());
		}

		shovelerViewEntityUpdateMaterial(entity, &configuration);
	});

	dispatcher.OnRemoveComponent<Material>([&, view](const worker::RemoveComponentOp& op) {
		ShovelerViewEntity *entity = shovelerViewGetEntity(view, op.EntityId);
		shovelerViewEntityRemoveMaterial(entity);
	});
}

static ShovelerComponentMaterialType convertMaterialType(MaterialType type)
{
	switch(type) {
		case MaterialType::COLOR:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_COLOR;
		case MaterialType::TEXTURE:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_TEXTURE;
		case MaterialType::PARTICLE:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_PARTICLE;
		case MaterialType::TILEMAP:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_TILEMAP;
		case MaterialType::CANVAS:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_CANVAS;
		case MaterialType::CHUNK:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_CHUNK;
		case MaterialType::TILE_SPRITE:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_TILE_SPRITE;
		case MaterialType::TEXT:
			return SHOVELER_COMPONENT_MATERIAL_TYPE_TEXT;
	}
}
<|endoftext|>


<commit_before>#ifndef SILICIUM_THREAD_GENERATOR_HPP
#define SILICIUM_THREAD_GENERATOR_HPP

#include <silicium/observable/observer.hpp>
#include <silicium/config.hpp>
#include <silicium/exchange.hpp>
#include <silicium/observable/yield_context.hpp>
#include <future>
#include <boost/thread/future.hpp>
#include <boost/optional.hpp>
#include <boost/concept_check.hpp>

namespace Si
{
	namespace detail
	{
		template <class ThreadingAPI>
		struct event : private observer<nothing>
		{
			event()
				: got_something(false)
			{
			}

			template <class NothingObservable>
			void block(NothingObservable &&blocked_on)
			{
				assert(!got_something);
				blocked_on.async_get_one(observe_by_ref(static_cast<observer<nothing> &>(*this)));
				typename ThreadingAPI::unique_lock lock(got_something_mutex);
				while (!got_something)
				{
					got_something_set.wait(lock);
				}
				got_something = false;
			}

		private:

			typename ThreadingAPI::mutex got_something_mutex;
			typename ThreadingAPI::condition_variable got_something_set;
			bool got_something;

			virtual void got_element(nothing) SILICIUM_OVERRIDE
			{
				wake_get_one();
			}

			virtual void ended() SILICIUM_OVERRIDE
			{
				wake_get_one();
			}

			void wake_get_one()
			{
				typename ThreadingAPI::unique_lock lock(got_something_mutex);
				got_something = true;
				got_something_set.notify_one();
			}
		};
	}

	template <class Element, class ThreadingAPI>
	struct thread_generator_observable
	{
		typedef Element element_type;

		thread_generator_observable()
		{
		}

		template <class Action>
		explicit thread_generator_observable(Action &&action)
			: state(Si::make_unique<state_type>(std::forward<Action>(action)))
		{
		}

#if !SILICIUM_COMPILER_GENERATES_MOVES
		thread_generator_observable(thread_generator_observable &&other) BOOST_NOEXCEPT
			: state(std::move(other.state))
		{
		}

		thread_generator_observable &operator = (thread_generator_observable &&other) BOOST_NOEXCEPT
		{
			state = std::move(other.state);
			return *this;
		}
#endif

		void wait()
		{
			return state->wait();
		}

		void async_get_one(ptr_observer<observer<element_type>> receiver)
		{
			return state->async_get_one(receiver);
		}

	private:

		struct state_type : private detail::push_context_impl<Element>
		{
			template <class Action>
			explicit state_type(Action &&action)
				: receiver(nullptr)
				, has_ended(false)
			{
				worker = ThreadingAPI::launch_async([action, this]() mutable
				{
					push_context<Element> yield(*this);
					(std::forward<Action>(action))(yield);

					typename ThreadingAPI::unique_lock lock(receiver_mutex);
					if (receiver)
					{
						auto receiver_ = Si::exchange(receiver, nullptr);
						lock.unlock();
						receiver_->ended();
					}
					else
					{
						has_ended = true;
					}
				});
			}

			void async_get_one(ptr_observer<observer<element_type>> new_receiver)
			{
				typename ThreadingAPI::unique_lock lock(receiver_mutex);
				assert(!receiver);
				if (ready_result)
				{
					Element result = std::move(*ready_result);
					ready_result = boost::none;
					receiver_ready.notify_one();
					lock.unlock();
					new_receiver.get()->got_element(std::move(result));
				}
				else
				{
					if (has_ended)
					{
						return new_receiver.get()->ended();
					}
					receiver = new_receiver.get();
					receiver_ready.notify_one();
				}
			}

			void wait()
			{
				worker.get();
			}

		private:

			typename ThreadingAPI::template future<void>::type worker;
			typename ThreadingAPI::mutex receiver_mutex;
			observer<Element> *receiver;
			boost::optional<Element> ready_result;
			typename ThreadingAPI::condition_variable receiver_ready;
			bool has_ended;

			detail::event<ThreadingAPI> got_something;

			virtual void push_result(Element result) SILICIUM_OVERRIDE
			{
				typename ThreadingAPI::unique_lock lock(receiver_mutex);
				while (ready_result && !receiver)
				{
					receiver_ready.wait(lock);
				}
				if (receiver)
				{
					auto * const receiver_ = Si::exchange(receiver, nullptr);
					lock.unlock();
					receiver_->got_element(std::move(result));
				}
				else
				{
					ready_result = std::move(result);
				}
			}

			virtual void get_one(observable<nothing, ptr_observer<observer<nothing>>> &target) SILICIUM_OVERRIDE
			{
				got_something.block(target);
			}
		};

		std::unique_ptr<state_type> state;
	};

	template <class Element, class ThreadingAPI, class Action>
	auto make_thread_generator(Action &&action) -> thread_generator_observable<Element, ThreadingAPI>
	{
		return thread_generator_observable<Element, ThreadingAPI>(std::forward<Action>(action));
	}
}

#endif
<commit_msg>thread_generator works with owning observers<commit_after>#ifndef SILICIUM_THREAD_GENERATOR_HPP
#define SILICIUM_THREAD_GENERATOR_HPP

#include <silicium/observable/observer.hpp>
#include <silicium/config.hpp>
#include <silicium/exchange.hpp>
#include <silicium/observable/yield_context.hpp>
#include <silicium/observable/erased_observer.hpp>
#include <future>
#include <boost/thread/future.hpp>
#include <boost/optional.hpp>
#include <boost/concept_check.hpp>

namespace Si
{
	namespace detail
	{
		template <class ThreadingAPI>
		struct event : private observer<nothing>
		{
			event()
				: got_something(false)
			{
			}

			template <class NothingObservable>
			void block(NothingObservable &&blocked_on)
			{
				assert(!got_something);
				blocked_on.async_get_one(observe_by_ref(static_cast<observer<nothing> &>(*this)));
				typename ThreadingAPI::unique_lock lock(got_something_mutex);
				while (!got_something)
				{
					got_something_set.wait(lock);
				}
				got_something = false;
			}

		private:

			typename ThreadingAPI::mutex got_something_mutex;
			typename ThreadingAPI::condition_variable got_something_set;
			bool got_something;

			virtual void got_element(nothing) SILICIUM_OVERRIDE
			{
				wake_get_one();
			}

			virtual void ended() SILICIUM_OVERRIDE
			{
				wake_get_one();
			}

			void wake_get_one()
			{
				typename ThreadingAPI::unique_lock lock(got_something_mutex);
				got_something = true;
				got_something_set.notify_one();
			}
		};
	}

	template <class Element, class ThreadingAPI>
	struct thread_generator_observable
	{
		typedef Element element_type;

		thread_generator_observable()
		{
		}

		template <class Action>
		explicit thread_generator_observable(Action &&action)
			: state(Si::make_unique<state_type>(std::forward<Action>(action)))
		{
		}

#if !SILICIUM_COMPILER_GENERATES_MOVES
		thread_generator_observable(thread_generator_observable &&other) BOOST_NOEXCEPT
			: state(std::move(other.state))
		{
		}

		thread_generator_observable &operator = (thread_generator_observable &&other) BOOST_NOEXCEPT
		{
			state = std::move(other.state);
			return *this;
		}
#endif

		void wait()
		{
			return state->wait();
		}

		template <class Observer>
		void async_get_one(Observer &&receiver)
		{
			return state->async_get_one(std::forward<Observer>(receiver));
		}

	private:

		struct state_type : private detail::push_context_impl<Element>
		{
			template <class Action>
			explicit state_type(Action &&action)
				: has_ended(false)
			{
				worker = ThreadingAPI::launch_async([action, this]() mutable
				{
					push_context<Element> yield(*this);
					(std::forward<Action>(action))(yield);

					typename ThreadingAPI::unique_lock lock(receiver_mutex);
					if (receiver.get())
					{
						auto receiver_ = Si::exchange(receiver, erased_observer<Element>());
						lock.unlock();
						std::move(receiver_).ended();
					}
					else
					{
						has_ended = true;
					}
				});
			}

			template <class Observer>
			void async_get_one(Observer &&new_receiver)
			{
				typename ThreadingAPI::unique_lock lock(receiver_mutex);
				if (ready_result)
				{
					Element result = std::move(*ready_result);
					ready_result = boost::none;
					receiver_ready.notify_one();
					lock.unlock();
					std::forward<Observer>(new_receiver).got_element(std::move(result));
				}
				else
				{
					if (has_ended)
					{
						return std::forward<Observer>(new_receiver).ended();
					}
					receiver = erased_observer<Element>(std::forward<Observer>(new_receiver));
					receiver_ready.notify_one();
				}
			}

			void wait()
			{
				worker.get();
			}

		private:

			typename ThreadingAPI::template future<void>::type worker;
			typename ThreadingAPI::mutex receiver_mutex;
			erased_observer<Element> receiver;
			boost::optional<Element> ready_result;
			typename ThreadingAPI::condition_variable receiver_ready;
			bool has_ended;

			detail::event<ThreadingAPI> got_something;

			virtual void push_result(Element result) SILICIUM_OVERRIDE
			{
				typename ThreadingAPI::unique_lock lock(receiver_mutex);
				while (ready_result && !receiver.get())
				{
					receiver_ready.wait(lock);
				}
				if (receiver.get())
				{
					auto receiver_ = Si::exchange(receiver, erased_observer<Element>());
					lock.unlock();
					std::move(receiver_).got_element(std::move(result));
				}
				else
				{
					ready_result = std::move(result);
				}
			}

			virtual void get_one(observable<nothing, ptr_observer<observer<nothing>>> &target) SILICIUM_OVERRIDE
			{
				got_something.block(target);
			}
		};

		std::unique_ptr<state_type> state;
	};

	template <class Element, class ThreadingAPI, class Action>
	auto make_thread_generator(Action &&action) -> thread_generator_observable<Element, ThreadingAPI>
	{
		return thread_generator_observable<Element, ThreadingAPI>(std::forward<Action>(action));
	}
}

#endif
<|endoftext|>


<commit_before>//
// Created by dar on 11/24/15.
//

#include <GLES3/gl3.h>
#include "Fbo.h"

Fbo::~Fbo() {
    glDeleteTextures(1, &this->fbo_texture);
    glDeleteBuffers(1, &texture_vertices);
    glDeleteVertexArrays(1, &vaoId);
    glDeleteFramebuffers(1, &this->id);
}

unsigned char Fbo::initShader() {
    unsigned char errCode = 0;
    if (!vert_shader.load(this->shaderName + ".vert", GL_VERTEX_SHADER)) errCode |= 1 << 0;
    if (!frag_shader.load(this->shaderName + ".frag", GL_FRAGMENT_SHADER)) errCode |= 1 << 1;
    this->shader_program.createProgram();
    if (!this->shader_program.addShaderToProgram(&vert_shader)) errCode |= 1 << 2;
    if (!this->shader_program.addShaderToProgram(&frag_shader)) errCode |= 1 << 3;

    if (!this->shader_program.linkProgram()) errCode |= 1 << 4;
    this->shader_program.useProgram();

    GLint tmp_uniform_location = glGetUniformLocation(shader_program.getProgramID(), "fbo_texture");
    if (tmp_uniform_location < 0) errCode |= 1 << 5;
    this->shader_tex_uniform = (GLuint) glGetUniformLocation(shader_program.getProgramID(), "fbo_texture");
    return errCode;
}

int Fbo::init(int texId, unsigned int width, unsigned int height, float bgColor[], string shaderName) {
    this->texId = texId;
    this->width = width;
    this->height = height;
    this->bgColor = bgColor;
    this->shaderName = shaderName;

    unsigned char shaderRet = this->initShader();
    if (shaderRet != 0) {
        return shaderRet;
    }

    glActiveTexture(GL_TEXTURE0);
    glGenTextures(1, &this->fbo_texture);
    glBindTexture(GL_TEXTURE_2D, this->fbo_texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->width, this->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glBindTexture(GL_TEXTURE_2D, 0);

    glGenFramebuffers(1, &this->id);
    glBindFramebuffer(GL_FRAMEBUFFER, this->id);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->fbo_texture, 0);
    GLenum status = (GLenum) (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    return status;
}

void Fbo::resize(unsigned int width, unsigned int height) {
    this->width = width;
    this->height = height;
    glBindTexture(GL_TEXTURE_2D, this->fbo_texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->width, this->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glBindTexture(GL_TEXTURE_2D, 0);
}

void Fbo::bind() {
    glBindFramebuffer(GL_FRAMEBUFFER, this->id);
}

void Fbo::unbind() {
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void Fbo::render(GLuint renderTo) {
    glBindFramebuffer(GL_FRAMEBUFFER, renderTo);
    glClearColor(this->bgColor[0], this->bgColor[1], this->bgColor[2], this->bgColor[3]);
    glClear(GL_COLOR_BUFFER_BIT);

    shader_program.useProgram();
    shader_program.setUniform("uResolution", glm::vec2(this->width, this->height));
    glActiveTexture(GL_TEXTURE0 + this->texId);
    glBindTexture(GL_TEXTURE_2D, this->fbo_texture);
    glUniform1i(this->shader_tex_uniform, /*GL_TEXTURE*/ this->texId);
    glBindVertexArray(vaoId);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindVertexArray(0);
}

void initTexData() {
    glGenVertexArrays(1, &vaoId);
    glGenBuffers(1, &texture_vertices);

    GLfloat fbo_vertices[] = {
            -1.0f, 1.0f,
            -1.0f, -1.0f,
            1.0f, 1.0f,
            1.0f, -1.0f,
    };

    glBindVertexArray(vaoId);
    glBindBuffer(GL_ARRAY_BUFFER, texture_vertices);
    glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float), fbo_vertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray((GLuint) 0);
    glVertexAttribPointer((GLuint) 0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glBindVertexArray(0);
}<commit_msg>Change init method return status<commit_after>//
// Created by dar on 11/24/15.
//

#include <GLES3/gl3.h>
#include "Fbo.h"

Fbo::~Fbo() {
    glDeleteTextures(1, &this->fbo_texture);
    glDeleteBuffers(1, &texture_vertices);
    glDeleteVertexArrays(1, &vaoId);
    glDeleteFramebuffers(1, &this->id);
}

unsigned char Fbo::initShader() {
    unsigned char errCode = 0;
    if (!vert_shader.load(this->shaderName + ".vert", GL_VERTEX_SHADER)) errCode |= 1 << 0;
    if (!frag_shader.load(this->shaderName + ".frag", GL_FRAGMENT_SHADER)) errCode |= 1 << 1;
    this->shader_program.createProgram();
    if (!this->shader_program.addShaderToProgram(&vert_shader)) errCode |= 1 << 2;
    if (!this->shader_program.addShaderToProgram(&frag_shader)) errCode |= 1 << 3;

    if (!this->shader_program.linkProgram()) errCode |= 1 << 4;
    this->shader_program.useProgram();

    GLint tmp_uniform_location = glGetUniformLocation(shader_program.getProgramID(), "fbo_texture");
    if (tmp_uniform_location < 0) errCode |= 1 << 5;
    this->shader_tex_uniform = (GLuint) glGetUniformLocation(shader_program.getProgramID(), "fbo_texture");
    return errCode;
}

int Fbo::init(int texId, unsigned int width, unsigned int height, float bgColor[], string shaderName) {
    this->texId = texId;
    this->width = width;
    this->height = height;
    this->bgColor = bgColor;
    this->shaderName = shaderName;

    unsigned char shaderRet = this->initShader();
    if (shaderRet != 0) {
        return shaderRet;
    }

    glActiveTexture(GL_TEXTURE0);
    glGenTextures(1, &this->fbo_texture);
    glBindTexture(GL_TEXTURE_2D, this->fbo_texture);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->width, this->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glBindTexture(GL_TEXTURE_2D, 0);

    glGenFramebuffers(1, &this->id);
    glBindFramebuffer(GL_FRAMEBUFFER, this->id);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->fbo_texture, 0);
    GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);

    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    return status;
}

void Fbo::resize(unsigned int width, unsigned int height) {
    this->width = width;
    this->height = height;
    glBindTexture(GL_TEXTURE_2D, this->fbo_texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, this->width, this->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
    glBindTexture(GL_TEXTURE_2D, 0);
}

void Fbo::bind() {
    glBindFramebuffer(GL_FRAMEBUFFER, this->id);
}

void Fbo::unbind() {
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void Fbo::render(GLuint renderTo) {
    glBindFramebuffer(GL_FRAMEBUFFER, renderTo);
    glClearColor(this->bgColor[0], this->bgColor[1], this->bgColor[2], this->bgColor[3]);
    glClear(GL_COLOR_BUFFER_BIT);

    shader_program.useProgram();
    shader_program.setUniform("uResolution", glm::vec2(this->width, this->height));
    glActiveTexture(GL_TEXTURE0 + this->texId);
    glBindTexture(GL_TEXTURE_2D, this->fbo_texture);
    glUniform1i(this->shader_tex_uniform, /*GL_TEXTURE*/ this->texId);
    glBindVertexArray(vaoId);
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    glBindTexture(GL_TEXTURE_2D, 0);
    glBindVertexArray(0);
}

void initTexData() {
    glGenVertexArrays(1, &vaoId);
    glGenBuffers(1, &texture_vertices);

    GLfloat fbo_vertices[] = {
            -1.0f, 1.0f,
            -1.0f, -1.0f,
            1.0f, 1.0f,
            1.0f, -1.0f,
    };

    glBindVertexArray(vaoId);
    glBindBuffer(GL_ARRAY_BUFFER, texture_vertices);
    glBufferData(GL_ARRAY_BUFFER, 4 * 2 * sizeof(float), fbo_vertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray((GLuint) 0);
    glVertexAttribPointer((GLuint) 0, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glBindVertexArray(0);
}<|endoftext|>


<commit_before>#include "agn_frac.h"
#include "lumfunct.h"

agn_frac::agn_frac(int agn_types){
  if(agn_types <= 1){
    _types=1;
    generate=false;
    printf("No AGN Detected\n");
  }
  else{
    _types=2;
    generate=true;
  }
  lf=NULL;
}

void agn_frac::set_lumfunct(lumfunct *lf){
  if(lf != NULL){
    this->lf = lf;
  }
  else
    cout << "ERROR: NULL Pointer Passed to Simulator" << endl;
}
//Fraction of galaxies as a function of luminosity and redshift that are AGN (note ALL AGN including obscured and unobscured, can try to sub-divide at some future point.
double agn_frac::get_agn_frac(double lum, double redshift){

  map <tuple<double,double>,double> values;
  tuple<double,double> point(lum,redshift);

  if(values.count(point) == 0){
    printf("Initializing AGN_FRAC %f %f\n",lum,redshift);
    //the Chen,Hickox et al. 2013 relation between average(Log(Lx)) and Log(Lir)
    //here Lx is in ergs/s while lum (i.e. Lir) is in Lsun;
    float av_lglx=30.37+1.05*lum;

    //the Lutz et al. 2004 relation between Log(Lx) and Log(L6um) for Seybert 1s
    //both luminosities as in ergs/s;
    float av_lgl6um=av_lglx-0.41;

    //the average lgl6 to lg(Lagn_ir) conversion including converting to Lsun
    // for now a placeholder only, will need to calculate properly
    float av_lgAGNir=av_lgl6um-7-26-log10(3.86)+0.4;

  //the logic here is that if the average Lir_agn is comparable to the Lir of the given bin, essentially 100% of the galaxies are AGN and scales from there. With the Chen+13 relation, we end up with fairly low AGN fractions even at the highest luminosities.
    values[point]= pow(10,(av_lgAGNir-lum));
  }

  return values[point];
}

//here agntype = 0 (all agn) or 1 or 2 (includes Type 2 and reddened Type 1)
double agn_frac::get_agn_frac2(double lum, double redshift, int agntype){

    //Using the quasar LFs from Lacy et al. 2015, note that lum,lstar0,lstar, and phistar are all given in log_10
    //note the luminosities in that paper are given in terms of the 5um monochromatic restframe luminosity [ergs*Hz]

    float phistar,lstar0,gamma1,gamma2,k1,k2,k3;

    if (agntype == 0){
      phistar=-4.75;
      gamma1=1.07;
      gamma2=2.48;
      lstar0=31.92;
      k1=1.05;
      k2=-4.71;
      k3=-0.034;
    }

    if (agntype == 1){
      phistar=-5.18;
      gamma1=0.25;
      gamma2=2.68;
      lstar0=31.99;
      k1=0.537;
      k2=-5.48;
      k3=0.768;
    }

    if (agntype == 2){
      phistar=-4.98;
      gamma1=1.09;
      gamma2=2.61;
      lstar0=31.91;
      k1=1.165;
      k2=-4.45;
      k3=-0.23;
    }

    float eps=log10((1+redshift)/(1+2.5));
    float lstar=lstar0+k1*eps+k2*pow(eps,2)+k3*pow(eps,3);

    //the average lgl6 to lg(Lagn_ir) conversion including converting to Lsun
    // for now a placeholder only, will need to calculate properly
    float lum5um=lum+7+26+log10(3.86)-0.4;

    float denom=pow(pow(10,lum5um)/pow(10,lstar),gamma1)+pow(pow(10,lum5um)/pow(10,lstar),gamma2);
    float phi=pow(10,phistar)/denom;

    float phi_all,fagn;
    phi_all = lf->get_nsrcs(redshift,lum);

    //the AGN fraction is the ratio of AGN Luminosity Function computed here and the overall luminosity function (from lumfunc.cpp), ensure that this does not exceed 100%

    fagn=pow(10,(phi-phi_all));
    if (fagn > 1)
      fagn=1.0;

    return fagn;

}

int agn_frac::get_sedtype(double lum, double redshift){
  if(generate)
    return get_agn_frac(lum,redshift) > rng.flat(0,1) ? 0 : 1;
  else
    return 0;
}
<commit_msg>fixed bug in agn_frac<commit_after>#include "agn_frac.h"
#include "lumfunct.h"

agn_frac::agn_frac(int agn_types){
  if(agn_types <= 1){
    _types=1;
    generate=false;
    printf("No AGN Detected\n");
  }
  else{
    _types=2;
    generate=true;
  }
  lf=NULL;
}

void agn_frac::set_lumfunct(lumfunct *lf){
  if(lf != NULL){
    this->lf = lf;
  }
  else
    cout << "ERROR: NULL Pointer Passed to Simulator" << endl;
}
//Fraction of galaxies as a function of luminosity and redshift that are AGN (note ALL AGN including obscured and unobscured, can try to sub-divide at some future point.
double agn_frac::get_agn_frac(double lum, double redshift){

  map <tuple<double,double>,double> values;
  tuple<double,double> point(lum,redshift);

  if(values.count(point) == 0){
    printf("Initializing AGN_FRAC %f %f\n",lum,redshift);
    //the Chen,Hickox et al. 2013 relation between average(Log(Lx)) and Log(Lir)
    //here Lx is in ergs/s while lum (i.e. Lir) is in Lsun;
    float av_lglx=30.37+1.05*lum;

    //the Lutz et al. 2004 relation between Log(Lx) and Log(L6um) for Seybert 1s
    //both luminosities as in ergs/s;
    float av_lgl6um=av_lglx-0.41;

    //the average lgl6 to lg(Lagn_ir) conversion including converting to Lsun
    // for now a placeholder only, will need to calculate properly
    float av_lgAGNir=av_lgl6um-7-26-log10(3.86)+0.4;

  //the logic here is that if the average Lir_agn is comparable to the Lir of the given bin, essentially 100% of the galaxies are AGN and scales from there. With the Chen+13 relation, we end up with fairly low AGN fractions even at the highest luminosities.
    values[point]= pow(10,(av_lgAGNir-lum));
  }

  return values[point];
}

//here agntype = 0 (all agn) or 1 or 2 (includes Type 2 and reddened Type 1)
double agn_frac::get_agn_frac2(double lum, double redshift, int agntype){

    //Using the quasar LFs from Lacy et al. 2015, note that lum,lstar0,lstar, and phistar are all given in log_10
    //note the luminosities in that paper are given in terms of the 5um monochromatic restframe luminosity [ergs*Hz]

    float phistar,lstar0,gamma1,gamma2,k1,k2,k3;

    if (agntype == 0){
      phistar=-4.75;
      gamma1=1.07;
      gamma2=2.48;
      lstar0=31.92;
      k1=1.05;
      k2=-4.71;
      k3=-0.034;
    }

    if (agntype == 1){
      phistar=-5.18;
      gamma1=0.25;
      gamma2=2.68;
      lstar0=31.99;
      k1=0.537;
      k2=-5.48;
      k3=0.768;
    }

    if (agntype == 2){
      phistar=-4.98;
      gamma1=1.09;
      gamma2=2.61;
      lstar0=31.91;
      k1=1.165;
      k2=-4.45;
      k3=-0.23;
    }

    float eps=log10((1+redshift)/(1+2.5));
    float lstar=lstar0+k1*eps+k2*pow(eps,2)+k3*pow(eps,3);

    //the lgl5 [ergs/Hz] to lgLagn_ir [Lsun] conversion
    float lum5um=lum+33+log10(3.86)-13.7782-0.48;

    float denom=pow(pow(10,lum5um)/pow(10,lstar),gamma1)+pow(pow(10,lum5um)/pow(10,lstar),gamma2);
    float phi=pow(10,phistar)/denom;

    float phi_all,fagn;
    phi_all = lf->get_nsrcs(redshift,lum);

    //the AGN fraction is the ratio of AGN Luminosity Function computed here and the overall luminosity function (from lumfunc.cpp), ensure that this does not exceed 100%

    fagn=pow(10,(phi-phi_all));
    if (fagn > 1)
      fagn=1.0;

    return fagn;

}

int agn_frac::get_sedtype(double lum, double redshift){
  if(generate)
    return get_agn_frac(lum,redshift) > rng.flat(0,1) ? 0 : 1;
  else
    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>
#include "../inc/Frisk.h"
#include "../inc/ConsoleReporter.h"

int mult(int x, int y) { return x * y; }

DEF_TEST(mult_test)
{
  BEGIN_TEST(self);

  self.setOption(FRISK_OPTION_CONTINUE, true);

  EXPECT_EQUAL(self, mult(0, 0), 0, "0 times anything should be 0");
  EXPECT_EQUAL(self, mult(0, 5), 0, "0 times anything should be 0");
  EXPECT_EQUAL(self, mult(5, 0), 0, "0 times anything should be 0");
  EXPECT_EQUAL(self, mult(1, 5), 5, "1 times anything is itself");
  EXPECT_EQUAL(self, mult(5, 1), 5, "1 times anything is itself");
  EXPECT_EQUAL(self, mult(5, 5), 25, "5 times itself is its square");
  EXPECT_EQUAL(self, mult(1, -5), -5, "1 times a negative number is that negative number");
  EXPECT_EQUAL(self, mult(-5, 1), -5, "1 times a negative number is that negative number");
  EXPECT_GREATER(self, mult(-5, -5), 0, "Two negatives mutlipled should be positive.");
  EXPECT_LESS(self, mult(-5, 5), 0, "One negative times one positive should be negative.");
}

class myClass
{
public:
  DEF_TEST(myTest)
  {
    BEGIN_TEST(self);
    EXPECT_EQUAL(self, 10, 25, "should be equal!");
  }
};

int main()
{
	Frisk::TestCollection tests;
  tests.addTest(mult_test, "mult_test");
  tests.addTest(myClass::myTest, "myClass::myTest");

	Frisk::ConsoleReporter reporter;
  reporter.setOption("description", true);
	std::list<Frisk::Test> results = tests.runTests(false, &reporter);

	return 1;
}
<commit_msg>updated demo test<commit_after>#include <iostream>
#include "../inc/Frisk.h"
#include "../inc/ConsoleReporter.h"

int mult(int x, int y) { return x * y; }

DEF_TEST(mult_test)
{
  BEGIN_TEST(self);

  self.setOption(FRISK_OPTION_CONTINUE, true);

  EXPECT_EQUAL(self, mult(0, 0), 0, "0 times anything should be 0");
  EXPECT_EQUAL(self, mult(0, 5), 0, "0 times anything should be 0");
  EXPECT_EQUAL(self, mult(5, 0), 0, "0 times anything should be 0");
  EXPECT_EQUAL(self, mult(1, 5), 5, "1 times anything is itself");
  EXPECT_EQUAL(self, mult(5, 1), 5, "1 times anything is itself");
  EXPECT_EQUAL(self, mult(5, 5), 25, "5 times itself is its square");
  EXPECT_EQUAL(self, mult(1, -5), -5, "1 times a negative number is that negative number");
  EXPECT_EQUAL(self, mult(-5, 1), -5, "1 times a negative number is that negative number");
  EXPECT_GREATER(self, mult(-5, -5), 0, "Two negatives mutlipled should be positive.");
  EXPECT_LESS(self, mult(-5, 5), 0, "One negative times one positive should be negative.");
}

int main()
{
	Frisk::TestCollection tests;
  tests.addTest(mult_test, "mult_test");

	Frisk::ConsoleReporter reporter;
  reporter.setOption("description", true);
	std::list<Frisk::Test> results = tests.runTests(false, &reporter);

	return 1;
}
<|endoftext|>


<commit_before>#include "OpenGL.h"
#include "window.h"
#include "screenrenderer.h"
#include "scenemanager.h"
#include "transformation.h"
#include "KeyboardTransformation.h"
#include "animatedtransformation.h"
#include "interpolatedrotation.h"
#include "controllablecamera.h"
#include "color.h"

#include "ui_dockwidget.h"

Node *initScene1();

void SceneManager::initScenes()
{
    Ui_FPSWidget *lDock;
    QDockWidget *lDockWidget = new QDockWidget(QString("FPS"), SceneManager::getMainWindow());

    ControllableCamera *cam = new ControllableCamera();
    RenderingContext *myContext=new RenderingContext(cam);
    unsigned int myContextNr = SceneManager::instance()->addContext(myContext);
    unsigned int myScene = SceneManager::instance()->addScene(initScene1());
    ScreenRenderer *myRenderer = new ScreenRenderer(myContextNr, myScene);

    //Vorsicht: Die Szene muss initialisiert sein, bevor das Fenster verändert wird (Fullscreen)
    SceneManager::instance()->setActiveScene(myScene);
    SceneManager::instance()->setActiveContext(myContextNr);
//    SceneManager::instance()->setFullScreen();

    lDock = new Ui_FPSWidget();
    lDock->setupUi(lDockWidget);
    lDockWidget->resize(200,100);
    SceneManager::getMainWindow()->addDockWidget(Qt::RightDockWidgetArea, lDockWidget);
    lDockWidget->show();
    QObject::connect(Window::getInstance(), SIGNAL(sigFPS(int)), lDock->lcdNumber, SLOT(display(int)));
}

Node *initScene1()
{
    Node* sonnensystem = new Node();

    return sonnensystem;
}
<commit_msg>fps dock aus main window rausgenommen<commit_after>#include "OpenGL.h"
#include "window.h"
#include "screenrenderer.h"
#include "scenemanager.h"
#include "transformation.h"
#include "KeyboardTransformation.h"
#include "animatedtransformation.h"
#include "interpolatedrotation.h"
#include "controllablecamera.h"
#include "color.h"

#include "ui_dockwidget.h"

Node* initHalbzeitScene();

void SceneManager::initScenes()
{
    //Ui_FPSWidget *lDock;
    //QDockWidget *lDockWidget = new QDockWidget(QString("FPS"), SceneManager::getMainWindow());

    ControllableCamera *cam = new ControllableCamera();
    RenderingContext *myContext=new RenderingContext(cam);
    unsigned int myContextNr = SceneManager::instance()->addContext(myContext);
    unsigned int myScene = SceneManager::instance()->addScene(initHalbzeitScene());
    ScreenRenderer *myRenderer = new ScreenRenderer(myContextNr, myScene);
    Q_UNUSED(myRenderer)

    //Vorsicht: Die Szene muss initialisiert sein, bevor das Fenster verändert wird (Fullscreen)
    SceneManager::instance()->setActiveScene(myScene);
    SceneManager::instance()->setActiveContext(myContextNr);
//    SceneManager::instance()->setFullScreen();

    // Hab mir angeschaut wie man evtl die doofen ränder wegbekommt. Das ui Element was hier
    // ist das Widget was angezeit wird im MainWindow. Definiert wird das ganze in der Datei
    // glwithwidgets.ui im FrameworkSource und evtl kann es über die variable noch ein bisschen
    // konfiguriert werden ohne das man den kompletten Szenegraphen rekompiliert
    Ui::GLwithWidgets* ui = MainWindow::getUi();
    Q_UNUSED(ui)

//    lDock = new Ui_FPSWidget();
//    lDock->setupUi(lDockWidget);
//    lDockWidget->resize(200,100);
//    SceneManager::getMainWindow()->addDockWidget(Qt::RightDockWidgetArea, lDockWidget);
//    lDockWidget->show();
//    QObject::connect(Window::getInstance(), SIGNAL(sigFPS(int)), lDock->lcdNumber, SLOT(display(int)));
}

Node *initHalbzeitScene()
{
    Node* sonnensystem = new Node();

    return sonnensystem;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2004 The Apache Software Foundation.
 *
 * Licensed 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * imitations under the License.
 */

/*
 * XSEC
 *
 * XSECSOAPRequestorSimple := (Very) Basic implementation of a SOAP
 *                         HTTP wrapper for testing the client code.
 *
 *
 * $Id$
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>

#include <xsec/utils/XSECSOAPRequestorSimple.hpp>
#include <xsec/utils/XSECSafeBuffer.hpp>
#include <xsec/framework/XSECError.hpp>

#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/XMLNetAccessor.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/XMLUniDefs.hpp>

XERCES_CPP_NAMESPACE_USE

// --------------------------------------------------------------------------------
//           Platform specific constructor
// --------------------------------------------------------------------------------

XSECSOAPRequestorSimple::XSECSOAPRequestorSimple(const XMLCh * uri) : m_uri(uri) {

}

// --------------------------------------------------------------------------------
//           Interface
// --------------------------------------------------------------------------------

DOMDocument * XSECSOAPRequestorSimple::doRequest(DOMDocument * request) {

	char * content = wrapAndSerialise(request);

	// First we need to serialise

    char                fBuffer[4000];
    char *              fBufferEnd;
    char *              fBufferPos;

    //
    // Pull all of the parts of the URL out of th m_uri object, and transcode them
    //   and transcode them back to ASCII.
    //
    const XMLCh*        hostName = m_uri.getHost();
    char*               hostNameAsCharStar = XMLString::transcode(hostName);
    ArrayJanitor<char>  janBuf1(hostNameAsCharStar);

    const XMLCh*        path = m_uri.getPath();
    char*               pathAsCharStar = XMLString::transcode(path);
    ArrayJanitor<char>  janBuf2(pathAsCharStar);

    const XMLCh*        fragment = m_uri.getFragment();
    char*               fragmentAsCharStar = 0;
    if (fragment)
        fragmentAsCharStar = XMLString::transcode(fragment);
    ArrayJanitor<char>  janBuf3(fragmentAsCharStar);

    const XMLCh*        query = m_uri.getQueryString();
    char*               queryAsCharStar = 0;
    if (query)
        queryAsCharStar = XMLString::transcode(query);
    ArrayJanitor<char>  janBuf4(queryAsCharStar);

    unsigned short      portNumber = (unsigned short) m_uri.getPort();

	// If no number is set, go with port 80
	if (portNumber == USHRT_MAX)
		portNumber = 80;

    //
    // Set up a socket.
    //
    struct hostent*     hostEntPtr = 0;
    struct sockaddr_in  sa;

    if ((hostEntPtr = gethostbyname(hostNameAsCharStar)) == NULL)
    {
        unsigned long  numAddress = inet_addr(hostNameAsCharStar);
        if (numAddress == 0)
        {
            ThrowXML(NetAccessorException,
                     XMLExcepts::NetAcc_TargetResolution);
        }
        if ((hostEntPtr =
                gethostbyaddr((char *) &numAddress,
                              sizeof(unsigned long), AF_INET)) == NULL)
        {
            ThrowXML(NetAccessorException,
                     XMLExcepts::NetAcc_TargetResolution);
        }
    }

    memcpy((void *) &sa.sin_addr,
           (const void *) hostEntPtr->h_addr, hostEntPtr->h_length);
    sa.sin_family = hostEntPtr->h_addrtype;
    sa.sin_port = htons(portNumber);

    int s = socket(hostEntPtr->h_addrtype, SOCK_STREAM, 0);
    if (s < 0)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error creating socket");

    }

    if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error connecting to end server");
    }

    // The port is open and ready to go.
    // Build up the http GET command to send to the server.
    // To do:  We should really support http 1.1.  This implementation
    //         is weak.

    memset(fBuffer, 0, sizeof(fBuffer));

    strcpy(fBuffer, "POST ");
    strcat(fBuffer, pathAsCharStar);

    if (queryAsCharStar != 0)
    {
        // Tack on a ? before the fragment
        strcat(fBuffer,"?");
        strcat(fBuffer, queryAsCharStar);
    }

    if (fragmentAsCharStar != 0)
    {
        strcat(fBuffer, fragmentAsCharStar);
    }
    strcat(fBuffer, " HTTP/1.0\r\n");

	strcat(fBuffer, "Content-Type: text/xml; charset=utf-8\r\n");

    strcat(fBuffer, "Host: ");
    strcat(fBuffer, hostNameAsCharStar);
    if (portNumber != 80)
    {
        int i = strlen(fBuffer);
		sprintf(fBuffer+i, ":%d", portNumber);
    }
	strcat(fBuffer, "\r\n");

	strcat(fBuffer, "Content-Length: ");
    int i = (int) strlen(fBuffer);
	sprintf(fBuffer+i, "%d", strlen(content));
	strcat(fBuffer, "\r\n");
	strcat(fBuffer, "SOAPAction: \"\"\r\n");

/*	strcat(fBuffer, "Connection: Close\r\n");
	strcat(fBuffer, "Cache-Control: no-cache\r\n");*/
    strcat(fBuffer, "\r\n");

	// Now the content
	strcat(fBuffer, content);

    // Send the http request
    int lent = strlen(fBuffer);
    int  aLent = 0;
    if ((aLent = write(s, (void *) fBuffer, lent)) != lent)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error writing to socket");
    }

    //
    // get the response, check the http header for errors from the server.
    //
    aLent = read(s, (void *)fBuffer, sizeof(fBuffer)-1);
	/*
	fBuffer[aLent] = '\0';
	printf(fBuffer);
	*/
    if (aLent <= 0)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error reported reading socket");
    }

    fBufferEnd = fBuffer+aLent;
    *fBufferEnd = 0;

    // Find the break between the returned http header and any data.
    //  (Delimited by a blank line)
    // Hang on to any data for use by the first read from this BinHTTPURLInputStream.
    //
    fBufferPos = strstr(fBuffer, "\r\n\r\n");
    if (fBufferPos != 0)
    {
        fBufferPos += 4;
        *(fBufferPos-2) = 0;
    }
    else
    {
        fBufferPos = strstr(fBuffer, "\n\n");
        if (fBufferPos != 0)
        {
            fBufferPos += 2;
            *(fBufferPos-1) = 0;
        }
        else
            fBufferPos = fBufferEnd;
    }

    // Make sure the header includes an HTTP 200 OK response.
    //
    char *p = strstr(fBuffer, "HTTP");
    if (p == 0)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error reported reading socket");
    }

    p = strchr(p, ' ');
    if (p == 0)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error reported reading socket");
    }

    int httpResponse = atoi(p);

	if (httpResponse == 302 || httpResponse == 301) {
		//Once grows, should use a switch
		char redirectBuf[256];
		int q;

		// Find the "Location:" string
		p = strstr(p, "Location:");
		if (p == 0)
        {
			throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error reported reading socket");
		}
		p = strchr(p, ' ');
		if (p == 0)
		{
			throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error reported reading socket");
		}

		// Now read
		p++;
		for (q=0; q < 255 && p[q] != '\r' && p[q] !='\n'; ++q)
			redirectBuf[q] = p[q];

		redirectBuf[q] = '\0';

		// Try to find this location
		m_uri = XMLUri(XMLString::transcode(redirectBuf));

		return doRequest(request);

	}

    else if (httpResponse != 200)
    {
        // Most likely a 404 Not Found error.
        //   Should recognize and handle the forwarding responses.
        //
		char * q = strstr(p, "\n");
		if (q == NULL)
			q = strstr(p, "\r");
		if (q != NULL)
			*q = '\0';
		safeBuffer sb;
		sb.sbStrcpyIn("SOAPRequestorSimple HTTP Error : ");
		if (strlen(p) < 256)
			sb.sbStrcatIn(p);
        throw XSECException(XSECException::HTTPURIInputStreamError, sb.rawCharBuffer());

    }

	/* Now find out how long the return is */

	p = strstr(fBuffer, "Content-Length:");
	if (p == NULL) {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Content-Length required in SOAP HTTP Response");
	}

	p = strchr(p, ' ');
	p++;

	int responseLength = atoi(p);

	char * responseBuffer;
	XSECnew(responseBuffer, char[responseLength]);
	ArrayJanitor<char> j_responseBuffer(responseBuffer);

	lent = fBufferEnd - fBufferPos;
	memcpy(responseBuffer, fBufferPos, lent);
	while (lent < responseLength) {
	    aLent = read(s, &responseBuffer[lent], responseLength - lent);
		lent += aLent;
	}

    return parseAndUnwrap(responseBuffer, responseLength);

}

<commit_msg>Fix SOAP client bugs<commit_after>/*
 * Copyright 2004 The Apache Software Foundation.
 *
 * Licensed 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
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * imitations under the License.
 */

/*
 * XSEC
 *
 * XSECSOAPRequestorSimple := (Very) Basic implementation of a SOAP
 *                         HTTP wrapper for testing the client code.
 *
 *
 * $Id$
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>

#include <xsec/utils/XSECSOAPRequestorSimple.hpp>
#include <xsec/utils/XSECSafeBuffer.hpp>
#include <xsec/framework/XSECError.hpp>

#include <xercesc/dom/DOM.hpp>
#include <xercesc/util/XMLNetAccessor.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/util/XMLExceptMsgs.hpp>
#include <xercesc/util/Janitor.hpp>
#include <xercesc/util/XMLUniDefs.hpp>

XERCES_CPP_NAMESPACE_USE

// --------------------------------------------------------------------------------
//           Platform specific constructor
// --------------------------------------------------------------------------------

XSECSOAPRequestorSimple::XSECSOAPRequestorSimple(const XMLCh * uri) : m_uri(uri) {

}

// --------------------------------------------------------------------------------
//           Interface
// --------------------------------------------------------------------------------

DOMDocument * XSECSOAPRequestorSimple::doRequest(DOMDocument * request) {

	char * content = wrapAndSerialise(request);

	// First we need to serialise

    char                fBuffer[4000];
    char *              fBufferEnd;
    char *              fBufferPos;

    //
    // Pull all of the parts of the URL out of th m_uri object, and transcode them
    //   and transcode them back to ASCII.
    //
    const XMLCh*        hostName = m_uri.getHost();
    char*               hostNameAsCharStar = XMLString::transcode(hostName);
    ArrayJanitor<char>  janBuf1(hostNameAsCharStar);

    const XMLCh*        path = m_uri.getPath();
    char*               pathAsCharStar = XMLString::transcode(path);
    ArrayJanitor<char>  janBuf2(pathAsCharStar);

    const XMLCh*        fragment = m_uri.getFragment();
    char*               fragmentAsCharStar = 0;
    if (fragment)
        fragmentAsCharStar = XMLString::transcode(fragment);
    ArrayJanitor<char>  janBuf3(fragmentAsCharStar);

    const XMLCh*        query = m_uri.getQueryString();
    char*               queryAsCharStar = 0;
    if (query)
        queryAsCharStar = XMLString::transcode(query);
    ArrayJanitor<char>  janBuf4(queryAsCharStar);

    unsigned short      portNumber = (unsigned short) m_uri.getPort();

	// If no number is set, go with port 80
	if (portNumber == USHRT_MAX)
		portNumber = 80;

    //
    // Set up a socket.
    //
    struct hostent*     hostEntPtr = 0;
    struct sockaddr_in  sa;

    if ((hostEntPtr = gethostbyname(hostNameAsCharStar)) == NULL)
    {
        unsigned long  numAddress = inet_addr(hostNameAsCharStar);
        if (numAddress == 0)
        {
            ThrowXML(NetAccessorException,
                     XMLExcepts::NetAcc_TargetResolution);
        }
        if ((hostEntPtr =
                gethostbyaddr((char *) &numAddress,
                              sizeof(unsigned long), AF_INET)) == NULL)
        {
            ThrowXML(NetAccessorException,
                     XMLExcepts::NetAcc_TargetResolution);
        }
    }

    memcpy((void *) &sa.sin_addr,
           (const void *) hostEntPtr->h_addr, hostEntPtr->h_length);
    sa.sin_family = hostEntPtr->h_addrtype;
    sa.sin_port = htons(portNumber);

    int s = socket(hostEntPtr->h_addrtype, SOCK_STREAM, 0);
    if (s < 0)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error creating socket");

    }

    if (connect(s, (struct sockaddr *) &sa, sizeof(sa)) < 0)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error connecting to end server");
    }

    // The port is open and ready to go.
    // Build up the http GET command to send to the server.
    // To do:  We should really support http 1.1.  This implementation
    //         is weak.

    memset(fBuffer, 0, sizeof(fBuffer));

    strcpy(fBuffer, "POST ");
    strcat(fBuffer, pathAsCharStar);

    if (queryAsCharStar != 0)
    {
        // Tack on a ? before the fragment
        strcat(fBuffer,"?");
        strcat(fBuffer, queryAsCharStar);
    }

    if (fragmentAsCharStar != 0)
    {
        strcat(fBuffer, fragmentAsCharStar);
    }
    strcat(fBuffer, " HTTP/1.0\r\n");

	strcat(fBuffer, "Content-Type: text/xml; charset=utf-8\r\n");

    strcat(fBuffer, "Host: ");
    strcat(fBuffer, hostNameAsCharStar);
    if (portNumber != 80)
    {
        int i = strlen(fBuffer);
		sprintf(fBuffer+i, ":%d", portNumber);
    }
	strcat(fBuffer, "\r\n");

	strcat(fBuffer, "Content-Length: ");
    int i = (int) strlen(fBuffer);
	sprintf(fBuffer+i, "%d", strlen(content));
	strcat(fBuffer, "\r\n");
	strcat(fBuffer, "SOAPAction: \"\"\r\n");

/*	strcat(fBuffer, "Connection: Close\r\n");
	strcat(fBuffer, "Cache-Control: no-cache\r\n");*/
    strcat(fBuffer, "\r\n");

	// Now the content
	strcat(fBuffer, content);

    // Send the http request
    int lent = strlen(fBuffer);
    int  aLent = 0;
    if ((aLent = write(s, (void *) fBuffer, lent)) != lent)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error writing to socket");
    }

    //
    // get the response, check the http header for errors from the server.
    //
    aLent = read(s, (void *)fBuffer, sizeof(fBuffer)-1);
	/*
	fBuffer[aLent] = '\0';
	printf(fBuffer);
	*/
    if (aLent <= 0)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error reported reading socket");
    }

    fBufferEnd = fBuffer+aLent;
    *fBufferEnd = 0;

    // Find the break between the returned http header and any data.
    //  (Delimited by a blank line)
    // Hang on to any data for use by the first read from this BinHTTPURLInputStream.
    //
    fBufferPos = strstr(fBuffer, "\r\n\r\n");
    if (fBufferPos != 0)
    {
        fBufferPos += 4;
        *(fBufferPos-2) = 0;
    }
    else
    {
        fBufferPos = strstr(fBuffer, "\n\n");
        if (fBufferPos != 0)
        {
            fBufferPos += 2;
            *(fBufferPos-1) = 0;
        }
        else
            fBufferPos = fBufferEnd;
    }

    // Make sure the header includes an HTTP 200 OK response.
    //
    char *p = strstr(fBuffer, "HTTP");
    if (p == 0)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error reported reading socket");
    }

    p = strchr(p, ' ');
    if (p == 0)
    {
        throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error reported reading socket");
    }

    int httpResponse = atoi(p);

	if (httpResponse == 302 || httpResponse == 301) {
		//Once grows, should use a switch
		char redirectBuf[256];
		int q;

		// Find the "Location:" string
		p = strstr(p, "Location:");
		if (p == 0)
        {
			throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error reported reading socket");
		}
		p = strchr(p, ' ');
		if (p == 0)
		{
			throw XSECException(XSECException::HTTPURIInputStreamError,
							"Error reported reading socket");
		}

		// Now read
		p++;
		for (q=0; q < 255 && p[q] != '\r' && p[q] !='\n'; ++q)
			redirectBuf[q] = p[q];

		redirectBuf[q] = '\0';

		// Try to find this location
		m_uri = XMLUri(XMLString::transcode(redirectBuf));

		return doRequest(request);

	}

    else if (httpResponse != 200)
    {
        // Most likely a 404 Not Found error.
        //   Should recognize and handle the forwarding responses.
        //
		char * q = strstr(p, "\n");
		if (q == NULL)
			q = strstr(p, "\r");
		if (q != NULL)
			*q = '\0';
		safeBuffer sb;
		sb.sbStrcpyIn("SOAPRequestorSimple HTTP Error : ");
		if (strlen(p) < 256)
			sb.sbStrcatIn(p);
        throw XSECException(XSECException::HTTPURIInputStreamError, sb.rawCharBuffer());

    }

	/* Now find out how long the return is */

	p = strstr(fBuffer, "Content-Length:");
	int responseLength;

	if (p == NULL) {
		// Need to work it out from the amount of data returned
		responseLength = -1;
	}
	else {

		p = strchr(p, ' ');
		p++;

		responseLength = atoi(p);
	}

	safeBuffer responseBuffer;
	lent = fBufferEnd - fBufferPos;
	responseBuffer.sbMemcpyIn(fBufferPos, lent);

	while (responseLength == -1 || lent < responseLength) {
		aLent = read(s, (void *)fBuffer, sizeof(fBuffer)-1);
		if (aLent > 0) {
			responseBuffer.sbMemcpyIn(lent, fBuffer, aLent);
			lent += aLent;
		}
		else {
			responseLength = 0;
		}
	}

	return parseAndUnwrap(responseBuffer.rawCharBuffer(), lent);

#if 0

	char * responseBuffer;
	XSECnew(responseBuffer, char[responseLength]);
	ArrayJanitor<char> j_responseBuffer(responseBuffer);

	lent = fBufferEnd - fBufferPos;
	memcpy(responseBuffer, fBufferPos, lent);
	while (lent < responseLength) {
	    aLent = read(s, &responseBuffer[lent], responseLength - lent);
		lent += aLent;
	}

    return parseAndUnwrap(responseBuffer, responseLength);
#endif
}

<|endoftext|>