<commit_before>#include "Settings.h"

#include <Shlwapi.h>
#include <algorithm>

#include "HotkeyActions.h"
#include "Logger.h"
#include "MiscUtils.h"
#include "Skin.h"
#include "StringUtils.h"

#define XML_AUDIODEV "audioDeviceID"
#define XML_HIDEFULL "hideFullscreen"
#define XML_HIDETIME "hideDelay"
#define XML_HIDESPEED "hideSpeed"
#define XML_LANGUAGE "language"
#define XML_NOTIFYICON "notifyIcon"
#define XML_ONTOP "onTop"
#define XML_OSD_OFFSET "osdEdgeOffset"
#define XML_OSD_POS "osdPosition"
#define XML_OSD_X "osdX"
#define XML_OSD_Y "osdY"
#define XML_SKIN "skin"
#define XML_SOUNDS "soundEffects"

std::wstring Settings::_appDir(L"");
Settings *Settings::instance;

Settings::Settings() {

}

Settings *Settings::Instance() {
    if (instance == NULL) {
        instance = new Settings();
        instance->Reload();
    }
    return instance;
}

void Settings::Reload() {
    _file = AppDir() + L"\\Settings.xml";
    CLOG(L"Loading settings file: %s", _file.c_str());

    std::string u8FileName = StringUtils::Narrow(_file);
    tinyxml2::XMLError result = _xml.LoadFile(u8FileName.c_str());
    if (result != tinyxml2::XMLError::XML_SUCCESS) {
        throw std::runtime_error("Failed to parse XML file");
    }

    _root = _xml.GetDocument()->FirstChildElement("settings");
    if (_root == NULL) {
        throw std::runtime_error("Could not find root XML element");
    }

    _skin = new Skin(SkinXML());
}

int Settings::Save() {
    FILE *stream;
    errno_t err = _wfopen_s(&stream, _file.c_str(), L"w");
    if (err != 0) {
        CLOG(L"Could not open settings file for writing!");
        return 100 + err;
    }
    tinyxml2::XMLError result = _xml.SaveFile(stream);
    fclose(stream);
    return result;
}

std::wstring Settings::AppDir() {
    if (_appDir.empty()) {
        wchar_t path[MAX_PATH];
        GetModuleFileName(NULL, path, MAX_PATH);
        PathRemoveFileSpec(path);
        _appDir = std::wstring(path);
    }
    return _appDir;
}

std::wstring Settings::SettingsApp() {
    return Settings::AppDir() + L"\\" + SETTINGS_APP;
}

std::wstring Settings::LanguagesDir() {
    return AppDir() + L"\\" + LANG_DIR;
}

std::wstring Settings::AudioDeviceID() {
    return GetText(XML_AUDIODEV);
}

std::wstring Settings::LanguageName() {
    std::wstring lang = GetText(XML_LANGUAGE);

    if (lang == L"") {
        return DEFAULT_LANGUAGE;
    } else {
        return lang;
    }
}

bool Settings::AlwaysOnTop() {
    return GetEnabled(XML_ONTOP);
}

bool Settings::HideFullscreen() {
    return GetEnabled(XML_HIDEFULL);
}

int Settings::OSDEdgeOffset() {
    if (HasSetting(XML_OSD_OFFSET)) {
        return GetInt(XML_OSD_OFFSET);
    } else {
        return DEFAULT_OSD_OFFSET;
    }
}

Settings::OSDPos Settings::OSDPosition() {
    std::wstring pos = GetText(XML_OSD_POS);
    if (pos == L"") {
        return DEFAULT_OSD_POS;
    }

    std::transform(pos.begin(), pos.end(), pos.begin(), ::tolower);
    if (pos == L"top") {
        return Top;
    } else if (pos == L"bottom") {
        return Bottom;
    } else if (pos == L"left") {
        return Left;
    } else if (pos == L"right") {
        return Right;
    } else if (pos == L"center") {
        return Center;
    } else if (pos == L"custom") {
        return Custom;
    }

    /* Default: */
    return DEFAULT_OSD_POS;
}

int Settings::OSDX() {
    return GetInt(XML_OSD_X);
}

int Settings::OSDY() {
    return GetInt(XML_OSD_Y);
}

Skin *Settings::CurrentSkin() {
    return _skin;
}

int Settings::HideDelay() {
    return GetInt(XML_HIDETIME);
}

int Settings::HideSpeed() {
    return GetInt(XML_HIDESPEED);
}

bool Settings::CurrentSkin(std::wstring skinName) {
    std::string name = StringUtils::Narrow(skinName);
    std::wstring xml = SkinXML(skinName);
    if (MiscUtils::FileExists(xml) == false) {
        return false;
    }

    SetText(XML_SKIN, name);
    return true;
}

std::wstring Settings::SkinName() {
    std::wstring name = GetText("skin");

    if (name == L"") {
        return DEFAULT_SKIN;
    } else {
        return name;
    }
}

std::wstring Settings::SkinXML() {
    return SkinXML(SkinName());
}

std::wstring Settings::SkinXML(std::wstring skinName) {
    std::wstring skinXML = Settings::AppDir() + L"\\" + SKINS_DIR L"\\"
        + skinName + L"\\" SKIN_XML;
    return skinXML;
}

std::unordered_map<int, int> Settings::Hotkeys() {
    std::unordered_map<int, int> keyMappings;

    tinyxml2::XMLElement *hotkeys = _root->FirstChildElement("hotkeys");
    tinyxml2::XMLElement *hotkey = hotkeys->FirstChildElement("hotkey");

    for (; hotkey != NULL; hotkey = hotkey->NextSiblingElement()) {
        int action = -1;
        hotkey->QueryIntAttribute("action", &action);
        if (action == -1) {
            CLOG(L"No action provided for hotkey; skipping");
            continue;
        }

        int combination = -1;
        hotkey->QueryIntAttribute("combination", &combination);
        if (combination == -1) {
            CLOG(L"No key combination provided for hotkey; skipping");
            continue;
        }

        /* Whew, we made it! */
        CLOG(L"Adding hotkey mapping: %d -> %d", combination, action);
        keyMappings[combination] = action;
    }

    return keyMappings;
}

bool Settings::NotifyIconEnabled() {
    return GetEnabled(XML_NOTIFYICON);
}

void Settings::NotifyIconEnabled(bool enable) {
    SetEnabled(XML_NOTIFYICON, enable);
}

bool Settings::SoundEffectsEnabled() {
    return GetEnabled(XML_SOUNDS);
}

void Settings::SoundEffectsEnabled(bool enable) {
    SetEnabled(XML_SOUNDS, enable);
}

bool Settings::HasSetting(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    return (el != NULL);
}

bool Settings::GetEnabled(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element '%s' not found", elementName.c_str());
        return false;
    } else {
        bool val = false;
        el->QueryBoolText(&val);
        return val;
    }
}

void Settings::SetEnabled(std::string elementName, bool enabled) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(enabled ? "true" : "false");
}

std::wstring Settings::GetText(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element '%s' not found", elementName.c_str());
        return L"";
    }

    const char* str = el->GetText();
    if (str == NULL) {
        return L"";
    } else {
        return StringUtils::Widen(str);
    }
}

void Settings::SetText(std::string elementName, std::string text) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(text.c_str());
}

int Settings::GetInt(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element '%s' not found", elementName.c_str());
        return 0;
    }

    int val = 0;
    el->QueryIntText(&val);
    return val;
}

void Settings::SetInt(std::string elementName, int value) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(value);
}

tinyxml2::XMLElement *Settings::GetOrCreateElement(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        el = _xml.NewElement(elementName.c_str());
        _root->InsertEndChild(el);
    }
    return el;
}<commit_msg>Make xml tag for fullscreen detection clearer<commit_after>#include "Settings.h"

#include <Shlwapi.h>
#include <algorithm>

#include "HotkeyActions.h"
#include "Logger.h"
#include "MiscUtils.h"
#include "Skin.h"
#include "StringUtils.h"

#define XML_AUDIODEV "audioDeviceID"
#define XML_HIDE_WHENFULL "hideFullscreen"
#define XML_HIDETIME "hideDelay"
#define XML_HIDESPEED "hideSpeed"
#define XML_LANGUAGE "language"
#define XML_NOTIFYICON "notifyIcon"
#define XML_ONTOP "onTop"
#define XML_OSD_OFFSET "osdEdgeOffset"
#define XML_OSD_POS "osdPosition"
#define XML_OSD_X "osdX"
#define XML_OSD_Y "osdY"
#define XML_SKIN "skin"
#define XML_SOUNDS "soundEffects"

std::wstring Settings::_appDir(L"");
Settings *Settings::instance;

Settings::Settings() {

}

Settings *Settings::Instance() {
    if (instance == NULL) {
        instance = new Settings();
        instance->Reload();
    }
    return instance;
}

void Settings::Reload() {
    _file = AppDir() + L"\\Settings.xml";
    CLOG(L"Loading settings file: %s", _file.c_str());

    std::string u8FileName = StringUtils::Narrow(_file);
    tinyxml2::XMLError result = _xml.LoadFile(u8FileName.c_str());
    if (result != tinyxml2::XMLError::XML_SUCCESS) {
        throw std::runtime_error("Failed to parse XML file");
    }

    _root = _xml.GetDocument()->FirstChildElement("settings");
    if (_root == NULL) {
        throw std::runtime_error("Could not find root XML element");
    }

    _skin = new Skin(SkinXML());
}

int Settings::Save() {
    FILE *stream;
    errno_t err = _wfopen_s(&stream, _file.c_str(), L"w");
    if (err != 0) {
        CLOG(L"Could not open settings file for writing!");
        return 100 + err;
    }
    tinyxml2::XMLError result = _xml.SaveFile(stream);
    fclose(stream);
    return result;
}

std::wstring Settings::AppDir() {
    if (_appDir.empty()) {
        wchar_t path[MAX_PATH];
        GetModuleFileName(NULL, path, MAX_PATH);
        PathRemoveFileSpec(path);
        _appDir = std::wstring(path);
    }
    return _appDir;
}

std::wstring Settings::SettingsApp() {
    return Settings::AppDir() + L"\\" + SETTINGS_APP;
}

std::wstring Settings::LanguagesDir() {
    return AppDir() + L"\\" + LANG_DIR;
}

std::wstring Settings::AudioDeviceID() {
    return GetText(XML_AUDIODEV);
}

std::wstring Settings::LanguageName() {
    std::wstring lang = GetText(XML_LANGUAGE);

    if (lang == L"") {
        return DEFAULT_LANGUAGE;
    } else {
        return lang;
    }
}

bool Settings::AlwaysOnTop() {
    return GetEnabled(XML_ONTOP);
}

bool Settings::HideFullscreen() {
    return GetEnabled(XML_HIDE_WHENFULL);
}

int Settings::OSDEdgeOffset() {
    if (HasSetting(XML_OSD_OFFSET)) {
        return GetInt(XML_OSD_OFFSET);
    } else {
        return DEFAULT_OSD_OFFSET;
    }
}

