<commit_before>#ifndef SYSTEM_DEATH_HPP
#define SYSTEM_DEATH_HPP

#include "components/drawable.hpp"
#include "components/foreground.hpp"
#include "components/game-text.hpp"
#include "components/gravity.hpp"
#include "components/velocity.hpp"
#include "game.hpp"
#include "game_config.hpp"
#include "events.hpp"

#include "entityx/entityx.h"
#include <glm/vec2.hpp>
#ifdef __EMSCRIPTEN__
#include <SDL/SDL_mixer.h>
#else
#include <SDL_mixer.h>
#endif

#include<iostream>

class DeathSystem : public entityx::System<DeathSystem>, public entityx::Receiver<DeathSystem> {
    public:
        DeathSystem(Game *game): game(game), died(false), done(false), last(0.0f), reason(DeathReason::FALL) {

        }

        void configure(entityx::EventManager &event_manager) override {
            event_manager.subscribe<GameOver>(*this);
        }

        void receive(const GameOver &event) {
            (void)event;
            died = true;
            reason = event.reason;
        }

        void update(entityx::EntityManager &es, entityx::EventManager &events, double dt) {
            (void) events;
            (void) dt;
            auto player = game->getPlayer();
            auto pos = player.component<Position>()->getPosition();
            if (died) {
                if (!done) {
                    entityx::Entity splatter = es.create();
                    if (reason == DeathReason::INSANE) {
                        player.component<Drawable>()->getAnimation().setAnimation("dissolve", AnimationPlaybackType::FREEZE);
                        player.component<Drawable>()->getAnimation().pause(false);
                        //player.remove<Gravity>();
                        //player.component<Velocity>()->setVelocity(glm::vec2(0, 0));
                    }
                    else if (reason == DeathReason::SAW) {
                        auto splashAnimation = AnimationCollection("splash");
                        splashAnimation.addAnimation("splash", 0, 8, 1.0, glm::vec2(128, 128));
                        splashAnimation.setAnimation("splash", AnimationPlaybackType::FREEZE);
                        splatter.assign<Drawable>("splash", 64, 24, splashAnimation);
                        splatter.assign<Position>(pos + glm::vec2(0, 0));
                        player.remove<Gravity>();
                        player.component<Velocity>()->setVelocity(glm::vec2(0, 0));
                        player.remove<Drawable>();
                        Mix_Volume(5, 40);
                        Mix_PlayChannel(5, game->res_manager().sound("splatter"), 0);
                    }
                    else if (reason == DeathReason::FALL) {
                        auto splatterAnimation = AnimationCollection("splatter");
                        splatterAnimation.addAnimation("splatter", 0, 7, 1.0, glm::vec2(64, 24));
                        splatterAnimation.setAnimation("splatter", AnimationPlaybackType::FREEZE);
                        splatter.assign<Drawable>("splatter", 64, 24, splatterAnimation);
                        splatter.assign<Position>(pos + glm::vec2(0, 0));
                        player.remove<Drawable>();
                        Mix_Volume(5, 40);
                        Mix_PlayChannel(5, game->res_manager().sound("splatter"), 0);
                    }
                    else {
                        auto splatterAnimation = AnimationCollection("splatter-house");
                        splatterAnimation.addAnimation("splatter-house", 0, 7, 1.0, glm::vec2(64, 128));
                        splatterAnimation.setAnimation("splatter-house", AnimationPlaybackType::FREEZE);
                        splatter.assign<Drawable>("splatter-house", 64, 128, splatterAnimation);
                        splatter.assign<Position>(pos + glm::vec2(0, -5));
                        player.remove<Drawable>();
                        Mix_Volume(5, 40);
                        Mix_PlayChannel(5, game->res_manager().sound("splatter"), 0);
                    }
                    splatter.assign<Foreground>();
                    done = true;
                }
                last += dt;
                if (last > 0.5f) {
                    last = 0.0f;
                    auto text = es.create();
                    text.assign<GameText>(DEATH_MESSAGES[rand() % DEATH_MESSAGE_COUNT]);
                    text.assign<Position>(pos + glm::vec2(rand() % 40 - 20, 10));
                }
            }
        }

    private:
        Game *game;
        bool died;
        bool done;
        float last;
        DeathReason reason;
};
#endif
<commit_msg>Fixed death animation when stomped.<commit_after>#ifndef SYSTEM_DEATH_HPP
#define SYSTEM_DEATH_HPP

#include "components/drawable.hpp"
#include "components/foreground.hpp"
#include "components/game-text.hpp"
#include "components/gravity.hpp"
#include "components/velocity.hpp"
#include "game.hpp"
#include "game_config.hpp"
#include "events.hpp"

#include "entityx/entityx.h"
#include <glm/vec2.hpp>
#ifdef __EMSCRIPTEN__
#include <SDL/SDL_mixer.h>
#else
#include <SDL_mixer.h>
#endif

#include<iostream>

class DeathSystem : public entityx::System<DeathSystem>, public entityx::Receiver<DeathSystem> {
    public:
        DeathSystem(Game *game): game(game), died(false), done(false), last(0.0f), reason(DeathReason::FALL) {

        }

        void configure(entityx::EventManager &event_manager) override {
            event_manager.subscribe<GameOver>(*this);
        }

        void receive(const GameOver &event) {
            (void)event;
            died = true;
            reason = event.reason;
        }

        void update(entityx::EntityManager &es, entityx::EventManager &events, double dt) {
            (void) events;
            (void) dt;
            auto player = game->getPlayer();
            auto pos = player.component<Position>()->getPosition();
            if (died) {
                if (!done) {
                    auto height = player.component<Drawable>()->getHeight();
                    entityx::Entity splatter = es.create();
                    if (reason == DeathReason::INSANE) {
                        player.component<Drawable>()->getAnimation().setAnimation("dissolve", AnimationPlaybackType::FREEZE);
                        player.component<Drawable>()->getAnimation().pause(false);
                        //player.remove<Gravity>();
                        //player.component<Velocity>()->setVelocity(glm::vec2(0, 0));
                    }
                    else if (reason == DeathReason::SAW) {
                        auto splashAnimation = AnimationCollection("splash");
                        splashAnimation.addAnimation("splash", 0, 8, 1.0, glm::vec2(128, 128));
                        splashAnimation.setAnimation("splash", AnimationPlaybackType::FREEZE);
                        splatter.assign<Drawable>("splash", 64, 24, splashAnimation);
                        splatter.assign<Position>(pos + glm::vec2(0, 0));
                        player.remove<Gravity>();
                        player.component<Velocity>()->setVelocity(glm::vec2(0, 0));
                        player.remove<Drawable>();
                        Mix_Volume(5, 40);
                        Mix_PlayChannel(5, game->res_manager().sound("splatter"), 0);
                    }
                    else if (pos.y >= GAME_BOTTOM - height) {
                        auto splatterAnimation = AnimationCollection("splatter");
                        splatterAnimation.addAnimation("splatter", 0, 7, 1.0, glm::vec2(64, 24));
                        splatterAnimation.setAnimation("splatter", AnimationPlaybackType::FREEZE);
                        splatter.assign<Drawable>("splatter", 64, 24, splatterAnimation);
                        splatter.assign<Position>(pos + glm::vec2(0, 0));
                        player.remove<Drawable>();
                        Mix_Volume(5, 40);
                        Mix_PlayChannel(5, game->res_manager().sound("splatter"), 0);
                    }
                    else {
                        auto splatterAnimation = AnimationCollection("splatter-house");
                        splatterAnimation.addAnimation("splatter-house", 0, 7, 1.0, glm::vec2(64, 128));
                        splatterAnimation.setAnimation("splatter-house", AnimationPlaybackType::FREEZE);
                        splatter.assign<Drawable>("splatter-house", 64, 128, splatterAnimation);
                        splatter.assign<Position>(pos + glm::vec2(0, 1));
                        player.remove<Drawable>();
                        Mix_Volume(5, 40);
                        Mix_PlayChannel(5, game->res_manager().sound("splatter"), 0);
                    }
                    splatter.assign<Foreground>();
                    done = true;
                }
                last += dt;
                if (last > 0.5f) {
                    last = 0.0f;
                    auto text = es.create();
                    text.assign<GameText>(DEATH_MESSAGES[rand() % DEATH_MESSAGE_COUNT]);
                    text.assign<Position>(pos + glm::vec2(rand() % 40 - 20, 10));
                }
            }
        }

    private:
        Game *game;
        bool died;
        bool done;
        float last;
        DeathReason reason;
};
#endif
<|endoftext|>


<commit_before>#include "ContactAction.h"

#include "Factory.h"
#include "FEProblem.h"
#include "Parser.h"
#include "MooseApp.h"

template<>
InputParameters validParams<ContactAction>()
{
  MooseEnum orders("CONSTANT, FIRST, SECOND, THIRD, FOURTH", "FIRST");
  MooseEnum formulation("DEFAULT, PENALTY, AUGMENTED_LAGRANGE", "DEFAULT");

  InputParameters params = validParams<Action>();
  params.addRequiredParam<BoundaryName>("master", "The master surface");
  params.addRequiredParam<BoundaryName>("slave", "The slave surface");
  params.addRequiredParam<NonlinearVariableName>("disp_x", "The x displacement");
  params.addRequiredParam<NonlinearVariableName>("disp_y", "The y displacement");
  params.addParam<NonlinearVariableName>("disp_z", "", "The z displacement");
  params.addParam<Real>("penalty", 1e8, "The penalty to apply.  This can vary depending on the stiffness of your materials");
  params.addParam<Real>("friction_coefficient", 0, "The friction coefficient");
  params.addParam<Real>("tension_release", 0.0, "Tension release threshold.  A node in contact will not be released if its tensile load is below this value.  Must be positive.");
  params.addParam<std::string>("model", "frictionless", "The contact model to use");
  params.addParam<Real>("tangential_tolerance", "Tangential distance to extend edges of contact surfaces");
  params.addParam<MooseEnum>("order", orders, "The finite element order: FIRST, SECOND, etc.");
  params.addParam<MooseEnum>("formulation", formulation, "The contact formulation: default, penalty, augmented_lagrange");
  return params;
}

ContactAction::ContactAction(const std::string & name, InputParameters params) :
  Action(name, params),
  _master(getParam<BoundaryName>("master")),
  _slave(getParam<BoundaryName>("slave")),
  _disp_x(getParam<NonlinearVariableName>("disp_x")),
  _disp_y(getParam<NonlinearVariableName>("disp_y")),
  _disp_z(getParam<NonlinearVariableName>("disp_z")),
  _penalty(getParam<Real>("penalty")),
  _friction_coefficient(getParam<Real>("friction_coefficient")),
  _tension_release(getParam<Real>("tension_release")),
  _model(getParam<std::string>("model")),
  _formulation(getParam<MooseEnum>("formulation")),
  _order(getParam<MooseEnum>("order"))
{
}

