<commit_before>/*!
   \file
   \author Dane Gardner <dane.gardner@gmail.com>
   \version

   \section LICENSE
   This file is part of the Open|SpeedShop Graphical User Interface
   Copyright (C) 2010-2011 Argo Navis Technologies, LLC

   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

   \section DESCRIPTION

 */

#include "WelcomeData.h"

#include <QFile>
#include <QFileInfo>
#include <QApplication>
#include <PluginManager/PluginManager.h>
#include "OpenSpeedShopWidget.h"

using namespace Plugins::Welcome;

namespace Plugins {
namespace OpenSpeedShop {

WelcomeData::WelcomeData(QObject *parent) :
    QObject(parent),
    m_WelcomeData("WelcomeData")
{
}

bool WelcomeData::initialize()
{
#ifdef WIN32
    QFileInfo fileInfo(QString("%1/WelcomeData.xml").arg(QApplication::instance()->applicationDirPath()));
#else
    QFileInfo fileInfo(QString("%1/../etc/WelcomeData.xml").arg(QApplication::instance()->applicationDirPath()));
#endif

    Core::SettingManager::SettingManager &settingManager = Core::SettingManager::SettingManager::instance();
    settingManager.beginGroup("Plugins/OpenSpeedShop/Welcome");
    QString filePath = settingManager.value("welcomeDataPath", fileInfo.absoluteFilePath()).toString();
    settingManager.endGroup();

    if(filePath.isEmpty()) {
        filePath = fileInfo.absoluteFilePath();
    }

    bool defaultPath = (filePath == fileInfo.absoluteFilePath());

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        QString error = tr("Could not open welcome data file: %1").arg(filePath);
        qWarning(error.toLatin1());
        throw error;
    }
    if (!m_WelcomeData.setContent(&file)) {
        file.close();
        QString error = tr("Could not use welcome data file after opening, possibly invalid text: %1").arg(filePath);
        qWarning(error.toLatin1());
        throw error;
    }
    file.close();

    /* User convenience.  If the path wasn't set in the settings, we'll set it for the user the first time. */
    if(defaultPath) {
        settingManager.beginGroup("Plugins/OpenSpeedShop/Welcome");
        settingManager.setValue("welcomeDataPath", filePath);
        settingManager.endGroup();
    }

    return true;
}

QList<Link> WelcomeData::actions()
{
    QList<Link> list;

    Core::PluginManager::PluginManager &pluginManager = Core::PluginManager::PluginManager::instance();
    QList<OpenSpeedShopWidget *> openSpeedShopWidgets = pluginManager.getObjects<OpenSpeedShopWidget>();
    if(openSpeedShopWidgets.count() == 1) {
        OpenSpeedShopWidget *openSpeedShopWidget = openSpeedShopWidgets.at(0);

        //! \todo Enable this when we have the functionality!
//        list.append(Link(tr("Create Open|SpeedShop Experiment"),
//                         tr("create a new Open|SpeedShop experiment."),
//                         Link::Type_None, 127,
//                         openSpeedShopWidget, SLOT(createExperiment())));

        list.append(Link(tr("Load Open|SpeedShop Experiment"),
                         tr("open an existing Open|SpeedShop experiment database."),
                         Link::Type_None, 128,
                         openSpeedShopWidget, SLOT(loadExperiment())));
    }

    return list;
}

QList<Link> WelcomeData::recent()
{
    QList<Link> list;

    list.append(Link(tr("/home/dane/smg2000-pcsamp.openss"), QString(), Link::Type_None, 128,
                     QUrl("openss:///home/dane/smg2000-pcsamp.openss")));

    list.append(Link(tr("/home/dane/smg2000-io.openss"), QString(), Link::Type_None, 128,
                     QUrl("openss:///home/dane/smg2000-io.openss")));

    list.append(Link(tr("/home/dane/smg2000-iot.openss"), QString(), Link::Type_None, 128,
                     QUrl("openss:///home/dane/smg2000-iot.openss")));

    return list;
}

QList<Link> WelcomeData::tutorials()
{
    return createUrlLinks("Tutorials");
}

QList<Link> WelcomeData::examples()
{
    return createUrlLinks("Examples");
}

QList<Link> WelcomeData::support()
{
    return createUrlLinks("Support");
}

QStringList WelcomeData::tipsAndTricks()
{
    QStringList list;

    QDomElement welcomeData = m_WelcomeData.firstChildElement("WelcomeData");
    if(welcomeData.isNull()) {
        return list;
    }

    QDomElement element = welcomeData.firstChildElement("TipsAndTricks");
    if(element.isNull()) {
        return list;
    }

    QDomElement tip = element.firstChildElement("Tip");
    while(!tip.isNull()) {
        list.append(tip.attribute("text"));
        tip = tip.nextSiblingElement(tip.tagName());
    }

    return list;
}

QList<QUrl> WelcomeData::latestNewsRss()
{
    QList<QUrl> list;

    QDomElement welcomeData = m_WelcomeData.firstChildElement("WelcomeData");
    if(welcomeData.isNull()) {
        return list;
    }

    QDomElement element = welcomeData.firstChildElement("LatestNews");
    if(element.isNull()) {
        return list;
    }

    QDomElement rss = element.firstChildElement("Rss");
    while(!rss.isNull()) {
        list.append(QUrl(rss.attribute("url")));
        rss = rss.nextSiblingElement(rss.tagName());
    }

    return list;
}

QList<QWidget *> WelcomeData::additionalTabs()
{
    QList<QWidget *> list;
    return list;
}

QList<Link> WelcomeData::createUrlLinks(const QString &elementName)
{
    QList<Link> list;

    QDomElement welcomeData = m_WelcomeData.firstChildElement("WelcomeData");
    if(welcomeData.isNull()) {
        return list;
    }

    QDomElement element = welcomeData.firstChildElement(elementName);
    if(element.isNull()) {
        return list;
    }

    QDomElement link = element.firstChildElement("Link");
    while(!link.isNull()) {
        list.append(createUrlLink(link));
        link = link.nextSiblingElement(link.tagName());
    }

    return list;
}

Link WelcomeData::createUrlLink(const QDomElement &link)
{
    QString title = link.attribute("title");
    QString description = link.attribute("description");

    QString typeString = link.attribute("type");
    Link::Type type = Link::Type_None;
    if(typeString == "text") {
        type = Link::Type_Text;
    } else if(typeString == "video") {
        type = Link::Type_Video;
    } else if(typeString == "web") {
        type = Link::Type_Web;
    }

    bool okay;
    int priority = link.attribute("priority", "128").toInt(&okay);
    if(!okay) priority = 128;

    QUrl url(link.attribute("url"));

    return Link(title, description, type, priority, url);
}

} // namespace OpenSpeedShop
} // namespace Plugins
<commit_msg>Fixed issues with finding WelcomeData.xml<commit_after>/*!
   \file
   \author Dane Gardner <dane.gardner@gmail.com>
   \version

   \section LICENSE
   This file is part of the Open|SpeedShop Graphical User Interface
   Copyright (C) 2010-2011 Argo Navis Technologies, LLC

   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

   \section DESCRIPTION

 */

#include "WelcomeData.h"

#include <QFile>
#include <QFileInfo>
#include <QApplication>
#include <PluginManager/PluginManager.h>
#include "OpenSpeedShopWidget.h"

using namespace Plugins::Welcome;

namespace Plugins {
namespace OpenSpeedShop {

WelcomeData::WelcomeData(QObject *parent) :
    QObject(parent),
    m_WelcomeData("WelcomeData")
{
}

bool WelcomeData::initialize()
{
#ifdef WIN32
    QFileInfo fileInfo(QString("%1/WelcomeData.xml").arg(QApplication::instance()->applicationDirPath()));
#else
    QFileInfo fileInfo(QString("%1/../etc/WelcomeData.xml").arg(QApplication::instance()->applicationDirPath()));
#endif

    QString filePath;
//    Core::SettingManager::SettingManager &settingManager = Core::SettingManager::SettingManager::instance();
//    settingManager.beginGroup("Plugins/OpenSpeedShop/Welcome");
//    filePath = settingManager.value("welcomeDataPath", fileInfo.absoluteFilePath()).toString();
//    settingManager.endGroup();

    if(filePath.isEmpty()) {
        filePath = fileInfo.absoluteFilePath();
    }

    bool defaultPath = (filePath == fileInfo.absoluteFilePath());

    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        QString error = tr("Could not open welcome data file: %1").arg(filePath);
        qWarning(error.toLatin1());
        throw error;
    }
    if (!m_WelcomeData.setContent(&file)) {
        file.close();
        QString error = tr("Could not use welcome data file after opening, possibly invalid text: %1").arg(filePath);
        qWarning(error.toLatin1());
        throw error;
    }
    file.close();

//    /* User convenience.  If the path wasn't set in the settings, we'll set it for the user the first time. */
//    if(defaultPath) {
//        settingManager.beginGroup("Plugins/OpenSpeedShop/Welcome");
//        settingManager.setValue("welcomeDataPath", filePath);
//        settingManager.endGroup();
//    }

    return true;
}

QList<Link> WelcomeData::actions()
{
    QList<Link> list;

    Core::PluginManager::PluginManager &pluginManager = Core::PluginManager::PluginManager::instance();
    QList<OpenSpeedShopWidget *> openSpeedShopWidgets = pluginManager.getObjects<OpenSpeedShopWidget>();
    if(openSpeedShopWidgets.count() == 1) {
        OpenSpeedShopWidget *openSpeedShopWidget = openSpeedShopWidgets.at(0);

        //! \todo Enable this when we have the functionality!
//        list.append(Link(tr("Create Open|SpeedShop Experiment"),
//                         tr("create a new Open|SpeedShop experiment."),
//                         Link::Type_None, 127,
//                         openSpeedShopWidget, SLOT(createExperiment())));

        list.append(Link(tr("Load Open|SpeedShop Experiment"),
                         tr("open an existing Open|SpeedShop experiment database."),
                         Link::Type_None, 128,
                         openSpeedShopWidget, SLOT(loadExperiment())));
    }

    return list;
}

QList<Link> WelcomeData::recent()
{
    QList<Link> list;

    list.append(Link(tr("/home/dane/smg2000-pcsamp.openss"), QString(), Link::Type_None, 128,
                     QUrl("openss:///home/dane/smg2000-pcsamp.openss")));

    list.append(Link(tr("/home/dane/smg2000-io.openss"), QString(), Link::Type_None, 128,
                     QUrl("openss:///home/dane/smg2000-io.openss")));

    list.append(Link(tr("/home/dane/smg2000-iot.openss"), QString(), Link::Type_None, 128,
                     QUrl("openss:///home/dane/smg2000-iot.openss")));

    return list;
}

QList<Link> WelcomeData::tutorials()
{
    return createUrlLinks("Tutorials");
}

QList<Link> WelcomeData::examples()
{
    return createUrlLinks("Examples");
}

QList<Link> WelcomeData::support()
{
    return createUrlLinks("Support");
}

QStringList WelcomeData::tipsAndTricks()
{
    QStringList list;

    QDomElement welcomeData = m_WelcomeData.firstChildElement("WelcomeData");
    if(welcomeData.isNull()) {
        return list;
    }

    QDomElement element = welcomeData.firstChildElement("TipsAndTricks");
    if(element.isNull()) {
        return list;
    }

    QDomElement tip = element.firstChildElement("Tip");
    while(!tip.isNull()) {
        list.append(tip.attribute("text"));
        tip = tip.nextSiblingElement(tip.tagName());
    }

    return list;
}

QList<QUrl> WelcomeData::latestNewsRss()
{
    QList<QUrl> list;

    QDomElement welcomeData = m_WelcomeData.firstChildElement("WelcomeData");
    if(welcomeData.isNull()) {
        return list;
    }

    QDomElement element = welcomeData.firstChildElement("LatestNews");
    if(element.isNull()) {
        return list;
    }

    QDomElement rss = element.firstChildElement("Rss");
    while(!rss.isNull()) {
        list.append(QUrl(rss.attribute("url")));
        rss = rss.nextSiblingElement(rss.tagName());
    }

    return list;
}

QList<QWidget *> WelcomeData::additionalTabs()
{
    QList<QWidget *> list;
    return list;
}

QList<Link> WelcomeData::createUrlLinks(const QString &elementName)
{
    QList<Link> list;

    QDomElement welcomeData = m_WelcomeData.firstChildElement("WelcomeData");
    if(welcomeData.isNull()) {
        return list;
    }

    QDomElement element = welcomeData.firstChildElement(elementName);
    if(element.isNull()) {
        return list;
    }

    QDomElement link = element.firstChildElement("Link");
    while(!link.isNull()) {
        list.append(createUrlLink(link));
        link = link.nextSiblingElement(link.tagName());
    }

    return list;
}

Link WelcomeData::createUrlLink(const QDomElement &link)
{
    QString title = link.attribute("title");
    QString description = link.attribute("description");

    QString typeString = link.attribute("type");
    Link::Type type = Link::Type_None;
    if(typeString == "text") {
        type = Link::Type_Text;
    } else if(typeString == "video") {
        type = Link::Type_Video;
    } else if(typeString == "web") {
        type = Link::Type_Web;
    }

    bool okay;
    int priority = link.attribute("priority", "128").toInt(&okay);
    if(!okay) priority = 128;

    QUrl url(link.attribute("url"));

    return Link(title, description, type, priority, url);
}

} // namespace OpenSpeedShop
} // namespace Plugins
<|endoftext|>


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