Settings::OSDPos Settings::OSDPosition() {
    std::wstring pos = GetText(XML_OSD_POS);
    if (pos == L"") {
        return DEFAULT_OSD_POS;
    }

    std::transform(pos.begin(), pos.end(), pos.begin(), ::tolower);
    if (pos == L"top") {
        return Top;
    } else if (pos == L"bottom") {
        return Bottom;
    } else if (pos == L"left") {
        return Left;
    } else if (pos == L"right") {
        return Right;
    } else if (pos == L"center") {
        return Center;
    } else if (pos == L"custom") {
        return Custom;
    }

    /* Default: */
    return DEFAULT_OSD_POS;
}

int Settings::OSDX() {
    return GetInt(XML_OSD_X);
}

int Settings::OSDY() {
    return GetInt(XML_OSD_Y);
}

Skin *Settings::CurrentSkin() {
    return _skin;
}

int Settings::HideDelay() {
    return GetInt(XML_HIDETIME);
}

int Settings::HideSpeed() {
    return GetInt(XML_HIDESPEED);
}

bool Settings::CurrentSkin(std::wstring skinName) {
    std::string name = StringUtils::Narrow(skinName);
    std::wstring xml = SkinXML(skinName);
    if (MiscUtils::FileExists(xml) == false) {
        return false;
    }

    SetText(XML_SKIN, name);
    return true;
}

std::wstring Settings::SkinName() {
    std::wstring name = GetText("skin");

    if (name == L"") {
        return DEFAULT_SKIN;
    } else {
        return name;
    }
}

std::wstring Settings::SkinXML() {
    return SkinXML(SkinName());
}

std::wstring Settings::SkinXML(std::wstring skinName) {
    std::wstring skinXML = Settings::AppDir() + L"\\" + SKINS_DIR L"\\"
        + skinName + L"\\" SKIN_XML;
    return skinXML;
}

std::unordered_map<int, int> Settings::Hotkeys() {
    std::unordered_map<int, int> keyMappings;

    tinyxml2::XMLElement *hotkeys = _root->FirstChildElement("hotkeys");
    tinyxml2::XMLElement *hotkey = hotkeys->FirstChildElement("hotkey");

    for (; hotkey != NULL; hotkey = hotkey->NextSiblingElement()) {
        int action = -1;
        hotkey->QueryIntAttribute("action", &action);
        if (action == -1) {
            CLOG(L"No action provided for hotkey; skipping");
            continue;
        }

        int combination = -1;
        hotkey->QueryIntAttribute("combination", &combination);
        if (combination == -1) {
            CLOG(L"No key combination provided for hotkey; skipping");
            continue;
        }

        /* Whew, we made it! */
        CLOG(L"Adding hotkey mapping: %d -> %d", combination, action);
        keyMappings[combination] = action;
    }

    return keyMappings;
}

bool Settings::NotifyIconEnabled() {
    return GetEnabled(XML_NOTIFYICON);
}

void Settings::NotifyIconEnabled(bool enable) {
    SetEnabled(XML_NOTIFYICON, enable);
}

bool Settings::SoundEffectsEnabled() {
    return GetEnabled(XML_SOUNDS);
}

void Settings::SoundEffectsEnabled(bool enable) {
    SetEnabled(XML_SOUNDS, enable);
}

bool Settings::HasSetting(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    return (el != NULL);
}

bool Settings::GetEnabled(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element '%s' not found", elementName.c_str());
        return false;
    } else {
        bool val = false;
        el->QueryBoolText(&val);
        return val;
    }
}

void Settings::SetEnabled(std::string elementName, bool enabled) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(enabled ? "true" : "false");
}

std::wstring Settings::GetText(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element '%s' not found", elementName.c_str());
        return L"";
    }

    const char* str = el->GetText();
    if (str == NULL) {
        return L"";
    } else {
        return StringUtils::Widen(str);
    }
}

void Settings::SetText(std::string elementName, std::string text) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(text.c_str());
}

int Settings::GetInt(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        CLOG(L"Warning: XML element '%s' not found", elementName.c_str());
        return 0;
    }

    int val = 0;
    el->QueryIntText(&val);
    return val;
}

void Settings::SetInt(std::string elementName, int value) {
    tinyxml2::XMLElement *el = GetOrCreateElement(elementName);
    el->SetText(value);
}

tinyxml2::XMLElement *Settings::GetOrCreateElement(std::string elementName) {
    tinyxml2::XMLElement *el = _root->FirstChildElement(elementName.c_str());
    if (el == NULL) {
        el = _xml.NewElement(elementName.c_str());
        _root->InsertEndChild(el);
    }
    return el;
}<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "TimeStepper.h"
#include "FEProblem.h"
#include "Transient.h"

template<>
InputParameters validParams<TimeStepper>()
{
  InputParameters params = validParams<MooseObject>();

  params.addPrivateParam<std::string>("built_by_action", "setup_time_stepper");
  params.addParam<bool>("reset_dt", false, "Use when restarting a calculation to force a change in dt.");
  return params;
}

TimeStepper::TimeStepper(const std::string & name, InputParameters parameters) :
    MooseObject(name, parameters),
    Restartable(name, parameters, "TimeSteppers"),
    _fe_problem(*getParam<FEProblem *>("_fe_problem")),
    _executioner(*getParam<Transient *>("_executioner")),
    _time(_fe_problem.time()),
    _time_old(_fe_problem.timeOld()),
    _t_step(_fe_problem.timeStep()),
    _dt(_fe_problem.dt()),
    _dt_min(_executioner.dtMin()),
    _dt_max(_executioner.dtMax()),
    _end_time(_executioner.endTime()),
    _sync_times(_executioner.syncTimes()),
    _timestep_tolerance(_executioner.timestepTol()),
    _verbose(_executioner.verbose()),
    _converged(true),
    _reset_dt(getParam<bool>("reset_dt")),
    _has_reset_dt(false),
    _current_dt(declareRestartableData("current_dt",1.0))
{
}

TimeStepper::~TimeStepper()
{
}

void
TimeStepper::init()
{
}

void
TimeStepper::preExecute()
{
  // Delete all sync times that are at or before the begin time
  while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin())
  {
    _sync_times.erase(_sync_times.begin());
  }
}

void
TimeStepper::computeStep()
{
  if (_t_step < 2 || (_reset_dt && !_has_reset_dt))
  {
    _has_reset_dt = true;

    if (converged())
      _current_dt = computeInitialDT();
    else
      _current_dt = computeFailedDT();
  }
  else
  {
    if (converged())
      _current_dt = computeDT();
    else
      _current_dt = computeFailedDT();
  }
}

bool
TimeStepper::constrainStep(Real &dt)
{
  bool force_output = false;

  std::ostringstream diag;

  // Don't let the time step size exceed maximum time step size
  if (dt > _dt_max)
  {
    dt = _dt_max;
    diag << "Limiting dt to dtmax: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << _dt_max
         << std::endl;
  }

  // Don't allow time step size to be smaller than minimum time step size
  if (dt < _dt_min)
  {
    dt = _dt_min;
    diag << "Increasing dt to dtmin: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << _dt_min
         << std::endl;
  }

  // Don't let time go beyond simulation end time
  if (_time + dt > _end_time)
  {
    dt = _end_time - _time;
    diag << "Limiting dt for end_time: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << _end_time
         << " dt: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << dt
         << std::endl;
  }

  // Adjust to a sync time if supplied
  if (!_sync_times.empty() && _time + dt + _timestep_tolerance >= (*_sync_times.begin()))
  {
    dt = *_sync_times.begin() - _time;
    diag << "Limiting dt for sync_time: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << *_sync_times.begin()
         << " dt: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << dt
         << std::endl;

    if (dt <= 0.0)
    {
      Moose::out << diag.str();
      mooseError("Adjusting to sync_time resulted in a non-positive time step.  dt: "
                 <<dt<<" sync_time: "<<*_sync_times.begin()<<" time: "<<_time);
    }

    force_output = true;
  }

  if (_verbose)
  {
    Moose::out << diag.str();
  }

  return force_output;
}

void
TimeStepper::step()
{
  _fe_problem.solve();
  _converged = _fe_problem.converged();
}

void
TimeStepper::acceptStep()
{
  // If there are sync times at or before the current time, delete them
  while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin())
  {
    _sync_times.erase(_sync_times.begin());
  }

}

void
TimeStepper::rejectStep()
{
  _fe_problem.restoreSolutions();
}

bool
TimeStepper::converged()
{
  return _converged;
}

Real
TimeStepper::computeFailedDT()
{
  if (_dt <= _dt_min)
    mooseError("Solve failed and timestep already at or below dtmin, cannot continue!");

  // cut the time step in a half
  if (0.5 * _dt >= _dt_min)
    return 0.5 * _dt;
  else // (0.5 * _current_dt < _dt_min)
    return _dt_min;
}

void
TimeStepper::forceTimeStep(Real dt)
{
  _current_dt = dt;
}
<commit_msg>Name change for consistency Ref #2265<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "TimeStepper.h"
#include "FEProblem.h"
#include "Transient.h"

template<>
InputParameters validParams<TimeStepper>()
{
  InputParameters params = validParams<MooseObject>();

  params.addPrivateParam<std::string>("built_by_action", "setup_time_stepper");
  params.addParam<bool>("reset_dt", false, "Use when restarting a calculation to force a change in dt.");
  return params;
}

TimeStepper::TimeStepper(const std::string & name, InputParameters parameters) :
    MooseObject(name, parameters),
    Restartable(name, parameters, "TimeSteppers"),
    _fe_problem(*getParam<FEProblem *>("_fe_problem")),
    _executioner(*getParam<Transient *>("_executioner")),
    _time(_fe_problem.time()),
    _time_old(_fe_problem.timeOld()),
    _t_step(_fe_problem.timeStep()),
    _dt(_fe_problem.dt()),
    _dt_min(_executioner.dtMin()),
    _dt_max(_executioner.dtMax()),
    _end_time(_executioner.endTime()),
    _sync_times(_executioner.syncTimes()),
    _timestep_tolerance(_executioner.timestepTol()),
    _verbose(_executioner.verbose()),
    _converged(true),
    _reset_dt(getParam<bool>("reset_dt")),
    _has_reset_dt(false),
    _current_dt(declareRestartableData("current_dt",1.0))
{
}

TimeStepper::~TimeStepper()
{
}

void
TimeStepper::init()
{
}

void
TimeStepper::preExecute()
{
  // Delete all sync times that are at or before the begin time
  while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin())
  {
    _sync_times.erase(_sync_times.begin());
  }
}

void
TimeStepper::computeStep()
{
  if (_t_step < 2 || (_reset_dt && !_has_reset_dt))
  {
    _has_reset_dt = true;

    if (converged())
      _current_dt = computeInitialDT();
    else
      _current_dt = computeFailedDT();
  }
  else
  {
    if (converged())
      _current_dt = computeDT();
    else
      _current_dt = computeFailedDT();
  }
}