void
ContactAction::act()
{
  if (!_problem->getDisplacedProblem())
  {
    mooseError("Contact requires updated coordinates.  Use the 'displacements = ...' line in the Mesh block.");
  }

  // Determine number of dimensions
  unsigned int dim(2);
  if (_disp_z != "")
  {
    ++dim;
  }

  std::string short_name(_name);
  // Chop off "Contact/"
  short_name.erase(0, 8);

  std::vector<NonlinearVariableName> vars;
  vars.push_back(_disp_x);
  vars.push_back(_disp_y);
  vars.push_back(_disp_z);

  {
    InputParameters params = Factory::instance()->getValidParams("ContactMaster");

    // Extract global params
    const std::string syntax = Moose::app->parser().getSyntaxByAction("ContactMaster", "");
    Moose::app->parser().extractParams(syntax, params);

    // Create master objects
    params.set<std::string>("model") = _model;
    params.set<std::string>("formulation") = _formulation;
    params.set<MooseEnum>("order") = _order;
    params.set<BoundaryName>("boundary") = _master;
    params.set<BoundaryName>("slave") = _slave;
    params.set<Real>("penalty") = _penalty;
    params.set<Real>("friction_coefficient") = _friction_coefficient;
    params.set<Real>("tension_release") = _tension_release;
    if (isParamValid("tangential_tolerance"))
    {
      params.set<Real>("tangential_tolerance") = getParam<Real>("tangential_tolerance");
    }
    params.addCoupledVar("disp_x", "The x displacement");
    params.set<std::vector<std::string> >("disp_x") = std::vector<std::string>(1, _disp_x);
    params.addCoupledVar("disp_y", "The y displacement");
    params.set<std::vector<std::string> >("disp_y") = std::vector<std::string>(1, _disp_y);
    params.addCoupledVar("disp_z", "The z displacement");
    if (dim == 3)
    {
      params.set<std::vector<std::string> >("disp_z") = std::vector<std::string>(1, _disp_z);
    }

    params.set<bool>("use_displaced_mesh") = true;

    for (unsigned int i(0); i < dim; ++i)
    {
      std::stringstream name;
      name << short_name;
      name << "_master_";
      name << i;

      params.set<unsigned int>("component") = i;
      params.set<NonlinearVariableName>("variable") = vars[i];

      _problem->addDiracKernel("ContactMaster",
                               name.str(),
                               params);
    }
  }

  {
    InputParameters params = Factory::instance()->getValidParams("SlaveConstraint");

    // Extract global params
    const std::string syntax = Moose::app->parser().getSyntaxByAction("SlaveConstraint", "");
    Moose::app->parser().extractParams(syntax, params);

    // Create slave objects
    params.set<std::string>("model") = _model;
    params.set<std::string>("formulation") = _formulation;
    params.set<MooseEnum>("order") = _order;
    params.set<BoundaryName>("boundary") = _slave;
    params.set<BoundaryName>("master") = _master;
    params.set<Real>("penalty") = _penalty;
    params.set<Real>("friction_coefficient") = _friction_coefficient;
    if (isParamValid("tangential_tolerance"))
    {
      params.set<Real>("tangential_tolerance") = getParam<Real>("tangential_tolerance");
    }
    params.addCoupledVar("disp_x", "The x displacement");
    params.set<std::vector<std::string> >("disp_x") = std::vector<std::string>(1, _disp_x);
    params.addCoupledVar("disp_y", "The y displacement");
    params.set<std::vector<std::string> >("disp_y") = std::vector<std::string>(1, _disp_y);
    params.addCoupledVar("disp_z", "The z displacement");
    if (dim == 3)
    {
      params.set<std::vector<std::string> >("disp_z") = std::vector<std::string>(1, _disp_z);
    }

    params.set<bool>("use_displaced_mesh") = true;

    for (unsigned int i(0); i < dim; ++i)
    {
      std::stringstream name;
      name << short_name;
      name << "_slave_";
      name << i;

      params.set<unsigned int>("component") = i;
      params.set<NonlinearVariableName>("variable") = vars[i];

      _problem->addDiracKernel("SlaveConstraint",
                               name.str(),
                               params);
    }
  }

}
<commit_msg>Small step toward contact for 1d<commit_after>#include "ContactAction.h"

#include "Factory.h"
#include "FEProblem.h"
#include "Parser.h"
#include "MooseApp.h"

template<>
InputParameters validParams<ContactAction>()
{
  MooseEnum orders("CONSTANT, FIRST, SECOND, THIRD, FOURTH", "FIRST");
  MooseEnum formulation("DEFAULT, PENALTY, AUGMENTED_LAGRANGE", "DEFAULT");

  InputParameters params = validParams<Action>();
  params.addRequiredParam<BoundaryName>("master", "The master surface");
  params.addRequiredParam<BoundaryName>("slave", "The slave surface");
  params.addRequiredParam<NonlinearVariableName>("disp_x", "The x displacement");
  params.addParam<NonlinearVariableName>("disp_y", "", "The y displacement");
  params.addParam<NonlinearVariableName>("disp_z", "", "The z displacement");
  params.addParam<Real>("penalty", 1e8, "The penalty to apply.  This can vary depending on the stiffness of your materials");
  params.addParam<Real>("friction_coefficient", 0, "The friction coefficient");
  params.addParam<Real>("tension_release", 0.0, "Tension release threshold.  A node in contact will not be released if its tensile load is below this value.  Must be positive.");
  params.addParam<std::string>("model", "frictionless", "The contact model to use");
  params.addParam<Real>("tangential_tolerance", "Tangential distance to extend edges of contact surfaces");
  params.addParam<MooseEnum>("order", orders, "The finite element order: FIRST, SECOND, etc.");
  params.addParam<MooseEnum>("formulation", formulation, "The contact formulation: default, penalty, augmented_lagrange");
  return params;
}

ContactAction::ContactAction(const std::string & name, InputParameters params) :
  Action(name, params),
  _master(getParam<BoundaryName>("master")),
  _slave(getParam<BoundaryName>("slave")),
  _disp_x(getParam<NonlinearVariableName>("disp_x")),
  _disp_y(getParam<NonlinearVariableName>("disp_y")),
  _disp_z(getParam<NonlinearVariableName>("disp_z")),
  _penalty(getParam<Real>("penalty")),
  _friction_coefficient(getParam<Real>("friction_coefficient")),
  _tension_release(getParam<Real>("tension_release")),
  _model(getParam<std::string>("model")),
  _formulation(getParam<MooseEnum>("formulation")),
  _order(getParam<MooseEnum>("order"))
{
}

void
ContactAction::act()
{
  if (!_problem->getDisplacedProblem())
  {
    mooseError("Contact requires updated coordinates.  Use the 'displacements = ...' line in the Mesh block.");
  }

  // Determine number of dimensions
  unsigned int dim(1);
  if (_disp_y != "")
  {
    ++dim;
  }
  if (_disp_z != "")
  {
    ++dim;
  }

  std::string short_name(_name);
  // Chop off "Contact/"
  short_name.erase(0, 8);

  std::vector<NonlinearVariableName> vars;
  vars.push_back(_disp_x);
  vars.push_back(_disp_y);
  vars.push_back(_disp_z);

  {
    InputParameters params = Factory::instance()->getValidParams("ContactMaster");

    // Extract global params
    const std::string syntax = Moose::app->parser().getSyntaxByAction("ContactMaster", "");
    Moose::app->parser().extractParams(syntax, params);

    // Create master objects
    params.set<std::string>("model") = _model;
    params.set<std::string>("formulation") = _formulation;
    params.set<MooseEnum>("order") = _order;
    params.set<BoundaryName>("boundary") = _master;
    params.set<BoundaryName>("slave") = _slave;
    params.set<Real>("penalty") = _penalty;
    params.set<Real>("friction_coefficient") = _friction_coefficient;
    params.set<Real>("tension_release") = _tension_release;
    if (isParamValid("tangential_tolerance"))
    {
      params.set<Real>("tangential_tolerance") = getParam<Real>("tangential_tolerance");
    }
    params.addCoupledVar("disp_x", "The x displacement");
    params.set<std::vector<std::string> >("disp_x") = std::vector<std::string>(1, _disp_x);
    params.addCoupledVar("disp_y", "The y displacement");
    if (dim > 1)
    {
      params.set<std::vector<std::string> >("disp_y") = std::vector<std::string>(1, _disp_y);
    }
    params.addCoupledVar("disp_z", "The z displacement");
    if (dim == 3)
    {
      params.set<std::vector<std::string> >("disp_z") = std::vector<std::string>(1, _disp_z);
    }

    params.set<bool>("use_displaced_mesh") = true;

    for (unsigned int i(0); i < dim; ++i)
    {
      std::stringstream name;
      name << short_name;
      name << "_master_";
      name << i;

      params.set<unsigned int>("component") = i;
      params.set<NonlinearVariableName>("variable") = vars[i];

      _problem->addDiracKernel("ContactMaster",
                               name.str(),
                               params);
    }
  }

  {
    InputParameters params = Factory::instance()->getValidParams("SlaveConstraint");

    // Extract global params
    const std::string syntax = Moose::app->parser().getSyntaxByAction("SlaveConstraint", "");
    Moose::app->parser().extractParams(syntax, params);

    // Create slave objects
    params.set<std::string>("model") = _model;
    params.set<std::string>("formulation") = _formulation;
    params.set<MooseEnum>("order") = _order;
    params.set<BoundaryName>("boundary") = _slave;
    params.set<BoundaryName>("master") = _master;
    params.set<Real>("penalty") = _penalty;
    params.set<Real>("friction_coefficient") = _friction_coefficient;
    if (isParamValid("tangential_tolerance"))
    {
      params.set<Real>("tangential_tolerance") = getParam<Real>("tangential_tolerance");
    }
    params.addCoupledVar("disp_x", "The x displacement");
    params.set<std::vector<std::string> >("disp_x") = std::vector<std::string>(1, _disp_x);
    params.addCoupledVar("disp_y", "The y displacement");
    if (dim > 1)
    {
      params.set<std::vector<std::string> >("disp_y") = std::vector<std::string>(1, _disp_y);
    }
    params.addCoupledVar("disp_z", "The z displacement");
    if (dim == 3)
    {
      params.set<std::vector<std::string> >("disp_z") = std::vector<std::string>(1, _disp_z);
    }

    params.set<bool>("use_displaced_mesh") = true;

    for (unsigned int i(0); i < dim; ++i)
    {
      std::stringstream name;
      name << short_name;
      name << "_slave_";
      name << i;

      params.set<unsigned int>("component") = i;
      params.set<NonlinearVariableName>("variable") = vars[i];

      _problem->addDiracKernel("SlaveConstraint",
                               name.str(),
                               params);
    }
  }

}
<|endoftext|>


<commit_before>/*****************************************************************************
 * open.cpp : Panels for the open dialogs
 ****************************************************************************
 * Copyright (C) 2006 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          Jean-Baptiste Kempf <jb@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "qt4.hpp"
#include "components/open.hpp"
#include "dialogs_provider.hpp"
#include "util/customwidgets.hpp"

#include <QFileDialog>
#include <QDialogButtonBox>
#include <QLineEdit>

/**************************************************************************
 * File open
 **************************************************************************/
FileOpenPanel::FileOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
    /* Classic UI Setup */
    ui.setupUi( this );

    /* Use a QFileDialog and customize it because we don't want to
       rewrite it all. Be careful to your eyes cause there are a few hacks.
       Be very careful and test correctly when you modify this. */

    /* Set Filters for file selection */
    QString fileTypes = "";
    ADD_FILTER_MEDIA( fileTypes );
    ADD_FILTER_VIDEO( fileTypes );
    ADD_FILTER_AUDIO( fileTypes );
    ADD_FILTER_PLAYLIST( fileTypes );
    ADD_FILTER_ALL( fileTypes );
    fileTypes.replace(QString(";*"), QString(" *"));

    // Make this QFileDialog a child of tempWidget from the ui.
    dialogBox = new QFileDialog( ui.tempWidget, NULL,
            qfu( p_intf->p_libvlc->psz_homedir ), fileTypes );
    dialogBox->setFileMode( QFileDialog::ExistingFiles );
    /* We don't want to see a grip in the middle of the window, do we? */
    dialogBox->setSizeGripEnabled( false );
    dialogBox->setToolTip( qtr( "Select one or multiple files, or a folder" ));

    // Add it to the layout
    ui.gridLayout->addWidget( dialogBox, 0, 0, 1, 3 );

    // But hide the two OK/Cancel buttons. Enable them for debug.
#ifndef WIN32
    findChild<QDialogButtonBox*>()->hide();
#endif

    /* Ugly hacks to get the good Widget */
    //This lineEdit is the normal line in the fileDialog.
    lineFileEdit = findChildren<QLineEdit*>()[3];
    lineFileEdit->hide();

    /* Make a list of QLabel inside the QFileDialog to access the good ones */
    QList<QLabel *> listLabel = findChildren<QLabel*>();

    /* Hide the FileNames one. Enable it for debug */
    listLabel[4]->hide();
    /* Change the text that was uncool in the usual box */
    listLabel[5]->setText( qtr( "Filter:" ) );

    /* Hacks Continued Catch the close event */
    dialogBox->installEventFilter( this );

    // Hide the subtitles control by default.
    ui.subFrame->hide();

    /* Build the subs size combo box */
    module_config_t *p_item =
        config_FindConfig( VLC_OBJECT(p_intf), "freetype-rel-fontsize" );
    if( p_item )
    {
        for( int i_index = 0; i_index < p_item->i_list; i_index++ )
        {
            ui.sizeSubComboBox->addItem(
                qfu( p_item->ppsz_list_text[i_index] ),
                QVariant( p_item->pi_list[i_index] ) );
            if( p_item->value.i == p_item->pi_list[i_index] )
            {
                ui.sizeSubComboBox->setCurrentIndex( i_index );
            }
        }
    }

    /* Build the subs align combo box */
    p_item = config_FindConfig( VLC_OBJECT(p_intf), "subsdec-align" );
    if( p_item )
    {
        for( int i_index = 0; i_index < p_item->i_list; i_index++ )
        {
            ui.alignSubComboBox->addItem(
                qfu( p_item->ppsz_list_text[i_index] ),
                QVariant( p_item->pi_list[i_index] ) );
            if( p_item->value.i == p_item->pi_list[i_index] )
            {
                ui.alignSubComboBox->setCurrentIndex( i_index );
            }
        }
    }

    BUTTONACT( ui.subBrowseButton, browseFileSub() );
    BUTTONACT( ui.subCheckBox, toggleSubtitleFrame());

    CONNECT( ui.fileInput, editTextChanged(QString ), this, updateMRL());
    CONNECT( ui.subInput, editTextChanged(QString ), this, updateMRL());
    CONNECT( ui.alignSubComboBox, currentIndexChanged(int), this, updateMRL());
    CONNECT( ui.sizeSubComboBox, currentIndexChanged(int), this, updateMRL());
    CONNECT( lineFileEdit, textChanged( QString ), this, browseFile());
}