#include "CDROutputElementList.h"

namespace libcdr
{

namespace
{

static void separateTabsAndInsertText(librevenge::RVNGDrawingInterface *iface, const librevenge::RVNGString &text)
{
  if (!iface || text.empty())
    return;
  librevenge::RVNGString tmpText;
  librevenge::RVNGString::Iter i(text);
  for (i.rewind(); i.next();)
  {
    if (*(i()) == '\t')
    {
      if (!tmpText.empty())
      {
        if (iface)
          iface->insertText(tmpText);
        tmpText.clear();
      }

      if (iface)
        iface->insertTab();
    }
    else if (*(i()) == '\n')
    {
      if (!tmpText.empty())
      {
        if (iface)
          iface->insertText(tmpText);
        tmpText.clear();
      }

      if (iface)
        iface->insertLineBreak();
    }
    else
    {
      tmpText.append(i());
    }
  }
  if (iface && !tmpText.empty())
    iface->insertText(tmpText);
}

static void separateSpacesAndInsertText(librevenge::RVNGDrawingInterface *iface, const librevenge::RVNGString &text)
{
  if (!iface)
    return;
  if (text.empty())
  {
    iface->insertText(text);
    return;
  }
  librevenge::RVNGString tmpText;
  int numConsecutiveSpaces = 0;
  librevenge::RVNGString::Iter i(text);
  for (i.rewind(); i.next();)
  {
    if (*(i()) == ' ')
      numConsecutiveSpaces++;
    else
      numConsecutiveSpaces = 0;

    if (numConsecutiveSpaces > 1)
    {
      if (!tmpText.empty())
      {
        separateTabsAndInsertText(iface, tmpText);
        tmpText.clear();
      }

      if (iface)
        iface->insertSpace();
    }
    else
    {
      tmpText.append(i());
    }
  }
  separateTabsAndInsertText(iface, tmpText);
}

} // anonymous namespace

class CDROutputElement
{
public:
  CDROutputElement() {}
  virtual ~CDROutputElement() {}
  virtual void draw(librevenge::RVNGDrawingInterface *painter) = 0;
  virtual CDROutputElement *clone() = 0;
};

class CDRStyleOutputElement : public CDROutputElement
{
public:
  CDRStyleOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDRStyleOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRStyleOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDRPathOutputElement : public CDROutputElement
{
public:
  CDRPathOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDRPathOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRPathOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDRGraphicObjectOutputElement : public CDROutputElement
{
public:
  CDRGraphicObjectOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDRGraphicObjectOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRGraphicObjectOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDRStartTextObjectOutputElement : public CDROutputElement
{
public:
  CDRStartTextObjectOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDRStartTextObjectOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRStartTextObjectOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDROpenParagraphOutputElement : public CDROutputElement
{
public:
  CDROpenParagraphOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDROpenParagraphOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDROpenParagraphOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDROpenSpanOutputElement : public CDROutputElement
{
public:
  CDROpenSpanOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDROpenSpanOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDROpenSpanOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDRInsertTextOutputElement : public CDROutputElement
{
public:
  CDRInsertTextOutputElement(const librevenge::RVNGString &text);
  ~CDRInsertTextOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRInsertTextOutputElement(m_text);
  }
private:
  librevenge::RVNGString m_text;
};

class CDRCloseSpanOutputElement : public CDROutputElement
{
public:
  CDRCloseSpanOutputElement();
  ~CDRCloseSpanOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRCloseSpanOutputElement();
  }
};

class CDRCloseParagraphOutputElement : public CDROutputElement
{
public:
  CDRCloseParagraphOutputElement();
  ~CDRCloseParagraphOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRCloseParagraphOutputElement();
  }
};

class CDREndTextObjectOutputElement : public CDROutputElement
{
public:
  CDREndTextObjectOutputElement();
  ~CDREndTextObjectOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDREndTextObjectOutputElement();
  }
};

class CDRStartLayerOutputElement : public CDROutputElement
{
public:
  CDRStartLayerOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDRStartLayerOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRStartLayerOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDREndLayerOutputElement : public CDROutputElement
{
public:
  CDREndLayerOutputElement();
  ~CDREndLayerOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDREndLayerOutputElement();
  }
};

} // namespace libcdr

libcdr::CDRStyleOutputElement::CDRStyleOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void libcdr::CDRStyleOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->setStyle(m_propList);
}

libcdr::CDRPathOutputElement::CDRPathOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void libcdr::CDRPathOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->drawPath(m_propList);
}

libcdr::CDRGraphicObjectOutputElement::CDRGraphicObjectOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void libcdr::CDRGraphicObjectOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->drawGraphicObject(m_propList);
}

libcdr::CDRStartTextObjectOutputElement::CDRStartTextObjectOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void libcdr::CDRStartTextObjectOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->startTextObject(m_propList);
}

libcdr::CDROpenSpanOutputElement::CDROpenSpanOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void libcdr::CDROpenSpanOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->openSpan(m_propList);
}

libcdr::CDROpenParagraphOutputElement::CDROpenParagraphOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void libcdr::CDROpenParagraphOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->openParagraph(m_propList);
}

libcdr::CDRInsertTextOutputElement::CDRInsertTextOutputElement(const librevenge::RVNGString &text) :
  m_text(text) {}

void libcdr::CDRInsertTextOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    separateSpacesAndInsertText(painter, m_text);
}

libcdr::CDRCloseSpanOutputElement::CDRCloseSpanOutputElement() {}

void libcdr::CDRCloseSpanOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->closeSpan();
}

libcdr::CDRCloseParagraphOutputElement::CDRCloseParagraphOutputElement() {}

void libcdr::CDRCloseParagraphOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->closeParagraph();
}

libcdr::CDREndTextObjectOutputElement::CDREndTextObjectOutputElement() {}

void libcdr::CDREndTextObjectOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->endTextObject();
}

libcdr::CDREndLayerOutputElement::CDREndLayerOutputElement() {}

void libcdr::CDREndLayerOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->endLayer();
}

libcdr::CDRStartLayerOutputElement::CDRStartLayerOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void libcdr::CDRStartLayerOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->startLayer(m_propList);
}

libcdr::CDROutputElementList::CDROutputElementList()
  : m_elements()
{
}

libcdr::CDROutputElementList::CDROutputElementList(const libcdr::CDROutputElementList &elementList)
  : m_elements()
{
  std::vector<libcdr::CDROutputElement *>::const_iterator iter;
  for (iter = elementList.m_elements.begin(); iter != elementList.m_elements.end(); ++iter)
    m_elements.push_back((*iter)->clone());
}

libcdr::CDROutputElementList &libcdr::CDROutputElementList::operator=(const libcdr::CDROutputElementList &elementList)
{
  for (auto &element : m_elements)
    delete element;

  m_elements.clear();

  for (auto element : elementList.m_elements)
    m_elements.push_back(element->clone());

  return *this;
}

libcdr::CDROutputElementList::~CDROutputElementList()
{
  for (auto &element : m_elements)
    delete element;
  m_elements.clear();
}

void libcdr::CDROutputElementList::draw(librevenge::RVNGDrawingInterface *painter) const
{
  for (auto element : m_elements)
    element->draw(painter);
}

void libcdr::CDROutputElementList::addStyle(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDRStyleOutputElement(propList));
}

void libcdr::CDROutputElementList::addPath(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDRPathOutputElement(propList));
}

void libcdr::CDROutputElementList::addGraphicObject(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDRGraphicObjectOutputElement(propList));
}

void libcdr::CDROutputElementList::addStartTextObject(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDRStartTextObjectOutputElement(propList));
}

void libcdr::CDROutputElementList::addOpenParagraph(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDROpenParagraphOutputElement(propList));
}

void libcdr::CDROutputElementList::addOpenSpan(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDROpenSpanOutputElement(propList));
}

void libcdr::CDROutputElementList::addInsertText(const librevenge::RVNGString &text)
{
  m_elements.push_back(new CDRInsertTextOutputElement(text));
}

void libcdr::CDROutputElementList::addCloseSpan()
{
  m_elements.push_back(new CDRCloseSpanOutputElement());
}

void libcdr::CDROutputElementList::addCloseParagraph()
{
  m_elements.push_back(new CDRCloseParagraphOutputElement());
}

void libcdr::CDROutputElementList::addEndTextObject()
{
  m_elements.push_back(new CDREndTextObjectOutputElement());
}

void libcdr::CDROutputElementList::addStartGroup(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDRStartLayerOutputElement(propList));
}

void libcdr::CDROutputElementList::addEndGroup()
{
  m_elements.push_back(new CDREndLayerOutputElement());
}

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<commit_msg>put the whole impl. in libcdr namespace<commit_after>/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
 * This file is part of the libcdr project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "CDROutputElementList.h"