bool
TimeStepper::constrainStep(Real &dt)
{
  bool at_sync_point = false;

  std::ostringstream diag;

  // Don't let the time step size exceed maximum time step size
  if (dt > _dt_max)
  {
    dt = _dt_max;
    diag << "Limiting dt to dtmax: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << _dt_max
         << std::endl;
  }

  // Don't allow time step size to be smaller than minimum time step size
  if (dt < _dt_min)
  {
    dt = _dt_min;
    diag << "Increasing dt to dtmin: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << _dt_min
         << std::endl;
  }

  // Don't let time go beyond simulation end time
  if (_time + dt > _end_time)
  {
    dt = _end_time - _time;
    diag << "Limiting dt for end_time: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << _end_time
         << " dt: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << dt
         << std::endl;
  }

  // Adjust to a sync time if supplied
  if (!_sync_times.empty() && _time + dt + _timestep_tolerance >= (*_sync_times.begin()))
  {
    dt = *_sync_times.begin() - _time;
    diag << "Limiting dt for sync_time: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << *_sync_times.begin()
         << " dt: "
         << std::setw(9)
         << std::setprecision(6)
         << std::setfill('0')
         << std::showpoint
         << std::left
         << dt
         << std::endl;

    if (dt <= 0.0)
    {
      Moose::out << diag.str();
      mooseError("Adjusting to sync_time resulted in a non-positive time step.  dt: "
                 <<dt<<" sync_time: "<<*_sync_times.begin()<<" time: "<<_time);
    }

    at_sync_point = true;
  }

  if (_verbose)
  {
    Moose::out << diag.str();
  }

  return at_sync_point;
}

void
TimeStepper::step()
{
  _fe_problem.solve();
  _converged = _fe_problem.converged();
}

void
TimeStepper::acceptStep()
{
  // If there are sync times at or before the current time, delete them
  while (!_sync_times.empty() && _time + _timestep_tolerance >= *_sync_times.begin())
  {
    _sync_times.erase(_sync_times.begin());
  }

}

void
TimeStepper::rejectStep()
{
  _fe_problem.restoreSolutions();
}

bool
TimeStepper::converged()
{
  return _converged;
}

Real
TimeStepper::computeFailedDT()
{
  if (_dt <= _dt_min)
    mooseError("Solve failed and timestep already at or below dtmin, cannot continue!");

  // cut the time step in a half
  if (0.5 * _dt >= _dt_min)
    return 0.5 * _dt;
  else // (0.5 * _current_dt < _dt_min)
    return _dt_min;
}

void
TimeStepper::forceTimeStep(Real dt)
{
  _current_dt = dt;
}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgShadow/ShadowMap>
#include <osgShadow/ShadowedScene>
#include <osg/Notify>
#include <osg/ComputeBoundsVisitor>
#include <osg/PolygonOffset>
#include <osg/CullFace>
#include <osg/io_utils>

using namespace osgShadow;

//////////////////////////////////////////////////////////////////
// fragment shader
//
char fragmentShaderSource_noBaseTexture[] =
    "uniform sampler2DShadow shadowTexture; \n"
    "uniform vec2 ambientBias; \n"
    "\n"
    "void main(void) \n"
    "{ \n"
    "    gl_FragColor = gl_Color * (ambientBias.x + shadow2DProj( shadowTexture, gl_TexCoord[0] ) * ambientBias.y); \n"
    "}\n";

//////////////////////////////////////////////////////////////////
// fragment shader
//
char fragmentShaderSource_withBaseTexture[] =
    "uniform sampler2D baseTexture; \n"
    "uniform sampler2DShadow shadowTexture; \n"
    "uniform vec2 ambientBias; \n"
    "\n"
    "void main(void) \n"
    "{ \n"
    "    vec4 color = gl_Color * texture2D( baseTexture, gl_TexCoord[0].xy ); \n"
    "    gl_FragColor = color * (ambientBias.x + shadow2DProj( shadowTexture, gl_TexCoord[1] ) * ambientBias.y); \n"
    "}\n";

ShadowMap::ShadowMap():
    _textureUnit(1)
{
    osg::notify(osg::NOTICE)<<"Warning: osgShadow::ShadowMap technique is in development."<<std::endl;
}

ShadowMap::ShadowMap(const ShadowMap& copy, const osg::CopyOp& copyop):
    ShadowTechnique(copy,copyop),
    _textureUnit(copy._textureUnit)
{
}

void ShadowMap::setTextureUnit(unsigned int unit)
{
    _textureUnit = unit;
}

void ShadowMap::init()
{
    if (!_shadowedScene) return;

    unsigned int tex_width = 1024;
    unsigned int tex_height = 1024;

    _texture = new osg::Texture2D;
    _texture->setTextureSize(tex_width, tex_height);
    _texture->setInternalFormat(GL_DEPTH_COMPONENT);
    _texture->setShadowComparison(true);
    _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
    _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
    _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);

    // set up the render to texture camera.
    {
        // create the camera
        _camera = new osg::Camera;

        _camera->setCullCallback(new CameraCullCallback(this));

        _camera->setClearMask(GL_DEPTH_BUFFER_BIT);
        //_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
        _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
        _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);

        // set viewport
        _camera->setViewport(0,0,tex_width,tex_height);

        // set the camera to render before the main camera.
        _camera->setRenderOrder(osg::Camera::PRE_RENDER);

        // tell the camera to use OpenGL frame buffer object where supported.
        _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
        //_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);

        // attach the texture and use it as the color buffer.
        _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get());

        osg::StateSet* stateset = _camera->getOrCreateStateSet();

        float factor = 0.0f;
        float units = 1.0f;

        osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset;
        polygon_offset->setFactor(factor);
        polygon_offset->setUnits(units);
        stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
        stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

        osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace;
        cull_face->setMode(osg::CullFace::FRONT);
        stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

    }

    {
        _stateset = new osg::StateSet;
        _stateset->setTextureAttributeAndModes(_textureUnit,_texture.get(),osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);

        _texgen = new osg::TexGen;

#if 1
        osg::Program* program = new osg::Program;
        _stateset->setAttribute(program);

        if (_textureUnit==0)
        {
            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_noBaseTexture);
            program->addShader(fragment_shader);

            osg::Uniform* shadowTextureSampler = new osg::Uniform("shadowTexture",(int)_textureUnit);
            _stateset->addUniform(shadowTextureSampler);
        }
        else
        {
            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_withBaseTexture);
            program->addShader(fragment_shader);

            osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0);
            _stateset->addUniform(baseTextureSampler);

            osg::Uniform* shadowTextureSampler = new osg::Uniform("shadowTexture",(int)_textureUnit);
            _stateset->addUniform(shadowTextureSampler);
        }

        osg::Uniform* ambientBias = new osg::Uniform("ambientBias",osg::Vec2(0.3f,1.2f));
        _stateset->addUniform(ambientBias);

#endif
    }

    _dirty = false;
}

void ShadowMap::update(osg::NodeVisitor& nv)
{
    _shadowedScene->osg::Group::traverse(nv);
}

void ShadowMap::cull(osgUtil::CullVisitor& cv)
{
    // record the traversal mask on entry so we can reapply it later.
    unsigned int traversalMask = cv.getTraversalMask();

    osgUtil::RenderStage* orig_rs = cv.getRenderStage();

    // do traversal of shadow recieving scene which does need to be decorated by the shadow map
    {
        cv.pushStateSet(_stateset.get());

        _shadowedScene->osg::Group::traverse(cv);

        cv.popStateSet();

    }

    // need to compute view frustum for RTT camera.
    // 1) get the light position
    // 2) get the center and extents of the view frustum

    const osg::Light* selectLight = 0;
    osg::Vec4 lightpos;

    osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList();
    for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin();
        itr != aml.end();
        ++itr)
    {
        const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get());
        if (light)
        {
            osg::RefMatrix* matrix = itr->second.get();
            if (matrix) lightpos = light->getPosition() * (*matrix);
            else lightpos = light->getPosition();

            selectLight = light;
        }
    }

    osg::Matrix eyeToWorld;
    eyeToWorld.invert(*cv.getModelViewMatrix());

    lightpos = lightpos * eyeToWorld;

    if (selectLight)
    {

        // get the bounds of the model.
        osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
        cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask());

        _shadowedScene->osg::Group::traverse(cbbv);

        osg::BoundingBox bb = cbbv.getBoundingBox();

        if (lightpos[3]!=0.0)
        {
            osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z());

            float centerDistance = (position-bb.center()).length();

            float znear = centerDistance-bb.radius();
            float zfar  = centerDistance+bb.radius();
            float zNearRatio = 0.001f;
            if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;

            float top   = (bb.radius()/centerDistance)*znear;
            float right = top;

            _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
            _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar);
            _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f));

            // compute the matrix which takes a vertex from local coords into tex coords
            // will use this later to specify osg::TexGen..
            osg::Matrix MVPT = _camera->getViewMatrix() *
                               _camera->getProjectionMatrix() *
                               osg::Matrix::translate(1.0,1.0,1.0) *
                               osg::Matrix::scale(0.5f,0.5f,0.5f);

            _texgen->setMode(osg::TexGen::EYE_LINEAR);
            _texgen->setPlanesFromMatrix(MVPT);
        }

        cv.setTraversalMask( traversalMask &
                             getShadowedScene()->getCastsShadowTraversalMask() );

        // do RTT camera traversal
        _camera->accept(cv);

        orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_textureUnit, cv.getModelViewMatrix(), _texgen.get());
    }

    // reapply the original traversal mask
    cv.setTraversalMask( traversalMask );
}

void ShadowMap::cleanSceneGraph()
{
}
<commit_msg>From Mihai Radu, Added support for directional lights to ShadowMap<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgShadow/ShadowMap>
#include <osgShadow/ShadowedScene>
#include <osg/Notify>
#include <osg/ComputeBoundsVisitor>
#include <osg/PolygonOffset>
#include <osg/CullFace>
#include <osg/io_utils>

using namespace osgShadow;

//////////////////////////////////////////////////////////////////
// fragment shader
//
char fragmentShaderSource_noBaseTexture[] =
    "uniform sampler2DShadow shadowTexture; \n"
    "uniform vec2 ambientBias; \n"
    "\n"
    "void main(void) \n"
    "{ \n"
    "    gl_FragColor = gl_Color * (ambientBias.x + shadow2DProj( shadowTexture, gl_TexCoord[0] ) * ambientBias.y); \n"
    "}\n";

//////////////////////////////////////////////////////////////////
// fragment shader
//
char fragmentShaderSource_withBaseTexture[] =
    "uniform sampler2D baseTexture; \n"
    "uniform sampler2DShadow shadowTexture; \n"
    "uniform vec2 ambientBias; \n"
    "\n"
    "void main(void) \n"
    "{ \n"
    "    vec4 color = gl_Color * texture2D( baseTexture, gl_TexCoord[0].xy ); \n"
    "    gl_FragColor = color * (ambientBias.x + shadow2DProj( shadowTexture, gl_TexCoord[1] ) * ambientBias.y); \n"
    "}\n";