FileOpenPanel::~FileOpenPanel()
{}

QStringList FileOpenPanel::browse(QString help)
{
    return THEDP->showSimpleOpen( help );
}

void FileOpenPanel::browseFile()
{
    QString fileString = "";
    foreach( QString file, dialogBox->selectedFiles() ) {
         fileString += "\"" + file + "\" ";
    }
    ui.fileInput->setEditText( fileString );
    updateMRL();
}

void FileOpenPanel::browseFileSub()
{
    // FIXME Handle selection of more than one subtitles file
    QStringList files = THEDP->showSimpleOpen( qtr("Open subtitles file"),
                            EXT_FILTER_SUBTITLE,
                            dialogBox->directory().absolutePath() );
    ui.subInput->setEditText( files.join(" ") );
    updateMRL();
}

void FileOpenPanel::updateMRL()
{
    QString mrl = ui.fileInput->currentText();

    if( ui.subCheckBox->isChecked() ) {
        mrl.append( " :sub-file=" + ui.subInput->currentText() );
        mrl.append( " :subsdec-align=" + ui.alignSubComboBox->currentText() );
        mrl.append( " :sub-rel-fontsize=" + ui.sizeSubComboBox->currentText() );
    }
    emit mrlUpdated( mrl );
    emit methodChanged( "file-caching" );
}

/* Function called by Open Dialog when clicke on Play/Enqueue */
void FileOpenPanel::accept()
{
    ui.fileInput->addItem(ui.fileInput->currentText());
    if ( ui.fileInput->count() > 8 ) ui.fileInput->removeItem(0);
}

/* Function called by Open Dialog when clicked on cancel */
void FileOpenPanel::clear()
{
    ui.fileInput->setEditText( "" );
    ui.subInput->setEditText( "" );
}

bool FileOpenPanel::eventFilter(QObject *object, QEvent *event)
{
    if ( ( object == dialogBox ) && ( event->type() == QEvent::Hide ) )
    {
         event->ignore();
         return true;
    }
    // standard event processing
    else
        return QObject::eventFilter(object, event);
}

void FileOpenPanel::toggleSubtitleFrame()
{
    if (ui.subFrame->isVisible())
    {
        ui.subFrame->hide();
//        setMinimumHeight(1);
        resize( sizeHint());
    }
    else
    {
        ui.subFrame->show();
    }

    /* Update the MRL */
    updateMRL();
}

/**************************************************************************
 * Disk open
 **************************************************************************/
DiskOpenPanel::DiskOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
    ui.setupUi( this );

    CONNECT( ui.deviceCombo, editTextChanged(QString ), this, updateMRL());
    BUTTONACT( ui.dvdRadioButton, updateMRL());
    BUTTONACT( ui.vcdRadioButton, updateMRL());
    BUTTONACT( ui.audioCDRadioButton, updateMRL());

    CONNECT( ui.titleSpin, valueChanged(int), this, updateMRL());
    CONNECT( ui.chapterSpin, valueChanged(int), this, updateMRL());
}

DiskOpenPanel::~DiskOpenPanel()
{}

void DiskOpenPanel::clear()
{
    ui.titleSpin->setValue(0);
    ui.chapterSpin->setValue(0);
}

void DiskOpenPanel::updateMRL()
{
    QString mrl = "";
    /* DVD */
    if( ui.dvdRadioButton->isChecked() ) {
        mrl = "dvd://" + ui.deviceCombo->currentText();
        emit methodChanged( "dvdnav-caching" );

        if ( ui.titleSpin->value() > 0 ) {
            mrl += QString("@%1").arg(ui.titleSpin->value());
            if ( ui.chapterSpin->value() > 0 ) {
                mrl+= QString(":%1").arg(ui.chapterSpin->value());
            }
        }

    /* VCD */
    } else if (ui.vcdRadioButton->isChecked() ) {
        mrl = "vcd://" + ui.deviceCombo->currentText();
        emit methodChanged( "vcd-caching" );

        if( ui.titleSpin->value() > 0 ) {
            mrl += QString("@%1").arg(ui.titleSpin->value());
        }

    /* CDDA */
    } else {
        mrl = "cdda://" + ui.deviceCombo->currentText();
    }

    emit mrlUpdated(mrl);
}

/**************************************************************************
 * Net open
 **************************************************************************/
NetOpenPanel::NetOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
    ui.setupUi( this );

    CONNECT( ui.protocolCombo, currentIndexChanged(int),
             this, updateProtocol(int) );
    CONNECT( ui.portSpin, valueChanged(int), this, updateMRL());
    CONNECT( ui.addressText, textChanged(QString), this, updateAddress());
    CONNECT( ui.timeShift, clicked(), this, updateMRL());
    CONNECT( ui.ipv6, clicked(), this, updateMRL());

    ui.protocolCombo->addItem("HTTP", QVariant("http"));
    ui.protocolCombo->addItem("FTP", QVariant("ftp"));
    ui.protocolCombo->addItem("MMS", QVariant("mms"));
    ui.protocolCombo->addItem("RTSP", QVariant("rtsp"));
    ui.protocolCombo->addItem("UDP/RTP (unicast)", QVariant("udp"));
    ui.protocolCombo->addItem("UDP/RTP (multicast)", QVariant("udp"));
}

NetOpenPanel::~NetOpenPanel()
{}

void NetOpenPanel::clear()
{}

void NetOpenPanel::updateProtocol(int idx) {
    QString addr = ui.addressText->text();
    QString proto = ui.protocolCombo->itemData(idx).toString();

    ui.timeShift->setEnabled( idx >= 4);
    ui.ipv6->setEnabled( idx == 4 );
    ui.addressText->setEnabled( idx != 4 );
    ui.portSpin->setEnabled( idx >= 4 );

    /* If we already have a protocol in the address, replace it */
    if( addr.contains( "://")) {
        msg_Err( p_intf, "replace");
        addr.replace(QRegExp("^.*://"), proto + "://");
        ui.addressText->setText(addr);
    }

    updateMRL();
}

void NetOpenPanel::updateAddress() {
    updateMRL();
}

void NetOpenPanel::updateMRL() {
    QString mrl = "";
    QString addr = ui.addressText->text();
    int proto = ui.protocolCombo->currentIndex();

    if( addr.contains( "://") && proto != 4 ) {
        mrl = addr;
    } else {
        switch(proto) {
        case 0:
            mrl = "http://" + addr;
            emit methodChanged("http-caching");
            break;
        case 2:
            mrl = "mms://" + addr;
            emit methodChanged("mms-caching");
            break;
        case 1:
            mrl = "ftp://" + addr;
            emit methodChanged("ftp-caching");
            break;
        case 3: /* RTSP */
            mrl = "rtsp://" + addr;
            emit methodChanged("rtsp-caching");
            break;
        case 4:
            mrl = "udp://@";
            if( ui.ipv6->isEnabled() && ui.ipv6->isChecked() ) {
                mrl += "[::]";
            }
            mrl += QString(":%1").arg(ui.portSpin->value());
            emit methodChanged("udp-caching");
            break;
        case 5: /* UDP multicast */
            mrl = "udp://@";
            /* Add [] to IPv6 */
            if ( addr.contains(':') && !addr.contains('[') ) {
                mrl += "[" + addr + "]";
            } else mrl += addr;
            mrl += QString(":%1").arg(ui.portSpin->value());
            emit methodChanged("udp-caching");
        }
    }
    if( ui.timeShift->isEnabled() && ui.timeShift->isChecked() ) {
        mrl += " :access-filter=timeshift";
    }
    emit mrlUpdated(mrl);
}

/**************************************************************************
 * Capture open
 **************************************************************************/
CaptureOpenPanel::CaptureOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
    ui.setupUi( this );
}

CaptureOpenPanel::~CaptureOpenPanel()
{}

void CaptureOpenPanel::clear()
{}

void CaptureOpenPanel::updateMRL()
{
    QString mrl = "";
    emit mrlUpdated(mrl);
}
<commit_msg>* open dialog: set subtitle size and align options<commit_after>/*****************************************************************************
 * open.cpp : Panels for the open dialogs
 ****************************************************************************
 * Copyright (C) 2006 the VideoLAN team
 * $Id$
 *
 * Authors: Clément Stenac <zorglub@videolan.org>
 *          Jean-Baptiste Kempf <jb@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

#include "qt4.hpp"
#include "components/open.hpp"
#include "dialogs_provider.hpp"
#include "util/customwidgets.hpp"

#include <QFileDialog>
#include <QDialogButtonBox>
#include <QLineEdit>

/**************************************************************************
 * File open
 **************************************************************************/
FileOpenPanel::FileOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
    /* Classic UI Setup */
    ui.setupUi( this );

    /* Use a QFileDialog and customize it because we don't want to
       rewrite it all. Be careful to your eyes cause there are a few hacks.
       Be very careful and test correctly when you modify this. */

    /* Set Filters for file selection */
    QString fileTypes = "";
    ADD_FILTER_MEDIA( fileTypes );
    ADD_FILTER_VIDEO( fileTypes );
    ADD_FILTER_AUDIO( fileTypes );
    ADD_FILTER_PLAYLIST( fileTypes );
    ADD_FILTER_ALL( fileTypes );
    fileTypes.replace(QString(";*"), QString(" *"));

    // Make this QFileDialog a child of tempWidget from the ui.
    dialogBox = new QFileDialog( ui.tempWidget, NULL,
            qfu( p_intf->p_libvlc->psz_homedir ), fileTypes );
    dialogBox->setFileMode( QFileDialog::ExistingFiles );
    /* We don't want to see a grip in the middle of the window, do we? */
    dialogBox->setSizeGripEnabled( false );
    dialogBox->setToolTip( qtr( "Select one or multiple files, or a folder" ));

    // Add it to the layout
    ui.gridLayout->addWidget( dialogBox, 0, 0, 1, 3 );

    // But hide the two OK/Cancel buttons. Enable them for debug.
#ifndef WIN32
    findChild<QDialogButtonBox*>()->hide();
#endif

    /* Ugly hacks to get the good Widget */
    //This lineEdit is the normal line in the fileDialog.
    lineFileEdit = findChildren<QLineEdit*>()[3];
    lineFileEdit->hide();

    /* Make a list of QLabel inside the QFileDialog to access the good ones */
    QList<QLabel *> listLabel = findChildren<QLabel*>();

    /* Hide the FileNames one. Enable it for debug */
    listLabel[4]->hide();
    /* Change the text that was uncool in the usual box */
    listLabel[5]->setText( qtr( "Filter:" ) );

    /* Hacks Continued Catch the close event */
    dialogBox->installEventFilter( this );

    // Hide the subtitles control by default.
    ui.subFrame->hide();

    /* Build the subs size combo box */
    module_config_t *p_item =
        config_FindConfig( VLC_OBJECT(p_intf), "freetype-rel-fontsize" );
    if( p_item )
    {
        for( int i_index = 0; i_index < p_item->i_list; i_index++ )
        {
            ui.sizeSubComboBox->addItem(
                qfu( p_item->ppsz_list_text[i_index] ),
                QVariant( p_item->pi_list[i_index] ) );
            if( p_item->value.i == p_item->pi_list[i_index] )
            {
                ui.sizeSubComboBox->setCurrentIndex( i_index );
            }
        }
    }

    /* Build the subs align combo box */
    p_item = config_FindConfig( VLC_OBJECT(p_intf), "subsdec-align" );
    if( p_item )
    {
        for( int i_index = 0; i_index < p_item->i_list; i_index++ )
        {
            ui.alignSubComboBox->addItem(
                qfu( p_item->ppsz_list_text[i_index] ),
                QVariant( p_item->pi_list[i_index] ) );
            if( p_item->value.i == p_item->pi_list[i_index] )
            {
                ui.alignSubComboBox->setCurrentIndex( i_index );
            }
        }
    }

    BUTTONACT( ui.subBrowseButton, browseFileSub() );
    BUTTONACT( ui.subCheckBox, toggleSubtitleFrame());

    CONNECT( ui.fileInput, editTextChanged(QString ), this, updateMRL());
    CONNECT( ui.subInput, editTextChanged(QString ), this, updateMRL());
    CONNECT( ui.alignSubComboBox, currentIndexChanged(int), this, updateMRL());
    CONNECT( ui.sizeSubComboBox, currentIndexChanged(int), this, updateMRL());
    CONNECT( lineFileEdit, textChanged( QString ), this, browseFile());
}