namespace libcdr
{

namespace
{

static void separateTabsAndInsertText(librevenge::RVNGDrawingInterface *iface, const librevenge::RVNGString &text)
{
  if (!iface || text.empty())
    return;
  librevenge::RVNGString tmpText;
  librevenge::RVNGString::Iter i(text);
  for (i.rewind(); i.next();)
  {
    if (*(i()) == '\t')
    {
      if (!tmpText.empty())
      {
        if (iface)
          iface->insertText(tmpText);
        tmpText.clear();
      }

      if (iface)
        iface->insertTab();
    }
    else if (*(i()) == '\n')
    {
      if (!tmpText.empty())
      {
        if (iface)
          iface->insertText(tmpText);
        tmpText.clear();
      }

      if (iface)
        iface->insertLineBreak();
    }
    else
    {
      tmpText.append(i());
    }
  }
  if (iface && !tmpText.empty())
    iface->insertText(tmpText);
}

static void separateSpacesAndInsertText(librevenge::RVNGDrawingInterface *iface, const librevenge::RVNGString &text)
{
  if (!iface)
    return;
  if (text.empty())
  {
    iface->insertText(text);
    return;
  }
  librevenge::RVNGString tmpText;
  int numConsecutiveSpaces = 0;
  librevenge::RVNGString::Iter i(text);
  for (i.rewind(); i.next();)
  {
    if (*(i()) == ' ')
      numConsecutiveSpaces++;
    else
      numConsecutiveSpaces = 0;

    if (numConsecutiveSpaces > 1)
    {
      if (!tmpText.empty())
      {
        separateTabsAndInsertText(iface, tmpText);
        tmpText.clear();
      }

      if (iface)
        iface->insertSpace();
    }
    else
    {
      tmpText.append(i());
    }
  }
  separateTabsAndInsertText(iface, tmpText);
}

} // anonymous namespace

class CDROutputElement
{
public:
  CDROutputElement() {}
  virtual ~CDROutputElement() {}
  virtual void draw(librevenge::RVNGDrawingInterface *painter) = 0;
  virtual CDROutputElement *clone() = 0;
};

class CDRStyleOutputElement : public CDROutputElement
{
public:
  CDRStyleOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDRStyleOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRStyleOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDRPathOutputElement : public CDROutputElement
{
public:
  CDRPathOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDRPathOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRPathOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDRGraphicObjectOutputElement : public CDROutputElement
{
public:
  CDRGraphicObjectOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDRGraphicObjectOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRGraphicObjectOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDRStartTextObjectOutputElement : public CDROutputElement
{
public:
  CDRStartTextObjectOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDRStartTextObjectOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRStartTextObjectOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDROpenParagraphOutputElement : public CDROutputElement
{
public:
  CDROpenParagraphOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDROpenParagraphOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDROpenParagraphOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDROpenSpanOutputElement : public CDROutputElement
{
public:
  CDROpenSpanOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDROpenSpanOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDROpenSpanOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDRInsertTextOutputElement : public CDROutputElement
{
public:
  CDRInsertTextOutputElement(const librevenge::RVNGString &text);
  ~CDRInsertTextOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRInsertTextOutputElement(m_text);
  }
private:
  librevenge::RVNGString m_text;
};

class CDRCloseSpanOutputElement : public CDROutputElement
{
public:
  CDRCloseSpanOutputElement();
  ~CDRCloseSpanOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRCloseSpanOutputElement();
  }
};

class CDRCloseParagraphOutputElement : public CDROutputElement
{
public:
  CDRCloseParagraphOutputElement();
  ~CDRCloseParagraphOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRCloseParagraphOutputElement();
  }
};

class CDREndTextObjectOutputElement : public CDROutputElement
{
public:
  CDREndTextObjectOutputElement();
  ~CDREndTextObjectOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDREndTextObjectOutputElement();
  }
};

class CDRStartLayerOutputElement : public CDROutputElement
{
public:
  CDRStartLayerOutputElement(const librevenge::RVNGPropertyList &propList);
  ~CDRStartLayerOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDRStartLayerOutputElement(m_propList);
  }
private:
  librevenge::RVNGPropertyList m_propList;
};

class CDREndLayerOutputElement : public CDROutputElement
{
public:
  CDREndLayerOutputElement();
  ~CDREndLayerOutputElement() override {}
  void draw(librevenge::RVNGDrawingInterface *painter) override;
  CDROutputElement *clone() override
  {
    return new CDREndLayerOutputElement();
  }
};

CDRStyleOutputElement::CDRStyleOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void CDRStyleOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->setStyle(m_propList);
}

CDRPathOutputElement::CDRPathOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void CDRPathOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->drawPath(m_propList);
}

CDRGraphicObjectOutputElement::CDRGraphicObjectOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void CDRGraphicObjectOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->drawGraphicObject(m_propList);
}

CDRStartTextObjectOutputElement::CDRStartTextObjectOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void CDRStartTextObjectOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->startTextObject(m_propList);
}

CDROpenSpanOutputElement::CDROpenSpanOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void CDROpenSpanOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->openSpan(m_propList);
}

CDROpenParagraphOutputElement::CDROpenParagraphOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void CDROpenParagraphOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->openParagraph(m_propList);
}

CDRInsertTextOutputElement::CDRInsertTextOutputElement(const librevenge::RVNGString &text) :
  m_text(text) {}

void CDRInsertTextOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    separateSpacesAndInsertText(painter, m_text);
}

CDRCloseSpanOutputElement::CDRCloseSpanOutputElement() {}

void CDRCloseSpanOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->closeSpan();
}

CDRCloseParagraphOutputElement::CDRCloseParagraphOutputElement() {}

void CDRCloseParagraphOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->closeParagraph();
}

CDREndTextObjectOutputElement::CDREndTextObjectOutputElement() {}

void CDREndTextObjectOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->endTextObject();
}

CDREndLayerOutputElement::CDREndLayerOutputElement() {}

void CDREndLayerOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->endLayer();
}

CDRStartLayerOutputElement::CDRStartLayerOutputElement(const librevenge::RVNGPropertyList &propList) :
  m_propList(propList) {}

void CDRStartLayerOutputElement::draw(librevenge::RVNGDrawingInterface *painter)
{
  if (painter)
    painter->startLayer(m_propList);
}

CDROutputElementList::CDROutputElementList()
  : m_elements()
{
}

CDROutputElementList::CDROutputElementList(const CDROutputElementList &elementList)
  : m_elements()
{
  std::vector<CDROutputElement *>::const_iterator iter;
  for (iter = elementList.m_elements.begin(); iter != elementList.m_elements.end(); ++iter)
    m_elements.push_back((*iter)->clone());
}

CDROutputElementList &CDROutputElementList::operator=(const CDROutputElementList &elementList)
{
  for (auto &element : m_elements)
    delete element;

  m_elements.clear();

  for (auto element : elementList.m_elements)
    m_elements.push_back(element->clone());

  return *this;
}

CDROutputElementList::~CDROutputElementList()
{
  for (auto &element : m_elements)
    delete element;
  m_elements.clear();
}

void CDROutputElementList::draw(librevenge::RVNGDrawingInterface *painter) const
{
  for (auto element : m_elements)
    element->draw(painter);
}

void CDROutputElementList::addStyle(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDRStyleOutputElement(propList));
}

void CDROutputElementList::addPath(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDRPathOutputElement(propList));
}

void CDROutputElementList::addGraphicObject(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDRGraphicObjectOutputElement(propList));
}

void CDROutputElementList::addStartTextObject(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDRStartTextObjectOutputElement(propList));
}

void CDROutputElementList::addOpenParagraph(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDROpenParagraphOutputElement(propList));
}

void CDROutputElementList::addOpenSpan(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDROpenSpanOutputElement(propList));
}

void CDROutputElementList::addInsertText(const librevenge::RVNGString &text)
{
  m_elements.push_back(new CDRInsertTextOutputElement(text));
}

void CDROutputElementList::addCloseSpan()
{
  m_elements.push_back(new CDRCloseSpanOutputElement());
}

void CDROutputElementList::addCloseParagraph()
{
  m_elements.push_back(new CDRCloseParagraphOutputElement());
}

void CDROutputElementList::addEndTextObject()
{
  m_elements.push_back(new CDREndTextObjectOutputElement());
}

void CDROutputElementList::addStartGroup(const librevenge::RVNGPropertyList &propList)
{
  m_elements.push_back(new CDRStartLayerOutputElement(propList));
}

void CDROutputElementList::addEndGroup()
{
  m_elements.push_back(new CDREndLayerOutputElement());
}

} // namespace libcdr

/* vim:set shiftwidth=2 softtabstop=2 expandtab: */
<|endoftext|>


<commit_before>/**
* @file Directory.cpp
* Implementation of a class for accessing directories.
* @author Colin Graf
*/

#include <nstd/Directory.h>
#include <nstd/File.h>
#include <nstd/Debug.h>

#include <cstring>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fnmatch.h>
#include <cerrno>
#endif

#if _MSC_VER
#define stricmp _stricmp
#endif

Directory::Directory()
{
#ifdef _WIN32
  ASSERT(sizeof(ffd) >= sizeof(WIN32_FIND_DATA));
  findFile = INVALID_HANDLE_VALUE;
#else
  dp = 0;
#endif
}

Directory::~Directory()
{
#ifdef _WIN32
  if(findFile != INVALID_HANDLE_VALUE)
    FindClose((HANDLE)findFile);
#else
  if(dp)
    closedir((DIR*)dp);
#endif
}

bool Directory::remove(const String& dir)
{
  String path = dir;
  while(path != ".")
  {
#ifdef _WIN32
    if(!RemoveDirectory(path))
      return false;
#else
    if(rmdir(path) != 0)
      return false;
#endif
    path = File::dirname(path);
  }
  return true;
}

bool Directory::open(const String& dirpath, const String& pattern, bool_t dirsOnly)
{
#ifdef _WIN32
  if(findFile != INVALID_HANDLE_VALUE)
  {
    SetLastError(ERROR_INVALID_HANDLE);
    return false;
  }

  this->dirsOnly = dirsOnly;
  this->dirpath = dirpath;
  const char_t* patExt = strrchr(pattern, '.');
  this->patternExtension = (patExt && !strpbrk(patExt + 1, "*?")) ? String(patExt + 1, -1) : String();

  String searchPath = dirpath;
  searchPath.reserve(dirpath.length() + 1 + pattern.length());
  if(!dirpath.isEmpty())
    searchPath.append('/');
  searchPath.append(pattern);

  findFile = FindFirstFileEx(searchPath,
#if _WIN32_WINNT > 0x0600
	  FindExInfoBasic,
#else
	  FindExInfoStandard,
#endif
	  (LPWIN32_FIND_DATA)ffd, dirsOnly ? FindExSearchLimitToDirectories : FindExSearchNameMatch, NULL, 0);
  if(findFile == INVALID_HANDLE_VALUE)
    return false;
  bufferedEntry = true;
  return true;
#else
  if(dp)
  {
    errno = EINVAL;
    return false;
  }

  this->dirsOnly = dirsOnly;
  this->dirpath = dirpath;
  this->pattern = pattern;

  dp = opendir(dirpath);
  return dp != 0;
#endif
}