ShadowMap::ShadowMap():
    _textureUnit(1)
{
    osg::notify(osg::NOTICE)<<"Warning: osgShadow::ShadowMap technique is in development."<<std::endl;
}

ShadowMap::ShadowMap(const ShadowMap& copy, const osg::CopyOp& copyop):
    ShadowTechnique(copy,copyop),
    _textureUnit(copy._textureUnit)
{
}

void ShadowMap::setTextureUnit(unsigned int unit)
{
    _textureUnit = unit;
}

void ShadowMap::init()
{
    if (!_shadowedScene) return;

    unsigned int tex_width = 1024;
    unsigned int tex_height = 1024;

    _texture = new osg::Texture2D;
    _texture->setTextureSize(tex_width, tex_height);
    _texture->setInternalFormat(GL_DEPTH_COMPONENT);
    _texture->setShadowComparison(true);
    _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE);
    _texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
    _texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);

    // set up the render to texture camera.
    {
        // create the camera
        _camera = new osg::Camera;

        _camera->setCullCallback(new CameraCullCallback(this));

        _camera->setClearMask(GL_DEPTH_BUFFER_BIT);
        //_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
        _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
        _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);

        // set viewport
        _camera->setViewport(0,0,tex_width,tex_height);

        // set the camera to render before the main camera.
        _camera->setRenderOrder(osg::Camera::PRE_RENDER);

        // tell the camera to use OpenGL frame buffer object where supported.
        _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
        //_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);

        // attach the texture and use it as the color buffer.
        _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get());

        osg::StateSet* stateset = _camera->getOrCreateStateSet();

        float factor = 0.0f;
        float units = 1.0f;

        osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset;
        polygon_offset->setFactor(factor);
        polygon_offset->setUnits(units);
        stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
        stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

        osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace;
        cull_face->setMode(osg::CullFace::FRONT);
        stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
        stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

    }

    {
        _stateset = new osg::StateSet;
        _stateset->setTextureAttributeAndModes(_textureUnit,_texture.get(),osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
        _stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);

        _texgen = new osg::TexGen;

#if 1
        osg::Program* program = new osg::Program;
        _stateset->setAttribute(program);

        if (_textureUnit==0)
        {
            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_noBaseTexture);
            program->addShader(fragment_shader);

            osg::Uniform* shadowTextureSampler = new osg::Uniform("shadowTexture",(int)_textureUnit);
            _stateset->addUniform(shadowTextureSampler);
        }
        else
        {
            osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentShaderSource_withBaseTexture);
            program->addShader(fragment_shader);

            osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0);
            _stateset->addUniform(baseTextureSampler);

            osg::Uniform* shadowTextureSampler = new osg::Uniform("shadowTexture",(int)_textureUnit);
            _stateset->addUniform(shadowTextureSampler);
        }

        osg::Uniform* ambientBias = new osg::Uniform("ambientBias",osg::Vec2(0.3f,1.2f));
        _stateset->addUniform(ambientBias);

#endif
    }

    _dirty = false;
}

void ShadowMap::update(osg::NodeVisitor& nv)
{
    _shadowedScene->osg::Group::traverse(nv);
}

void ShadowMap::cull(osgUtil::CullVisitor& cv)
{
    // record the traversal mask on entry so we can reapply it later.
    unsigned int traversalMask = cv.getTraversalMask();

    osgUtil::RenderStage* orig_rs = cv.getRenderStage();

    // do traversal of shadow recieving scene which does need to be decorated by the shadow map
    {
        cv.pushStateSet(_stateset.get());

        _shadowedScene->osg::Group::traverse(cv);

        cv.popStateSet();

    }

    // need to compute view frustum for RTT camera.
    // 1) get the light position
    // 2) get the center and extents of the view frustum

    const osg::Light* selectLight = 0;
    osg::Vec4 lightpos;

    osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList();
    for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin();
        itr != aml.end();
        ++itr)
    {
        const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get());
        if (light)
        {
            osg::RefMatrix* matrix = itr->second.get();
            if (matrix) lightpos = light->getPosition() * (*matrix);
            else lightpos = light->getPosition();

            selectLight = light;
        }
    }

    osg::Matrix eyeToWorld;
    eyeToWorld.invert(*cv.getModelViewMatrix());

    lightpos = lightpos * eyeToWorld;

    if (selectLight)
    {

        // get the bounds of the model.
        osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
        cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask());

        _shadowedScene->osg::Group::traverse(cbbv);

        osg::BoundingBox bb = cbbv.getBoundingBox();

        if (lightpos[3]!=0.0)
        {
            osg::Vec3 position(lightpos.x(), lightpos.y(), lightpos.z());

            float centerDistance = (position-bb.center()).length();

            float znear = centerDistance-bb.radius();
            float zfar  = centerDistance+bb.radius();
            float zNearRatio = 0.001f;
            if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;

            float top   = (bb.radius()/centerDistance)*znear;
            float right = top;

            _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
            _camera->setProjectionMatrixAsFrustum(-right,right,-top,top,znear,zfar);
            _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f));

            // compute the matrix which takes a vertex from local coords into tex coords
            // will use this later to specify osg::TexGen..
            osg::Matrix MVPT = _camera->getViewMatrix() *
                               _camera->getProjectionMatrix() *
                               osg::Matrix::translate(1.0,1.0,1.0) *
                               osg::Matrix::scale(0.5f,0.5f,0.5f);

            _texgen->setMode(osg::TexGen::EYE_LINEAR);
            _texgen->setPlanesFromMatrix(MVPT);
        }
        else
        {
            // make an orthographic projection
            osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z());
            lightDir.normalize();

            // set the position far away along the light direction
            osg::Vec3 position = lightDir * bb.radius()  * 20;

            float centerDistance = (position-bb.center()).length();

            float znear = centerDistance-bb.radius();
            float zfar  = centerDistance+bb.radius();
            float zNearRatio = 0.001f;
            if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;

            float top   = bb.radius();
            float right = top;

            _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
            _camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar);
            _camera->setViewMatrixAsLookAt(position,bb.center(),osg::Vec3(0.0f,1.0f,0.0f));

            // compute the matrix which takes a vertex from local coords into tex coords
            // will use this later to specify osg::TexGen..
            osg::Matrix MVPT = _camera->getViewMatrix() *
                               _camera->getProjectionMatrix() *
                               osg::Matrix::translate(1.0,1.0,1.0) *
                               osg::Matrix::scale(0.5f,0.5f,0.5f);

            _texgen->setMode(osg::TexGen::EYE_LINEAR);
            _texgen->setPlanesFromMatrix(MVPT);
        }

        cv.setTraversalMask( traversalMask &
                             getShadowedScene()->getCastsShadowTraversalMask() );

        // do RTT camera traversal
        _camera->accept(cv);

        orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_textureUnit, cv.getModelViewMatrix(), _texgen.get());
    }

    // reapply the original traversal mask
    cv.setTraversalMask( traversalMask );
}

void ShadowMap::cleanSceneGraph()
{
}
<|endoftext|>