FileOpenPanel::~FileOpenPanel()
{}

QStringList FileOpenPanel::browse(QString help)
{
    return THEDP->showSimpleOpen( help );
}

void FileOpenPanel::browseFile()
{
    QString fileString = "";
    foreach( QString file, dialogBox->selectedFiles() ) {
         fileString += "\"" + file + "\" ";
    }
    ui.fileInput->setEditText( fileString );
    updateMRL();
}

void FileOpenPanel::browseFileSub()
{
    // FIXME Handle selection of more than one subtitles file
    QStringList files = THEDP->showSimpleOpen( qtr("Open subtitles file"),
                            EXT_FILTER_SUBTITLE,
                            dialogBox->directory().absolutePath() );
    ui.subInput->setEditText( files.join(" ") );
    updateMRL();
}

void FileOpenPanel::updateMRL()
{
    QString mrl = ui.fileInput->currentText();

    if( ui.subCheckBox->isChecked() ) {
        mrl.append( " :sub-file=" + ui.subInput->currentText() );
        int align = ui.alignSubComboBox->itemData( ui.alignSubComboBox->currentIndex() ).toInt();
        mrl.append( " :subsdec-align=" + QString().setNum( align ) );
        int size = ui.sizeSubComboBox->itemData( ui.sizeSubComboBox->currentIndex() ).toInt();
        mrl.append( " :sub-rel-fontsize=" + QString().setNum( size ) );
    }
    emit mrlUpdated( mrl );
    emit methodChanged( "file-caching" );
}

/* Function called by Open Dialog when clicke on Play/Enqueue */
void FileOpenPanel::accept()
{
    ui.fileInput->addItem(ui.fileInput->currentText());
    if ( ui.fileInput->count() > 8 ) ui.fileInput->removeItem(0);
}

/* Function called by Open Dialog when clicked on cancel */
void FileOpenPanel::clear()
{
    ui.fileInput->setEditText( "" );
    ui.subInput->setEditText( "" );
}

bool FileOpenPanel::eventFilter(QObject *object, QEvent *event)
{
    if ( ( object == dialogBox ) && ( event->type() == QEvent::Hide ) )
    {
         event->ignore();
         return true;
    }
    // standard event processing
    else
        return QObject::eventFilter(object, event);
}

void FileOpenPanel::toggleSubtitleFrame()
{
    if (ui.subFrame->isVisible())
    {
        ui.subFrame->hide();
//        setMinimumHeight(1);
        resize( sizeHint());
    }
    else
    {
        ui.subFrame->show();
    }

    /* Update the MRL */
    updateMRL();
}

/**************************************************************************
 * Disk open
 **************************************************************************/
DiskOpenPanel::DiskOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
    ui.setupUi( this );

    CONNECT( ui.deviceCombo, editTextChanged(QString ), this, updateMRL());
    BUTTONACT( ui.dvdRadioButton, updateMRL());
    BUTTONACT( ui.vcdRadioButton, updateMRL());
    BUTTONACT( ui.audioCDRadioButton, updateMRL());

    CONNECT( ui.titleSpin, valueChanged(int), this, updateMRL());
    CONNECT( ui.chapterSpin, valueChanged(int), this, updateMRL());
}

DiskOpenPanel::~DiskOpenPanel()
{}

void DiskOpenPanel::clear()
{
    ui.titleSpin->setValue(0);
    ui.chapterSpin->setValue(0);
}

void DiskOpenPanel::updateMRL()
{
    QString mrl = "";
    /* DVD */
    if( ui.dvdRadioButton->isChecked() ) {
        mrl = "dvd://" + ui.deviceCombo->currentText();
        emit methodChanged( "dvdnav-caching" );

        if ( ui.titleSpin->value() > 0 ) {
            mrl += QString("@%1").arg(ui.titleSpin->value());
            if ( ui.chapterSpin->value() > 0 ) {
                mrl+= QString(":%1").arg(ui.chapterSpin->value());
            }
        }

    /* VCD */
    } else if (ui.vcdRadioButton->isChecked() ) {
        mrl = "vcd://" + ui.deviceCombo->currentText();
        emit methodChanged( "vcd-caching" );

        if( ui.titleSpin->value() > 0 ) {
            mrl += QString("@%1").arg(ui.titleSpin->value());
        }

    /* CDDA */
    } else {
        mrl = "cdda://" + ui.deviceCombo->currentText();
    }

    emit mrlUpdated(mrl);
}

/**************************************************************************
 * Net open
 **************************************************************************/
NetOpenPanel::NetOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
    ui.setupUi( this );

    CONNECT( ui.protocolCombo, currentIndexChanged(int),
             this, updateProtocol(int) );
    CONNECT( ui.portSpin, valueChanged(int), this, updateMRL());
    CONNECT( ui.addressText, textChanged(QString), this, updateAddress());
    CONNECT( ui.timeShift, clicked(), this, updateMRL());
    CONNECT( ui.ipv6, clicked(), this, updateMRL());

    ui.protocolCombo->addItem("HTTP", QVariant("http"));
    ui.protocolCombo->addItem("FTP", QVariant("ftp"));
    ui.protocolCombo->addItem("MMS", QVariant("mms"));
    ui.protocolCombo->addItem("RTSP", QVariant("rtsp"));
    ui.protocolCombo->addItem("UDP/RTP (unicast)", QVariant("udp"));
    ui.protocolCombo->addItem("UDP/RTP (multicast)", QVariant("udp"));
}

NetOpenPanel::~NetOpenPanel()
{}

void NetOpenPanel::clear()
{}

void NetOpenPanel::updateProtocol(int idx) {
    QString addr = ui.addressText->text();
    QString proto = ui.protocolCombo->itemData(idx).toString();

    ui.timeShift->setEnabled( idx >= 4);
    ui.ipv6->setEnabled( idx == 4 );
    ui.addressText->setEnabled( idx != 4 );
    ui.portSpin->setEnabled( idx >= 4 );

    /* If we already have a protocol in the address, replace it */
    if( addr.contains( "://")) {
        msg_Err( p_intf, "replace");
        addr.replace(QRegExp("^.*://"), proto + "://");
        ui.addressText->setText(addr);
    }

    updateMRL();
}

void NetOpenPanel::updateAddress() {
    updateMRL();
}

void NetOpenPanel::updateMRL() {
    QString mrl = "";
    QString addr = ui.addressText->text();
    int proto = ui.protocolCombo->currentIndex();

    if( addr.contains( "://") && proto != 4 ) {
        mrl = addr;
    } else {
        switch(proto) {
        case 0:
            mrl = "http://" + addr;
            emit methodChanged("http-caching");
            break;
        case 2:
            mrl = "mms://" + addr;
            emit methodChanged("mms-caching");
            break;
        case 1:
            mrl = "ftp://" + addr;
            emit methodChanged("ftp-caching");
            break;
        case 3: /* RTSP */
            mrl = "rtsp://" + addr;
            emit methodChanged("rtsp-caching");
            break;
        case 4:
            mrl = "udp://@";
            if( ui.ipv6->isEnabled() && ui.ipv6->isChecked() ) {
                mrl += "[::]";
            }
            mrl += QString(":%1").arg(ui.portSpin->value());
            emit methodChanged("udp-caching");
            break;
        case 5: /* UDP multicast */
            mrl = "udp://@";
            /* Add [] to IPv6 */
            if ( addr.contains(':') && !addr.contains('[') ) {
                mrl += "[" + addr + "]";
            } else mrl += addr;
            mrl += QString(":%1").arg(ui.portSpin->value());
            emit methodChanged("udp-caching");
        }
    }
    if( ui.timeShift->isEnabled() && ui.timeShift->isChecked() ) {
        mrl += " :access-filter=timeshift";
    }
    emit mrlUpdated(mrl);
}

/**************************************************************************
 * Capture open
 **************************************************************************/
CaptureOpenPanel::CaptureOpenPanel( QWidget *_parent, intf_thread_t *_p_intf ) :
                                OpenPanel( _parent, _p_intf )
{
    ui.setupUi( this );
}

CaptureOpenPanel::~CaptureOpenPanel()
{}

void CaptureOpenPanel::clear()
{}