bool Directory::read(String& name, bool_t& isDir)
{
#ifdef _WIN32
  if(!findFile)
  {
    SetLastError(ERROR_INVALID_HANDLE);
    return false;
  }
  for(;;)
  {
    if(bufferedEntry)
      bufferedEntry = false;
    else if(!FindNextFile((HANDLE)findFile, (LPWIN32_FIND_DATA)ffd))
    {
      DWORD lastError = GetLastError();
      FindClose((HANDLE)findFile);
      findFile = INVALID_HANDLE_VALUE;
      SetLastError(lastError);
      return false;
    }
    isDir = (((LPWIN32_FIND_DATA)ffd)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
    if(dirsOnly && !isDir)
      continue;
    const char_t* str = ((LPWIN32_FIND_DATA)ffd)->cFileName;
    if(isDir && *str == '.' && (str[1] == '\0' || (str[1] == '.' && str[2] == '\0')))
      continue;

    if(!patternExtension.isEmpty())
    {
      const char_t* patExt = strrchr(str, '.');
      if(!patExt || stricmp(patternExtension, patExt + 1) != 0)
        continue;
    }

    name = String(str, strlen(str));
    return true;
  }
#else
  if(!dp)
  {
    errno = EINVAL;
    return false;
  }

  for(;;)
  {
    struct dirent* dent = readdir((DIR*)dp);
    if(!dent)
    {
      int lastErrno = errno;
      closedir((DIR*)dp);
      dp = 0;
      errno = lastErrno;
      return false;
    }
    const char_t* const str = dent->d_name;
    if(fnmatch(pattern, str, 0) == 0)
    {
      name = String(str, strlen(str));
      isDir = false;
      if(dent->d_type == DT_DIR)
        isDir = true;
      else if(dent->d_type == DT_LNK || dent->d_type == DT_UNKNOWN)
      {
        String path = dirpath;
        path.append('/');
        path.append(name);
        struct stat buff;
        if(stat(path, &buff) == 0)
          if(S_ISDIR(buff.st_mode))
            isDir = true;
      }
      if(dirsOnly && !isDir)
        continue;
      if(isDir && *str == '.' && (str[1] == '\0' || (str[1] == '.' && str[2] == '\0')))
        continue;
      return true;
    }
  }
  return false; // unreachable
#endif
}

bool Directory::exists(const String& dir)
{
#ifdef _WIN32
  WIN32_FIND_DATAA wfd;
  HANDLE hFind = FindFirstFileA(dir, &wfd);
  if(hFind == INVALID_HANDLE_VALUE)
    return false;
  bool_t isDir = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
  FindClose(hFind);
  return isDir;
#else
  struct stat buf;
  if(stat(dir, &buf) != 0)
    return false;
  return S_ISDIR(buf.st_mode);
#endif
}

bool Directory::create(const String& dir)
{
  // TODO: set errno correctly

  const char_t* start = dir;
  const char_t* pos = &start[dir.length() - 1];
  for(; pos >= start; --pos)
    if(*pos == '\\' || *pos == '/')
    {
      if(!create(dir.substr(0, pos - start)))
      {
        return false;
      }
      break;
    }
  ++pos;
  bool_t result = false;
  if(*pos)
#ifdef _WIN32
    result = CreateDirectory(dir, NULL) == TRUE;
#else
    result = mkdir(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0;
#endif
  return result;
}

bool Directory::change(const String& dir)
{
#ifdef _WIN32
  return SetCurrentDirectory(dir) != FALSE;
#else
  return chdir(dir) == 0;
#endif
}
<commit_msg>Directory: Remove warnings<commit_after>/**
* @file Directory.cpp
* Implementation of a class for accessing directories.
* @author Colin Graf
*/

#include <nstd/Directory.h>
#include <nstd/File.h>
#include <nstd/Debug.h>

#include <cstring>
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fnmatch.h>
#include <cerrno>
#endif

#if _MSC_VER
#define stricmp _stricmp
#endif

Directory::Directory()
{
#ifdef _WIN32
  ASSERT(sizeof(ffd) >= sizeof(WIN32_FIND_DATA));
  findFile = INVALID_HANDLE_VALUE;
#else
  dp = 0;
#endif
}

Directory::~Directory()
{
#ifdef _WIN32
  if(findFile != INVALID_HANDLE_VALUE)
    FindClose((HANDLE)findFile);
#else
  if(dp)
    closedir((DIR*)dp);
#endif
}

bool Directory::remove(const String& dir)
{
  String path = dir;
  while(path != ".")
  {
#ifdef _WIN32
    if(!RemoveDirectory(path))
      return false;
#else
    if(rmdir(path) != 0)
      return false;
#endif
    path = File::dirname(path);
  }
  return true;
}

bool Directory::open(const String& dirpath, const String& pattern, bool_t dirsOnly)
{
#ifdef _WIN32
  if(findFile != INVALID_HANDLE_VALUE)
  {
    SetLastError(ERROR_INVALID_HANDLE);
    return false;
  }

  this->dirsOnly = dirsOnly;
  this->dirpath = dirpath;
  const char_t* patExt = strrchr(pattern, '.');
  this->patternExtension = (patExt && !strpbrk(patExt + 1, "*?")) ? String(patExt + 1, -1) : String();

  String searchPath = dirpath;
  searchPath.reserve(dirpath.length() + 1 + pattern.length());
  if(!dirpath.isEmpty())
    searchPath.append('/');
  searchPath.append(pattern);

  findFile = FindFirstFileEx(searchPath,
#if _WIN32_WINNT > 0x0600
	  FindExInfoBasic,
#else
	  FindExInfoStandard,
#endif
	  (LPWIN32_FIND_DATA)ffd, dirsOnly ? FindExSearchLimitToDirectories : FindExSearchNameMatch, NULL, 0);
  if(findFile == INVALID_HANDLE_VALUE)
    return false;
  bufferedEntry = true;
  return true;
#else
  if(dp)
  {
    errno = EINVAL;
    return false;
  }

  this->dirsOnly = dirsOnly;
  this->dirpath = dirpath;
  this->pattern = pattern;

  dp = opendir(dirpath);
  return dp != 0;
#endif
}

bool Directory::read(String& name, bool_t& isDir)
{
#ifdef _WIN32
  if(!findFile)
  {
    SetLastError(ERROR_INVALID_HANDLE);
    return false;
  }
  for(;;)
  {
    if(bufferedEntry)
      bufferedEntry = false;
    else if(!FindNextFile((HANDLE)findFile, (LPWIN32_FIND_DATA)ffd))
    {
      DWORD lastError = GetLastError();
      FindClose((HANDLE)findFile);
      findFile = INVALID_HANDLE_VALUE;
      SetLastError(lastError);
      return false;
    }
    isDir = (((LPWIN32_FIND_DATA)ffd)->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
    if(dirsOnly && !isDir)
      continue;
    const char_t* str = ((LPWIN32_FIND_DATA)ffd)->cFileName;
    if(isDir && *str == '.' && (str[1] == '\0' || (str[1] == '.' && str[2] == '\0')))
      continue;

    if(!patternExtension.isEmpty())
    {
      const char_t* patExt = strrchr(str, '.');
      if(!patExt || stricmp(patternExtension, patExt + 1) != 0)
        continue;
    }

    name = String(str, (uint_t)strlen(str));
    return true;
  }
#else
  if(!dp)
  {
    errno = EINVAL;
    return false;
  }

  for(;;)
  {
    struct dirent* dent = readdir((DIR*)dp);
    if(!dent)
    {
      int lastErrno = errno;
      closedir((DIR*)dp);
      dp = 0;
      errno = lastErrno;
      return false;
    }
    const char_t* const str = dent->d_name;
    if(fnmatch(pattern, str, 0) == 0)
    {
      name = String(str, strlen(str));
      isDir = false;
      if(dent->d_type == DT_DIR)
        isDir = true;
      else if(dent->d_type == DT_LNK || dent->d_type == DT_UNKNOWN)
      {
        String path = dirpath;
        path.append('/');
        path.append(name);
        struct stat buff;
        if(stat(path, &buff) == 0)
          if(S_ISDIR(buff.st_mode))
            isDir = true;
      }
      if(dirsOnly && !isDir)
        continue;
      if(isDir && *str == '.' && (str[1] == '\0' || (str[1] == '.' && str[2] == '\0')))
        continue;
      return true;
    }
  }
  return false; // unreachable
#endif
}

bool Directory::exists(const String& dir)
{
#ifdef _WIN32
  WIN32_FIND_DATAA wfd;
  HANDLE hFind = FindFirstFileA(dir, &wfd);
  if(hFind == INVALID_HANDLE_VALUE)
    return false;
  bool_t isDir = (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
  FindClose(hFind);
  return isDir;
#else
  struct stat buf;
  if(stat(dir, &buf) != 0)
    return false;
  return S_ISDIR(buf.st_mode);
#endif
}

bool Directory::create(const String& dir)
{
  // TODO: set errno correctly

  const char_t* start = dir;
  const char_t* pos = &start[dir.length() - 1];
  for(; pos >= start; --pos)
    if(*pos == '\\' || *pos == '/')
    {
      if(!create(dir.substr(0, (int_t)(pos - start))))
      {
        return false;
      }
      break;
    }
  ++pos;
  bool_t result = false;
  if(*pos)
#ifdef _WIN32
    result = CreateDirectory(dir, NULL) == TRUE;
#else
    result = mkdir(dir, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) == 0;
#endif
  return result;
}

bool Directory::change(const String& dir)
{
#ifdef _WIN32
  return SetCurrentDirectory(dir) != FALSE;
#else
  return chdir(dir) == 0;
#endif
}
<|endoftext|>


<commit_before>#include "DtlsSocket.h"

#include <stdlib.h>

#include "mbedtls/error.h"

#include <stdio.h>
#define mbedtls_printf     printf
#define mbedtls_fprintf    fprintf

using namespace node;

static void my_debug( void *ctx, int level,
											const char *file, int line,
											const char *str )
{
	((void) level);

	mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
	fflush((FILE *) ctx);
}

Nan::Persistent<v8::FunctionTemplate> DtlsSocket::constructor;

void
DtlsSocket::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
	Nan::HandleScope scope;

	// Constructor
	v8::Local<v8::FunctionTemplate> ctor = Nan::New<v8::FunctionTemplate>(DtlsSocket::New);
	constructor.Reset(ctor);
	v8::Local<v8::ObjectTemplate>	ctorInst = ctor->InstanceTemplate();
	ctorInst->SetInternalFieldCount(1);
	ctor->SetClassName(Nan::New("DtlsSocket").ToLocalChecked());

	Nan::SetPrototypeMethod(ctor, "receiveData", ReceiveDataFromNode);
	Nan::SetPrototypeMethod(ctor, "close", Close);
	Nan::SetPrototypeMethod(ctor, "send", Send);
	Nan::SetPrototypeMethod(ctor, "connect", Connect);

	Nan::Set(target, Nan::New("DtlsSocket").ToLocalChecked(), ctor->GetFunction());
}

void DtlsSocket::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {

	size_t pub_key_len = Buffer::Length(info[0]);
	size_t priv_key_len = Buffer::Length(info[1]);
	size_t peer_pub_key_len = Buffer::Length(info[2]);

	const unsigned char *pub_key = (const unsigned char *)Buffer::Data(info[0]);
	const unsigned char *priv_key = (const unsigned char *)Buffer::Data(info[1]);
	const unsigned char *peer_pub_key = (const unsigned char *)Buffer::Data(info[2]);

	Nan::Callback* send_cb = new Nan::Callback(info[3].As<v8::Function>());
	Nan::Callback* hs_cb = new Nan::Callback(info[4].As<v8::Function>());
	Nan::Callback* error_cb = new Nan::Callback(info[5].As<v8::Function>());

	int debug_level = 0;
	if (info.Length() > 6) {
		debug_level = info[6]->Uint32Value();
	}

	DtlsSocket *socket = new DtlsSocket(
		pub_key, pub_key_len,
		priv_key, priv_key_len,
		peer_pub_key, peer_pub_key_len,
		send_cb, hs_cb, error_cb,
		debug_level);
	socket->Wrap(info.This());
	info.GetReturnValue().Set(info.This());
}

void DtlsSocket::ReceiveDataFromNode(const Nan::FunctionCallbackInfo<v8::Value>& info) {
	DtlsSocket *socket = Nan::ObjectWrap::Unwrap<DtlsSocket>(info.This());
	const unsigned char *recv_data = (const unsigned char *)Buffer::Data(info[0]);
	socket->store_data(recv_data, Buffer::Length(info[0]));

	int len = 1024;
	unsigned char buf[len];
	len = socket->receive_data(buf, len);

	if (len > 0) {
		info.GetReturnValue().Set(Nan::CopyBuffer((char*)buf, len).ToLocalChecked());
	}
}

void DtlsSocket::Close(const Nan::FunctionCallbackInfo<v8::Value>& info) {
	DtlsSocket *socket = Nan::ObjectWrap::Unwrap<DtlsSocket>(info.This());
	socket->close();
}

void DtlsSocket::Send(const Nan::FunctionCallbackInfo<v8::Value>& info) {
	DtlsSocket *socket = Nan::ObjectWrap::Unwrap<DtlsSocket>(info.This());

	const unsigned char *send_data = (const unsigned char *)Buffer::Data(info[0]);
	socket->send(send_data, Buffer::Length(info[0]));
}

void DtlsSocket::Connect(const Nan::FunctionCallbackInfo<v8::Value>& info) {
	DtlsSocket *socket = Nan::ObjectWrap::Unwrap<DtlsSocket>(info.This());
	socket->step();
}

int net_send( void *ctx, const unsigned char *buf, size_t len ) {
	DtlsSocket* socket = (DtlsSocket*)ctx;
	return socket->send_encrypted(buf, len);
}

int net_recv( void *ctx, unsigned char *buf, size_t len ) {
	DtlsSocket* socket = (DtlsSocket*)ctx;
	return socket->recv(buf, len);
}

DtlsSocket::DtlsSocket(const unsigned char *pub_key,
											 size_t pub_key_len,
											 const unsigned char *priv_key,
											 size_t priv_key_len,
											 const unsigned char *peer_pub_key,
											 size_t peer_pub_key_len,
											 Nan::Callback* send_callback,
											 Nan::Callback* hs_callback,
											 Nan::Callback* error_callback,
											 int debug_level)
		: Nan::ObjectWrap(),
		send_cb(send_callback),
		error_cb(error_callback),
		handshake_cb(hs_callback) {
	int ret;
	const char *pers = "dtls_client";

	mbedtls_ssl_init(&ssl_context);
  mbedtls_ssl_config_init(&conf);
  mbedtls_x509_crt_init(&clicert);
  mbedtls_pk_init(&pkey);
  mbedtls_entropy_init(&entropy);
  mbedtls_ctr_drbg_init(&ctr_drbg);

#if defined(MBEDTLS_DEBUG_C)
	mbedtls_debug_set_threshold(debug_level);
#endif

  ret = mbedtls_pk_parse_public_key(&pkey,
																		(const unsigned char *)pub_key,
																		pub_key_len);
	if (ret != 0) goto exit;

	ret = mbedtls_pk_parse_key(&pkey,
														 (const unsigned char *)priv_key,
														 priv_key_len,
														 NULL,
														 0);
	if (ret != 0) goto exit;

  ret = mbedtls_ctr_drbg_seed(&ctr_drbg,
															mbedtls_entropy_func,
															&entropy,
															(const unsigned char *) pers,
															strlen(pers));
  if (ret != 0) goto exit;

  ret = mbedtls_ssl_config_defaults(&conf,
																		MBEDTLS_SSL_IS_CLIENT,
																		MBEDTLS_SSL_TRANSPORT_DATAGRAM,
																		MBEDTLS_SSL_PRESET_DEFAULT);
	if (ret != 0) goto exit;
	mbedtls_ssl_conf_min_version(&conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);

	mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
	mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);

	ret = mbedtls_ssl_conf_own_cert(&conf, &clicert, &pkey);
	if (ret != 0) goto exit;

	mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
	static int ssl_cert_types[] = { MBEDTLS_TLS_CERT_TYPE_RAW_PUBLIC_KEY, MBEDTLS_TLS_CERT_TYPE_NONE };
	mbedtls_ssl_conf_client_certificate_types(&conf, ssl_cert_types);
	mbedtls_ssl_conf_server_certificate_types(&conf, ssl_cert_types);
	mbedtls_ssl_conf_certificate_receive(&conf, MBEDTLS_SSL_RECEIVE_CERTIFICATE_DISABLED);

  if((ret = mbedtls_ssl_setup(&ssl_context, &conf)) != 0) goto exit;

  if((ssl_context.session_negotiate->peer_cert = (mbedtls_x509_crt*)calloc(1,
                    sizeof(mbedtls_x509_crt))) == NULL)
  {
      ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
      goto exit;
  }
  mbedtls_x509_crt_init(ssl_context.session_negotiate->peer_cert);
  ret = mbedtls_pk_parse_public_key(&ssl_context.session_negotiate->peer_cert->pk,
																		(const unsigned char *)peer_pub_key,
																		peer_pub_key_len);
  if (ret != 0) goto exit;

	mbedtls_ssl_set_timer_cb(&ssl_context,
													 &timer,
													 mbedtls_timing_set_delay,
													 mbedtls_timing_get_delay);
	mbedtls_ssl_set_bio(&ssl_context, this, net_send, net_recv, NULL);

	return;
exit:
	throwError(ret);
	return;
}

int DtlsSocket::send_encrypted(const unsigned char *buf, size_t len) {
	v8::Local<v8::Value> argv[] = {
		Nan::CopyBuffer((char *)buf, len).ToLocalChecked()
	};
	send_cb->Call(1, argv);
	return len;
}

int DtlsSocket::recv(unsigned char *buf, size_t len) {
	if (recv_len != 0) {
		len = recv_len;
		memcpy(buf, recv_buf, recv_len);
		recv_buf = NULL;
		recv_len = 0;
		return len;
	}

	return MBEDTLS_ERR_SSL_WANT_READ;
}

int DtlsSocket::send(const unsigned char *buf, size_t len) {
	int ret;
	ret = mbedtls_ssl_write(&ssl_context, buf, len);
	if (ret < 0)
	{
		error(ret);
		return ret;
	}
	len = ret;
	return ret;
}

int DtlsSocket::receive_data(unsigned char *buf, int len) {
	int ret;

	if (ssl_context.state == MBEDTLS_SSL_HANDSHAKE_OVER) {
		// normal reading of unencrypted data
		memset(buf, 0, len);
		ret = mbedtls_ssl_read(&ssl_context, buf, len);
		if (ret <= 0) {
			error(ret);
			return 0;
		}
		return ret;
	}

	return step();
}

int DtlsSocket::step() {
	int ret;
	// handshake
	while (ssl_context.state != MBEDTLS_SSL_HANDSHAKE_OVER) {
		ret = mbedtls_ssl_handshake_step(&ssl_context);
		if (ret == 0) {
			// in these states we are waiting for more input
			if (
				ssl_context.state == MBEDTLS_SSL_SERVER_HELLO ||
				ssl_context.state == MBEDTLS_SSL_SERVER_KEY_EXCHANGE ||
				ssl_context.state == MBEDTLS_SSL_CERTIFICATE_REQUEST ||
				ssl_context.state == MBEDTLS_SSL_SERVER_HELLO_DONE ||
				ssl_context.state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ||
				ssl_context.state == MBEDTLS_SSL_SERVER_FINISHED
				) {
				return 0;
			}
			// keep looping to send everything
			continue;
		}
		// else if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) {
		// 	// client will start a new session, so reset things
		// 	reset();
		// 	continue;
		// }
		else if (ret != 0) {
			// bad things
			error(ret);
			return 0;
		}
	}

	// this should only be called once when we first finish the handshake
	handshake_cb->Call(0, NULL);
	return 0;
}

void DtlsSocket::throwError(int ret) {
	char error_buf[100];
	mbedtls_strerror(ret, error_buf, 100);
	Nan::ThrowError(error_buf);
}

void DtlsSocket::error(int ret) {
	char error_buf[100];
	mbedtls_strerror(ret, error_buf, 100);
	v8::Local<v8::Value> argv[] = {
		Nan::New(ret),
		Nan::New(error_buf).ToLocalChecked()
	};
	error_cb->Call(2, argv);
}

void DtlsSocket::store_data(const unsigned char *buf, size_t len) {
	recv_buf = buf;
	recv_len = len;
}

void DtlsSocket::close() {
	mbedtls_ssl_close_notify(&ssl_context);
}

DtlsSocket::~DtlsSocket() {
	delete send_cb;
	send_cb = nullptr;
	delete error_cb;
	error_cb = nullptr;
	delete handshake_cb;
	handshake_cb = nullptr;
	recv_buf = nullptr;
	mbedtls_x509_crt_free(&clicert);
	mbedtls_pk_free(&pkey);
	mbedtls_ssl_config_free(&conf);
	mbedtls_ctr_drbg_free(&ctr_drbg);
	mbedtls_entropy_free(&entropy);
	mbedtls_ssl_free(&ssl_context);
}
<commit_msg>Fix indent<commit_after>#include "DtlsSocket.h"

#include <stdlib.h>

#include "mbedtls/error.h"

#include <stdio.h>
#define mbedtls_printf     printf
#define mbedtls_fprintf    fprintf

using namespace node;

static void my_debug( void *ctx, int level,
											const char *file, int line,
											const char *str )
{
	((void) level);

	mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
	fflush((FILE *) ctx);
}

Nan::Persistent<v8::FunctionTemplate> DtlsSocket::constructor;

void
DtlsSocket::Initialize(Nan::ADDON_REGISTER_FUNCTION_ARGS_TYPE target) {
	Nan::HandleScope scope;

	// Constructor
	v8::Local<v8::FunctionTemplate> ctor = Nan::New<v8::FunctionTemplate>(DtlsSocket::New);
	constructor.Reset(ctor);
	v8::Local<v8::ObjectTemplate>	ctorInst = ctor->InstanceTemplate();
	ctorInst->SetInternalFieldCount(1);
	ctor->SetClassName(Nan::New("DtlsSocket").ToLocalChecked());

	Nan::SetPrototypeMethod(ctor, "receiveData", ReceiveDataFromNode);
	Nan::SetPrototypeMethod(ctor, "close", Close);
	Nan::SetPrototypeMethod(ctor, "send", Send);
	Nan::SetPrototypeMethod(ctor, "connect", Connect);

	Nan::Set(target, Nan::New("DtlsSocket").ToLocalChecked(), ctor->GetFunction());
}

void DtlsSocket::New(const Nan::FunctionCallbackInfo<v8::Value>& info) {

	size_t pub_key_len = Buffer::Length(info[0]);
	size_t priv_key_len = Buffer::Length(info[1]);
	size_t peer_pub_key_len = Buffer::Length(info[2]);

	const unsigned char *pub_key = (const unsigned char *)Buffer::Data(info[0]);
	const unsigned char *priv_key = (const unsigned char *)Buffer::Data(info[1]);
	const unsigned char *peer_pub_key = (const unsigned char *)Buffer::Data(info[2]);

	Nan::Callback* send_cb = new Nan::Callback(info[3].As<v8::Function>());
	Nan::Callback* hs_cb = new Nan::Callback(info[4].As<v8::Function>());
	Nan::Callback* error_cb = new Nan::Callback(info[5].As<v8::Function>());

	int debug_level = 0;
	if (info.Length() > 6) {
		debug_level = info[6]->Uint32Value();
	}

	DtlsSocket *socket = new DtlsSocket(
		pub_key, pub_key_len,
		priv_key, priv_key_len,
		peer_pub_key, peer_pub_key_len,
		send_cb, hs_cb, error_cb,
		debug_level);
	socket->Wrap(info.This());
	info.GetReturnValue().Set(info.This());
}

void DtlsSocket::ReceiveDataFromNode(const Nan::FunctionCallbackInfo<v8::Value>& info) {
	DtlsSocket *socket = Nan::ObjectWrap::Unwrap<DtlsSocket>(info.This());
	const unsigned char *recv_data = (const unsigned char *)Buffer::Data(info[0]);
	socket->store_data(recv_data, Buffer::Length(info[0]));

	int len = 1024;
	unsigned char buf[len];
	len = socket->receive_data(buf, len);

	if (len > 0) {
		info.GetReturnValue().Set(Nan::CopyBuffer((char*)buf, len).ToLocalChecked());
	}
}

void DtlsSocket::Close(const Nan::FunctionCallbackInfo<v8::Value>& info) {
	DtlsSocket *socket = Nan::ObjectWrap::Unwrap<DtlsSocket>(info.This());
	socket->close();
}

void DtlsSocket::Send(const Nan::FunctionCallbackInfo<v8::Value>& info) {
	DtlsSocket *socket = Nan::ObjectWrap::Unwrap<DtlsSocket>(info.This());

	const unsigned char *send_data = (const unsigned char *)Buffer::Data(info[0]);
	socket->send(send_data, Buffer::Length(info[0]));
}

void DtlsSocket::Connect(const Nan::FunctionCallbackInfo<v8::Value>& info) {
	DtlsSocket *socket = Nan::ObjectWrap::Unwrap<DtlsSocket>(info.This());
	socket->step();
}

int net_send( void *ctx, const unsigned char *buf, size_t len ) {
	DtlsSocket* socket = (DtlsSocket*)ctx;
	return socket->send_encrypted(buf, len);
}

int net_recv( void *ctx, unsigned char *buf, size_t len ) {
	DtlsSocket* socket = (DtlsSocket*)ctx;
	return socket->recv(buf, len);
}

DtlsSocket::DtlsSocket(const unsigned char *pub_key,
											 size_t pub_key_len,
											 const unsigned char *priv_key,
											 size_t priv_key_len,
											 const unsigned char *peer_pub_key,
											 size_t peer_pub_key_len,
											 Nan::Callback* send_callback,
											 Nan::Callback* hs_callback,
											 Nan::Callback* error_callback,
											 int debug_level)
		: Nan::ObjectWrap(),
		send_cb(send_callback),
		error_cb(error_callback),
		handshake_cb(hs_callback) {
	int ret;
	const char *pers = "dtls_client";

	mbedtls_ssl_init(&ssl_context);
	mbedtls_ssl_config_init(&conf);
	mbedtls_x509_crt_init(&clicert);
	mbedtls_pk_init(&pkey);
	mbedtls_entropy_init(&entropy);
	mbedtls_ctr_drbg_init(&ctr_drbg);

#if defined(MBEDTLS_DEBUG_C)
	mbedtls_debug_set_threshold(debug_level);
#endif

	ret = mbedtls_pk_parse_public_key(&pkey,
																		(const unsigned char *)pub_key,
																		pub_key_len);
	if (ret != 0) goto exit;

	ret = mbedtls_pk_parse_key(&pkey,
														 (const unsigned char *)priv_key,
														 priv_key_len,
														 NULL,
														 0);
	if (ret != 0) goto exit;

	ret = mbedtls_ctr_drbg_seed(&ctr_drbg,
															mbedtls_entropy_func,
															&entropy,
															(const unsigned char *) pers,
															strlen(pers));
	if (ret != 0) goto exit;

	ret = mbedtls_ssl_config_defaults(&conf,
																		MBEDTLS_SSL_IS_CLIENT,
																		MBEDTLS_SSL_TRANSPORT_DATAGRAM,
																		MBEDTLS_SSL_PRESET_DEFAULT);
	if (ret != 0) goto exit;
	mbedtls_ssl_conf_min_version(&conf, MBEDTLS_SSL_MAJOR_VERSION_3, MBEDTLS_SSL_MINOR_VERSION_3);

	mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
	mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);

	ret = mbedtls_ssl_conf_own_cert(&conf, &clicert, &pkey);
	if (ret != 0) goto exit;

	mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
	static int ssl_cert_types[] = { MBEDTLS_TLS_CERT_TYPE_RAW_PUBLIC_KEY, MBEDTLS_TLS_CERT_TYPE_NONE };
	mbedtls_ssl_conf_client_certificate_types(&conf, ssl_cert_types);
	mbedtls_ssl_conf_server_certificate_types(&conf, ssl_cert_types);
	mbedtls_ssl_conf_certificate_receive(&conf, MBEDTLS_SSL_RECEIVE_CERTIFICATE_DISABLED);

	if((ret = mbedtls_ssl_setup(&ssl_context, &conf)) != 0) goto exit;

	if((ssl_context.session_negotiate->peer_cert = (mbedtls_x509_crt*)calloc(1,
										sizeof(mbedtls_x509_crt))) == NULL)
	{
			ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
			goto exit;
	}
	mbedtls_x509_crt_init(ssl_context.session_negotiate->peer_cert);
	ret = mbedtls_pk_parse_public_key(&ssl_context.session_negotiate->peer_cert->pk,
																		(const unsigned char *)peer_pub_key,
																		peer_pub_key_len);
	if (ret != 0) goto exit;

	mbedtls_ssl_set_timer_cb(&ssl_context,
													 &timer,
													 mbedtls_timing_set_delay,
													 mbedtls_timing_get_delay);
	mbedtls_ssl_set_bio(&ssl_context, this, net_send, net_recv, NULL);

	return;
exit:
	throwError(ret);
	return;
}

int DtlsSocket::send_encrypted(const unsigned char *buf, size_t len) {
	v8::Local<v8::Value> argv[] = {
		Nan::CopyBuffer((char *)buf, len).ToLocalChecked()
	};
	send_cb->Call(1, argv);
	return len;
}

int DtlsSocket::recv(unsigned char *buf, size_t len) {
	if (recv_len != 0) {
		len = recv_len;
		memcpy(buf, recv_buf, recv_len);
		recv_buf = NULL;
		recv_len = 0;
		return len;
	}

	return MBEDTLS_ERR_SSL_WANT_READ;
}

int DtlsSocket::send(const unsigned char *buf, size_t len) {
	int ret;
	ret = mbedtls_ssl_write(&ssl_context, buf, len);
	if (ret < 0)
	{
		error(ret);
		return ret;
	}
	len = ret;
	return ret;
}

int DtlsSocket::receive_data(unsigned char *buf, int len) {
	int ret;

	if (ssl_context.state == MBEDTLS_SSL_HANDSHAKE_OVER) {
		// normal reading of unencrypted data
		memset(buf, 0, len);
		ret = mbedtls_ssl_read(&ssl_context, buf, len);
		if (ret <= 0) {
			error(ret);
			return 0;
		}
		return ret;
	}

	return step();
}

int DtlsSocket::step() {
	int ret;
	// handshake
	while (ssl_context.state != MBEDTLS_SSL_HANDSHAKE_OVER) {
		ret = mbedtls_ssl_handshake_step(&ssl_context);
		if (ret == 0) {
			// in these states we are waiting for more input
			if (
				ssl_context.state == MBEDTLS_SSL_SERVER_HELLO ||
				ssl_context.state == MBEDTLS_SSL_SERVER_KEY_EXCHANGE ||
				ssl_context.state == MBEDTLS_SSL_CERTIFICATE_REQUEST ||
				ssl_context.state == MBEDTLS_SSL_SERVER_HELLO_DONE ||
				ssl_context.state == MBEDTLS_SSL_SERVER_CHANGE_CIPHER_SPEC ||
				ssl_context.state == MBEDTLS_SSL_SERVER_FINISHED
				) {
				return 0;
			}
			// keep looping to send everything
			continue;
		}
		// else if (ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) {
		// 	// client will start a new session, so reset things
		// 	reset();
		// 	continue;
		// }
		else if (ret != 0) {
			// bad things
			error(ret);
			return 0;
		}
	}

	// this should only be called once when we first finish the handshake
	handshake_cb->Call(0, NULL);
	return 0;
}

void DtlsSocket::throwError(int ret) {
	char error_buf[100];
	mbedtls_strerror(ret, error_buf, 100);
	Nan::ThrowError(error_buf);
}

void DtlsSocket::error(int ret) {
	char error_buf[100];
	mbedtls_strerror(ret, error_buf, 100);
	v8::Local<v8::Value> argv[] = {
		Nan::New(ret),
		Nan::New(error_buf).ToLocalChecked()
	};
	error_cb->Call(2, argv);
}

void DtlsSocket::store_data(const unsigned char *buf, size_t len) {
	recv_buf = buf;
	recv_len = len;
}

void DtlsSocket::close() {
	mbedtls_ssl_close_notify(&ssl_context);
}

DtlsSocket::~DtlsSocket() {
	delete send_cb;
	send_cb = nullptr;
	delete error_cb;
	error_cb = nullptr;
	delete handshake_cb;
	handshake_cb = nullptr;
	recv_buf = nullptr;
	mbedtls_x509_crt_free(&clicert);
	mbedtls_pk_free(&pkey);
	mbedtls_ssl_config_free(&conf);
	mbedtls_ctr_drbg_free(&ctr_drbg);
	mbedtls_entropy_free(&entropy);
	mbedtls_ssl_free(&ssl_context);
}
<|endoftext|>


<commit_before>#include "EBCReader.h"

#include <cstdio>
#include <sstream>

namespace osgtt {

bool EBCReader::setCRDFile(const std::string& crd) {
	char buff[1024];

	_vertices = new osg::Vec3Array();

	FILE* fp = std::fopen(crd.c_str(), "r");

	if(!fp) return false;

	char* ptr = 0;

	while((ptr = std::fgets(buff, 1024, fp))) {
		osg::Vec3 v;

		// TODO: Handle doubles here properly...
		std::sscanf(buff, "%f %f %f %f", &v.x(), &v.x(), &v.y(), &v.z());

		_vertices->push_back(v);
	}

	std::fclose(fp);

	return true;
}

EBCNode* EBCReader::readEBCFile(const std::string& ebc, osg::PrimitiveSet::Mode mode) {
	char buff[1024];

	osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(mode, 0);

	FILE* fp = std::fopen(ebc.c_str(), "r");

	if(!fp) return 0;

	char* ptr = 0;

	while((ptr = std::fgets(buff, 1024, fp))) {
		if(mode == osg::PrimitiveSet::TRIANGLES) {
		unsigned int e0;
		unsigned int e1;
		unsigned int e2;

		sscanf(buff, "%d %d %d", &e0, &e1, &e2);

		elements->push_back(e0);
		elements->push_back(e1);
		elements->push_back(e2);
	}
	}

	std::fclose(fp);

	EBCNode* ebcNode = new EBCNode(_vertices, elements, mode);

	std::ostringstream geometryName;

	geometryName << ebc << " (Geometry)";

	ebcNode->setName(ebc);
	ebcNode->getDrawable(0)->setName(geometryName.str());

	return ebcNode;
}

}

<commit_msg>Reverse order of polygon vertices to invert back-ness.<commit_after>#include "EBCReader.h"

#include <cstdio>
#include <sstream>

namespace osgtt {

bool EBCReader::setCRDFile(const std::string& crd) {
	char buff[1024];

	_vertices = new osg::Vec3Array();

	FILE* fp = std::fopen(crd.c_str(), "r");

	if(!fp) return false;

	char* ptr = 0;

	while((ptr = std::fgets(buff, 1024, fp))) {
		osg::Vec3 v;

		// TODO: Handle doubles here properly...
		std::sscanf(buff, "%f %f %f %f", &v.x(), &v.x(), &v.y(), &v.z());

		_vertices->push_back(v);
	}

	std::fclose(fp);

	return true;
}

EBCNode* EBCReader::readEBCFile(const std::string& ebc, osg::PrimitiveSet::Mode mode) {
	char buff[1024];

	osg::DrawElementsUInt* elements = new osg::DrawElementsUInt(mode, 0);

	FILE* fp = std::fopen(ebc.c_str(), "r");

	if(!fp) return 0;

	char* ptr = 0;

	while((ptr = std::fgets(buff, 1024, fp))) {
		if(mode == osg::PrimitiveSet::TRIANGLES) {
		unsigned int e0;
		unsigned int e1;
		unsigned int e2;

		sscanf(buff, "%d %d %d", &e0, &e1, &e2);

		elements->push_back(e2);
		elements->push_back(e1);
		elements->push_back(e0);
	}
	}

	std::fclose(fp);

	EBCNode* ebcNode = new EBCNode(_vertices, elements, mode);

	std::ostringstream geometryName;

	geometryName << ebc << " (Geometry)";

	ebcNode->setName(ebc);
	ebcNode->getDrawable(0)->setName(geometryName.str());

	return ebcNode;
}

}

<|endoftext|>


<commit_before>/*
 * FTGL - OpenGL font library
 *
 * Copyright (c) 2001-2004 Henry Maddocks <ftgl@opengl.geek.nz>
 * Copyright (c) 2008 Sam Hocevar <sam@hocevar.net>
 * Copyright (c) 2008 Éric Beets <ericbeets@free.fr>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "config.h"

#include "FTContour.h"

#include <math.h>

static const unsigned int BEZIER_STEPS = 5;

void FTContour::AddPoint(FTPoint point)
{
    if(pointList.empty() || (point != pointList[pointList.size() - 1]
                              && point != pointList[0]))
    {
        pointList.push_back(point);
    }
}

void FTContour::AddOutsetPoint(FTPoint point)
{
    outsetPointList.push_back(point);
}

void FTContour::AddFrontPoint(FTPoint point)
{
    frontPointList.push_back(point);
}

void FTContour::AddBackPoint(FTPoint point)
{
    backPointList.push_back(point);
}

void FTContour::evaluateQuadraticCurve(FTPoint A, FTPoint B, FTPoint C)
{
    for(unsigned int i = 1; i < BEZIER_STEPS; i++)
    {
        float t = static_cast<float>(i) / BEZIER_STEPS;

        FTPoint U = (1.0f - t) * A + t * B;
        FTPoint V = (1.0f - t) * B + t * C;

        AddPoint((1.0f - t) * U + t * V);
    }
}

void FTContour::evaluateCubicCurve(FTPoint A, FTPoint B, FTPoint C, FTPoint D)
{
    for(unsigned int i = 0; i < BEZIER_STEPS; i++)
    {
        float t = static_cast<float>(i) / BEZIER_STEPS;

        FTPoint U = (1.0f - t) * A + t * B;
        FTPoint V = (1.0f - t) * B + t * C;
        FTPoint W = (1.0f - t) * C + t * D;

        FTPoint M = (1.0f - t) * U + t * V;
        FTPoint N = (1.0f - t) * V + t * W;

        AddPoint((1.0f - t) * M + t * N);
    }
}

// This function is a bit tricky. Given a path ABC, it returns the
// coordinates of the outset point facing B on the left at a distance
// of 64.0.
//                                         M
//                            - - - - - - X
//                             ^         / '
//                             | 64.0   /   '
//  X---->-----X     ==>    X--v-------X     '
// A          B \          A          B \   .>'
//               \                       \<'  64.0
//                \                       \                  .
//                 \                       \                 .
//                C X                     C X
//
FTPoint FTContour::ComputeOutsetPoint(FTPoint A, FTPoint B, FTPoint C)
{
    /* Build the rotation matrix from 'ba' vector */
    FTPoint ba = (A - B).Normalise();
    FTPoint bc = C - B;

    /* Rotate bc to the left */
    FTPoint tmp(bc.X() * -ba.X() + bc.Y() * -ba.Y(),
                bc.X() * ba.Y() + bc.Y() * -ba.X());

    /* Compute the vector bisecting 'abc' */
    FTGL_DOUBLE norm = sqrt(tmp.X() * tmp.X() + tmp.Y() * tmp.Y());
    FTGL_DOUBLE dist = 64.0 * sqrt((norm - tmp.X()) / (norm + tmp.X()));
    tmp.X(tmp.Y() < 0.0 ? dist : -dist);
    tmp.Y(64.0);

    /* Rotate the new bc to the right */
    return FTPoint(tmp.X() * -ba.X() + tmp.Y() * ba.Y(),
                   tmp.X() * -ba.Y() + tmp.Y() * -ba.X());
}