<commit_before>/*
* oxygenwindowmanager.cpp
* pass some window mouse press/release/move event actions to window manager
* -------------------
*
* Copyright (c) 2010 Cédric Bellegarde <gnumdk@gmail.com>
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* Largely inspired from Qtcurve style
* Copyright (C) Craig Drummond, 2003 - 2010 craig.p.drummond@gmail.com
*
* 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 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 St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygenwindowmanager.h"
#include "oxygenstyle.h"
#include "config.h"

#include <gdk/gdkx.h>

namespace Oxygen
{

    //_________________________________________________
    WindowManager::WindowManager( void ):
        _mode( Full ),
        _drag( false ),
        _dragDistance( 4 ),
        _dragDelay( 500 ),
        _widget( 0L ),
        _x(-1),
        _y(-1)
    { initializeBlackList(); }

    //_________________________________________________
    WindowManager::~WindowManager( void )
    {
        _map.disconnectAll();
        _map.clear();
    }

    //_________________________________________________
    void WindowManager::registerWidget( GtkWidget* widget )
    {

        if( _map.contains( widget ) || widgetIsBlackListed( widget ) ) return;

        // Window with no decorations (set by app), let window manage it self
        if( GTK_IS_WINDOW( widget ) && !gtk_window_get_decorated( GTK_WINDOW( widget ) ) ) return;

        // widgets used in tabs also must be ignored (happens, unfortunately)
        GtkWidget* parent( gtk_widget_get_parent( widget ) );
        if( GTK_IS_NOTEBOOK( parent ) && Gtk::gtk_notebook_is_tab_label( GTK_NOTEBOOK( parent ), widget ) )
        { return; }

        #if OXYGEN_DEBUG
        std::cout << "Oxygen::WindowManager::registerWidget - " << widget << "(" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        // Force widget to listen to relevant events
        gtk_widget_add_events( widget,
            GDK_BUTTON_RELEASE_MASK |
            GDK_BUTTON_PRESS_MASK   |
            GDK_LEAVE_NOTIFY_MASK   |
            GDK_BUTTON1_MOTION_MASK );

        // allocate new Data object
        Data& data( _map.registerWidget( widget ) );

        // connect signals
        if( _mode != Disabled ) connect( widget, data );

    }

    //_________________________________________________
    void WindowManager::unregisterWidget( GtkWidget* widget )
    {
        if( !_map.contains( widget ) ) return;

        #if OXYGEN_DEBUG
        std::cout << "Oxygen::WindowManager::unregisterWidget - " << widget << "(" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        _map.value( widget ).disconnect( widget );
        _map.erase( widget );

        if( _widget == widget )
        {
            _widget = 0L;
            _x = -1;
            _y = -1;
            _drag = false;
        }

    }

    //_________________________________________________
    void WindowManager::setMode( WindowManager::Mode mode )
    {
        if( mode == _mode ) return;

        // connect/disconnect all data in map, based on new and old mode
        if( mode == Disabled ) { _map.disconnectAll(); }
        else if( _mode == Disabled )
        {
            DataMap<Data>::Map& map( _map.map() );
            for( DataMap<Data>::Map::iterator iter = map.begin(); iter != map.end(); ++iter )
            { connect( iter->first, iter->second ); }
        }

        // assign new mode
        _mode = mode;

    }

    //_________________________________________________
    gboolean WindowManager::wmStyleSet( GtkWidget* widget, GtkStyle* , gpointer data )
    {
        static_cast<WindowManager*>(data)->unregisterWidget( widget );
        return false;
    }

    //_________________________________________________
    gboolean WindowManager::wmDestroy( GtkWidget* widget, gpointer data )
    {
        static_cast<WindowManager*>(data)->unregisterWidget( widget );
        return false;
    }

    //_________________________________________________
    gboolean WindowManager::wmButtonPress(GtkWidget *widget, GdkEventButton* event, gpointer data )
    {

        if( event->type == GDK_BUTTON_PRESS && event->button == Gtk::LeftButton )
        {

            #if OXYGEN_DEBUG
            std::cout << "Oxygen::WindowManager::wmButtonPress - "
                << widget
                << "(" << G_OBJECT_TYPE_NAME( widget ) << ")"
                << " " << gtk_widget_get_name( widget )
                << std::endl;
            #endif

            return static_cast<WindowManager*>(data)->isWindowDragWidget( widget, event );

        } else return false;

    }

    //_________________________________________________
    gboolean WindowManager::wmButtonRelease(GtkWidget *widget, GdkEventButton*, gpointer data )
    { return static_cast<WindowManager*>( data )->finishDrag( widget ); }

    //_________________________________________________
    gboolean WindowManager::wmLeave(GtkWidget *widget, GdkEventCrossing*, gpointer data )
    { return static_cast<WindowManager*>( data )->finishDrag( widget ); }

    //_________________________________________________
    gboolean WindowManager::wmMotion( GtkWidget *widget, GdkEventMotion* event, gpointer data )
    { return static_cast<WindowManager*>(data)->startDrag( widget, event ); }

    //_________________________________________________________________
    gboolean WindowManager::startDelayedDrag( gpointer data )
    {
        static_cast<WindowManager*>( data )->startDrag();
        return FALSE;
    }

    //_________________________________________________
    bool WindowManager::isWindowDragWidget( GtkWidget* widget, GdkEventButton* event )
    {
        if( _mode == Disabled ) return false;
        else if( (!_drag) && withinWidget(widget, event ) && useEvent( widget, event ) )
        {

            // store widget and event position
            _widget = widget;
            _x = int(event->x_root);
            _y = int(event->y_root);

            // start timer
            if( _timer.isRunning() ) _timer.stop();
            _timer.start( _dragDelay, (GSourceFunc)startDelayedDrag, this );

            // enable drag and accept
            _drag = true;
            return true;

        } else return false;
    }

    //_________________________________________________________________
    bool WindowManager::startDrag( GtkWidget* widget, GdkEventMotion* event )
    {

        // make sure drag is enabled
        if( !_drag ) return false;

        // check displacement with respect to drag start
        const int distance( abs( _x - int(event->x_root) ) + abs( _y - int(event->y_root) ) );

        if( distance > 0 && _timer.isRunning() ) _timer.stop();
        if( distance < _dragDistance ) return false;

        // start drag from current position
        return startDrag( widget, int(event->x_root), int(event->y_root) );

    }

    //_________________________________________________________________
    bool WindowManager::startDrag( GtkWidget* widget, int x, int y )
    {
        // create xevent and send.
        XEvent     xev;
        GtkWindow  *topLevel = GTK_WINDOW( gtk_widget_get_toplevel( widget ) );
        GdkWindow  *window = gtk_widget_get_window( GTK_WIDGET( topLevel ) );
        GdkDisplay *display = gtk_widget_get_display( GTK_WIDGET( topLevel ) );
        GdkWindow  *root = gdk_screen_get_root_window( gtk_window_get_screen( topLevel ) );

        xev.xclient.type = ClientMessage;
        xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display(display, "_NET_WM_MOVERESIZE");
        xev.xclient.display = GDK_DISPLAY_XDISPLAY(display);
        xev.xclient.window = GDK_WINDOW_XID(window);
        xev.xclient.format = 32;
        xev.xclient.data.l[0] = x;
        xev.xclient.data.l[1] = y;
        xev.xclient.data.l[2] = 8; // NET::Move
        xev.xclient.data.l[3] = Button1;
        xev.xclient.data.l[4] = 0;
        XUngrabPointer(GDK_DISPLAY_XDISPLAY(display), CurrentTime);

        XSendEvent(
            GDK_DISPLAY_XDISPLAY(display),
            GDK_WINDOW_XID(root),
            False,
            SubstructureRedirectMask | SubstructureNotifyMask,
            &xev);

        // force a release as some widgets miss it...
        wmButtonRelease( widget, 0L, this );
        return true;
    }

    //_________________________________________________
    bool WindowManager::finishDrag( GtkWidget* widget )
    {

        _widget = 0L;
        _x = -1;
        _y = -1;

        if( _drag )
        {

            gtk_grab_remove(widget);
            gdk_pointer_ungrab( CurrentTime );
            _drag = false;
            return true;

        } else return false;

    }

    //_________________________________________________
    bool WindowManager::withinWidget( GtkWidget* widget, GdkEventButton* event ) const
    {

        // get widget window
        GdkWindow *window( gtk_widget_get_parent_window( widget ) );

        // Some widgets aren't realized (GeditWindow for exemple) ...
        if( !window ) return true;

        GtkAllocation allocation;

        if( GTK_IS_NOTEBOOK( widget ) )
        {

            Gtk::gtk_notebook_get_tabbar_rect( GTK_NOTEBOOK( widget ), &allocation );

        } else {

            #if GTK_CHECK_VERSION(2, 18, 0)
            gtk_widget_get_allocation( widget, &allocation );
            #else
            allocation = widget->allocation;
            #endif

        }

        // Need to get absolute coordinates
        int nx(0);
        int ny(0);
        gdk_window_get_origin(window, &nx, &ny );
        allocation.x += nx;
        allocation.y += ny;

        return Gtk::gdk_rectangle_contains( &allocation, int(event->x_root), int(event->y_root) );

    }

    //_________________________________________________
    bool WindowManager::useEvent( GtkWidget* widget, GdkEventButton* event ) const
    {

        // check against mode
        if( _mode == Disabled ) return false;
        if( _mode == Minimal && !( GTK_IS_TOOLBAR( widget ) || GTK_IS_MENU_BAR( widget ) ) ) return false;

        // always accept if widget is not a container
        if( !GTK_IS_CONTAINER( widget ) ) return true;

        // if widget is a notebook, accept if there is no hovered tab
        if( GTK_IS_NOTEBOOK( widget ) )
        {

            return
                ( !Gtk::gtk_notebook_has_visible_arrows( GTK_NOTEBOOK( widget ) ) ) &&
                Style::instance().animations().tabWidgetEngine().contains( widget ) &&
                Style::instance().animations().tabWidgetEngine().hoveredTab( widget ) == -1 &&
                childrenUseEvent( widget, event, false );

        } else {

            return childrenUseEvent( widget, event, false );

        }

    }

    //_________________________________________________
    bool WindowManager::childrenUseEvent( GtkWidget* widget, GdkEventButton* event, bool inNoteBook ) const
    {
        // accept, by default
        bool usable = true;

        // get children and check
        GList *children = gtk_container_get_children( GTK_CONTAINER( widget ) );
        for( GList *child = g_list_first( children ); child && usable ; child = g_list_next( child ) )
        {

            // cast child to GtkWidget
            if( !GTK_IS_WIDGET( child->data ) ) continue;
            GtkWidget* childWidget( GTK_WIDGET( child->data ) );

            // check widget state and type
            if( gtk_widget_get_state( childWidget ) == GTK_STATE_PRELIGHT ) {

                // if widget is prelight, we don't need to check where event happen,
                // any prelight widget indicate we can't do a move
                usable = false;

            } else if( GTK_IS_NOTEBOOK( childWidget ) ) {

                inNoteBook = true;

            } else if( event && withinWidget( childWidget, event ) ) {

                #if OXYGEN_DEBUG
                std::cout << "Oxygen::WindowManager::childrenUseEvent - "
                    << widget
                    << "(" << G_OBJECT_TYPE_NAME( childWidget ) << ")"
                    << " " << gtk_widget_get_name( childWidget )
                    << std::endl;
                #endif

                GdkWindow *window = gtk_widget_get_window( childWidget );
                if( window && gdk_window_is_visible( window ) )
                {

                    // check against black-list
                    if( widgetIsBlackListed( childWidget ) )
                    {

                        usable = false;

                    } else if( GTK_IS_BUTTON( childWidget ) && gtk_widget_get_state( childWidget ) != GTK_STATE_INSENSITIVE ) {

                        usable = false;

                    } else if( gtk_widget_get_events ( childWidget ) & (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK) ) {

                        // widget listening to press event
                        usable = false;

                    } else if( GTK_IS_MENU_ITEM( childWidget ) ) {

                        // deal with menu item, GtkMenuItem only listen to
                        // GDK_BUTTON_PRESS_MASK when state == GTK_STATE_PRELIGHT
                        // so previous check are invalids :(
                        usable = false;

                    } else if( GTK_IS_SCROLLED_WINDOW( childWidget ) && ( !inNoteBook || gtk_widget_is_focus( childWidget ) ) ) {

                        // Scrolled do not send release events
                        // to parents so not usable
                        usable = false;

                    }
                }
            }

            // if child is a container and event has been accepted so far, also check it, recursively
            if( usable && GTK_IS_CONTAINER( childWidget ) )
            { usable = childrenUseEvent( childWidget, event, inNoteBook); }

        }

        // free list
        if( children ) g_list_free( children );

        return usable;
    }

    //_________________________________________________
    void WindowManager::initializeBlackList( void )
    {
        // clear list
        _blackList.clear();
        _blackList.push_back( "GtkPizza" );
        _blackList.push_back( "MetaFrames" );
        _blackList.push_back( "GladeDesignLayout" );
    }

    //________________________________________________________________________________
    void WindowManager::connect( GtkWidget* widget, WindowManager::Data& data )
    {
        data._destroyId.connect( G_OBJECT( widget ), "destroy", G_CALLBACK( wmDestroy ), this );
        data._styleId.connect( G_OBJECT( widget ), "style-set", G_CALLBACK( wmStyleSet ), this );

        data._pressId.connect( G_OBJECT( widget ), "button-press-event", G_CALLBACK( wmButtonPress ), this );
        data._releaseId.connect( G_OBJECT( widget ), "button-release-event", G_CALLBACK( wmButtonRelease ), this );
        data._leaveId.connect( G_OBJECT( widget ), "leave-notify-event", G_CALLBACK( wmLeave ), this );
        data._motionId.connect( G_OBJECT( widget ), "motion-notify-event", G_CALLBACK( wmMotion ), this );
    }

    //_________________________________________________
    void WindowManager::Data::disconnect( GtkWidget* )
    {

        _leaveId.disconnect();
        _destroyId.disconnect();
        _pressId.disconnect();
        _releaseId.disconnect();
        _motionId.disconnect();
        _styleId.disconnect();

    }

}
<commit_msg>Added one more check on window drag from notebooks.<commit_after>/*
* oxygenwindowmanager.cpp
* pass some window mouse press/release/move event actions to window manager
* -------------------
*
* Copyright (c) 2010 Cédric Bellegarde <gnumdk@gmail.com>
* Copyright (c) 2010 Hugo Pereira Da Costa <hugo@oxygen-icons.org>
*
* Largely inspired from Qtcurve style
* Copyright (C) Craig Drummond, 2003 - 2010 craig.p.drummond@gmail.com
*
* 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 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 St, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/

#include "oxygenwindowmanager.h"
#include "oxygenstyle.h"
#include "config.h"

#include <gdk/gdkx.h>

namespace Oxygen
{

    //_________________________________________________
    WindowManager::WindowManager( void ):
        _mode( Full ),
        _drag( false ),
        _dragDistance( 4 ),
        _dragDelay( 500 ),
        _widget( 0L ),
        _x(-1),
        _y(-1)
    { initializeBlackList(); }

    //_________________________________________________
    WindowManager::~WindowManager( void )
    {
        _map.disconnectAll();
        _map.clear();
    }

    //_________________________________________________
    void WindowManager::registerWidget( GtkWidget* widget )
    {

        if( _map.contains( widget ) || widgetIsBlackListed( widget ) ) return;

        // Window with no decorations (set by app), let window manage it self
        if( GTK_IS_WINDOW( widget ) && !gtk_window_get_decorated( GTK_WINDOW( widget ) ) ) return;

        // widgets used in tabs also must be ignored (happens, unfortunately)
        GtkWidget* parent( gtk_widget_get_parent( widget ) );
        if( GTK_IS_NOTEBOOK( parent ) && Gtk::gtk_notebook_is_tab_label( GTK_NOTEBOOK( parent ), widget ) )
        { return; }

        #if OXYGEN_DEBUG
        std::cout << "Oxygen::WindowManager::registerWidget - " << widget << "(" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        // Force widget to listen to relevant events
        gtk_widget_add_events( widget,
            GDK_BUTTON_RELEASE_MASK |
            GDK_BUTTON_PRESS_MASK   |
            GDK_LEAVE_NOTIFY_MASK   |
            GDK_BUTTON1_MOTION_MASK );

        // allocate new Data object
        Data& data( _map.registerWidget( widget ) );

        // connect signals
        if( _mode != Disabled ) connect( widget, data );

    }

    //_________________________________________________
    void WindowManager::unregisterWidget( GtkWidget* widget )
    {
        if( !_map.contains( widget ) ) return;

        #if OXYGEN_DEBUG
        std::cout << "Oxygen::WindowManager::unregisterWidget - " << widget << "(" << G_OBJECT_TYPE_NAME( widget ) << ")" << std::endl;
        #endif

        _map.value( widget ).disconnect( widget );
        _map.erase( widget );

        if( _widget == widget )
        {
            _widget = 0L;
            _x = -1;
            _y = -1;
            _drag = false;
        }

    }

    //_________________________________________________
    void WindowManager::setMode( WindowManager::Mode mode )
    {
        if( mode == _mode ) return;

        // connect/disconnect all data in map, based on new and old mode
        if( mode == Disabled ) { _map.disconnectAll(); }
        else if( _mode == Disabled )
        {
            DataMap<Data>::Map& map( _map.map() );
            for( DataMap<Data>::Map::iterator iter = map.begin(); iter != map.end(); ++iter )
            { connect( iter->first, iter->second ); }
        }

        // assign new mode
        _mode = mode;

    }

    //_________________________________________________
    gboolean WindowManager::wmStyleSet( GtkWidget* widget, GtkStyle* , gpointer data )
    {
        static_cast<WindowManager*>(data)->unregisterWidget( widget );
        return false;
    }

    //_________________________________________________
    gboolean WindowManager::wmDestroy( GtkWidget* widget, gpointer data )
    {
        static_cast<WindowManager*>(data)->unregisterWidget( widget );
        return false;
    }

    //_________________________________________________
    gboolean WindowManager::wmButtonPress(GtkWidget *widget, GdkEventButton* event, gpointer data )
    {

        if( event->type == GDK_BUTTON_PRESS && event->button == Gtk::LeftButton )
        {

            #if OXYGEN_DEBUG
            std::cout << "Oxygen::WindowManager::wmButtonPress - "
                << widget
                << "(" << G_OBJECT_TYPE_NAME( widget ) << ")"
                << " " << gtk_widget_get_name( widget )
                << std::endl;
            #endif

            return static_cast<WindowManager*>(data)->isWindowDragWidget( widget, event );

        } else return false;

    }

    //_________________________________________________
    gboolean WindowManager::wmButtonRelease(GtkWidget *widget, GdkEventButton*, gpointer data )
    { return static_cast<WindowManager*>( data )->finishDrag( widget ); }

    //_________________________________________________
    gboolean WindowManager::wmLeave(GtkWidget *widget, GdkEventCrossing*, gpointer data )
    { return static_cast<WindowManager*>( data )->finishDrag( widget ); }

    //_________________________________________________
    gboolean WindowManager::wmMotion( GtkWidget *widget, GdkEventMotion* event, gpointer data )
    { return static_cast<WindowManager*>(data)->startDrag( widget, event ); }

    //_________________________________________________________________
    gboolean WindowManager::startDelayedDrag( gpointer data )
    {
        static_cast<WindowManager*>( data )->startDrag();
        return FALSE;
    }

    //_________________________________________________
    bool WindowManager::isWindowDragWidget( GtkWidget* widget, GdkEventButton* event )
    {
        if( _mode == Disabled ) return false;
        else if( (!_drag) && withinWidget(widget, event ) && useEvent( widget, event ) )
        {

            // store widget and event position
            _widget = widget;
            _x = int(event->x_root);
            _y = int(event->y_root);

            // start timer
            if( _timer.isRunning() ) _timer.stop();
            _timer.start( _dragDelay, (GSourceFunc)startDelayedDrag, this );

            // enable drag and accept
            _drag = true;
            return true;

        } else return false;
    }

    //_________________________________________________________________
    bool WindowManager::startDrag( GtkWidget* widget, GdkEventMotion* event )
    {

        // make sure drag is enabled
        if( !_drag ) return false;

        // check displacement with respect to drag start
        const int distance( abs( _x - int(event->x_root) ) + abs( _y - int(event->y_root) ) );

        if( distance > 0 && _timer.isRunning() ) _timer.stop();
        if( distance < _dragDistance ) return false;

        // start drag from current position
        return startDrag( widget, int(event->x_root), int(event->y_root) );

    }

    //_________________________________________________________________
    bool WindowManager::startDrag( GtkWidget* widget, int x, int y )
    {
        // create xevent and send.
        XEvent     xev;
        GtkWindow  *topLevel = GTK_WINDOW( gtk_widget_get_toplevel( widget ) );
        GdkWindow  *window = gtk_widget_get_window( GTK_WIDGET( topLevel ) );
        GdkDisplay *display = gtk_widget_get_display( GTK_WIDGET( topLevel ) );
        GdkWindow  *root = gdk_screen_get_root_window( gtk_window_get_screen( topLevel ) );

        xev.xclient.type = ClientMessage;
        xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display(display, "_NET_WM_MOVERESIZE");
        xev.xclient.display = GDK_DISPLAY_XDISPLAY(display);
        xev.xclient.window = GDK_WINDOW_XID(window);
        xev.xclient.format = 32;
        xev.xclient.data.l[0] = x;
        xev.xclient.data.l[1] = y;
        xev.xclient.data.l[2] = 8; // NET::Move
        xev.xclient.data.l[3] = Button1;
        xev.xclient.data.l[4] = 0;
        XUngrabPointer(GDK_DISPLAY_XDISPLAY(display), CurrentTime);

        XSendEvent(
            GDK_DISPLAY_XDISPLAY(display),
            GDK_WINDOW_XID(root),
            False,
            SubstructureRedirectMask | SubstructureNotifyMask,
            &xev);

        // force a release as some widgets miss it...
        wmButtonRelease( widget, 0L, this );
        return true;
    }

    //_________________________________________________
    bool WindowManager::finishDrag( GtkWidget* widget )
    {

        _widget = 0L;
        _x = -1;
        _y = -1;

        if( _drag )
        {

            gtk_grab_remove(widget);
            gdk_pointer_ungrab( CurrentTime );
            _drag = false;
            return true;

        } else return false;

    }

    //_________________________________________________
    bool WindowManager::withinWidget( GtkWidget* widget, GdkEventButton* event ) const
    {

        // get widget window
        GdkWindow *window( gtk_widget_get_parent_window( widget ) );

        // Some widgets aren't realized (GeditWindow for exemple) ...
        if( !window ) return true;

        GtkAllocation allocation;

        if( GTK_IS_NOTEBOOK( widget ) )
        {

            Gtk::gtk_notebook_get_tabbar_rect( GTK_NOTEBOOK( widget ), &allocation );

        } else {

            #if GTK_CHECK_VERSION(2, 18, 0)
            gtk_widget_get_allocation( widget, &allocation );
            #else
            allocation = widget->allocation;
            #endif

        }

        // Need to get absolute coordinates
        int nx(0);
        int ny(0);
        gdk_window_get_origin(window, &nx, &ny );
        allocation.x += nx;
        allocation.y += ny;

        return Gtk::gdk_rectangle_contains( &allocation, int(event->x_root), int(event->y_root) );

    }

    //_________________________________________________
    bool WindowManager::useEvent( GtkWidget* widget, GdkEventButton* event ) const
    {

        // check against mode
        if( _mode == Disabled ) return false;
        if( _mode == Minimal && !( GTK_IS_TOOLBAR( widget ) || GTK_IS_MENU_BAR( widget ) ) ) return false;

        // always accept if widget is not a container
        if( !GTK_IS_CONTAINER( widget ) ) return true;

        // if widget is a notebook, accept if there is no hovered tab
        if( GTK_IS_NOTEBOOK( widget ) )
        {

            return
                ( !Gtk::gtk_notebook_has_visible_arrows( GTK_NOTEBOOK( widget ) ) ) &&
                Style::instance().animations().tabWidgetEngine().contains( widget ) &&
                Style::instance().animations().tabWidgetEngine().hoveredTab( widget ) == -1 &&
                childrenUseEvent( widget, event, false );

        } else {

            return childrenUseEvent( widget, event, false );

        }

    }

    //_________________________________________________
    bool WindowManager::childrenUseEvent( GtkWidget* widget, GdkEventButton* event, bool inNoteBook ) const
    {
        // accept, by default
        bool usable = true;

        // get children and check
        GList *children = gtk_container_get_children( GTK_CONTAINER( widget ) );
        for( GList *child = g_list_first( children ); child && usable ; child = g_list_next( child ) )
        {

            // cast child to GtkWidget
            if( !GTK_IS_WIDGET( child->data ) ) continue;
            GtkWidget* childWidget( GTK_WIDGET( child->data ) );

            // check widget state and type
            if( gtk_widget_get_state( childWidget ) == GTK_STATE_PRELIGHT ) {

                // if widget is prelight, we don't need to check where event happen,
                // any prelight widget indicate we can't do a move
                usable = false;

            } else if( GTK_IS_NOTEBOOK( childWidget ) ) {

                inNoteBook = true;

            } else if( event && withinWidget( childWidget, event ) ) {

                #if OXYGEN_DEBUG
                std::cout << "Oxygen::WindowManager::childrenUseEvent - "
                    << widget
                    << "(" << G_OBJECT_TYPE_NAME( childWidget ) << ")"
                    << " " << gtk_widget_get_name( childWidget )
                    << std::endl;
                #endif

                GdkWindow *window = gtk_widget_get_window( childWidget );
                if( window && gdk_window_is_visible( window ) )
                {

                    // check against black-list
                    if( widgetIsBlackListed( childWidget ) )
                    {

                        usable = false;

                    } else if( GTK_IS_NOTEBOOK( widget ) && Gtk::gtk_notebook_is_tab_label( GTK_NOTEBOOK( widget ), childWidget ) ) {

                        usable = false;

                   } else if( GTK_IS_BUTTON( childWidget ) && gtk_widget_get_state( childWidget ) != GTK_STATE_INSENSITIVE ) {

                        usable = false;

                    } else if( gtk_widget_get_events ( childWidget ) & (GDK_BUTTON_PRESS_MASK|GDK_BUTTON_RELEASE_MASK) ) {

                        // widget listening to press event
                        usable = false;

                    } else if( GTK_IS_MENU_ITEM( childWidget ) ) {

                        // deal with menu item, GtkMenuItem only listen to
                        // GDK_BUTTON_PRESS_MASK when state == GTK_STATE_PRELIGHT
                        // so previous check are invalids :(
                        usable = false;

                    } else if( GTK_IS_SCROLLED_WINDOW( childWidget ) && ( !inNoteBook || gtk_widget_is_focus( childWidget ) ) ) {

                        // Scrolled do not send release events
                        // to parents so not usable
                        usable = false;

                    }
                }
            }

            // if child is a container and event has been accepted so far, also check it, recursively
            if( usable && GTK_IS_CONTAINER( childWidget ) )
            { usable = childrenUseEvent( childWidget, event, inNoteBook); }

        }

        // free list
        if( children ) g_list_free( children );

        return usable;
    }

    //_________________________________________________
    void WindowManager::initializeBlackList( void )
    {
        // clear list
        _blackList.clear();
        _blackList.push_back( "GtkPizza" );
        _blackList.push_back( "MetaFrames" );
        _blackList.push_back( "GladeDesignLayout" );
    }

    //________________________________________________________________________________
    void WindowManager::connect( GtkWidget* widget, WindowManager::Data& data )
    {
        data._destroyId.connect( G_OBJECT( widget ), "destroy", G_CALLBACK( wmDestroy ), this );
        data._styleId.connect( G_OBJECT( widget ), "style-set", G_CALLBACK( wmStyleSet ), this );

        data._pressId.connect( G_OBJECT( widget ), "button-press-event", G_CALLBACK( wmButtonPress ), this );
        data._releaseId.connect( G_OBJECT( widget ), "button-release-event", G_CALLBACK( wmButtonRelease ), this );
        data._leaveId.connect( G_OBJECT( widget ), "leave-notify-event", G_CALLBACK( wmLeave ), this );
        data._motionId.connect( G_OBJECT( widget ), "motion-notify-event", G_CALLBACK( wmMotion ), this );
    }

    //_________________________________________________
    void WindowManager::Data::disconnect( GtkWidget* )
    {

        _leaveId.disconnect();
        _destroyId.disconnect();
        _pressId.disconnect();
        _releaseId.disconnect();
        _motionId.disconnect();
        _styleId.disconnect();

    }

}
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Artur Troian
 *
 * 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 <iostream>
#include <sstream>
#include <iomanip>

#include <strings.h>

#include <jwt/jwt.hpp>
#include <tools/base64.hpp>

jwt::jwt(jwt_alg_t alg) :
	  m_alg(alg)
{
	m_header["typ"] = "JWT";
	m_header["alg"] = alg2str(m_alg);
}

jwt::jwt(const std::string &token)
{
	try {
		parse(token);
	} catch (...) {
		throw;
	}
}

jwt::~jwt()
{
	cleanup();
}

void jwt::sign_rsa(std::string &signature, const std::string &data, RSA *r)
{
	uint8_t  digest[SHA512_DIGEST_LENGTH];
	uint32_t digest_len;

	uint32_t type;

	switch (m_alg) {
	case JWT_ALG_RS256: {
		SHA256_CTX sha_ctx;

		digest_len = SHA256_DIGEST_LENGTH;
		type = NID_sha256;

		if (SHA256_Init(&sha_ctx) != 1) {

		}

		if (SHA256_Update(&sha_ctx, (const uint8_t *)data.c_str(), data.size()) != 1) {
			throw std::runtime_error("Couldn't calculate hash");
		}

		if (SHA256_Final(digest, &sha_ctx) != 1) {

		}

		break;
	}
	default:
		break;
	}

	uint32_t sig_len;

	uint8_t *sig = new uint8_t[RSA_size(r)];

	RSA_sign(type, digest, digest_len, sig, &sig_len, r);

	delete[] sig;
}

void jwt::sign_hmac(std::string &signature, const std::string &data, const uint8_t *key, size_t key_size)
{
	if (data.empty()) {
		throw std::invalid_argument("Data is empty");
	}

	signature.clear();

	const EVP_MD *alg;

	switch (m_alg) {
	case JWT_ALG_HS256:
		alg = EVP_sha256();
		//do_hmac(EVP_sha256(), key, key_size, (const uint8_t *)data.c_str(), data.size(), signature);
		break;
	case JWT_ALG_HS384:
		alg = EVP_sha384();
		break;
	case JWT_ALG_HS512:
		alg = EVP_sha512();
		break;
	default:
		break;
	}

	uint32_t size;

	HMAC(alg, key, key_size, (const uint8_t *)data.c_str(), data.size(), nullptr, &size);

	uint8_t *res = new uint8_t[size];

	HMAC(alg, key, key_size, (const uint8_t *)data.c_str(), data.size(), res, &size);

	tools::base64::encode(signature, res, size);

	delete[] res;
}

void jwt::encode_token(std::string &token)
{
	// Encode header into Base64
	std::string jhead = tools::serialize_json(m_header);
	tools::base64::encode(token, jhead);
	token += ".";

	// Encode parameters into Base64
	jhead.clear();
	jhead = tools::serialize_json(m_payload);
	tools::base64::encode(token, jhead);
}

void jwt::sign(std::string &token, const uint8_t *key, size_t key_size)
{
	encode_token(token);

	// Make signature
	sign_hmac(m_signature, token, key, key_size);

	token += ".";
	token += m_signature;
}

void jwt::sign(std::string &token, RSA *r)
{
	encode_token(token);

	sign_rsa(m_signature, token, r);

	token += ".";
	token += m_signature;
}

bool jwt::verify(const uint8_t *key, size_t size)
{
	// Make signature
	std::string token = m_tokens[0] + "." + m_tokens[1];
	sign_hmac(m_signature, token, key, size);

	if (m_signature.compare(m_tokens[2]) == 0) {
		return true;
	} else {
		return false;
	}
}

void jwt::add_grant(const std::string &grant, const std::string &value)
{
	if (grant.empty() || value.empty())
		throw std::invalid_argument("Invalid params");

	if (m_payload.isMember(grant)) {
		throw std::runtime_error("Grant already exists");
	} else {
		m_payload[grant] = value;
	}
}

bool jwt::grant_verify(const std::string &grant, const std::string &value)
{
	if (grant.empty() || value.empty())
		throw std::invalid_argument("Invalid params");

	if (!m_payload.isMember(grant)) {
		throw std::runtime_error("Grant not found");
	}

	std::string val = m_payload.get(grant, "").asString();
	if (val.compare(value) == 0) {
		return true;
	} else {
		return false;
	}
}

void jwt::cleanup()
{
	m_header.clear();
	m_payload.clear();
	m_signature.clear();
	m_tokens.clear();
}

void jwt::parse(const std::string &token)
{
	if (token.empty()) {
		throw std::runtime_error("Invalid argument");
	}

	// extracting the algorithm, payload, signature and data
	m_tokens = split(token, '.');

	std::string decoded_header  = tools::base64::decode<std::string>(m_tokens[0]);
	std::string decoded_payload = tools::base64::decode<std::string>(m_tokens[1]);

	if (m_tokens.size() != 3) {
		throw std::runtime_error("Invalid token string");
	}

	try {
		tools::str2json(decoded_header, m_header);
	} catch (const std::exception &e) {
		std::cout << e.what();
	}

	std::string ser = tools::serialize_json(m_header);

	std::string typ = m_header.get("typ", "Unknown").asString();

	if (typ.compare("Unknown") == 0) {
		throw std::runtime_error("Bad token type");
	}

	std::string alg = m_header.get("alg", "Unknown").asString();

	m_alg = str2alg(alg.c_str());
	if (m_alg == JWT_ALG_UKNOWN) {
		std::string error("Bad algorithm [");
		error += alg;
		error += "]";
		throw std::runtime_error(error);
	}

	try {
		tools::str2json(decoded_payload, m_payload);
	} catch (const std::exception &e) {
		std::cout << e.what();
	}
}

std::vector<std::string> jwt::split(const std::string &text, char sep)
{
	std::vector<std::string> tokens;
	std::size_t start = 0;
	std::size_t end = 0;

	while ((end = text.find(sep, start)) != std::string::npos) {
		tokens.push_back(text.substr(start, end - start));
		start = end + 1;
	}

	tokens.push_back(text.substr(start));

	return tokens;
}

void jwt::base64uri_encode(std::string &str)
{
	size_t t;

	for (size_t i = t = 0; i < str.size(); i++) {
		switch (str[i]) {
		case '+':
			str[t] = '-';
			break;
		case '/':
			str[t] = '_';
			break;
		case '=':
			continue;
		}

		t++;
	}
}

void jwt::base64uri_encode(uint8_t *buf, size_t len)
{
	int i, t;

	for (i = t = 0; i < len; i++) {
		switch (buf[i]) {
		case '+':
			buf[t] = '-';
			break;
		case '/':
			buf[t] = '_';
			break;
		case '=':
			continue;
		}

		t++;
	}
}

const char *jwt::alg2str(jwt_alg_t alg)
{
	switch (alg) {
	case JWT_ALG_NONE:
		return "none";
	case JWT_ALG_HS256:
		return "HS256";
	case JWT_ALG_HS384:
		return "HS384";
	case JWT_ALG_HS512:
		return "HS512";
	default:
		return nullptr;
	}
}

jwt_alg_t jwt::str2alg(const char *alg)
{
	if (!strcasecmp(alg, "none"))
		return JWT_ALG_NONE;
	else if (!strcasecmp(alg, "HS256"))
		return JWT_ALG_HS256;
	else if (!strcasecmp(alg, "HS384"))
		return JWT_ALG_HS384;
	else if (!strcasecmp(alg, "HS512"))
		return JWT_ALG_HS512;
	else
		return JWT_ALG_UKNOWN;
}

int jwt::alg_key_len(jwt_alg_t alg)
{
	switch (alg) {
	case JWT_ALG_NONE:
		return 0;
	case JWT_ALG_HS256:
		return 32;
	case JWT_ALG_HS384:
		return 48;
	case JWT_ALG_HS512:
		return 64;
	default:
		return -1; // LCOV_EXCL_LINE
	}
}
<commit_msg>Duplicates: Reuse code for base64uri_encode<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2016 Artur Troian
 *
 * 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 <iostream>
#include <sstream>
#include <iomanip>

#include <strings.h>

#include <jwt/jwt.hpp>
#include <tools/base64.hpp>

jwt::jwt(jwt_alg_t alg) :
	  m_alg(alg)
{
	m_header["typ"] = "JWT";
	m_header["alg"] = alg2str(m_alg);
}

jwt::jwt(const std::string &token)
{
	try {
		parse(token);
	} catch (...) {
		throw;
	}
}

jwt::~jwt()
{
	cleanup();
}

void jwt::sign_rsa(std::string &signature, const std::string &data, RSA *r)
{
	uint8_t  digest[SHA512_DIGEST_LENGTH];
	uint32_t digest_len;

	uint32_t type;

	switch (m_alg) {
	case JWT_ALG_RS256: {
		SHA256_CTX sha_ctx;

		digest_len = SHA256_DIGEST_LENGTH;
		type = NID_sha256;

		if (SHA256_Init(&sha_ctx) != 1) {

		}

		if (SHA256_Update(&sha_ctx, (const uint8_t *)data.c_str(), data.size()) != 1) {
			throw std::runtime_error("Couldn't calculate hash");
		}

		if (SHA256_Final(digest, &sha_ctx) != 1) {

		}

		break;
	}
	default:
		break;
	}

	uint32_t sig_len;

	uint8_t *sig = new uint8_t[RSA_size(r)];

	RSA_sign(type, digest, digest_len, sig, &sig_len, r);

	delete[] sig;
}

void jwt::sign_hmac(std::string &signature, const std::string &data, const uint8_t *key, size_t key_size)
{
	if (data.empty()) {
		throw std::invalid_argument("Data is empty");
	}

	signature.clear();

	const EVP_MD *alg;

	switch (m_alg) {
	case JWT_ALG_HS256:
		alg = EVP_sha256();
		//do_hmac(EVP_sha256(), key, key_size, (const uint8_t *)data.c_str(), data.size(), signature);
		break;
	case JWT_ALG_HS384:
		alg = EVP_sha384();
		break;
	case JWT_ALG_HS512:
		alg = EVP_sha512();
		break;
	default:
		break;
	}

	uint32_t size;

	HMAC(alg, key, key_size, (const uint8_t *)data.c_str(), data.size(), nullptr, &size);

	uint8_t *res = new uint8_t[size];

	HMAC(alg, key, key_size, (const uint8_t *)data.c_str(), data.size(), res, &size);

	tools::base64::encode(signature, res, size);

	delete[] res;
}

void jwt::encode_token(std::string &token)
{
	// Encode header into Base64
	std::string jhead = tools::serialize_json(m_header);
	tools::base64::encode(token, jhead);
	token += ".";

	// Encode parameters into Base64
	jhead.clear();
	jhead = tools::serialize_json(m_payload);
	tools::base64::encode(token, jhead);
}

void jwt::sign(std::string &token, const uint8_t *key, size_t key_size)
{
	encode_token(token);

	// Make signature
	sign_hmac(m_signature, token, key, key_size);

	token += ".";
	token += m_signature;
}

void jwt::sign(std::string &token, RSA *r)
{
	encode_token(token);

	sign_rsa(m_signature, token, r);

	token += ".";
	token += m_signature;
}

bool jwt::verify(const uint8_t *key, size_t size)
{
	// Make signature
	std::string token = m_tokens[0] + "." + m_tokens[1];
	sign_hmac(m_signature, token, key, size);

	if (m_signature.compare(m_tokens[2]) == 0) {
		return true;
	} else {
		return false;
	}
}

void jwt::add_grant(const std::string &grant, const std::string &value)
{
	if (grant.empty() || value.empty())
		throw std::invalid_argument("Invalid params");

	if (m_payload.isMember(grant)) {
		throw std::runtime_error("Grant already exists");
	} else {
		m_payload[grant] = value;
	}
}

bool jwt::grant_verify(const std::string &grant, const std::string &value)
{
	if (grant.empty() || value.empty())
		throw std::invalid_argument("Invalid params");

	if (!m_payload.isMember(grant)) {
		throw std::runtime_error("Grant not found");
	}

	std::string val = m_payload.get(grant, "").asString();
	if (val.compare(value) == 0) {
		return true;
	} else {
		return false;
	}
}

void jwt::cleanup()
{
	m_header.clear();
	m_payload.clear();
	m_signature.clear();
	m_tokens.clear();
}

void jwt::parse(const std::string &token)
{
	if (token.empty()) {
		throw std::runtime_error("Invalid argument");
	}

	// extracting the algorithm, payload, signature and data
	m_tokens = split(token, '.');

	std::string decoded_header  = tools::base64::decode<std::string>(m_tokens[0]);
	std::string decoded_payload = tools::base64::decode<std::string>(m_tokens[1]);

	if (m_tokens.size() != 3) {
		throw std::runtime_error("Invalid token string");
	}

	try {
		tools::str2json(decoded_header, m_header);
	} catch (const std::exception &e) {
		std::cout << e.what();
	}

	std::string ser = tools::serialize_json(m_header);

	std::string typ = m_header.get("typ", "Unknown").asString();

	if (typ.compare("Unknown") == 0) {
		throw std::runtime_error("Bad token type");
	}

	std::string alg = m_header.get("alg", "Unknown").asString();

	m_alg = str2alg(alg.c_str());
	if (m_alg == JWT_ALG_UKNOWN) {
		std::string error("Bad algorithm [");
		error += alg;
		error += "]";
		throw std::runtime_error(error);
	}

	try {
		tools::str2json(decoded_payload, m_payload);
	} catch (const std::exception &e) {
		std::cout << e.what();
	}
}

std::vector<std::string> jwt::split(const std::string &text, char sep)
{
	std::vector<std::string> tokens;
	std::size_t start = 0;
	std::size_t end = 0;

	while ((end = text.find(sep, start)) != std::string::npos) {
		tokens.push_back(text.substr(start, end - start));
		start = end + 1;
	}

	tokens.push_back(text.substr(start));

	return tokens;
}

void jwt::base64uri_encode(std::string &str)
{
	base64uri_encode((uint8_t *)str.data(), str.size());
}

void jwt::base64uri_encode(uint8_t *buf, size_t len)
{
	int i, t;

	for (i = t = 0; i < len; i++) {
		switch (buf[i]) {
		case '+':
			buf[t] = '-';
			break;
		case '/':
			buf[t] = '_';
			break;
		case '=':
			continue;
		}

		t++;
	}
}

const char *jwt::alg2str(jwt_alg_t alg)
{
	switch (alg) {
	case JWT_ALG_NONE:
		return "none";
	case JWT_ALG_HS256:
		return "HS256";
	case JWT_ALG_HS384:
		return "HS384";
	case JWT_ALG_HS512:
		return "HS512";
	default:
		return nullptr;
	}
}

jwt_alg_t jwt::str2alg(const char *alg)
{
	if (!strcasecmp(alg, "none"))
		return JWT_ALG_NONE;
	else if (!strcasecmp(alg, "HS256"))
		return JWT_ALG_HS256;
	else if (!strcasecmp(alg, "HS384"))
		return JWT_ALG_HS384;
	else if (!strcasecmp(alg, "HS512"))
		return JWT_ALG_HS512;
	else
		return JWT_ALG_UKNOWN;
}

int jwt::alg_key_len(jwt_alg_t alg)
{
	switch (alg) {
	case JWT_ALG_NONE:
		return 0;
	case JWT_ALG_HS256:
		return 32;
	case JWT_ALG_HS384:
		return 48;
	case JWT_ALG_HS512:
		return 64;
	default:
		return -1; // LCOV_EXCL_LINE
	}
}
<|endoftext|>


<commit_before>#include "ArraySequence.h"

//maps a sequence (array) of type inputType to a sequence (array) of type resultType
template<typename resultType,typename inputType>
 seqType<resultType> ArraySequence::map(resultType (*fun)(inputType),seqType<inputType> seq){
  //TODO make parllel
  //TODO add error handling

  //creates the new sequence to store values in
  seqType<resultType> result;
  result.seq = new resultType [seq.length];
  result.length = seq.length;

  for(int i = 0;i<seq.length;i++){
    result.seq[i] = fun(seq.seq[i]);
  }
  //clean up
  delete(seq.seq);
  delete(seq);
}

  //reduces a sequence (array) to a single element using function fun
  template<typename type>
  type ArraySequence::reduce(type (*fun)(type,type),type baseCase,seqType<type> seq){
    //TODO implment
  }

  //evaluates to the nth elment in the sequence(array)
  template<typename type>
  type ArraySequence::nth(int i,seqType<type> seq){
    assert(i>-1 && i <seq.length);
    return seq.seq[i];
  }

  //evalutes to the length(number of elements) in the sequence
  template<typename type>
  int ArraySequence::length(seqType<type> seq){
    return seq.length;
  }

  template<typename type>
  seqType<type> ArraySequence::empty(){
    seqType<type> result;
    result.seq = new type [0]; //not strictly required consider removing
    result.length = 0;
    return result;
  }

  //creates a sequence of length n where each element has the value fun(i)
  template<typename type>
  seqType<type> ArraySequence::tabulate(type (*fun)(int i),int n){
    //TODO parllize
    //TODO add error handling
    seqType<type> result;
    result.seq= new type [n];
    for(int i = 0;i<n;i++){
      result.seq[i] =  fun(i);
    }
    return result;
  }

  template<typename type>
  seqType<type> ArraySequence::singleton(type a){
    seqType<type> result;
    result.length = 1;
    result.seq = new type[1];
    result.seq[0] = a;
    return result;
  }

  template<typename type>
  bool ArraySequence::equal(bool (*fun)(type,type),seqType<type> a,seqType<type> b){
    if(a.length != b.length){
      //ensures that if a is shorter then b that false positive can not be returned
      return false;
    }
    struct temp{
      type reduce(bool l ,bool r){ return l && r; }
      //Try to find a better solution
      type map(int i){ return this->fun( ArraySequence::nth<type>(i,this->a),ArraySequence::nth<type>(i,this->b));}
    };
    struct temp f;
    seqType<bool> c = ArraySequence::tabulate<bool>(&f.map,a.length);
    return ArraySequence::reduce<bool>(&f.reduce,true,c);
  }

  template<typename type>
  seqType<type> ArraySequence::rev(seqType<type> seq){
    struct temp{

      type f(int i){
	seqType<type> seq;//temp until I inline
	return ArraySequence::nth<type>(seq.length - i -1,seq);
      }
    };
    //I know this is ugly and I am trying to find a better solution
    struct temp fun;
    return ArraySequence::tabulate(&fun.f ,seq.length);
  }

  template<typename type>
  seqType<type> ArraySequence::append(seqType<type> a,seqType<type> b){
    //TODO implmment
  }

  template<typename type>
  seqType<type> ArraySequence::drop(int i,seqType<type> seq){
    //TODO implment
  }

  template<typename type>
  seqType<type> ArraySequence::take(int i,seqType<type> seq){
    //TODO implment
  }
<commit_msg>Delete ArraySequence.cpp<commit_after><|endoftext|>


<commit_before><commit_msg>cppcheck: fix Variable "hr" reassignment<commit_after><|endoftext|>