void CaptureOpenPanel::updateMRL()
{
    QString mrl = "";
    emit mrlUpdated(mrl);
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
//
//    Copyright (C) Streamlet. All rights reserved.
//
//    File Name:   xlRegExpTest.cpp
//    Author:      Streamlet
//    Create Time: 2012-06-02
//    Description:
//
//    Version history:
//
//
//
//------------------------------------------------------------------------------

#include <xl/Parser/xlRegExp.h>
#include <xl/Test/xlUnitTest.h>

namespace
{
    using namespace xl;

    XL_TEST_CASE()
    {
        RegExp r;
        XL_TEST_ASSERT(r.Parse(L""));
        XL_TEST_ASSERT(r.Parse(L"||"));
        XL_TEST_ASSERT(r.Parse(L"()"));
        XL_TEST_ASSERT(r.Parse(L"|"));
        XL_TEST_ASSERT(r.Parse(L"(|)"));
        XL_TEST_ASSERT(r.Parse(L"(||)"));
        XL_TEST_ASSERT(r.Parse(L"()|()"));
        XL_TEST_ASSERT(!r.Parse(L"("));
        XL_TEST_ASSERT(!r.Parse(L")"));
    }

    XL_TEST_CASE()
    {
        RegExp r;

        XL_TEST_ASSERT(r.Parse(L""));
        XL_TEST_ASSERT(r.Match(L""));
        XL_TEST_ASSERT(!r.Match(L"a"));

        XL_TEST_ASSERT(r.Parse(L"a"));
        XL_TEST_ASSERT(r.Match(L"a"));
        XL_TEST_ASSERT(!r.Match(L"ab"));
        XL_TEST_ASSERT(!r.Match(L"b"));

        XL_TEST_ASSERT(r.Parse(L"(a)"));
        XL_TEST_ASSERT(r.Match(L"a"));
        XL_TEST_ASSERT(!r.Match(L"ab"));
        XL_TEST_ASSERT(!r.Match(L"b"));

        XL_TEST_ASSERT(r.Parse(L"ab|c"));
        XL_TEST_ASSERT(!r.Match(L"a"));
        XL_TEST_ASSERT(!r.Match(L"b"));
        XL_TEST_ASSERT(r.Match(L"c"));
        XL_TEST_ASSERT(r.Match(L"ab"));
        XL_TEST_ASSERT(!r.Match(L"bc"));
        XL_TEST_ASSERT(!r.Match(L"ac"));

        XL_TEST_ASSERT(r.Parse(L"a(b|c)"));
        XL_TEST_ASSERT(!r.Match(L"a"));
        XL_TEST_ASSERT(!r.Match(L"b"));
        XL_TEST_ASSERT(!r.Match(L"c"));
        XL_TEST_ASSERT(r.Match(L"ab"));
        XL_TEST_ASSERT(r.Match(L"ac"));
        XL_TEST_ASSERT(!r.Match(L"bc"));
    }

    XL_TEST_CASE()
    {
        RegExp r;
        // an integer from 0 to 255
        // 1 digit: (0|1|2|3|4|5|6|7|8|9)
        // 2 digit: (0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)
        // 3 digit:
        //   0-199: (0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)
        // 200-249: 2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)
        // 250-255: 25(0|1|2|3|4|5)
        XL_TEST_ASSERT(r.Parse(L"(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)|"
                               L"25(0|1|2|3|4|5)"));
        XL_TEST_ASSERT(r.Match(L"0"));
        XL_TEST_ASSERT(r.Match(L"1"));
        XL_TEST_ASSERT(r.Match(L"2"));
        XL_TEST_ASSERT(r.Match(L"3"));
        XL_TEST_ASSERT(r.Match(L"4"));
        XL_TEST_ASSERT(r.Match(L"5"));
        XL_TEST_ASSERT(r.Match(L"6"));
        XL_TEST_ASSERT(r.Match(L"7"));
        XL_TEST_ASSERT(r.Match(L"8"));
        XL_TEST_ASSERT(r.Match(L"9"));
        XL_TEST_ASSERT(r.Match(L"10"));
        XL_TEST_ASSERT(r.Match(L"20"));
        XL_TEST_ASSERT(r.Match(L"30"));
        XL_TEST_ASSERT(r.Match(L"40"));
        XL_TEST_ASSERT(r.Match(L"50"));
        XL_TEST_ASSERT(r.Match(L"60"));
        XL_TEST_ASSERT(r.Match(L"70"));
        XL_TEST_ASSERT(r.Match(L"80"));
        XL_TEST_ASSERT(r.Match(L"90"));
        XL_TEST_ASSERT(r.Match(L"100"));
        XL_TEST_ASSERT(r.Match(L"199"));
        XL_TEST_ASSERT(r.Match(L"200"));
        XL_TEST_ASSERT(r.Match(L"249"));
        XL_TEST_ASSERT(r.Match(L"250"));
        XL_TEST_ASSERT(r.Match(L"251"));
        XL_TEST_ASSERT(r.Match(L"252"));
        XL_TEST_ASSERT(r.Match(L"253"));
        XL_TEST_ASSERT(r.Match(L"254"));
        XL_TEST_ASSERT(r.Match(L"255"));
        XL_TEST_ASSERT(!r.Match(L"256"));
        XL_TEST_ASSERT(!r.Match(L"260"));
        XL_TEST_ASSERT(!r.Match(L"300"));

        // IPv4 address
        XL_TEST_ASSERT(r.Parse(L"("
                               L"(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)|"
                               L"25(0|1|2|3|4|5)"
                               L").("
                               L"(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)|"
                               L"25(0|1|2|3|4|5)"
                               L").("
                               L"(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)|"
                               L"25(0|1|2|3|4|5)"
                               L").("
                               L"(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)|"
                               L"25(0|1|2|3|4|5)"
                               L")"));
        XL_TEST_ASSERT(r.Match(L"192.168.1.1"));
        XL_TEST_ASSERT(r.Match(L"0.0.0.0"));
        XL_TEST_ASSERT(r.Match(L"255.255.255.255"));
        XL_TEST_ASSERT(!r.Match(L"0.0.0.256"));
    }

}
<commit_msg>add unit test for RegExp<commit_after>//------------------------------------------------------------------------------
//
//    Copyright (C) Streamlet. All rights reserved.
//
//    File Name:   xlRegExpTest.cpp
//    Author:      Streamlet
//    Create Time: 2012-06-02
//    Description:
//
//    Version history:
//
//
//
//------------------------------------------------------------------------------

#include <xl/Parser/xlRegExp.h>
#include <xl/Test/xlUnitTest.h>

namespace
{
    using namespace xl;

    XL_TEST_CASE()
    {
        RegExp r;
        XL_TEST_ASSERT(r.Parse(L""));
        XL_TEST_ASSERT(r.Parse(L"||"));
        XL_TEST_ASSERT(r.Parse(L"()"));
        XL_TEST_ASSERT(r.Parse(L"|"));
        XL_TEST_ASSERT(r.Parse(L"(|)"));
        XL_TEST_ASSERT(r.Parse(L"(||)"));
        XL_TEST_ASSERT(r.Parse(L"()|()"));
        XL_TEST_ASSERT(!r.Parse(L"("));
        XL_TEST_ASSERT(!r.Parse(L")"));
    }

    XL_TEST_CASE()
    {
        RegExp r;

        XL_TEST_ASSERT(r.Parse(L""));
        XL_TEST_ASSERT(r.Match(L""));
        XL_TEST_ASSERT(!r.Match(L"a"));

        XL_TEST_ASSERT(r.Parse(L"a"));
        XL_TEST_ASSERT(r.Match(L"a"));
        XL_TEST_ASSERT(!r.Match(L"ab"));
        XL_TEST_ASSERT(!r.Match(L"b"));

        XL_TEST_ASSERT(r.Parse(L"(a)"));
        XL_TEST_ASSERT(r.Match(L"a"));
        XL_TEST_ASSERT(!r.Match(L"ab"));
        XL_TEST_ASSERT(!r.Match(L"b"));

        XL_TEST_ASSERT(r.Parse(L"ab|c"));
        XL_TEST_ASSERT(!r.Match(L"a"));
        XL_TEST_ASSERT(!r.Match(L"b"));
        XL_TEST_ASSERT(r.Match(L"c"));
        XL_TEST_ASSERT(r.Match(L"ab"));
        XL_TEST_ASSERT(!r.Match(L"bc"));
        XL_TEST_ASSERT(!r.Match(L"ac"));

        XL_TEST_ASSERT(r.Parse(L"a(b|c)"));
        XL_TEST_ASSERT(!r.Match(L"a"));
        XL_TEST_ASSERT(!r.Match(L"b"));
        XL_TEST_ASSERT(!r.Match(L"c"));
        XL_TEST_ASSERT(r.Match(L"ab"));
        XL_TEST_ASSERT(r.Match(L"ac"));
        XL_TEST_ASSERT(!r.Match(L"bc"));
    }

    XL_TEST_CASE()
    {
        RegExp r;

        XL_TEST_ASSERT(r.Parse(L"\\|"));
        XL_TEST_ASSERT(r.Match(L"|"));

        XL_TEST_ASSERT(r.Parse(L"\\("));
        XL_TEST_ASSERT(r.Match(L"("));

        XL_TEST_ASSERT(r.Parse(L"\\)"));
        XL_TEST_ASSERT(r.Match(L")"));

        XL_TEST_ASSERT(r.Parse(L"\\\\"));
        XL_TEST_ASSERT(r.Match(L"\\"));

        XL_TEST_ASSERT(r.Parse(L"\\"));
        XL_TEST_ASSERT(r.Match(L"\\"));

        XL_TEST_ASSERT(r.Parse(L"\\|(\\(|\\))"));
        XL_TEST_ASSERT(r.Match(L"|("));
        XL_TEST_ASSERT(r.Match(L"|)"));
    }

    XL_TEST_CASE()
    {
        RegExp r;
        // an integer from 0 to 255
        // 1 digit: (0|1|2|3|4|5|6|7|8|9)
        // 2 digit: (0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)
        // 3 digit:
        //   0-199: (0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)
        // 200-249: 2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)
        // 250-255: 25(0|1|2|3|4|5)
        XL_TEST_ASSERT(r.Parse(L"(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)|"
                               L"25(0|1|2|3|4|5)"));
        XL_TEST_ASSERT(r.Match(L"0"));
        XL_TEST_ASSERT(r.Match(L"1"));
        XL_TEST_ASSERT(r.Match(L"2"));
        XL_TEST_ASSERT(r.Match(L"3"));
        XL_TEST_ASSERT(r.Match(L"4"));
        XL_TEST_ASSERT(r.Match(L"5"));
        XL_TEST_ASSERT(r.Match(L"6"));
        XL_TEST_ASSERT(r.Match(L"7"));
        XL_TEST_ASSERT(r.Match(L"8"));
        XL_TEST_ASSERT(r.Match(L"9"));
        XL_TEST_ASSERT(r.Match(L"10"));
        XL_TEST_ASSERT(r.Match(L"20"));
        XL_TEST_ASSERT(r.Match(L"30"));
        XL_TEST_ASSERT(r.Match(L"40"));
        XL_TEST_ASSERT(r.Match(L"50"));
        XL_TEST_ASSERT(r.Match(L"60"));
        XL_TEST_ASSERT(r.Match(L"70"));
        XL_TEST_ASSERT(r.Match(L"80"));
        XL_TEST_ASSERT(r.Match(L"90"));
        XL_TEST_ASSERT(r.Match(L"100"));
        XL_TEST_ASSERT(r.Match(L"199"));
        XL_TEST_ASSERT(r.Match(L"200"));
        XL_TEST_ASSERT(r.Match(L"249"));
        XL_TEST_ASSERT(r.Match(L"250"));
        XL_TEST_ASSERT(r.Match(L"251"));
        XL_TEST_ASSERT(r.Match(L"252"));
        XL_TEST_ASSERT(r.Match(L"253"));
        XL_TEST_ASSERT(r.Match(L"254"));
        XL_TEST_ASSERT(r.Match(L"255"));
        XL_TEST_ASSERT(!r.Match(L"256"));
        XL_TEST_ASSERT(!r.Match(L"260"));
        XL_TEST_ASSERT(!r.Match(L"300"));

        // IPv4 address
        XL_TEST_ASSERT(r.Parse(L"("
                               L"(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)|"
                               L"25(0|1|2|3|4|5)"
                               L").("
                               L"(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)|"
                               L"25(0|1|2|3|4|5)"
                               L").("
                               L"(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)|"
                               L"25(0|1|2|3|4|5)"
                               L").("
                               L"(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"(0|1)(0|1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)|"
                               L"2(0|1|2|3|4)(0|1|2|3|4|5|6|7|8|9)|"
                               L"25(0|1|2|3|4|5)"
                               L")"));
        XL_TEST_ASSERT(r.Match(L"192.168.1.1"));
        XL_TEST_ASSERT(r.Match(L"0.0.0.0"));
        XL_TEST_ASSERT(r.Match(L"255.255.255.255"));
        XL_TEST_ASSERT(!r.Match(L"0.0.0.256"));
    }

}
<|endoftext|>


<commit_before>#include "thp/wpi/interfaces.hpp"

#include "toast/memory.hpp"

#include "SpeedController.h"
#include "SD540.h"
#include "Spark.h"
#include "Talon.h"
#include "Victor.h"
#include "VictorSP.h"
#include "TalonSRX.h"
#include "Servo.h"
#include "PWM.h"

using namespace Toast;

typedef Memory::Shared::IO::MotorType MType;

static SpeedController *motors[16];
static Servo *servos[20];
static PWM *pwms[20];

void init_itf_motor() {
	Memory::Shared::IO::ServoStatic *stat = Memory::shared()->servo_static();
	stat->set_angle_range(Servo::GetMaxAngle() - Servo::GetMinAngle());
	stat->set_max_angle(Servo::GetMaxAngle());
	stat->set_min_angle(Servo::GetMinAngle());
}

void tick_itf_motor() {
	Concurrent::IPCMutex *mtx = Memory::shared_mutex()->motor;
	for (int i = 0; i < 16; i++) {
		MTX_LOCK(mtx, i);
		Memory::Shared::IO::Motor *motor = Memory::shared()->motor(i);
		if (motor->get_init()) {
			Memory::Shared::IO::MotorType type = motor->get_type();
			Memory::Shared::IO::MotorInterface intf = motor->get_interface();
			int port = motor->get_port();
			if (!motor->get_bootstrap()) {
				SpeedController *controller = nullptr;
				if (type == MType::SD540)
					controller = (SpeedController *)(new SD540(port));
				else if (type == MType::Spark)
					controller = (SpeedController *)(new Spark(port));
				else if (type == MType::Talon)
					controller = (SpeedController *)(new Talon(port));
				else if (type == MType::Victor)
					controller = (SpeedController *)(new Victor(port));
				else if (type == MType::VictorSP)
					controller = (SpeedController *)(new VictorSP(port));
				else if (type == MType::TalonSRX)
					controller = (SpeedController *)(new TalonSRX(port));

				motors[i] = controller;
				motor->set_bootstrap(true);
			}

			SpeedController *m = motors[i];
			m->Set(motor->get_value());
		}
		MTX_UNLOCK(mtx, i);
	}

	mtx = Memory::shared_mutex()->servo;
	for (int i = 0; i < 20; i++) {
		MTX_LOCK(mtx, i);
		Memory::Shared::IO::Servo *servo = Memory::shared()->servo(i);
		if (servo->get_init()) {
			if (!servo->get_bootstrap()) {
				servos[i] = new Servo(i);
				servo->set_bootstrap(true);
			}

			Servo *srv = servos[i];
			if (servo->get_offline_pending()) {
				if (servo->get_offline()) srv->SetOffline();
				servo->set_offline_pending(false);
			}

			if (servo->get_update_pending()) {
				srv->Set(servo->get_value());
				servo->set_update_pending(false);
			}
		}
		MTX_UNLOCK(mtx, i);
	}

	mtx = Memory::shared_mutex()->pwm;
	for (int i = 0; i < 20; i++) {
		MTX_LOCK(mtx, i);
		Memory::Shared::IO::PWM *pwm = Memory::shared()->pwm;
		if (pwm->get_init()) {
			if (!pwm->get_bootstrap) {
				pwms[i] = new PWM(i);
				pwm->set_bootstrap(true);
			}

			PWM *p = pwms[i];
			if (pwm->get_period_mult_pending()) {
				p->SetPeriodMultiplier((PWM::PeriodMultiplier)(int)pwm->get_period_multiplier());
				pwm->set_period_mult_pending(false);
			}
			if (pwm->get_raw_pending()) {
				p->SetRaw(pwm->get_raw());
				pwm->set_raw_pending(false);
			}
			if (pwm->get_position_pending()) {
				p->SetPosition(pwm->get_position());
				pwm->set_position_pending(false);
			}
			if (pwm->get_speed_pending()) {
				p->SetSpeed(pwm->get_speed());
				pwm->set_speed_pending(false);
			}
			if (pwm->get_deadband_elimination_pending()) {
				p->EnableDeadbandElimination(pwm->get_deadband_elimination());
				pwm->set_deadband_elimination_pending(false);
			}
			if (pwm->get_bounds_pending()) {
				if (pwm->get_bounds_int32()) {
					p->SetRawBounds(
						(int)pwm->get_bounds_max(),
						(int)pwm->get_bounds_deadband_max(),
						(int)pwm->get_bounds_center(),
						(int)pwm->get_bounds_deadband_min(),
						(int)pwm->get_bounds_min()
					);
				} else {
					p->SetBounds(
						pwm->get_bounds_max(),
						pwm->get_bounds_deadband_max(),
						pwm->get_bounds_center(),
						pwm->get_bounds_deadband_min(),
						pwm->get_bounds_min()
					);
				}
				pwm->set_bounds_pending(false);
			}
			if (pwm->get_zero_latch()) {
				p->SetZeroLatch();
				pwm->set_zero_latch(false);
			}
			// This is just used so the module process can read, i.e. if GetRaw is called, GetSpeed is indirectly
			// changed.
			pwm->set_raw(p->GetRaw());
			pwm->set_position(p->GetPosition());
			pwm->set_speed(p->GetSpeed());
		}
		MTX_UNLOCK(mtx, i);
	}
}<commit_msg>Fix motor class build<commit_after>#include "thp/wpi/interfaces.hpp"

#include "toast/memory.hpp"

#include "SpeedController.h"
#include "SD540.h"
#include "Spark.h"
#include "Talon.h"
#include "Victor.h"
#include "VictorSP.h"
#include "TalonSRX.h"
#include "Servo.h"
#include "PWM.h"

using namespace Toast;

typedef Memory::Shared::IO::MotorType MType;

static SpeedController *motors[16];
static Servo *servos[20];
static PWM *pwms[20];

void init_itf_motor() {
	Memory::Shared::IO::ServoStatic *stat = Memory::shared()->servo_static();
	stat->set_angle_range(Servo::GetMaxAngle() - Servo::GetMinAngle());
	stat->set_max_angle(Servo::GetMaxAngle());
	stat->set_min_angle(Servo::GetMinAngle());
}

void tick_itf_motor() {
	Concurrent::IPCMutex *mtx = Memory::shared_mutex()->motor;
	for (int i = 0; i < 16; i++) {
		MTX_LOCK(mtx, i);
		Memory::Shared::IO::Motor *motor = Memory::shared()->motor(i);
		if (motor->get_init()) {
			Memory::Shared::IO::MotorType type = motor->get_type();
			Memory::Shared::IO::MotorInterface intf = motor->get_interface();
			int port = motor->get_port();
			if (!motor->get_bootstrap()) {
				SpeedController *controller = nullptr;
				if (type == MType::SD540)
					controller = (SpeedController *)(new SD540(port));
				else if (type == MType::Spark)
					controller = (SpeedController *)(new Spark(port));
				else if (type == MType::Talon)
					controller = (SpeedController *)(new Talon(port));
				else if (type == MType::Victor)
					controller = (SpeedController *)(new Victor(port));
				else if (type == MType::VictorSP)
					controller = (SpeedController *)(new VictorSP(port));
				else if (type == MType::TalonSRX)
					controller = (SpeedController *)(new TalonSRX(port));

				motors[i] = controller;
				motor->set_bootstrap(true);
			}

			SpeedController *m = motors[i];
			m->Set(motor->get_value());
		}
		MTX_UNLOCK(mtx, i);
	}

	mtx = Memory::shared_mutex()->servo;
	for (int i = 0; i < 20; i++) {
		MTX_LOCK(mtx, i);
		Memory::Shared::IO::Servo *servo = Memory::shared()->servo(i);
		if (servo->get_init()) {
			if (!servo->get_bootstrap()) {
				servos[i] = new Servo(i);
				servo->set_bootstrap(true);
			}

			Servo *srv = servos[i];
			if (servo->get_offline_pending()) {
				if (servo->get_offline()) srv->SetOffline();
				servo->set_offline_pending(false);
			}

			if (servo->get_update_pending()) {
				srv->Set(servo->get_value());
				servo->set_update_pending(false);
			}
		}
		MTX_UNLOCK(mtx, i);
	}

	mtx = Memory::shared_mutex()->pwm;
	for (int i = 0; i < 20; i++) {
		MTX_LOCK(mtx, i);
		Memory::Shared::IO::PWM *pwm = Memory::shared()->pwm;
		if (pwm->get_init()) {
			if (!pwm->get_bootstrap()) {
				pwms[i] = new PWM(i);
				pwm->set_bootstrap(true);
			}

			PWM *p = pwms[i];
			if (pwm->get_period_mult_pending()) {
				p->SetPeriodMultiplier((PWM::PeriodMultiplier)(int)pwm->get_period_multiplier());
				pwm->set_period_mult_pending(false);
			}
			if (pwm->get_raw_pending()) {
				p->SetRaw(pwm->get_raw());
				pwm->set_raw_pending(false);
			}
			if (pwm->get_position_pending()) {
				p->SetPosition(pwm->get_position());
				pwm->set_position_pending(false);
			}
			if (pwm->get_speed_pending()) {
				p->SetSpeed(pwm->get_speed());
				pwm->set_speed_pending(false);
			}
			if (pwm->get_deadband_elimination_pending()) {
				p->EnableDeadbandElimination(pwm->get_deadband_elimination());
				pwm->set_deadband_elimination_pending(false);
			}
			if (pwm->get_bounds_pending()) {
				if (pwm->get_bounds_int32()) {
					p->SetRawBounds(
						(int)pwm->get_bounds_max(),
						(int)pwm->get_bounds_deadband_max(),
						(int)pwm->get_bounds_center(),
						(int)pwm->get_bounds_deadband_min(),
						(int)pwm->get_bounds_min()
					);
				} else {
					p->SetBounds(
						pwm->get_bounds_max(),
						pwm->get_bounds_deadband_max(),
						pwm->get_bounds_center(),
						pwm->get_bounds_deadband_min(),
						pwm->get_bounds_min()
					);
				}
				pwm->set_bounds_pending(false);
			}
			if (pwm->get_zero_latch()) {
				p->SetZeroLatch();
				pwm->set_zero_latch(false);
			}
			// This is just used so the module process can read, i.e. if GetRaw is called, GetSpeed is indirectly
			// changed.
			pwm->set_raw(p->GetRaw());
			pwm->set_position(p->GetPosition());
			pwm->set_speed(p->GetSpeed());
		}
		MTX_UNLOCK(mtx, i);
	}
}<|endoftext|>


<commit_before>/*****************************************************************************
 * dash.cpp: DASH module
 *****************************************************************************
 * Copyright © 2010 - 2011 Klagenfurt University
 *
 * Created on: Aug 10, 2010
 * Authors: Christopher Mueller <christopher.mueller@itec.uni-klu.ac.at>
 *          Christian Timmerer  <christian.timmerer@itec.uni-klu.ac.at>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program 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 program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#define __STDC_CONSTANT_MACROS 1

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdint.h>

#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_demux.h>

#include <errno.h>

#include "dash.hpp"
#include "xml/DOMParser.h"
#include "mpd/MPDFactory.h"

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open    (vlc_object_t *);
static void Close   (vlc_object_t *);

#define DASH_WIDTH_TEXT N_("Preferred Width")
#define DASH_WIDTH_LONGTEXT N_("Preferred Width")

#define DASH_HEIGHT_TEXT N_("Preferred Height")
#define DASH_HEIGHT_LONGTEXT N_("Preferred Height")

#define DASH_BW_TEXT N_("Fixed Bandwidth in KiB/s")
#define DASH_BW_LONGTEXT N_("Preferred bandwidth for non adaptative streams")

vlc_module_begin ()
        set_shortname( N_("DASH"))
        set_description( N_("Dynamic Adaptive Streaming over HTTP") )
        set_capability( "demux", 10 )
        set_category( CAT_INPUT )
        set_subcategory( SUBCAT_INPUT_DEMUX )
        add_integer( "dash-prefwidth",  480, DASH_WIDTH_TEXT,  DASH_WIDTH_LONGTEXT,  true )
        add_integer( "dash-prefheight", 360, DASH_HEIGHT_TEXT, DASH_HEIGHT_LONGTEXT, true )
        add_integer( "dash-prefbw",     250, DASH_BW_TEXT,     DASH_BW_LONGTEXT,     false )
        set_callbacks( Open, Close )
vlc_module_end ()

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/

static int  Demux( demux_t * );
static int  Control         (demux_t *p_demux, int i_query, va_list args);

/*****************************************************************************
 * Open:
 *****************************************************************************/
static int Open(vlc_object_t *p_obj)
{
    demux_t *p_demux = (demux_t*) p_obj;

    if(!dash::xml::DOMParser::isDash(p_demux->s))
        return VLC_EGENERIC;

    //Build a XML tree
    dash::xml::DOMParser        parser(p_demux->s);
    if( !parser.parse() )
    {
        msg_Err( p_demux, "Could not parse MPD" );
        return VLC_EGENERIC;
    }

    //Begin the actual MPD parsing:
    dash::mpd::MPD *mpd = dash::mpd::MPDFactory::create(parser.getRootNode(), p_demux->s, parser.getProfile());
    if(mpd == NULL)
    {
        msg_Err( p_demux, "Cannot create/unknown MPD for profile");
        return VLC_EGENERIC;
    }

    demux_sys_t        *p_sys = (demux_sys_t *) malloc(sizeof(demux_sys_t));
    if (unlikely(p_sys == NULL))
        return VLC_ENOMEM;

    p_sys->p_mpd = mpd;
    dash::DASHManager*p_dashManager = new dash::DASHManager(p_sys->p_mpd,
                                          dash::logic::IAdaptationLogic::Default,
                                          p_demux->s);

    dash::mpd::Period *period = mpd->getFirstPeriod();
    if(period && !p_dashManager->start(p_demux))
    {
        delete p_dashManager;
        free( p_sys );
        return VLC_EGENERIC;
    }
    p_sys->p_dashManager    = p_dashManager;
    p_demux->p_sys         = p_sys;
    p_demux->pf_demux      = Demux;
    p_demux->pf_control    = Control;

    msg_Dbg(p_obj,"opening mpd file (%s)", p_demux->s->psz_path);

    return VLC_SUCCESS;
}
/*****************************************************************************
 * Close:
 *****************************************************************************/
static void Close(vlc_object_t *p_obj)
{
    demux_t                            *p_demux       = (demux_t*) p_obj;
    demux_sys_t                        *p_sys          = (demux_sys_t *) p_demux->p_sys;
    dash::DASHManager                   *p_dashManager  = p_sys->p_dashManager;

    delete p_dashManager;
    free(p_sys);
}
/*****************************************************************************
 * Callbacks:
 *****************************************************************************/
static int Demux(demux_t *p_demux)
{
    demux_sys_t *p_sys = p_demux->p_sys;
    if ( p_sys->p_dashManager->read() > 0 )
    {
        if ( p_sys->p_dashManager->esCount() )
        {
            mtime_t pcr = p_sys->p_dashManager->getPCR();
            int group = p_sys->p_dashManager->getGroup();
            if(group > 0)
                es_out_Control(p_demux->out, ES_OUT_SET_GROUP_PCR, group, pcr);
            else
                es_out_Control(p_demux->out, ES_OUT_SET_PCR, pcr);
        }
        return VLC_DEMUXER_SUCCESS;
    }
    else
        return VLC_DEMUXER_EOF;
}

static int  Control         (demux_t *p_demux, int i_query, va_list args)
{
    demux_sys_t *p_sys = p_demux->p_sys;

    switch (i_query)
    {
        case DEMUX_CAN_SEEK:
            *(va_arg (args, bool *)) = false;
            break;

        case DEMUX_CAN_CONTROL_PACE:
            *(va_arg (args, bool *)) = true;
            break;

        case DEMUX_CAN_PAUSE:
            *(va_arg (args, bool *)) = p_sys->p_mpd->isLive();
            break;

        case DEMUX_GET_TIME:
            *(va_arg (args, int64_t *)) = p_sys->p_dashManager->getPCR();
            break;

        case DEMUX_GET_LENGTH:
            *(va_arg (args, int64_t *)) = p_sys->p_dashManager->getDuration();
            break;

        case DEMUX_GET_POSITION:
            if(!p_sys->p_dashManager->getDuration())
                return VLC_EGENERIC;

            *(va_arg (args, double *)) = (double) p_sys->p_dashManager->getPCR()
                                         / p_sys->p_dashManager->getDuration();
            break;

        case DEMUX_GET_PTS_DELAY:
            *va_arg (args, int64_t *) = INT64_C(1000) *
                var_InheritInteger(p_demux, "network-caching");
             break;

        default:
            return VLC_EGENERIC;
    }
    return VLC_SUCCESS;
}
<commit_msg>demux: dash: add logic pref variable<commit_after>/*****************************************************************************
 * dash.cpp: DASH module
 *****************************************************************************
 * Copyright © 2010 - 2011 Klagenfurt University
 *
 * Created on: Aug 10, 2010
 * Authors: Christopher Mueller <christopher.mueller@itec.uni-klu.ac.at>
 *          Christian Timmerer  <christian.timmerer@itec.uni-klu.ac.at>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * This program 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 program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#define __STDC_CONSTANT_MACROS 1

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <stdint.h>

#include <vlc_common.h>
#include <vlc_plugin.h>
#include <vlc_demux.h>

#include <errno.h>

#include "dash.hpp"
#include "xml/DOMParser.h"
#include "mpd/MPDFactory.h"

/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
static int  Open    (vlc_object_t *);
static void Close   (vlc_object_t *);

#define DASH_WIDTH_TEXT N_("Preferred Width")
#define DASH_WIDTH_LONGTEXT N_("Preferred Width")

#define DASH_HEIGHT_TEXT N_("Preferred Height")
#define DASH_HEIGHT_LONGTEXT N_("Preferred Height")

#define DASH_BW_TEXT N_("Fixed Bandwidth in KiB/s")
#define DASH_BW_LONGTEXT N_("Preferred bandwidth for non adaptative streams")

#define DASH_LOGIC_TEXT N_("Adaptation Logic")

static const int pi_logics[] = {dash::logic::IAdaptationLogic::RateBased,
                                dash::logic::IAdaptationLogic::FixedRate,
                                dash::logic::IAdaptationLogic::AlwaysLowest,
                                dash::logic::IAdaptationLogic::AlwaysBest};

static const char *const ppsz_logics[] = { N_("Bandwidth Adaptive"),
                                           N_("Fixed Bandwidth"),
                                           N_("Lowest Bandwidth/Quality"),
                                           N_("Highest Bandwith/Quality")};

vlc_module_begin ()
        set_shortname( N_("DASH"))
        set_description( N_("Dynamic Adaptive Streaming over HTTP") )
        set_capability( "demux", 10 )
        set_category( CAT_INPUT )
        set_subcategory( SUBCAT_INPUT_DEMUX )
        add_integer( "dash-logic",      dash::logic::IAdaptationLogic::Default,
                                             DASH_LOGIC_TEXT, NULL, false )
            change_integer_list( pi_logics, ppsz_logics )
        add_integer( "dash-prefwidth",  480, DASH_WIDTH_TEXT,  DASH_WIDTH_LONGTEXT,  true )
        add_integer( "dash-prefheight", 360, DASH_HEIGHT_TEXT, DASH_HEIGHT_LONGTEXT, true )
        add_integer( "dash-prefbw",     250, DASH_BW_TEXT,     DASH_BW_LONGTEXT,     false )
        set_callbacks( Open, Close )
vlc_module_end ()

/*****************************************************************************
 * Local prototypes
 *****************************************************************************/

static int  Demux( demux_t * );
static int  Control         (demux_t *p_demux, int i_query, va_list args);

/*****************************************************************************
 * Open:
 *****************************************************************************/
static int Open(vlc_object_t *p_obj)
{
    demux_t *p_demux = (demux_t*) p_obj;

    if(!dash::xml::DOMParser::isDash(p_demux->s))
        return VLC_EGENERIC;

    //Build a XML tree
    dash::xml::DOMParser        parser(p_demux->s);
    if( !parser.parse() )
    {
        msg_Err( p_demux, "Could not parse MPD" );
        return VLC_EGENERIC;
    }

    //Begin the actual MPD parsing:
    dash::mpd::MPD *mpd = dash::mpd::MPDFactory::create(parser.getRootNode(), p_demux->s, parser.getProfile());
    if(mpd == NULL)
    {
        msg_Err( p_demux, "Cannot create/unknown MPD for profile");
        return VLC_EGENERIC;
    }

    demux_sys_t        *p_sys = (demux_sys_t *) malloc(sizeof(demux_sys_t));
    if (unlikely(p_sys == NULL))
        return VLC_ENOMEM;

    p_sys->p_mpd = mpd;
    int logic = var_InheritInteger( p_obj, "dash-logic" );
    dash::DASHManager*p_dashManager = new dash::DASHManager(p_sys->p_mpd,
            static_cast<dash::logic::IAdaptationLogic::LogicType>(logic),
            p_demux->s);

    dash::mpd::Period *period = mpd->getFirstPeriod();
    if(period && !p_dashManager->start(p_demux))
    {
        delete p_dashManager;
        free( p_sys );
        return VLC_EGENERIC;
    }
    p_sys->p_dashManager    = p_dashManager;
    p_demux->p_sys         = p_sys;
    p_demux->pf_demux      = Demux;
    p_demux->pf_control    = Control;

    msg_Dbg(p_obj,"opening mpd file (%s)", p_demux->s->psz_path);

    return VLC_SUCCESS;
}
/*****************************************************************************
 * Close:
 *****************************************************************************/
static void Close(vlc_object_t *p_obj)
{
    demux_t                            *p_demux       = (demux_t*) p_obj;
    demux_sys_t                        *p_sys          = (demux_sys_t *) p_demux->p_sys;
    dash::DASHManager                   *p_dashManager  = p_sys->p_dashManager;

    delete p_dashManager;
    free(p_sys);
}
/*****************************************************************************
 * Callbacks:
 *****************************************************************************/
static int Demux(demux_t *p_demux)
{
    demux_sys_t *p_sys = p_demux->p_sys;
    if ( p_sys->p_dashManager->read() > 0 )
    {
        if ( p_sys->p_dashManager->esCount() )
        {
            mtime_t pcr = p_sys->p_dashManager->getPCR();
            int group = p_sys->p_dashManager->getGroup();
            if(group > 0)
                es_out_Control(p_demux->out, ES_OUT_SET_GROUP_PCR, group, pcr);
            else
                es_out_Control(p_demux->out, ES_OUT_SET_PCR, pcr);
        }
        return VLC_DEMUXER_SUCCESS;
    }
    else
        return VLC_DEMUXER_EOF;
}

static int  Control         (demux_t *p_demux, int i_query, va_list args)
{
    demux_sys_t *p_sys = p_demux->p_sys;

    switch (i_query)
    {
        case DEMUX_CAN_SEEK:
            *(va_arg (args, bool *)) = false;
            break;

        case DEMUX_CAN_CONTROL_PACE:
            *(va_arg (args, bool *)) = true;
            break;

        case DEMUX_CAN_PAUSE:
            *(va_arg (args, bool *)) = p_sys->p_mpd->isLive();
            break;

        case DEMUX_GET_TIME:
            *(va_arg (args, int64_t *)) = p_sys->p_dashManager->getPCR();
            break;

        case DEMUX_GET_LENGTH:
            *(va_arg (args, int64_t *)) = p_sys->p_dashManager->getDuration();
            break;

        case DEMUX_GET_POSITION:
            if(!p_sys->p_dashManager->getDuration())
                return VLC_EGENERIC;

            *(va_arg (args, double *)) = (double) p_sys->p_dashManager->getPCR()
                                         / p_sys->p_dashManager->getDuration();
            break;

        case DEMUX_GET_PTS_DELAY:
            *va_arg (args, int64_t *) = INT64_C(1000) *
                var_InheritInteger(p_demux, "network-caching");
             break;

        default:
            return VLC_EGENERIC;
    }
    return VLC_SUCCESS;
}
<|endoftext|>


<commit_before>
#include "Font.hh"
#include "BaseDisplay.hh"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>

#include <string>
#include <iostream>
using namespace std;

class App:public BaseDisplay {
public:
	App(const char *displayname):BaseDisplay("app", displayname) {

		// using screen 0
		m_win = XCreateSimpleWindow(getXDisplay(),
			DefaultRootWindow(getXDisplay()),
			0, 0,
			640, 480,
			1,
			0,
			0xFFFF);
		XSelectInput(getXDisplay(), m_win,  KeyPressMask|ExposureMask);
		XMapWindow(getXDisplay(), m_win);
	}
	~App() {
		XDestroyWindow(getXDisplay(), m_win);
	}

	void handleEvent(XEvent * const ev) {
		switch (ev->type) {
			case KeyPress:
				KeySym ks;
				char keychar[1];
				XLookupString(&ev->xkey, keychar, 1, &ks, 0);
				if (ks == XK_Escape)
					shutdown();
				else { // toggle antialias
					m_font.setAntialias(!m_font.isAntialias());
					cerr<<boolalpha;
					cerr<<"antialias: "<<m_font.isAntialias()<<endl;
					redraw();
				}
			break;
			case Expose:
				redraw();
			break;
		}
	}
	void redraw() {
		XClearWindow(getXDisplay(), m_win);
		GC wingc = DefaultGC(getXDisplay(), 0);
		m_font.drawText(m_win, 0, wingc,
		m_text.c_str(), m_text.size(),
		640/2 - m_font.textWidth(m_text.c_str(), m_text.size())/2, 480/2);

	}
	Window win() const { return m_win; }
	FbTk::Font &font() { return m_font; }
	void setText(const std::string& text) { m_text = text; }
private:
	Window m_win;
	FbTk::Font m_font;
	string m_text;
};

int main(int argc, char **argv) {
	bool antialias = false;
	string fontname("fixed");
	string displayname("");
	string text("testTEST0123456789,-+.;:\\!{}[]()");
	for (int a=1; a<argc; ++a) {
		if (strcmp("-font", argv[a])==0 && a + 1 < argc) {
			fontname = argv[++a];
		} else if (strcmp("-antialias", argv[a]) == 0) {
			antialias = true;
		} else if (strcmp("-display", argv[a]) == 0 && a + 1 < argc) {
			displayname = argv[++a];
		} else if (strcmp("-text", argv[a]) == 0 && a + 1 < argc) {
			text = argv[++a];
		}
	}

	App app(displayname.c_str());
	app.font().setAntialias(antialias);
	if (!app.font().load(fontname.c_str()))
		cerr<<"Failed to load: "<<fontname<<endl;

	app.setText(text);
	app.redraw();
	app.eventLoop();

}
<commit_msg>minor<commit_after>// testFont.cc for fbtk test suite
// Copyright (c) 2002 Henrik Kinnunen (fluxgen@linuxmail.org)
//
// 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.

// $Id: testFont.cc,v 1.2 2002/10/19 10:04:20 fluxgen Exp $

#include "Font.hh"
#include "BaseDisplay.hh"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/keysym.h>

#include <string>
#include <iostream>
using namespace std;

class App:public BaseDisplay {
public:
	App(const char *displayname):BaseDisplay("app", displayname) {

		// using screen 0
		m_win = XCreateSimpleWindow(getXDisplay(),
			DefaultRootWindow(getXDisplay()),
			0, 0,
			640, 480,
			1,
			0,
			0xFFFF);
		XSelectInput(getXDisplay(), m_win,  KeyPressMask|ExposureMask);
		XMapWindow(getXDisplay(), m_win);
	}
	~App() {
		XDestroyWindow(getXDisplay(), m_win);
	}

	void handleEvent(XEvent * const ev) {
		switch (ev->type) {
			case KeyPress:
				KeySym ks;
				char keychar[1];
				XLookupString(&ev->xkey, keychar, 1, &ks, 0);
				if (ks == XK_Escape)
					shutdown();
				else { // toggle antialias
					m_font.setAntialias(!m_font.isAntialias());
					cerr<<boolalpha;
					cerr<<"antialias: "<<m_font.isAntialias()<<endl;
					redraw();
				}
			break;
			case Expose:
				redraw();
			break;
		}
	}
	void redraw() {
		XClearWindow(getXDisplay(), m_win);
		GC wingc = DefaultGC(getXDisplay(), 0);
		m_font.drawText(m_win, 0, wingc,
		m_text.c_str(), m_text.size(),
		640/2 - m_font.textWidth(m_text.c_str(), m_text.size())/2, 480/2);

	}
	Window win() const { return m_win; }
	FbTk::Font &font() { return m_font; }
	void setText(const std::string& text) { m_text = text; }
private:
	Window m_win;
	FbTk::Font m_font;
	string m_text;
};

int main(int argc, char **argv) {
	bool antialias = false;
	string fontname("fixed");
	string displayname("");
	string text("testTEST0123456789,-+.;:\\!{}[]()");
	for (int a=1; a<argc; ++a) {
		if (strcmp("-font", argv[a])==0 && a + 1 < argc) {
			fontname = argv[++a];
		} else if (strcmp("-antialias", argv[a]) == 0) {
			antialias = true;
		} else if (strcmp("-display", argv[a]) == 0 && a + 1 < argc) {
			displayname = argv[++a];
		} else if (strcmp("-text", argv[a]) == 0 && a + 1 < argc) {
			text = argv[++a];
		}
	}

	App app(displayname.c_str());
	app.font().setAntialias(antialias);
	if (!app.font().load(fontname.c_str()))
		cerr<<"Failed to load: "<<fontname<<endl;

	app.setText(text);
	app.redraw();
	app.eventLoop();

}
<|endoftext|>


<commit_before>#include <textformatter.h>
#include <utils.h>
#include <strprintf.h>
#include <htmlrenderer.h>
#include <stflpp.h>
#include <assert.h>
#include <limits.h>

namespace newsbeuter {

textformatter::textformatter() { }

textformatter::~textformatter() { }

void textformatter::add_line(LineType type, std::string line) {
	LOG(level::DEBUG,
		"textformatter::add_line: `%s' (line type %i)",
		line,
		type);

	auto clean_line =
		utils::wstr2str(
			utils::clean_nonprintable_characters(utils::str2wstr(line)));
	lines.push_back(std::make_pair(type, clean_line));
}

void textformatter::add_lines(
		const std::vector<std::pair<LineType, std::string>>& lines)
{
	for (auto line : lines) {
		add_line(line.first,
			utils::replace_all(line.second, "\t", "        "));
	}
}

std::vector<std::string> wrap_line(
		const std::string& line,
		const size_t width)
{
	std::vector<std::string> result;
	std::vector<std::string> words = utils::tokenize_spaced(line);
	std::string curline = "";

	for (auto word : words){
		size_t word_length = utils::strwidth_stfl(word);
		size_t curline_length = utils::strwidth_stfl(curline);

		// For words wider than the available width we have no other choice but
		// to force splits at width limit
		while (word_length > width) {
			size_t space_left = width - curline_length;
			curline.append(word.substr(0, space_left));
			word.erase(0, space_left);
			result.push_back(curline);
			curline = "";

			word_length = utils::strwidth_stfl(word);
			curline_length = utils::strwidth_stfl(curline);
		}

		if ((curline_length + word_length) > width) {
			result.push_back(curline);
			if (word == " ") {
				curline = "";
			} else {
				curline = word;
			}
		} else {
			curline.append(word);
		}
	}

	if (curline.length() > 0) {
		result.push_back(curline);
	}

	return result;
}

std::vector<std::string> format_text_plain_helper(
		const std::vector<std::pair<LineType, std::string>>& lines,
		regexmanager * rxman,
		const std::string& location,
		// wrappable lines are wrapped at this width
		const size_t wrap_width,
		// if non-zero, softwrappable lines are wrapped at this width
		const size_t total_width)
{
	LOG(level::DEBUG,
		"textformatter::format_text_plain: rxman = %p, location = `%s', "
		"wrap_width = %zu, total_width = %zu, %u lines",
		rxman, location, wrap_width, total_width, lines.size());

	std::vector<std::string> format_cache;

	auto store_line =
		[&format_cache]
		(std::string line) {
			format_cache.push_back(line);

			LOG(level::DEBUG,
				"textformatter::format_text_plain: stored `%s'",
				line);
		};

	for (auto line : lines) {
		auto type = line.first;
		auto text = line.second;

		LOG(level::DEBUG,
			"textformatter::format_text_plain: got line `%s' type %u",
			text, type);

		if (rxman && type != LineType::hr) {
			rxman->quote_and_highlight(text, location);
		}

		switch(type) {
			case LineType::wrappable:
				if(text == "") {
					store_line(" ");
					continue;
				}
				text = utils::consolidate_whitespace(text);
				for (auto line : wrap_line(text, wrap_width)) {
					store_line(line);
				}
				break;

			case LineType::softwrappable:
				if(text == "") {
					store_line(" ");
					continue;
				}
				if (total_width == 0) {
					store_line(text);
				} else {
					for (auto line : wrap_line(text, total_width)) {
						store_line(line);
					}
				}
				break;

			case LineType::nonwrappable:
				store_line(text);
				break;

			case LineType::hr:
				store_line(htmlrenderer::render_hr(wrap_width));
				break;
		}
	}

	return format_cache;
}

std::pair<std::string, std::size_t>
textformatter::format_text_to_list(
		regexmanager * rxman,
		const std::string& location,
		const size_t wrap_width,
		const size_t total_width)
{
	auto formatted = format_text_plain_helper(
			lines, rxman, location, wrap_width, total_width);

	auto format_cache = std::string("{list");
	for (auto line : formatted) {
		if (line != "") {
			utils::trim_end(line);
			format_cache.append(
					strprintf::fmt(
						"{listitem text:%s}",
						stfl::quote(line)));
		}
	}
	format_cache.append(1, '}');

	auto line_count = formatted.size();

	return { format_cache, line_count };
}

std::string textformatter::format_text_plain(
		const size_t width, const size_t total_width)
{
	std::string result;
	auto formatted = format_text_plain_helper(
			lines, nullptr, "", width, total_width);
	for (const auto& line : formatted) {
		result += line + "\n";
	}

	return result;
}

}
<commit_msg>When wrapping, repeat indentation on each line<commit_after>#include <textformatter.h>
#include <utils.h>
#include <strprintf.h>
#include <htmlrenderer.h>
#include <stflpp.h>
#include <assert.h>
#include <limits.h>
#include <algorithm>

namespace newsbeuter {

textformatter::textformatter() { }

textformatter::~textformatter() { }

void textformatter::add_line(LineType type, std::string line) {
	LOG(level::DEBUG,
		"textformatter::add_line: `%s' (line type %i)",
		line,
		type);

	auto clean_line =
		utils::wstr2str(
			utils::clean_nonprintable_characters(utils::str2wstr(line)));
	lines.push_back(std::make_pair(type, clean_line));
}

void textformatter::add_lines(
		const std::vector<std::pair<LineType, std::string>>& lines)
{
	for (auto line : lines) {
		add_line(line.first,
			utils::replace_all(line.second, "\t", "        "));
	}
}

std::vector<std::string> wrap_line(
		const std::string& line,
		const size_t width)
{
	if (line.empty()) {
		return { "" };
	}

	std::vector<std::string> result;
	std::vector<std::string> words = utils::tokenize_spaced(line);

	std::string prefix;
	auto iswhitespace =
		[](const std::string& input)
		{
			return std::all_of(
					input.cbegin(),
					input.cend(),
					[](std::string::value_type c) { return std::isspace(c); });
		};
	if (iswhitespace(words[0])) {
		prefix = words[0];
	}

	std::string curline = "";

	for (auto word : words) {
		size_t word_length = utils::strwidth_stfl(word);
		size_t curline_length = utils::strwidth_stfl(curline);

		// For words wider than the available width we have no other choice but
		// to force splits at width limit
		while (word_length > width) {
			size_t space_left = width - curline_length;
			curline.append(word.substr(0, space_left));
			word.erase(0, space_left);
			result.push_back(curline);
			curline = prefix;

			word_length = utils::strwidth_stfl(word);
			curline_length = utils::strwidth_stfl(curline);
		}

		if ((curline_length + word_length) > width) {
			result.push_back(curline);
			if (iswhitespace(word)) {
				curline = prefix;
			} else {
				curline = prefix + word;
			}
		} else {
			curline.append(word);
		}
	}

	if (curline.length() > 0) {
		result.push_back(curline);
	}

	return result;
}

std::vector<std::string> format_text_plain_helper(
		const std::vector<std::pair<LineType, std::string>>& lines,
		regexmanager * rxman,
		const std::string& location,
		// wrappable lines are wrapped at this width
		const size_t wrap_width,
		// if non-zero, softwrappable lines are wrapped at this width
		const size_t total_width)
{
	LOG(level::DEBUG,
		"textformatter::format_text_plain: rxman = %p, location = `%s', "
		"wrap_width = %zu, total_width = %zu, %u lines",
		rxman, location, wrap_width, total_width, lines.size());

	std::vector<std::string> format_cache;

	auto store_line =
		[&format_cache]
		(std::string line) {
			format_cache.push_back(line);

			LOG(level::DEBUG,
				"textformatter::format_text_plain: stored `%s'",
				line);
		};

	for (auto line : lines) {
		auto type = line.first;
		auto text = line.second;

		LOG(level::DEBUG,
			"textformatter::format_text_plain: got line `%s' type %u",
			text, type);

		if (rxman && type != LineType::hr) {
			rxman->quote_and_highlight(text, location);
		}

		switch(type) {
			case LineType::wrappable:
				if(text == "") {
					store_line(" ");
					continue;
				}
				text = utils::consolidate_whitespace(text);
				for (auto line : wrap_line(text, wrap_width)) {
					store_line(line);
				}
				break;

			case LineType::softwrappable:
				if(text == "") {
					store_line(" ");
					continue;
				}
				if (total_width == 0) {
					store_line(text);
				} else {
					for (auto line : wrap_line(text, total_width)) {
						store_line(line);
					}
				}
				break;

			case LineType::nonwrappable:
				store_line(text);
				break;

			case LineType::hr:
				store_line(htmlrenderer::render_hr(wrap_width));
				break;
		}
	}

	return format_cache;
}

std::pair<std::string, std::size_t>
textformatter::format_text_to_list(
		regexmanager * rxman,
		const std::string& location,
		const size_t wrap_width,
		const size_t total_width)
{
	auto formatted = format_text_plain_helper(
			lines, rxman, location, wrap_width, total_width);

	auto format_cache = std::string("{list");
	for (auto line : formatted) {
		if (line != "") {
			utils::trim_end(line);
			format_cache.append(
					strprintf::fmt(
						"{listitem text:%s}",
						stfl::quote(line)));
		}
	}
	format_cache.append(1, '}');

	auto line_count = formatted.size();

	return { format_cache, line_count };
}

std::string textformatter::format_text_plain(
		const size_t width, const size_t total_width)
{
	std::string result;
	auto formatted = format_text_plain_helper(
			lines, nullptr, "", width, total_width);
	for (const auto& line : formatted) {
		result += line + "\n";
	}

	return result;
}

}
<|endoftext|>