void FTContour::SetParity(int parity)
{
    size_t size = PointCount();
    FTPoint vOutset;

    if(((parity & 1) && clockwise) || (!(parity & 1) && !clockwise))
    {
        // Contour orientation is wrong! We must reverse all points.
        // FIXME: could it be worth writing FTVector::reverse() for this?
        for(size_t i = 0; i < size / 2; i++)
        {
            FTPoint tmp = pointList[i];
            pointList[i] = pointList[size - 1 - i];
            pointList[size - 1 -i] = tmp;
        }

        clockwise = !clockwise;
    }

    for(size_t i = 0; i < size; i++)
    {
        size_t prev, cur, next;

        prev = (i + size - 1) % size;
        cur = i;
        next = (i + size + 1) % size;

        vOutset = ComputeOutsetPoint(Point(prev), Point(cur), Point(next));
        AddOutsetPoint(vOutset);
    }
}

FTContour::FTContour(FT_Vector* contour, char* tags, unsigned int n)
{
    FTPoint prev, cur(contour[(n - 1) % n]), next(contour[0]);
    FTPoint a, b = next - cur;
    double olddir, dir = atan2((next - cur).Y(), (next - cur).X());
    double angle = 0.0;

    // See http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-6.html
    // for a full description of FreeType tags.
    for(unsigned int i = 0; i < n; i++)
    {
        prev = cur;
        cur = next;
        next = FTPoint(contour[(i + 1) % n]);
        olddir = dir;
        dir = atan2((next - cur).Y(), (next - cur).X());

        // Compute our path's new direction.
        double t = dir - olddir;
        if(t < -M_PI) t += 2 * M_PI;
        if(t > M_PI) t -= 2 * M_PI;
        angle += t;

        // Only process point tags we know.
        if(n < 2 || FT_CURVE_TAG(tags[i]) == FT_Curve_Tag_On)
        {
            AddPoint(cur);
        }
        else if(FT_CURVE_TAG(tags[i]) == FT_Curve_Tag_Conic)
        {
            FTPoint prev2 = prev, next2 = next;

            // Previous point is either the real previous point (an "on"
            // point), or the midpoint between the current one and the
            // previous "conic off" point.
            if(FT_CURVE_TAG(tags[(i - 1 + n) % n]) == FT_Curve_Tag_Conic)
            {
                prev2 = (cur + prev) * 0.5;
                AddPoint(prev2);
            }

            // Next point is either the real next point or the midpoint.
            if(FT_CURVE_TAG(tags[(i + 1) % n]) == FT_Curve_Tag_Conic)
            {
                next2 = (cur + next) * 0.5;
            }

            evaluateQuadraticCurve(prev2, cur, next2);
        }
        else if(FT_CURVE_TAG(tags[i]) == FT_Curve_Tag_Cubic
                 && FT_CURVE_TAG(tags[(i + 1) % n]) == FT_Curve_Tag_Cubic)
        {
            evaluateCubicCurve(prev, cur, next,
                               FTPoint(contour[(i + 2) % n]));
        }
    }

    // If final angle is positive (+2PI), it's an anti-clockwise contour,
    // otherwise (-2PI) it's clockwise.
    clockwise = (angle < 0.0);
}

void FTContour::buildFrontOutset(float outset)
{
    for(size_t i = 0; i < PointCount(); ++i)
    {
        AddFrontPoint(Point(i) + Outset(i) * outset);
    }
}

void FTContour::buildBackOutset(float outset)
{
    for(size_t i = 0; i < PointCount(); ++i)
    {
        AddBackPoint(Point(i) + Outset(i) * outset);
    }
}

<commit_msg>FTContour: fix a memory leak in the outset building. SF #3302743.<commit_after>/*
 * FTGL - OpenGL font library
 *
 * Copyright (c) 2001-2004 Henry Maddocks <ftgl@opengl.geek.nz>
 * Copyright (c) 2008 Sam Hocevar <sam@hocevar.net>
 * Copyright (c) 2008 Éric Beets <ericbeets@free.fr>
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include "config.h"

#include "FTContour.h"

#include <math.h>

static const unsigned int BEZIER_STEPS = 5;

void FTContour::AddPoint(FTPoint point)
{
    if(pointList.empty() || (point != pointList[pointList.size() - 1]
                              && point != pointList[0]))
    {
        pointList.push_back(point);
    }
}

void FTContour::AddOutsetPoint(FTPoint point)
{
    outsetPointList.push_back(point);
}

void FTContour::AddFrontPoint(FTPoint point)
{
    frontPointList.push_back(point);
}

void FTContour::AddBackPoint(FTPoint point)
{
    backPointList.push_back(point);
}

void FTContour::evaluateQuadraticCurve(FTPoint A, FTPoint B, FTPoint C)
{
    for(unsigned int i = 1; i < BEZIER_STEPS; i++)
    {
        float t = static_cast<float>(i) / BEZIER_STEPS;

        FTPoint U = (1.0f - t) * A + t * B;
        FTPoint V = (1.0f - t) * B + t * C;

        AddPoint((1.0f - t) * U + t * V);
    }
}

void FTContour::evaluateCubicCurve(FTPoint A, FTPoint B, FTPoint C, FTPoint D)
{
    for(unsigned int i = 0; i < BEZIER_STEPS; i++)
    {
        float t = static_cast<float>(i) / BEZIER_STEPS;

        FTPoint U = (1.0f - t) * A + t * B;
        FTPoint V = (1.0f - t) * B + t * C;
        FTPoint W = (1.0f - t) * C + t * D;

        FTPoint M = (1.0f - t) * U + t * V;
        FTPoint N = (1.0f - t) * V + t * W;

        AddPoint((1.0f - t) * M + t * N);
    }
}

// This function is a bit tricky. Given a path ABC, it returns the
// coordinates of the outset point facing B on the left at a distance
// of 64.0.
//                                         M
//                            - - - - - - X
//                             ^         / '
//                             | 64.0   /   '
//  X---->-----X     ==>    X--v-------X     '
// A          B \          A          B \   .>'
//               \                       \<'  64.0
//                \                       \                  .
//                 \                       \                 .
//                C X                     C X
//
FTPoint FTContour::ComputeOutsetPoint(FTPoint A, FTPoint B, FTPoint C)
{
    /* Build the rotation matrix from 'ba' vector */
    FTPoint ba = (A - B).Normalise();
    FTPoint bc = C - B;

    /* Rotate bc to the left */
    FTPoint tmp(bc.X() * -ba.X() + bc.Y() * -ba.Y(),
                bc.X() * ba.Y() + bc.Y() * -ba.X());

    /* Compute the vector bisecting 'abc' */
    FTGL_DOUBLE norm = sqrt(tmp.X() * tmp.X() + tmp.Y() * tmp.Y());
    FTGL_DOUBLE dist = 64.0 * sqrt((norm - tmp.X()) / (norm + tmp.X()));
    tmp.X(tmp.Y() < 0.0 ? dist : -dist);
    tmp.Y(64.0);

    /* Rotate the new bc to the right */
    return FTPoint(tmp.X() * -ba.X() + tmp.Y() * ba.Y(),
                   tmp.X() * -ba.Y() + tmp.Y() * -ba.X());
}

void FTContour::SetParity(int parity)
{
    size_t size = PointCount();
    FTPoint vOutset;

    if(((parity & 1) && clockwise) || (!(parity & 1) && !clockwise))
    {
        // Contour orientation is wrong! We must reverse all points.
        // FIXME: could it be worth writing FTVector::reverse() for this?
        for(size_t i = 0; i < size / 2; i++)
        {
            FTPoint tmp = pointList[i];
            pointList[i] = pointList[size - 1 - i];
            pointList[size - 1 -i] = tmp;
        }

        clockwise = !clockwise;
    }

    for(size_t i = 0; i < size; i++)
    {
        size_t prev, cur, next;

        prev = (i + size - 1) % size;
        cur = i;
        next = (i + size + 1) % size;

        vOutset = ComputeOutsetPoint(Point(prev), Point(cur), Point(next));
        AddOutsetPoint(vOutset);
    }
}

FTContour::FTContour(FT_Vector* contour, char* tags, unsigned int n)
{
    FTPoint prev, cur(contour[(n - 1) % n]), next(contour[0]);
    FTPoint a, b = next - cur;
    double olddir, dir = atan2((next - cur).Y(), (next - cur).X());
    double angle = 0.0;

    // See http://freetype.sourceforge.net/freetype2/docs/glyphs/glyphs-6.html
    // for a full description of FreeType tags.
    for(unsigned int i = 0; i < n; i++)
    {
        prev = cur;
        cur = next;
        next = FTPoint(contour[(i + 1) % n]);
        olddir = dir;
        dir = atan2((next - cur).Y(), (next - cur).X());

        // Compute our path's new direction.
        double t = dir - olddir;
        if(t < -M_PI) t += 2 * M_PI;
        if(t > M_PI) t -= 2 * M_PI;
        angle += t;

        // Only process point tags we know.
        if(n < 2 || FT_CURVE_TAG(tags[i]) == FT_Curve_Tag_On)
        {
            AddPoint(cur);
        }
        else if(FT_CURVE_TAG(tags[i]) == FT_Curve_Tag_Conic)
        {
            FTPoint prev2 = prev, next2 = next;

            // Previous point is either the real previous point (an "on"
            // point), or the midpoint between the current one and the
            // previous "conic off" point.
            if(FT_CURVE_TAG(tags[(i - 1 + n) % n]) == FT_Curve_Tag_Conic)
            {
                prev2 = (cur + prev) * 0.5;
                AddPoint(prev2);
            }

            // Next point is either the real next point or the midpoint.
            if(FT_CURVE_TAG(tags[(i + 1) % n]) == FT_Curve_Tag_Conic)
            {
                next2 = (cur + next) * 0.5;
            }

            evaluateQuadraticCurve(prev2, cur, next2);
        }
        else if(FT_CURVE_TAG(tags[i]) == FT_Curve_Tag_Cubic
                 && FT_CURVE_TAG(tags[(i + 1) % n]) == FT_Curve_Tag_Cubic)
        {
            evaluateCubicCurve(prev, cur, next,
                               FTPoint(contour[(i + 2) % n]));
        }
    }

    // If final angle is positive (+2PI), it's an anti-clockwise contour,
    // otherwise (-2PI) it's clockwise.
    clockwise = (angle < 0.0);
}

void FTContour::buildFrontOutset(float outset)
{
    frontPointList.clear();

    for(size_t i = 0; i < PointCount(); ++i)
    {
        AddFrontPoint(Point(i) + Outset(i) * outset);
    }
}

void FTContour::buildBackOutset(float outset)
{
    backPointList.clear();

    for(size_t i = 0; i < PointCount(); ++i)
    {
        AddBackPoint(Point(i) + Outset(i) * outset);
    }
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: frmhtml.cxx,v $
 *
 *  $Revision: 1.13 $
 *
 *  last change: $Author: obo $ $Date: 2008-02-26 15:06:27 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"

#include <tools/list.hxx>
#include <tools/table.hxx>

#ifndef _HTMLTOKN_H
#include <svtools/htmltokn.h>
#endif
#ifndef   SVTOOLS_ASYNCLINK_HXX
#include <svtools/asynclink.hxx>
#endif

#define _SVSTDARR_USHORTS
#define _SVSTDARR_ULONGS
#include <svtools/svstdarr.hxx>

#include <sfx2/sfx.hrc>

#include <sfx2/frmhtml.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/evntconf.hxx>
#include <sfx2/request.hxx>
#include <sfx2/fcontnr.hxx>
#include "sfxtypes.hxx"

#define SFX_HTMLFRMSIZE_REL 0x0001
#define SFX_HTMLFRMSIZE_PERCENT 0x0002

static sal_Char __READONLY_DATA sHTML_SC_yes[] =    "YES";
static sal_Char __READONLY_DATA sHTML_SC_no[] =     "NO";
static sal_Char __READONLY_DATA sHTML_SC_auto[] =   "AUTO";

#define HTML_O_READONLY "READONLY"
#define HTML_O_EDIT     "EDIT"

static HTMLOptionEnum __READONLY_DATA aScollingTable[] =
{
    { sHTML_SC_yes,     ScrollingYes    },
    { sHTML_SC_no,      ScrollingNo     },
    { sHTML_SC_auto,    ScrollingAuto   },
    { 0,                0               }
};

void SfxFrameHTMLParser::ParseFrameOptions( SfxFrameDescriptor *pFrame, const HTMLOptions *pOptions, const String& rBaseURL )
{
    // die Optionen holen und setzen
    Size aMargin( pFrame->GetMargin() );

    // MIB 15.7.97: Netscape scheint marginwidth auf 0 zu setzen, sobald
    // marginheight gesetzt wird und umgekehrt. Machen wir jetzt wegen
    // bug #41665# auch so.
    // Netscape l"a\st aber ein direktes Setzen auf 0 nicht zu, IE4.0 schon.
    // Den Bug machen wir nicht mit!
    BOOL bMarginWidth = FALSE, bMarginHeight = FALSE;

    USHORT nArrLen = pOptions->Count();
    for ( USHORT i=0; i<nArrLen; i++ )
    {
        const HTMLOption *pOption = (*pOptions)[i];
        switch( pOption->GetToken() )
        {
        case HTML_O_BORDERCOLOR:
            {
                Color aColor;
                pOption->GetColor( aColor );
                pFrame->SetWallpaper( Wallpaper( aColor ) );
                break;
            }
        case HTML_O_SRC:
            pFrame->SetURL(
                String(
                    INetURLObject::GetAbsURL(
                        rBaseURL, pOption->GetString())) );
            break;
        case HTML_O_NAME:
            pFrame->SetName( pOption->GetString() );
            break;
        case HTML_O_MARGINWIDTH:
            aMargin.Width() = pOption->GetNumber();

//          if( aMargin.Width() < 1 )
//              aMargin.Width() = 1;
            if( !bMarginHeight )
                aMargin.Height() = 0;
            bMarginWidth = TRUE;
            break;
        case HTML_O_MARGINHEIGHT:
            aMargin.Height() = pOption->GetNumber();

//          if( aMargin.Height() < 1 )
//              aMargin.Height() = 1;
            if( !bMarginWidth )
                aMargin.Width() = 0;
            bMarginHeight = TRUE;
            break;
        case HTML_O_SCROLLING:
            pFrame->SetScrollingMode(
                (ScrollingMode)pOption->GetEnum( aScollingTable,
                                                 ScrollingAuto ) );
            break;
        case HTML_O_FRAMEBORDER:
        {
            String aStr = pOption->GetString();
            BOOL bBorder = TRUE;
            if ( aStr.EqualsIgnoreCaseAscii("NO") ||
                 aStr.EqualsIgnoreCaseAscii("0") )
                bBorder = FALSE;
            pFrame->SetFrameBorder( bBorder );
            break;
        }
        case HTML_O_NORESIZE:
            pFrame->SetResizable( FALSE );
            break;
        default:
            if ( pOption->GetTokenString().EqualsIgnoreCaseAscii(
                                                        HTML_O_READONLY ) )
            {
                String aStr = pOption->GetString();
                BOOL bReadonly = TRUE;
                if ( aStr.EqualsIgnoreCaseAscii("FALSE") )
                    bReadonly = FALSE;
                pFrame->SetReadOnly( bReadonly );
            }
            else if ( pOption->GetTokenString().EqualsIgnoreCaseAscii(
                                                        HTML_O_EDIT ) )
            {
                String aStr = pOption->GetString();
                BOOL bEdit = TRUE;
                if ( aStr.EqualsIgnoreCaseAscii("FALSE") )
                    bEdit = FALSE;
                pFrame->SetEditable( bEdit );
            }

            break;
        }
    }

    pFrame->SetMargin( aMargin );
}
<commit_msg>INTEGRATION: CWS changefileheader (1.13.44); FILE MERGED 2008/04/01 15:38:53 thb 1.13.44.2: #i85898# Stripping all external header guards 2008/03/31 13:38:10 rt 1.13.44.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: frmhtml.cxx,v $
 * $Revision: 1.14 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"

#include <tools/list.hxx>
#include <tools/table.hxx>
#include <svtools/htmltokn.h>
#include <svtools/asynclink.hxx>

#define _SVSTDARR_USHORTS
#define _SVSTDARR_ULONGS
#include <svtools/svstdarr.hxx>

#include <sfx2/sfx.hrc>

#include <sfx2/frmhtml.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/viewfrm.hxx>
#include <sfx2/evntconf.hxx>
#include <sfx2/request.hxx>
#include <sfx2/fcontnr.hxx>
#include "sfxtypes.hxx"

#define SFX_HTMLFRMSIZE_REL 0x0001
#define SFX_HTMLFRMSIZE_PERCENT 0x0002

static sal_Char __READONLY_DATA sHTML_SC_yes[] =    "YES";
static sal_Char __READONLY_DATA sHTML_SC_no[] =     "NO";
static sal_Char __READONLY_DATA sHTML_SC_auto[] =   "AUTO";

#define HTML_O_READONLY "READONLY"
#define HTML_O_EDIT     "EDIT"

static HTMLOptionEnum __READONLY_DATA aScollingTable[] =
{
    { sHTML_SC_yes,     ScrollingYes    },
    { sHTML_SC_no,      ScrollingNo     },
    { sHTML_SC_auto,    ScrollingAuto   },
    { 0,                0               }
};

void SfxFrameHTMLParser::ParseFrameOptions( SfxFrameDescriptor *pFrame, const HTMLOptions *pOptions, const String& rBaseURL )
{
    // die Optionen holen und setzen
    Size aMargin( pFrame->GetMargin() );

    // MIB 15.7.97: Netscape scheint marginwidth auf 0 zu setzen, sobald
    // marginheight gesetzt wird und umgekehrt. Machen wir jetzt wegen
    // bug #41665# auch so.
    // Netscape l"a\st aber ein direktes Setzen auf 0 nicht zu, IE4.0 schon.
    // Den Bug machen wir nicht mit!
    BOOL bMarginWidth = FALSE, bMarginHeight = FALSE;

    USHORT nArrLen = pOptions->Count();
    for ( USHORT i=0; i<nArrLen; i++ )
    {
        const HTMLOption *pOption = (*pOptions)[i];
        switch( pOption->GetToken() )
        {
        case HTML_O_BORDERCOLOR:
            {
                Color aColor;
                pOption->GetColor( aColor );
                pFrame->SetWallpaper( Wallpaper( aColor ) );
                break;
            }
        case HTML_O_SRC:
            pFrame->SetURL(
                String(
                    INetURLObject::GetAbsURL(
                        rBaseURL, pOption->GetString())) );
            break;
        case HTML_O_NAME:
            pFrame->SetName( pOption->GetString() );
            break;
        case HTML_O_MARGINWIDTH:
            aMargin.Width() = pOption->GetNumber();

//          if( aMargin.Width() < 1 )
//              aMargin.Width() = 1;
            if( !bMarginHeight )
                aMargin.Height() = 0;
            bMarginWidth = TRUE;
            break;
        case HTML_O_MARGINHEIGHT:
            aMargin.Height() = pOption->GetNumber();

//          if( aMargin.Height() < 1 )
//              aMargin.Height() = 1;
            if( !bMarginWidth )
                aMargin.Width() = 0;
            bMarginHeight = TRUE;
            break;
        case HTML_O_SCROLLING:
            pFrame->SetScrollingMode(
                (ScrollingMode)pOption->GetEnum( aScollingTable,
                                                 ScrollingAuto ) );
            break;
        case HTML_O_FRAMEBORDER:
        {
            String aStr = pOption->GetString();
            BOOL bBorder = TRUE;
            if ( aStr.EqualsIgnoreCaseAscii("NO") ||
                 aStr.EqualsIgnoreCaseAscii("0") )
                bBorder = FALSE;
            pFrame->SetFrameBorder( bBorder );
            break;
        }
        case HTML_O_NORESIZE:
            pFrame->SetResizable( FALSE );
            break;
        default:
            if ( pOption->GetTokenString().EqualsIgnoreCaseAscii(
                                                        HTML_O_READONLY ) )
            {
                String aStr = pOption->GetString();
                BOOL bReadonly = TRUE;
                if ( aStr.EqualsIgnoreCaseAscii("FALSE") )
                    bReadonly = FALSE;
                pFrame->SetReadOnly( bReadonly );
            }
            else if ( pOption->GetTokenString().EqualsIgnoreCaseAscii(
                                                        HTML_O_EDIT ) )
            {
                String aStr = pOption->GetString();
                BOOL bEdit = TRUE;
                if ( aStr.EqualsIgnoreCaseAscii("FALSE") )
                    bEdit = FALSE;
                pFrame->SetEditable( bEdit );
            }

            break;
        }
    }

    pFrame->SetMargin( aMargin );
}
<|endoftext|>