<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

#include <boost/python.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

#include <mapnik/rule.hpp>
#include <mapnik/filter_factory.hpp>

using namespace boost::python;
using mapnik::rule_type;
using mapnik::filter;
using mapnik::filter_ptr;
using mapnik::filter_factory;
using mapnik::Feature;
using mapnik::point_symbolizer;
using mapnik::line_symbolizer;
using mapnik::line_pattern_symbolizer;
using mapnik::polygon_symbolizer;
using mapnik::polygon_pattern_symbolizer;
using mapnik::raster_symbolizer;
using mapnik::shield_symbolizer;
using mapnik::text_symbolizer;
using mapnik::building_symbolizer;
using mapnik::symbolizer;
using mapnik::symbolizers;

struct rule_pickle_suite : boost::python::pickle_suite
{
   static boost::python::tuple
   getinitargs(const rule_type& r)
   {
      return boost::python::make_tuple(r.get_name(),r.get_title(),r.get_min_scale(),r.get_max_scale());
   }

   static  boost::python::tuple
   getstate(const rule_type& r)
   {
        boost::python::list syms;
        symbolizers::const_iterator it = r.begin();
        symbolizers::const_iterator end = r.end();
        for (; it != end; ++it)
        {
            syms.append( *it );
        }

        // Here the filter string is used rather than the actual Filter object
        // Need to look into how to get the Filter object
        std::string filter_expr = r.get_filter()->to_string();
        return boost::python::make_tuple(r.get_abstract(),filter_expr,r.has_else_filter(),syms);
   }

   static void
   setstate (rule_type& r, boost::python::tuple state)
   {
        using namespace boost::python;
        if (len(state) != 4)
        {
            PyErr_SetObject(PyExc_ValueError,
                         ("expected 4-item tuple in call to __setstate__; got %s"
                          % state).ptr()
            );
            throw_error_already_set();
        }

        if (state[0])
        {
            r.set_title(extract<std::string>(state[0]));
        }

        if (state[1])
        {
            std::string filter_expr=extract<std::string>(state[1]);
            r.set_filter(mapnik::create_filter(filter_expr,"utf8"));
        }

        if (state[2])
        {
            r.set_else(true);
        }

        boost::python::list syms=extract<boost::python::list>(state[3]);
        for (int i=0;i<len(syms);++i)
        {
            r.append(extract<symbolizer>(syms[i]));
        }

   }

};

void export_rule()
{

    implicitly_convertible<point_symbolizer,symbolizer>();
    implicitly_convertible<line_symbolizer,symbolizer>();
    implicitly_convertible<line_pattern_symbolizer,symbolizer>();
    implicitly_convertible<polygon_symbolizer,symbolizer>();
    implicitly_convertible<building_symbolizer,symbolizer>();
    implicitly_convertible<polygon_pattern_symbolizer,symbolizer>();
    implicitly_convertible<raster_symbolizer,symbolizer>();
    implicitly_convertible<shield_symbolizer,symbolizer>();
    implicitly_convertible<text_symbolizer,symbolizer>();

    class_<symbolizers>("Symbolizers",init<>("TODO"))
    	.def(vector_indexing_suite<symbolizers>())
    	;

    class_<rule_type>("Rule",init<>("default constructor"))
        .def(init<std::string const&,
             boost::python::optional<std::string const&,double,double> >())
        .def_pickle(rule_pickle_suite()
           )
        .add_property("name",make_function
                      (&rule_type::get_name,
                       return_value_policy<copy_const_reference>()),
                      &rule_type::set_name)
        .add_property("title",make_function
                      (&rule_type::get_title,return_value_policy<copy_const_reference>()),
                      &rule_type::set_title)
        .add_property("abstract",make_function
                      (&rule_type::get_abstract,return_value_policy<copy_const_reference>()),
                      &rule_type::set_abstract)
        .add_property("filter",make_function
                      (&rule_type::get_filter,return_value_policy<copy_const_reference>()),
                      &rule_type::set_filter)
        .add_property("min_scale",&rule_type::get_min_scale,&rule_type::set_min_scale)
        .add_property("max_scale",&rule_type::get_max_scale,&rule_type::set_max_scale)
        .def("set_else",&rule_type::set_else)
        .def("has_else",&rule_type::has_else_filter)
        .def("active",&rule_type::active)
        .add_property("symbols",make_function
                      (&rule_type::get_symbolizers,return_value_policy<reference_existing_object>()))
        ;
}

<commit_msg>move the boost::python namespace back to original location<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
//$Id$

#include <boost/python.hpp>
#include <boost/python/implicit.hpp>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>

#include <mapnik/rule.hpp>
#include <mapnik/filter_factory.hpp>

using mapnik::rule_type;
using mapnik::filter;
using mapnik::filter_ptr;
using mapnik::filter_factory;
using mapnik::Feature;
using mapnik::point_symbolizer;
using mapnik::line_symbolizer;
using mapnik::line_pattern_symbolizer;
using mapnik::polygon_symbolizer;
using mapnik::polygon_pattern_symbolizer;
using mapnik::raster_symbolizer;
using mapnik::shield_symbolizer;
using mapnik::text_symbolizer;
using mapnik::building_symbolizer;
using mapnik::symbolizer;
using mapnik::symbolizers;

struct rule_pickle_suite : boost::python::pickle_suite
{
   static boost::python::tuple
   getinitargs(const rule_type& r)
   {
      return boost::python::make_tuple(r.get_name(),r.get_title(),r.get_min_scale(),r.get_max_scale());
   }

   static  boost::python::tuple
   getstate(const rule_type& r)
   {
        boost::python::list syms;
        symbolizers::const_iterator it = r.begin();
        symbolizers::const_iterator end = r.end();
        for (; it != end; ++it)
        {
            syms.append( *it );
        }

        // Here the filter string is used rather than the actual Filter object
        // Need to look into how to get the Filter object
        std::string filter_expr = r.get_filter()->to_string();
        return boost::python::make_tuple(r.get_abstract(),filter_expr,r.has_else_filter(),syms);
   }

   static void
   setstate (rule_type& r, boost::python::tuple state)
   {
        using namespace boost::python;
        if (len(state) != 4)
        {
            PyErr_SetObject(PyExc_ValueError,
                         ("expected 4-item tuple in call to __setstate__; got %s"
                          % state).ptr()
            );
            throw_error_already_set();
        }

        if (state[0])
        {
            r.set_title(extract<std::string>(state[0]));
        }

        if (state[1])
        {
            std::string filter_expr=extract<std::string>(state[1]);
            r.set_filter(mapnik::create_filter(filter_expr,"utf8"));
        }

        if (state[2])
        {
            r.set_else(true);
        }

        boost::python::list syms=extract<boost::python::list>(state[3]);
        for (int i=0;i<len(syms);++i)
        {
            r.append(extract<symbolizer>(syms[i]));
        }

   }

};

void export_rule()
{
    using namespace boost::python;
    implicitly_convertible<point_symbolizer,symbolizer>();
    implicitly_convertible<line_symbolizer,symbolizer>();
    implicitly_convertible<line_pattern_symbolizer,symbolizer>();
    implicitly_convertible<polygon_symbolizer,symbolizer>();
    implicitly_convertible<building_symbolizer,symbolizer>();
    implicitly_convertible<polygon_pattern_symbolizer,symbolizer>();
    implicitly_convertible<raster_symbolizer,symbolizer>();
    implicitly_convertible<shield_symbolizer,symbolizer>();
    implicitly_convertible<text_symbolizer,symbolizer>();

    class_<symbolizers>("Symbolizers",init<>("TODO"))
    	.def(vector_indexing_suite<symbolizers>())
    	;

    class_<rule_type>("Rule",init<>("default constructor"))
        .def(init<std::string const&,
             boost::python::optional<std::string const&,double,double> >())
        .def_pickle(rule_pickle_suite()
           )
        .add_property("name",make_function
                      (&rule_type::get_name,
                       return_value_policy<copy_const_reference>()),
                      &rule_type::set_name)
        .add_property("title",make_function
                      (&rule_type::get_title,return_value_policy<copy_const_reference>()),
                      &rule_type::set_title)
        .add_property("abstract",make_function
                      (&rule_type::get_abstract,return_value_policy<copy_const_reference>()),
                      &rule_type::set_abstract)
        .add_property("filter",make_function
                      (&rule_type::get_filter,return_value_policy<copy_const_reference>()),
                      &rule_type::set_filter)
        .add_property("min_scale",&rule_type::get_min_scale,&rule_type::set_min_scale)
        .add_property("max_scale",&rule_type::get_max_scale,&rule_type::set_max_scale)
        .def("set_else",&rule_type::set_else)
        .def("has_else",&rule_type::has_else_filter)
        .def("active",&rule_type::active)
        .add_property("symbols",make_function
                      (&rule_type::get_symbolizers,return_value_policy<reference_existing_object>()))
        ;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: StartMarker.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2007-07-09 11:56:33 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include "precompiled_reportdesign.hxx"

#ifndef RPTUI_STARTMARKER_HXX
#include "StartMarker.hxx"
#endif
#ifndef _SV_IMAGE_HXX
#include <vcl/image.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef _RPTUI_DLGRESID_HRC
#include "RptResId.hrc"
#endif
#ifndef _RPTUI_MODULE_HELPER_RPT_HXX_
#include "ModuleHelper.hxx"
#endif
#ifndef RPTUI_COLORCHANGER_HXX
#include "ColorChanger.hxx"
#endif
#ifndef RPTUI_REPORT_DEFINES_HXX
#include "ReportDefines.hxx"
#endif
#ifndef RPTUI_SECTIONSWINDOW_HXX
#include "SectionsWindow.hxx"
#endif
#ifndef RTPUI_REPORTDESIGN_HELPID_HRC
#include "helpids.hrc"
#endif
#ifndef _SV_HELP_HXX
#include <vcl/help.hxx>
#endif
#include <vcl/gradient.hxx>
#include <vcl/lineinfo.hxx>
#ifndef _SFXSMPLHINT_HXX
#include <svtools/smplhint.hxx>
#endif

#define CORNER_SPACE     5
#define TEXT_WIDTH      10
#define STRT_BORDER      6

//=====================================================================
namespace rptui
{
//=====================================================================

Image*  OStartMarker::s_pDefCollapsed       = NULL;
Image*  OStartMarker::s_pDefExpanded        = NULL;
Image*  OStartMarker::s_pDefCollapsedHC = NULL;
Image*  OStartMarker::s_pDefExpandedHC  = NULL;
oslInterlockedCount OStartMarker::s_nImageRefCount  = 0;

DBG_NAME( rpt_OStartMarker )
// -----------------------------------------------------------------------------
OStartMarker::OStartMarker(OSectionsWindow* _pParent,const ::rtl::OUString& _sColorEntry)
: OColorListener(_pParent,_sColorEntry)
,m_aVRuler(this,WB_VERT)
,m_aText(this,WB_WORDBREAK)
,m_aImage(this,WB_LEFT|WB_TOP)
,m_pParent(_pParent)
,m_nCornerSize(CORNER_SPACE)
,m_bShowRuler(sal_True)
{
    DBG_CTOR( rpt_OStartMarker,NULL);
    SetUniqueId(HID_STARTMARKER);
    osl_incrementInterlockedCount(&s_nImageRefCount);
    initDefaultNodeImages();
    ImplInitSettings();
    m_aText.SetHelpId(HID_START_TITLE);
    m_aImage.SetHelpId(HID_START_IMAGE);
    m_aText.Show();
    m_aImage.Show();
    m_aVRuler.Show();
    m_aVRuler.Activate();
    m_aVRuler.SetPagePos(0);
    m_aVRuler.SetBorders();
    m_aVRuler.SetIndents();
    m_aVRuler.SetMargin1();
    m_aVRuler.SetMargin2();

}
// -----------------------------------------------------------------------------
OStartMarker::~OStartMarker()
{
    DBG_DTOR( rpt_OStartMarker,NULL);
    if ( osl_decrementInterlockedCount(&s_nImageRefCount) == 0 )
    {
        DELETEZ(s_pDefCollapsed);
        DELETEZ(s_pDefExpanded);
        DELETEZ(s_pDefCollapsedHC);
        DELETEZ(s_pDefExpandedHC);
    } // if ( osl_decrementInterlockedCount(&s_nImageRefCount) == 0 )
}
// -----------------------------------------------------------------------------
sal_Int32 OStartMarker::getWidth() const
{
    return (GetDisplayBackground().GetColor().IsDark() ? s_pDefExpandedHC : s_pDefCollapsed)->GetSizePixel().Width() + GetTextWidth(m_aText.GetText(),0,::std::min<USHORT>(TEXT_WIDTH,m_aText.GetText().Len())) + 2*REPORT_EXTRA_SPACE;
}
// -----------------------------------------------------------------------------
sal_Int32 OStartMarker::getMinHeight() const
{
    return m_aText.GetTextHeight() + 2*STRT_BORDER + 2;
}
// -----------------------------------------------------------------------------
void OStartMarker::Paint( const Rectangle& rRect )
{
    Window::Paint( rRect );
    //SetUpdateMode(FALSE);
    Size aSize = GetSizePixel();
    long nSize = aSize.Width();
    if ( !isCollapsed() )
        nSize = aSize.Width() - m_aVRuler.GetSizePixel().Width() - m_nCornerSize;
    SetClipRegion(Region(Rectangle(Point(),Size( nSize,aSize.Height()))));
    aSize.Width() += m_nCornerSize;

    Rectangle aWholeRect(Point(),aSize);
    {
        const ColorChanger aColors( this, m_nTextBoundaries, m_nColor );

        //aGradient.SetBorder(static_cast<USHORT>(m_nCornerSize));
        PolyPolygon aPoly;
        aPoly.Insert(Polygon(aWholeRect,m_nCornerSize,m_nCornerSize));

        Color aStartColor(m_nColor);
        aStartColor.IncreaseLuminance(10);
        USHORT nHue = 0;
        USHORT nSat = 0;
        USHORT nBri = 0;
        aStartColor.RGBtoHSB(nHue, nSat, nBri);
        nSat += 40;
        Color aEndColor(Color::HSBtoRGB(nHue, nSat, nBri));
        Gradient aGradient(GRADIENT_LINEAR,aStartColor,aEndColor);
        aGradient.SetSteps(static_cast<USHORT>(aSize.Height()));

        DrawGradient(aPoly ,aGradient);
    }
    if ( m_bMarked )
    {
#define DIFF_DIST    2
        Rectangle aRect( Point(m_nCornerSize,m_nCornerSize),
                         Size(aSize.Width() - m_nCornerSize- m_nCornerSize,aSize.Height() - m_nCornerSize- m_nCornerSize));
        ColorChanger aColors( this, COL_WHITE, COL_WHITE );
        DrawPolyLine(Polygon(aRect),LineInfo(LINE_SOLID,2));
    }
}
// -----------------------------------------------------------------------------
void OStartMarker::setColor()
{
    const Color aColor(m_nColor);
    Color aTextColor = GetTextColor();
    if ( aColor.GetLuminance() < 128 )
        aTextColor = COL_WHITE;
    m_aText.SetTextColor(aTextColor);
    m_aText.SetLineColor(m_nColor);
}
// -----------------------------------------------------------------------
void OStartMarker::MouseButtonUp( const MouseEvent& rMEvt )
{
    if ( !rMEvt.IsLeft() )
        return;

    Point aPos( rMEvt.GetPosPixel());

    const Size aOutputSize = GetOutputSizePixel();
    if( aPos.X() > aOutputSize.Width() || aPos.Y() > aOutputSize.Height() )
        return;
    Rectangle aRect(m_aImage.GetPosPixel(),m_aImage.GetImage().GetSizePixel());
    if ( rMEvt.GetClicks() == 2 || aRect.IsInside( aPos ) )
    {
        m_bCollapsed = !m_bCollapsed;

        Image* pImage = NULL;
        if ( GetDisplayBackground().GetColor().IsDark() )
            pImage = m_bCollapsed ? s_pDefCollapsedHC : s_pDefExpandedHC;
        else
            pImage = m_bCollapsed ? s_pDefCollapsed : s_pDefExpanded;
        m_aImage.SetImage(*pImage);

        m_aVRuler.Show(!m_bCollapsed && m_bShowRuler);
        m_nCornerSize = CORNER_SPACE;
        if ( m_aCollapsedLink.IsSet() )
            m_aCollapsedLink.Call(this);
    }

    m_pParent->showProperties(this);
}
// -----------------------------------------------------------------------
void OStartMarker::initDefaultNodeImages()
{
    if ( !s_pDefCollapsed )
    {
        s_pDefCollapsed = new Image( ModuleRes( RID_IMG_TREENODE_COLLAPSED) );
        s_pDefCollapsedHC = new Image( ModuleRes( RID_IMG_TREENODE_COLLAPSED_HC ) );
        s_pDefExpanded = new Image( ModuleRes( RID_IMG_TREENODE_EXPANDED ) );
        s_pDefExpandedHC = new Image( ModuleRes( RID_IMG_TREENODE_EXPANDED_HC ) );
    }

    Image* pImage = NULL;
    if ( GetDisplayBackground().GetColor().IsDark() )
    {
        pImage = m_bCollapsed ? s_pDefCollapsedHC : s_pDefExpandedHC;
    }
    else
    {
        pImage = m_bCollapsed ? s_pDefCollapsed : s_pDefExpanded;
    }
    m_aImage.SetImage(*pImage);
    m_aImage.SetMouseTransparent(TRUE);
    m_aImage.SetBackground();
    m_aText.SetBackground();
    m_aText.SetMouseTransparent(TRUE);
}
// -----------------------------------------------------------------------
void OStartMarker::ImplInitSettings()
{
    SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetDialogColor() ) );
    SetFillColor( Application::GetSettings().GetStyleSettings().GetDialogColor() );
    //SetTextFillColor( Application::GetSettings().GetStyleSettings().GetDarkShadowColor() );
    setColor();
}
//------------------------------------------------------------------------------
void OStartMarker::Resize()
{
    const Size aOutputSize( GetOutputSize() );
    const long nOutputWidth = aOutputSize.Width();
    const long nOutputHeight    = aOutputSize.Height();

    const Size aImageSize = m_aImage.GetImage().GetSizePixel();
    sal_Int32 nY = ::std::min<sal_Int32>(static_cast<sal_Int32>(REPORT_EXTRA_SPACE),static_cast<sal_Int32>((nOutputHeight - aImageSize.Height()) * 0.5));
    if ( m_bCollapsed )
        nY = static_cast<sal_Int32>((nOutputHeight - aImageSize.Height()) * 0.5);
    Point aPos(REPORT_EXTRA_SPACE,nY);

    m_aImage.SetPosSizePixel(aPos,Size(aImageSize.Width() + REPORT_EXTRA_SPACE,nOutputHeight - 2*nY));
    aPos.X() += aImageSize.Width() + REPORT_EXTRA_SPACE;
    aPos.Y() -= 2;

    const long nVRulerWidth = m_aVRuler.GetSizePixel().Width();
    const Point aRulerPos(nOutputWidth - nVRulerWidth - 5,0);

    m_aText.SetPosSizePixel(aPos,Size(aRulerPos.X() - aPos.X(),nOutputHeight - 2*aPos.Y()));

    m_aVRuler.SetPosSizePixel(aRulerPos,Size(nVRulerWidth,nOutputHeight));
}
// -----------------------------------------------------------------------------
void OStartMarker::setTitle(const String& _sTitle)
{
    m_aText.SetText(_sTitle);
}
// -----------------------------------------------------------------------------
void OStartMarker::Notify(SfxBroadcaster & rBc, SfxHint const & rHint)
{
    OColorListener::Notify(rBc, rHint);
    if (rHint.ISA(SfxSimpleHint)
        && (static_cast< SfxSimpleHint const & >(rHint).GetId()
            == SFX_HINT_COLORS_CHANGED))
    {
        setColor();
        //m_aText.Invalidate();
        Invalidate(INVALIDATE_CHILDREN);
    }
}
//----------------------------------------------------------------------------
void OStartMarker::showRuler(sal_Bool _bShow)
{
    m_bShowRuler = _bShow;
    m_aVRuler.Show(!m_bCollapsed && m_bShowRuler);
}
//------------------------------------------------------------------------------
sal_Int32 OStartMarker::getRulerOffset() const
{
    return m_aVRuler.GetSizePixel().Width();
}

//------------------------------------------------------------------------------
void OStartMarker::RequestHelp( const HelpEvent& rHEvt )
{
    if( m_aText.GetText().Len())
    {
        // Hilfe anzeigen
        Rectangle aItemRect(rHEvt.GetMousePosPixel(),Size(GetSizePixel().Width(),getMinHeight()));
        //aItemRect = LogicToPixel( aItemRect );
        Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
        aItemRect.Left()   = aPt.X();
        aItemRect.Top()    = aPt.Y();
        aPt = OutputToScreenPixel( aItemRect.BottomRight() );
        aItemRect.Right()  = aPt.X();
        aItemRect.Bottom() = aPt.Y();
        if( rHEvt.GetMode() == HELPMODE_BALLOON )
            Help::ShowBalloon( this, aItemRect.Center(), aItemRect, m_aText.GetText());
        else
            Help::ShowQuickHelp( this, aItemRect, m_aText.GetText() );
    }
}
// -----------------------------------------------------------------------------
void OStartMarker::setCollapsed(sal_Bool _bCollapsed)
{
    OColorListener::setCollapsed(_bCollapsed);
    showRuler(_bCollapsed);
}
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// =======================================================================
}
// =======================================================================
<commit_msg>INTEGRATION: CWS rpt23fix02 (1.2.4); FILE MERGED 2007/07/30 05:36:12 oj 1.2.4.1: #80161# apply gcc3 patch for strings<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: StartMarker.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2007-08-03 10:04:34 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#include "precompiled_reportdesign.hxx"

#ifndef RPTUI_STARTMARKER_HXX
#include "StartMarker.hxx"
#endif
#ifndef _SV_IMAGE_HXX
#include <vcl/image.hxx>
#endif
#ifndef _SV_SVAPP_HXX
#include <vcl/svapp.hxx>
#endif
#ifndef _RPTUI_DLGRESID_HRC
#include "RptResId.hrc"
#endif
#ifndef _RPTUI_MODULE_HELPER_RPT_HXX_
#include "ModuleHelper.hxx"
#endif
#ifndef RPTUI_COLORCHANGER_HXX
#include "ColorChanger.hxx"
#endif
#ifndef RPTUI_REPORT_DEFINES_HXX
#include "ReportDefines.hxx"
#endif
#ifndef RPTUI_SECTIONSWINDOW_HXX
#include "SectionsWindow.hxx"
#endif
#ifndef RTPUI_REPORTDESIGN_HELPID_HRC
#include "helpids.hrc"
#endif
#ifndef _SV_HELP_HXX
#include <vcl/help.hxx>
#endif
#include <vcl/gradient.hxx>
#include <vcl/lineinfo.hxx>
#ifndef _SFXSMPLHINT_HXX
#include <svtools/smplhint.hxx>
#endif

#define CORNER_SPACE     5
#define TEXT_WIDTH      10
#define STRT_BORDER      6

//=====================================================================
namespace rptui
{
//=====================================================================

Image*  OStartMarker::s_pDefCollapsed       = NULL;
Image*  OStartMarker::s_pDefExpanded        = NULL;
Image*  OStartMarker::s_pDefCollapsedHC = NULL;
Image*  OStartMarker::s_pDefExpandedHC  = NULL;
oslInterlockedCount OStartMarker::s_nImageRefCount  = 0;

DBG_NAME( rpt_OStartMarker )
// -----------------------------------------------------------------------------
OStartMarker::OStartMarker(OSectionsWindow* _pParent,const ::rtl::OUString& _sColorEntry)
: OColorListener(_pParent,_sColorEntry)
,m_aVRuler(this,WB_VERT)
,m_aText(this,WB_WORDBREAK)
,m_aImage(this,WB_LEFT|WB_TOP)
,m_pParent(_pParent)
,m_nCornerSize(CORNER_SPACE)
,m_bShowRuler(sal_True)
{
    DBG_CTOR( rpt_OStartMarker,NULL);
    SetUniqueId(HID_STARTMARKER);
    osl_incrementInterlockedCount(&s_nImageRefCount);
    initDefaultNodeImages();
    ImplInitSettings();
    m_aText.SetHelpId(HID_START_TITLE);
    m_aImage.SetHelpId(HID_START_IMAGE);
    m_aText.Show();
    m_aImage.Show();
    m_aVRuler.Show();
    m_aVRuler.Activate();
    m_aVRuler.SetPagePos(0);
    m_aVRuler.SetBorders();
    m_aVRuler.SetIndents();
    m_aVRuler.SetMargin1();
    m_aVRuler.SetMargin2();

}
// -----------------------------------------------------------------------------
OStartMarker::~OStartMarker()
{
    DBG_DTOR( rpt_OStartMarker,NULL);
    if ( osl_decrementInterlockedCount(&s_nImageRefCount) == 0 )
    {
        DELETEZ(s_pDefCollapsed);
        DELETEZ(s_pDefExpanded);
        DELETEZ(s_pDefCollapsedHC);
        DELETEZ(s_pDefExpandedHC);
    } // if ( osl_decrementInterlockedCount(&s_nImageRefCount) == 0 )
}
// -----------------------------------------------------------------------------
sal_Int32 OStartMarker::getWidth() const
{
    return (GetDisplayBackground().GetColor().IsDark() ? s_pDefExpandedHC : s_pDefCollapsed)->GetSizePixel().Width() + GetTextWidth(m_aText.GetText(),0,::std::min<USHORT>(TEXT_WIDTH,m_aText.GetText().Len())) + 2*REPORT_EXTRA_SPACE;
}
// -----------------------------------------------------------------------------
sal_Int32 OStartMarker::getMinHeight() const
{
    return m_aText.GetTextHeight() + 2*STRT_BORDER + 2;
}
// -----------------------------------------------------------------------------
void OStartMarker::Paint( const Rectangle& rRect )
{
    Window::Paint( rRect );
    //SetUpdateMode(FALSE);
    Size aSize = GetSizePixel();
    long nSize = aSize.Width();
    if ( !isCollapsed() )
        nSize = aSize.Width() - m_aVRuler.GetSizePixel().Width() - m_nCornerSize;
    SetClipRegion(Region(Rectangle(Point(),Size( nSize,aSize.Height()))));
    aSize.Width() += m_nCornerSize;

    Point aGcc3WorkaroundTemporary;
    Rectangle aWholeRect(aGcc3WorkaroundTemporary,aSize);
    {
        const ColorChanger aColors( this, m_nTextBoundaries, m_nColor );

        //aGradient.SetBorder(static_cast<USHORT>(m_nCornerSize));
        PolyPolygon aPoly;
        aPoly.Insert(Polygon(aWholeRect,m_nCornerSize,m_nCornerSize));

        Color aStartColor(m_nColor);
        aStartColor.IncreaseLuminance(10);
        USHORT nHue = 0;
        USHORT nSat = 0;
        USHORT nBri = 0;
        aStartColor.RGBtoHSB(nHue, nSat, nBri);
        nSat += 40;
        Color aEndColor(Color::HSBtoRGB(nHue, nSat, nBri));
        Gradient aGradient(GRADIENT_LINEAR,aStartColor,aEndColor);
        aGradient.SetSteps(static_cast<USHORT>(aSize.Height()));

        DrawGradient(aPoly ,aGradient);
    }
    if ( m_bMarked )
    {
#define DIFF_DIST    2
        Rectangle aRect( Point(m_nCornerSize,m_nCornerSize),
                         Size(aSize.Width() - m_nCornerSize- m_nCornerSize,aSize.Height() - m_nCornerSize- m_nCornerSize));
        ColorChanger aColors( this, COL_WHITE, COL_WHITE );
        DrawPolyLine(Polygon(aRect),LineInfo(LINE_SOLID,2));
    }
}
// -----------------------------------------------------------------------------
void OStartMarker::setColor()
{
    const Color aColor(m_nColor);
    Color aTextColor = GetTextColor();
    if ( aColor.GetLuminance() < 128 )
        aTextColor = COL_WHITE;
    m_aText.SetTextColor(aTextColor);
    m_aText.SetLineColor(m_nColor);
}
// -----------------------------------------------------------------------
void OStartMarker::MouseButtonUp( const MouseEvent& rMEvt )
{
    if ( !rMEvt.IsLeft() )
        return;

    Point aPos( rMEvt.GetPosPixel());

    const Size aOutputSize = GetOutputSizePixel();
    if( aPos.X() > aOutputSize.Width() || aPos.Y() > aOutputSize.Height() )
        return;
    Rectangle aRect(m_aImage.GetPosPixel(),m_aImage.GetImage().GetSizePixel());
    if ( rMEvt.GetClicks() == 2 || aRect.IsInside( aPos ) )
    {
        m_bCollapsed = !m_bCollapsed;

        Image* pImage = NULL;
        if ( GetDisplayBackground().GetColor().IsDark() )
            pImage = m_bCollapsed ? s_pDefCollapsedHC : s_pDefExpandedHC;
        else
            pImage = m_bCollapsed ? s_pDefCollapsed : s_pDefExpanded;
        m_aImage.SetImage(*pImage);

        m_aVRuler.Show(!m_bCollapsed && m_bShowRuler);
        m_nCornerSize = CORNER_SPACE;
        if ( m_aCollapsedLink.IsSet() )
            m_aCollapsedLink.Call(this);
    }

    m_pParent->showProperties(this);
}
// -----------------------------------------------------------------------
void OStartMarker::initDefaultNodeImages()
{
    if ( !s_pDefCollapsed )
    {
        s_pDefCollapsed = new Image( ModuleRes( RID_IMG_TREENODE_COLLAPSED) );
        s_pDefCollapsedHC = new Image( ModuleRes( RID_IMG_TREENODE_COLLAPSED_HC ) );
        s_pDefExpanded = new Image( ModuleRes( RID_IMG_TREENODE_EXPANDED ) );
        s_pDefExpandedHC = new Image( ModuleRes( RID_IMG_TREENODE_EXPANDED_HC ) );
    }

    Image* pImage = NULL;
    if ( GetDisplayBackground().GetColor().IsDark() )
    {
        pImage = m_bCollapsed ? s_pDefCollapsedHC : s_pDefExpandedHC;
    }
    else
    {
        pImage = m_bCollapsed ? s_pDefCollapsed : s_pDefExpanded;
    }
    m_aImage.SetImage(*pImage);
    m_aImage.SetMouseTransparent(TRUE);
    m_aImage.SetBackground();
    m_aText.SetBackground();
    m_aText.SetMouseTransparent(TRUE);
}
// -----------------------------------------------------------------------
void OStartMarker::ImplInitSettings()
{
    SetBackground( Wallpaper( Application::GetSettings().GetStyleSettings().GetDialogColor() ) );
    SetFillColor( Application::GetSettings().GetStyleSettings().GetDialogColor() );
    //SetTextFillColor( Application::GetSettings().GetStyleSettings().GetDarkShadowColor() );
    setColor();
}
//------------------------------------------------------------------------------
void OStartMarker::Resize()
{
    const Size aOutputSize( GetOutputSize() );
    const long nOutputWidth = aOutputSize.Width();
    const long nOutputHeight    = aOutputSize.Height();

    const Size aImageSize = m_aImage.GetImage().GetSizePixel();
    sal_Int32 nY = ::std::min<sal_Int32>(static_cast<sal_Int32>(REPORT_EXTRA_SPACE),static_cast<sal_Int32>((nOutputHeight - aImageSize.Height()) * 0.5));
    if ( m_bCollapsed )
        nY = static_cast<sal_Int32>((nOutputHeight - aImageSize.Height()) * 0.5);
    Point aPos(REPORT_EXTRA_SPACE,nY);

    m_aImage.SetPosSizePixel(aPos,Size(aImageSize.Width() + REPORT_EXTRA_SPACE,nOutputHeight - 2*nY));
    aPos.X() += aImageSize.Width() + REPORT_EXTRA_SPACE;
    aPos.Y() -= 2;

    const long nVRulerWidth = m_aVRuler.GetSizePixel().Width();
    const Point aRulerPos(nOutputWidth - nVRulerWidth - 5,0);

    m_aText.SetPosSizePixel(aPos,Size(aRulerPos.X() - aPos.X(),nOutputHeight - 2*aPos.Y()));

    m_aVRuler.SetPosSizePixel(aRulerPos,Size(nVRulerWidth,nOutputHeight));
}
// -----------------------------------------------------------------------------
void OStartMarker::setTitle(const String& _sTitle)
{
    m_aText.SetText(_sTitle);
}
// -----------------------------------------------------------------------------
void OStartMarker::Notify(SfxBroadcaster & rBc, SfxHint const & rHint)
{
    OColorListener::Notify(rBc, rHint);
    if (rHint.ISA(SfxSimpleHint)
        && (static_cast< SfxSimpleHint const & >(rHint).GetId()
            == SFX_HINT_COLORS_CHANGED))
    {
        setColor();
        //m_aText.Invalidate();
        Invalidate(INVALIDATE_CHILDREN);
    }
}
//----------------------------------------------------------------------------
void OStartMarker::showRuler(sal_Bool _bShow)
{
    m_bShowRuler = _bShow;
    m_aVRuler.Show(!m_bCollapsed && m_bShowRuler);
}
//------------------------------------------------------------------------------
sal_Int32 OStartMarker::getRulerOffset() const
{
    return m_aVRuler.GetSizePixel().Width();
}

//------------------------------------------------------------------------------
void OStartMarker::RequestHelp( const HelpEvent& rHEvt )
{
    if( m_aText.GetText().Len())
    {
        // Hilfe anzeigen
        Rectangle aItemRect(rHEvt.GetMousePosPixel(),Size(GetSizePixel().Width(),getMinHeight()));
        //aItemRect = LogicToPixel( aItemRect );
        Point aPt = OutputToScreenPixel( aItemRect.TopLeft() );
        aItemRect.Left()   = aPt.X();
        aItemRect.Top()    = aPt.Y();
        aPt = OutputToScreenPixel( aItemRect.BottomRight() );
        aItemRect.Right()  = aPt.X();
        aItemRect.Bottom() = aPt.Y();
        if( rHEvt.GetMode() == HELPMODE_BALLOON )
            Help::ShowBalloon( this, aItemRect.Center(), aItemRect, m_aText.GetText());
        else
            Help::ShowQuickHelp( this, aItemRect, m_aText.GetText() );
    }
}
// -----------------------------------------------------------------------------
void OStartMarker::setCollapsed(sal_Bool _bCollapsed)
{
    OColorListener::setCollapsed(_bCollapsed);
    showRuler(_bCollapsed);
}
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// -----------------------------------------------------------------------
// =======================================================================
}
// =======================================================================
<|endoftext|>


<commit_before>#include "Board.h"
#include "Pawn.h"
#include "Rook.h"
#include "Knight.h"
#include "Bishop.h"
#include "Queen.h"
#include "King.h"
#include <iostream>
#include <sstream>

namespace Chess {
	Board::Board() {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				pieces[x][y] = nullptr;
			}
		}

		// Black pawns
		for (int x = 0; x < 8; x++) {
			pieces[x][6] = new Pawn(Position(x, 6), false);
		}

		// White pawns
		for (int x = 0; x < 8; x++) {
			pieces[x][1] = new Pawn(Position(x, 1), true);
		}

		// Rooks
		pieces[0][7] = new Rook(Position(0, 7), false);
		pieces[7][7] = new Rook(Position(7, 7), false);
		pieces[0][0] = new Rook(Position(0, 0), true);
		pieces[7][0] = new Rook(Position(7, 0), true);

		// Knights
		pieces[1][7] = new Knight(Position(1, 7), false);
		pieces[6][7] = new Knight(Position(6, 7), false);
		pieces[1][0] = new Knight(Position(1, 0), true);
		pieces[6][0] = new Knight(Position(6, 0), true);

		// Bishops
		pieces[2][7] = new Bishop(Position(2, 7), false);
		pieces[5][7] = new Bishop(Position(5, 7), false);
		pieces[2][0] = new Bishop(Position(2, 0), true);
		pieces[5][0] = new Bishop(Position(5, 0), true);

		// Queens
		pieces[3][7] = new Queen(Position(3, 7), false);
		pieces[3][0] = new Queen(Position(3, 0), true);

		// Kings
		pieces[4][7] = new King(Position(4, 7), false);
		pieces[4][0] = new King(Position(4, 0), true);
		addBoardToMap();
	}

	Board::~Board() {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				if (pieces[x][y] != nullptr)
					delete pieces[x][y];
			}
		}
	}

	GameState Board::getState() const {
		return state;
	}

	Piece* Board::getPiece(const Position& position) const {
		return pieces[position.x][position.y];
	}

	bool Board::mustPromote() {
		return needsToPromote;
	}

	bool Board::move(const Position& oldPosition, const Position& newPosition) {
		Piece* piece = getPiece(oldPosition);
		Piece* targetPiece = getPiece(newPosition);

		if (piece != nullptr) {
			// Check if the piece is of the right color.
			if (piece->isWhite() == (turn % 2 == 0)) {
				halfMovesSinceCapture++;
				// Check if the move is legal.
				if (piece->isLegal(*this, newPosition)) {
					pieces[oldPosition.x][oldPosition.y] = nullptr;

					// En passant.
					if (pieces[newPosition.x][newPosition.y] == nullptr && (piece->notation() == 'p' || piece->notation() == 'P') && newPosition.x != oldPosition.x){
						if (piece->isWhite()) {
							delete pieces[newPosition.x][newPosition.y - 1];
							pieces[newPosition.x][newPosition.y - 1] = nullptr;
							halfMovesSinceCapture = 0;
						} else {
							delete pieces[newPosition.x][newPosition.y + 1];
							pieces[newPosition.x][newPosition.y + 1] = nullptr;
							halfMovesSinceCapture = 0;
						}
					}

					// Castling
					if (piece->notation() == 'k' || piece->notation() == 'K') {
						if (newPosition.x - oldPosition.x == 2){
							Piece* tempPiece = getPiece(Position(7, newPosition.y));
							pieces[7][newPosition.y] = nullptr;
							pieces[5][newPosition.y] = tempPiece;
							tempPiece->move(Position(5, newPosition.y));
						} else if (newPosition.x - oldPosition.x == -2) {
							Piece* tempPiece = getPiece(Position(0, newPosition.y));
							pieces[0][newPosition.y] = nullptr;
							pieces[3][newPosition.y] = tempPiece;
							tempPiece->move(Position(3, newPosition.y));
						}
					}

					// Delete captured enemy piece.
					if (pieces[newPosition.x][newPosition.y] != nullptr){
						delete pieces[newPosition.x][newPosition.y];
						halfMovesSinceCapture = 0;
					}
					// Update pieces and piece position
					pieces[newPosition.x][newPosition.y] = piece;
					if (piece->notation() == 'p' || piece->notation() == 'P')
						halfMovesSinceCapture = 0;
					piece->move(newPosition);

					// Promote pawns
					if(newPosition.y == 7 || newPosition.y == 0){
						if (piece->notation() == 'p' || piece->notation() == 'P'){
							needsToPromote = true;
						}
					}
					if ( (piece->notation() == 'p' || piece->notation() == 'P') ){
						if (abs(oldPosition.y - newPosition.y) == 2) {
							if (piece->notation() == 'p')
								enPassantPossible = Position(newPosition.x, newPosition.y + 1);
							else if (piece->notation() == 'P')
								enPassantPossible = Position(newPosition.x, newPosition.y - 1);
						}
					}
					else {
						enPassantPossible = Position(-1, -1);
					}

					printf("En passant possible at:\n X:%d, Y:%d\n", enPassantPossible.x, enPassantPossible.y);

					// Set and reset lastMovedPiece
					if (lastMovedPawn != nullptr){
						if (lastMovedPawn->getLastMoveWasDouble()){
							//lastMovedPawn->resetLastMoveWasDouble(); //orsakar krasch..
						}
					}
					lastMovedPawn = dynamic_cast<Pawn*>(getPiece(newPosition));

					turn++;
					if (state == GameState::BLACKPLAYS)
						state = GameState::WHITEPLAYS;
					else
						state = GameState::BLACKPLAYS;

					std::string tempstring = toFENString(false);
					std::cout << tempstring << '\n';
					addBoardToMap();
					if(isThreeFoldRepitition())
						state = GameState::DRAW;
					if (isFiftyMoveSincePawnOrCapture())
						state = GameState::DRAW;
					if (!sufficientMaterial())
						state = GameState::DRAW;
					checkWin();
					return true;
				}
			}
		}

		return false;
	}

	bool Board::willLeaveKingChecked(const Position& oldPosition, const Position& newPosition) {
		Piece* oldPiece = getPiece(oldPosition);
		Piece* newPiece = getPiece(newPosition);

		Piece* piece;
		switch (oldPiece->notation()) {
		case 'Q':
		case 'q':
			piece = new Queen(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		case 'K':
		case 'k':
			piece = new King(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		case 'P':
		case 'p':
			piece = new Pawn(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		case 'R':
		case 'r':
			piece = new Rook(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		case 'B':
		case 'b':
			piece = new Bishop(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		case 'N':
		case 'n':
			piece = new Knight(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		}

		pieces[newPosition.x][newPosition.y] = piece;
		piece->move(newPosition);
		pieces[oldPosition.x][oldPosition.y] = nullptr;

		King* king = getKing((turn % 2 == 0));
		bool checked = king->isChecked(*this);

		delete piece;
		pieces[newPosition.x][newPosition.y] = newPiece;
		pieces[oldPosition.x][oldPosition.y] = oldPiece;

		return checked;
	}

	void Board::promotePawn(Piece* pawn, PromoteTypes type) {
		Position position = pawn->getPosition();
		bool white = pawn->isWhite();
		delete pawn;

		switch (type) {
		case PromoteTypes::QUEEN:
			pieces[position.x][position.y] = new Queen(position, white);
			break;
		case PromoteTypes::ROOK:
			pieces[position.x][position.y] = new Rook(position, white);
			break;
		case PromoteTypes::BISHOP:
			pieces[position.x][position.y] = new Bishop(position, white);
			break;
		case PromoteTypes::KNIGHT:
			pieces[position.x][position.y] = new Knight(position, white);
			break;
		}
		checkWin();
		needsToPromote = false;
	}
	void Board::addBoardToMap() {
		std::string tempstring = toFENString(false);
		if (previousBoards.find(tempstring) == previousBoards.end()) {
			previousBoards[tempstring] = 0;
		} else{
			previousBoards[tempstring] += 1;
		}
	}

	std::string Board::toFENString(bool addExtraData) const {
		std::string tempstring;
		int emptyCounter = 0;
		for (int y = 7; y >= 0; y--) {
			for (int x = 0; x < 8; x++){
				if (pieces[x][y] == nullptr)
					emptyCounter++;
				else {
					if (emptyCounter != 0)
						tempstring += std::to_string(emptyCounter);
					tempstring.append(1, pieces[x][y]->notation());
					emptyCounter = 0;
				}
			}
			if (emptyCounter != 0) {
				tempstring += std::to_string(emptyCounter);
				emptyCounter = 0;
			}
			tempstring += '/';
		}
		// Who played the turn?
		if (state == GameState::BLACKPLAYS)
			tempstring += "w";
		else
			tempstring += "b";

		if (addExtraData) {
			// Number of half turns since last capture or pawn move.
			tempstring += ' ' + std::to_string(halfMovesSinceCapture) + ' ';
			// Number of full moves.
			tempstring += std::to_string((turn+1) / 2);
		}
		return tempstring;
	}

	bool Board::isThreeFoldRepitition() {
		return previousBoards[toFENString(false)] == 3;
	}

	bool Board::isFiftyMoveSincePawnOrCapture() const {
		return halfMovesSinceCapture >= 100;
	}

	void Board::checkWin() {
		bool white = (state == GameState::WHITEPLAYS);

		bool canMove = false;
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				Piece* piece = getPiece(Position(x, y));
				if (piece != nullptr && piece->isWhite() == white) {
					if (!piece->legalMoves(*this).empty()) {
						canMove = true;
						break;
					}
				}
			}
		}

		if (!canMove) {
			if (getKing(white)->isChecked(*this)) {
				if (white)
					state = GameState::BLACKWIN;
				else
					state = GameState::WHITEWIN;
			} else {
				state = GameState::DRAW;
			}
		}
	}

	bool Board::sufficientMaterial() const {
		// Get the material on the board.
		int pieceTypes[6] = { 0 };

		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				Piece* piece = getPiece(Position(x, y));
				if (piece != nullptr) {
					switch (piece->notation()) {
					case 'Q':
					case 'q':
						pieceTypes[0]++;
						break;
					case 'P':
					case 'p':
						pieceTypes[1]++;
						break;
					case 'R':
					case 'r':
						pieceTypes[2]++;
						break;
					case 'N':
					case 'n':
						pieceTypes[3]++;
						break;
					case 'B':
					case 'b':
						pieceTypes[((x + y) % 2 == 0) ? 4 : 5]++;
						break;
					}
				}
			}
		}

		// If there's a queen, pawn or rook on the board, there is sufficient material.
		if (pieceTypes[0] > 0 || pieceTypes[1] > 0 || pieceTypes[2] > 0)
			return true;

		// If there are 2 or more knights on the board, there is sufficient material.
		if (pieceTypes[3] > 1)
			return true;

		// If there are pieces from 2 or more categories (knight, bishop on light square, bishop on dark square), there is sufficient material.
		if ((pieceTypes[3] > 0) + (pieceTypes[4] > 0) + (pieceTypes[5] > 0) >= 2)
			return true;

		return false;

	}

	King* Board::getKing(bool white) const {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				Piece* piece = getPiece(Position(x, y));
				if (piece != nullptr && piece->notation() == (white ? 'K' : 'k'))
					return dynamic_cast<King*>(piece);
			}
		}

		return nullptr;
	}
}<commit_msg>Updated toFENString<commit_after>#include "Board.h"
#include "Pawn.h"
#include "Rook.h"
#include "Knight.h"
#include "Bishop.h"
#include "Queen.h"
#include "King.h"
#include <iostream>
#include <sstream>

namespace Chess {
	Board::Board() {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				pieces[x][y] = nullptr;
			}
		}

		// Black pawns
		for (int x = 0; x < 8; x++) {
			pieces[x][6] = new Pawn(Position(x, 6), false);
		}

		// White pawns
		for (int x = 0; x < 8; x++) {
			pieces[x][1] = new Pawn(Position(x, 1), true);
		}

		// Rooks
		pieces[0][7] = new Rook(Position(0, 7), false);
		pieces[7][7] = new Rook(Position(7, 7), false);
		pieces[0][0] = new Rook(Position(0, 0), true);
		pieces[7][0] = new Rook(Position(7, 0), true);

		// Knights
		pieces[1][7] = new Knight(Position(1, 7), false);
		pieces[6][7] = new Knight(Position(6, 7), false);
		pieces[1][0] = new Knight(Position(1, 0), true);
		pieces[6][0] = new Knight(Position(6, 0), true);

		// Bishops
		pieces[2][7] = new Bishop(Position(2, 7), false);
		pieces[5][7] = new Bishop(Position(5, 7), false);
		pieces[2][0] = new Bishop(Position(2, 0), true);
		pieces[5][0] = new Bishop(Position(5, 0), true);

		// Queens
		pieces[3][7] = new Queen(Position(3, 7), false);
		pieces[3][0] = new Queen(Position(3, 0), true);

		// Kings
		pieces[4][7] = new King(Position(4, 7), false);
		pieces[4][0] = new King(Position(4, 0), true);
		addBoardToMap();
	}

	Board::~Board() {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				if (pieces[x][y] != nullptr)
					delete pieces[x][y];
			}
		}
	}

	GameState Board::getState() const {
		return state;
	}

	Piece* Board::getPiece(const Position& position) const {
		return pieces[position.x][position.y];
	}

	bool Board::mustPromote() {
		return needsToPromote;
	}

	bool Board::move(const Position& oldPosition, const Position& newPosition) {
		Piece* piece = getPiece(oldPosition);
		Piece* targetPiece = getPiece(newPosition);

		if (piece != nullptr) {
			// Check if the piece is of the right color.
			if (piece->isWhite() == (turn % 2 == 0)) {
				halfMovesSinceCapture++;
				// Check if the move is legal.
				if (piece->isLegal(*this, newPosition)) {
					pieces[oldPosition.x][oldPosition.y] = nullptr;

					// En passant.
					if (pieces[newPosition.x][newPosition.y] == nullptr && (piece->notation() == 'p' || piece->notation() == 'P') && newPosition.x != oldPosition.x){
						if (piece->isWhite()) {
							delete pieces[newPosition.x][newPosition.y - 1];
							pieces[newPosition.x][newPosition.y - 1] = nullptr;
							halfMovesSinceCapture = 0;
						} else {
							delete pieces[newPosition.x][newPosition.y + 1];
							pieces[newPosition.x][newPosition.y + 1] = nullptr;
							halfMovesSinceCapture = 0;
						}
					}

					// Castling
					if (piece->notation() == 'k' || piece->notation() == 'K') {
						if (newPosition.x - oldPosition.x == 2){
							Piece* tempPiece = getPiece(Position(7, newPosition.y));
							pieces[7][newPosition.y] = nullptr;
							pieces[5][newPosition.y] = tempPiece;
							tempPiece->move(Position(5, newPosition.y));
						} else if (newPosition.x - oldPosition.x == -2) {
							Piece* tempPiece = getPiece(Position(0, newPosition.y));
							pieces[0][newPosition.y] = nullptr;
							pieces[3][newPosition.y] = tempPiece;
							tempPiece->move(Position(3, newPosition.y));
						}
					}

					// Delete captured enemy piece.
					if (pieces[newPosition.x][newPosition.y] != nullptr){
						delete pieces[newPosition.x][newPosition.y];
						halfMovesSinceCapture = 0;
					}
					// Update pieces and piece position
					pieces[newPosition.x][newPosition.y] = piece;
					if (piece->notation() == 'p' || piece->notation() == 'P')
						halfMovesSinceCapture = 0;
					piece->move(newPosition);

					// Promote pawns
					if(newPosition.y == 7 || newPosition.y == 0){
						if (piece->notation() == 'p' || piece->notation() == 'P'){
							needsToPromote = true;
						}
					}
					if ( (piece->notation() == 'p' || piece->notation() == 'P') ){
						if (abs(oldPosition.y - newPosition.y) == 2) {
							if (piece->notation() == 'p')
								enPassantPossible = Position(newPosition.x, newPosition.y + 1);
							else if (piece->notation() == 'P')
								enPassantPossible = Position(newPosition.x, newPosition.y - 1);
						}
					}
					else {
						enPassantPossible = Position(-1, -1);
					}

					printf("En passant possible at:\n X:%d, Y:%d\n", enPassantPossible.x, enPassantPossible.y);

					// Set and reset lastMovedPiece
					if (lastMovedPawn != nullptr){
						if (lastMovedPawn->getLastMoveWasDouble()){
							//lastMovedPawn->resetLastMoveWasDouble(); //orsakar krasch..
						}
					}
					lastMovedPawn = dynamic_cast<Pawn*>(getPiece(newPosition));

					turn++;
					if (state == GameState::BLACKPLAYS)
						state = GameState::WHITEPLAYS;
					else
						state = GameState::BLACKPLAYS;

					std::string tempstring = toFENString(true);
					std::cout << tempstring << '\n';
					addBoardToMap();
					if(isThreeFoldRepitition())
						state = GameState::DRAW;
					if (isFiftyMoveSincePawnOrCapture())
						state = GameState::DRAW;
					if (!sufficientMaterial())
						state = GameState::DRAW;
					checkWin();
					return true;
				}
			}
		}

		return false;
	}

	bool Board::willLeaveKingChecked(const Position& oldPosition, const Position& newPosition) {
		Piece* oldPiece = getPiece(oldPosition);
		Piece* newPiece = getPiece(newPosition);

		Piece* piece;
		switch (oldPiece->notation()) {
		case 'Q':
		case 'q':
			piece = new Queen(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		case 'K':
		case 'k':
			piece = new King(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		case 'P':
		case 'p':
			piece = new Pawn(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		case 'R':
		case 'r':
			piece = new Rook(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		case 'B':
		case 'b':
			piece = new Bishop(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		case 'N':
		case 'n':
			piece = new Knight(oldPiece->getPosition(), oldPiece->isWhite());
			break;
		}

		pieces[newPosition.x][newPosition.y] = piece;
		piece->move(newPosition);
		pieces[oldPosition.x][oldPosition.y] = nullptr;

		King* king = getKing((turn % 2 == 0));
		bool checked = king->isChecked(*this);

		delete piece;
		pieces[newPosition.x][newPosition.y] = newPiece;
		pieces[oldPosition.x][oldPosition.y] = oldPiece;

		return checked;
	}

	void Board::promotePawn(Piece* pawn, PromoteTypes type) {
		Position position = pawn->getPosition();
		bool white = pawn->isWhite();
		delete pawn;

		switch (type) {
		case PromoteTypes::QUEEN:
			pieces[position.x][position.y] = new Queen(position, white);
			break;
		case PromoteTypes::ROOK:
			pieces[position.x][position.y] = new Rook(position, white);
			break;
		case PromoteTypes::BISHOP:
			pieces[position.x][position.y] = new Bishop(position, white);
			break;
		case PromoteTypes::KNIGHT:
			pieces[position.x][position.y] = new Knight(position, white);
			break;
		}
		checkWin();
		needsToPromote = false;
	}
	void Board::addBoardToMap() {
		std::string tempstring = toFENString(false);
		if (previousBoards.find(tempstring) == previousBoards.end()) {
			previousBoards[tempstring] = 0;
		} else{
			previousBoards[tempstring] += 1;
		}
	}

	std::string Board::toFENString(bool addExtraData) const {
		std::string tempstring;
		int emptyCounter = 0;
		for (int y = 7; y >= 0; y--) {
			for (int x = 0; x < 8; x++){
				if (pieces[x][y] == nullptr)
					emptyCounter++;
				else {
					if (emptyCounter != 0)
						tempstring += std::to_string(emptyCounter);
					tempstring.append(1, pieces[x][y]->notation());
					emptyCounter = 0;
				}
			}
			if (emptyCounter != 0) {
				tempstring += std::to_string(emptyCounter);
				emptyCounter = 0;
			}
			tempstring += '/';
		}
		// Who played the turn?
		if (state == GameState::BLACKPLAYS)
			tempstring += "w";
		else
			tempstring += "b";

		if (addExtraData) {
			tempstring += '/' + std::to_string(enPassantPossible.x) + '.' + std::to_string(enPassantPossible.y);
			// Number of half turns since last capture or pawn move.
			tempstring += '/' + std::to_string(halfMovesSinceCapture) + '/';
			// Number of full moves.
			tempstring += std::to_string((turn+1) / 2);
		}
		return tempstring;
	}

	bool Board::isThreeFoldRepitition() {
		return previousBoards[toFENString(false)] == 3;
	}

	bool Board::isFiftyMoveSincePawnOrCapture() const {
		return halfMovesSinceCapture >= 100;
	}

	void Board::checkWin() {
		bool white = (state == GameState::WHITEPLAYS);

		bool canMove = false;
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				Piece* piece = getPiece(Position(x, y));
				if (piece != nullptr && piece->isWhite() == white) {
					if (!piece->legalMoves(*this).empty()) {
						canMove = true;
						break;
					}
				}
			}
		}

		if (!canMove) {
			if (getKing(white)->isChecked(*this)) {
				if (white)
					state = GameState::BLACKWIN;
				else
					state = GameState::WHITEWIN;
			} else {
				state = GameState::DRAW;
			}
		}
	}

	bool Board::sufficientMaterial() const {
		// Get the material on the board.
		int pieceTypes[6] = { 0 };

		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				Piece* piece = getPiece(Position(x, y));
				if (piece != nullptr) {
					switch (piece->notation()) {
					case 'Q':
					case 'q':
						pieceTypes[0]++;
						break;
					case 'P':
					case 'p':
						pieceTypes[1]++;
						break;
					case 'R':
					case 'r':
						pieceTypes[2]++;
						break;
					case 'N':
					case 'n':
						pieceTypes[3]++;
						break;
					case 'B':
					case 'b':
						pieceTypes[((x + y) % 2 == 0) ? 4 : 5]++;
						break;
					}
				}
			}
		}

		// If there's a queen, pawn or rook on the board, there is sufficient material.
		if (pieceTypes[0] > 0 || pieceTypes[1] > 0 || pieceTypes[2] > 0)
			return true;

		// If there are 2 or more knights on the board, there is sufficient material.
		if (pieceTypes[3] > 1)
			return true;

		// If there are pieces from 2 or more categories (knight, bishop on light square, bishop on dark square), there is sufficient material.
		if ((pieceTypes[3] > 0) + (pieceTypes[4] > 0) + (pieceTypes[5] > 0) >= 2)
			return true;

		return false;

	}

	King* Board::getKing(bool white) const {
		for (int x = 0; x < 8; x++) {
			for (int y = 0; y < 8; y++) {
				Piece* piece = getPiece(Position(x, y));
				if (piece != nullptr && piece->notation() == (white ? 'K' : 'k'))
					return dynamic_cast<King*>(piece);
			}
		}

		return nullptr;
	}
}<|endoftext|>


<commit_before>// test_keypairsign.cpp -- Test sodium::keypairsign
//
// ISC License
//
// Copyright (C) 2018 Farid Hajji <farid@hajji.name>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE sodium::keypairsign Test
#include <boost/test/included/unit_test.hpp>

#include "common.h"
#include "keypairsign.h"
#include "helpers.h"
#include "random.h"
#include <stdexcept>
#include <sodium.h>

using sodium::keypairsign;
using bytes = sodium::bytes;

static constexpr std::size_t ks_pub  = keypairsign<>::KEYSIZE_PUBLIC_KEY;
static constexpr std::size_t ks_priv = keypairsign<>::KEYSIZE_PRIVATE_KEY;
static constexpr std::size_t ks_seed = keypairsign<>::KEYSIZE_SEEDBYTES;

struct SodiumFixture {
  SodiumFixture()  {
    BOOST_REQUIRE(sodium_init() != -1);
    // BOOST_TEST_MESSAGE("SodiumFixture(): sodium_init() successful.");
  }
  ~SodiumFixture() {
    // BOOST_TEST_MESSAGE("~SodiumFixture(): teardown -- no-op.");
  }
};

BOOST_FIXTURE_TEST_SUITE ( sodium_test_suite, SodiumFixture )

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_size_ctor_default )
{
  keypairsign<> keypair;

  BOOST_TEST(keypair.public_key().size() == ks_pub);
  BOOST_TEST(keypair.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_size_ctor_seed )
{
  bytes seed(ks_seed);
  sodium::randombytes_buf_inplace(seed);

  keypairsign<> keypair(seed);

  BOOST_TEST(keypair.public_key().size() == ks_pub);
  BOOST_TEST(keypair.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_size_ctor_privkey )
{
  keypairsign<> keypair1;
  keypairsign<> keypair2(keypair1.private_key().data(), keypair1.private_key().size());

  BOOST_TEST(keypair2.public_key().size() == ks_pub);
  BOOST_TEST(keypair2.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE ( sodium_test_keypairsign_copy_ctor )
{
  keypairsign<> keypair;
  keypairsign<> keypair_copy {keypair};

  BOOST_TEST((keypair == keypair_copy)); // check also operator==()
  BOOST_TEST((keypair.private_key() == keypair_copy.private_key())); // key::operator==()
  BOOST_TEST(keypair.public_key()  == keypair_copy.public_key());  // std::vector::operator==()
}

BOOST_AUTO_TEST_CASE ( sodium_test_keypairsign_copy_assignement )
{
  keypairsign<> keypair;
  keypairsign<> keypair_copy = keypair;

  BOOST_TEST((keypair == keypair_copy));
  BOOST_TEST((keypair.private_key() == keypair_copy.private_key()));
  BOOST_TEST(keypair.public_key()  == keypair_copy.public_key());
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_nonzero_ctor_default )
{
  keypairsign<> keypair;

  BOOST_TEST(!sodium::is_zero(keypair.public_key()));
  BOOST_TEST(!sodium::is_zero(keypair.private_key()));
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_nonzero_ctor_seed )
{
  bytes seed(ks_seed);
  sodium::randombytes_buf_inplace(seed);

  keypairsign<> keypair(seed);

  BOOST_TEST(!sodium::is_zero(keypair.public_key()));
  BOOST_TEST(!sodium::is_zero(keypair.private_key()));
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_nonzero_ctor_privkey )
{
  keypairsign<> keypair1;
  keypairsign<> keypair2(keypair1.private_key().data(), keypair1.private_key().size());

  BOOST_TEST(!sodium::is_zero(keypair2.public_key()));
  BOOST_TEST(!sodium::is_zero(keypair2.private_key()));
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_seedcompare_ctor_same_seed )
{
  bytes seed(ks_seed);
  sodium::randombytes_buf_inplace(seed);

  keypairsign<> keypair1(seed);
  keypairsign<> keypair2(seed); // same seed

  BOOST_TEST(sodium::compare(keypair1.public_key(),
	  keypair2.public_key()));
  BOOST_TEST(sodium::compare(keypair1.private_key(),
	  keypair2.private_key()));

  BOOST_TEST((keypair1 == keypair2)); // check also operator==()
  BOOST_TEST((keypair1.private_key() == keypair2.private_key()));
  BOOST_TEST(keypair1.public_key() == keypair2.public_key());
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_seedcompare_ctor_different_seed )
{
  bytes seed1(ks_seed);
  sodium::randombytes_buf_inplace(seed1);
  bytes seed2(ks_seed);
  sodium::randombytes_buf_inplace(seed2);

  BOOST_TEST(seed1 != seed2); // very unlikely that they are the same

  keypairsign<> keypair1(seed1);
  keypairsign<> keypair2(seed2); // different seed

  BOOST_TEST(!sodium::compare(keypair1.public_key(),
	  keypair2.public_key()));
  BOOST_TEST(!sodium::compare(keypair1.private_key(),
	  keypair2.private_key()));

  BOOST_TEST((keypair1 != keypair2)); // check also operator!=()
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_seedcompare_extract_seed )
{
  bytes seed1(ks_seed);
  sodium::randombytes_buf_inplace(seed1);

  keypairsign<> keypair(seed1);

  // reconstruct seed from private key stored in keypair
  bytes seed2 = keypair.seed();

  BOOST_TEST(seed1 == seed2);
}

BOOST_AUTO_TEST_SUITE_END ()
<commit_msg>Added unit tests to sodium::keypairsign w/ different PK.<commit_after>// test_keypairsign.cpp -- Test sodium::keypairsign
//
// ISC License
//
// Copyright (C) 2018 Farid Hajji <farid@hajji.name>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE sodium::keypairsign Test
#include <boost/test/included/unit_test.hpp>

#include "common.h"
#include "keypairsign.h"
#include "helpers.h"
#include "random.h"
#include <stdexcept>
#include <sodium.h>

using sodium::keypairsign;
using bytes = sodium::bytes;

static constexpr std::size_t ks_pub  = keypairsign<>::KEYSIZE_PUBLIC_KEY;
static constexpr std::size_t ks_priv = keypairsign<>::KEYSIZE_PRIVATE_KEY;
static constexpr std::size_t ks_seed = keypairsign<>::KEYSIZE_SEEDBYTES;

struct SodiumFixture {
  SodiumFixture()  {
    BOOST_REQUIRE(sodium_init() != -1);
    // BOOST_TEST_MESSAGE("SodiumFixture(): sodium_init() successful.");
  }
  ~SodiumFixture() {
    // BOOST_TEST_MESSAGE("~SodiumFixture(): teardown -- no-op.");
  }
};

BOOST_FIXTURE_TEST_SUITE ( sodium_test_suite, SodiumFixture )

// 1. sodium::bytes -------------------------------------------------------

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_size_ctor_default_bytes )
{
  keypairsign<> keypair;

  BOOST_TEST(keypair.public_key().size() == ks_pub);
  BOOST_TEST(keypair.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_size_ctor_seed_bytes )
{
  bytes seed(ks_seed);
  sodium::randombytes_buf_inplace(seed);

  keypairsign<> keypair(seed);

  BOOST_TEST(keypair.public_key().size() == ks_pub);
  BOOST_TEST(keypair.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_size_ctor_privkey_bytes )
{
  keypairsign<> keypair1;
  keypairsign<> keypair2(keypair1.private_key().data(), keypair1.private_key().size());

  BOOST_TEST(keypair2.public_key().size() == ks_pub);
  BOOST_TEST(keypair2.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE ( sodium_test_keypairsign_copy_ctor_bytes )
{
  keypairsign<> keypair;
  keypairsign<> keypair_copy {keypair};

  BOOST_TEST((keypair == keypair_copy)); // check also operator==()
  BOOST_TEST((keypair.private_key() == keypair_copy.private_key())); // key::operator==()
  BOOST_TEST(keypair.public_key()  == keypair_copy.public_key());  // std::vector::operator==()
}

BOOST_AUTO_TEST_CASE ( sodium_test_keypairsign_copy_assignement_bytes )
{
  keypairsign<> keypair;
  keypairsign<> keypair_copy = keypair;

  BOOST_TEST((keypair == keypair_copy));
  BOOST_TEST((keypair.private_key() == keypair_copy.private_key()));
  BOOST_TEST(keypair.public_key()  == keypair_copy.public_key());
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_nonzero_ctor_default_bytes )
{
  keypairsign<> keypair;

  BOOST_TEST(!sodium::is_zero(keypair.public_key()));
  BOOST_TEST(!sodium::is_zero(keypair.private_key()));
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_nonzero_ctor_seed_bytes )
{
  bytes seed(ks_seed);
  sodium::randombytes_buf_inplace(seed);

  keypairsign<> keypair(seed);

  BOOST_TEST(!sodium::is_zero(keypair.public_key()));
  BOOST_TEST(!sodium::is_zero(keypair.private_key()));
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_nonzero_ctor_privkey_bytes )
{
  keypairsign<> keypair1;
  keypairsign<> keypair2(keypair1.private_key().data(), keypair1.private_key().size());

  BOOST_TEST(!sodium::is_zero(keypair2.public_key()));
  BOOST_TEST(!sodium::is_zero(keypair2.private_key()));
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_seedcompare_ctor_same_seed_bytes )
{
  bytes seed(ks_seed);
  sodium::randombytes_buf_inplace(seed);

  keypairsign<> keypair1(seed);
  keypairsign<> keypair2(seed); // same seed

  BOOST_TEST(sodium::compare(keypair1.public_key(),
	  keypair2.public_key()));
  BOOST_TEST(sodium::compare(keypair1.private_key(),
	  keypair2.private_key()));

  BOOST_TEST((keypair1 == keypair2)); // check also operator==()
  BOOST_TEST((keypair1.private_key() == keypair2.private_key()));
  BOOST_TEST(keypair1.public_key() == keypair2.public_key());
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_seedcompare_ctor_different_seed_bytes )
{
  bytes seed1(ks_seed);
  sodium::randombytes_buf_inplace(seed1);
  bytes seed2(ks_seed);
  sodium::randombytes_buf_inplace(seed2);

  BOOST_TEST(seed1 != seed2); // very unlikely that they are the same

  keypairsign<> keypair1(seed1);
  keypairsign<> keypair2(seed2); // different seed

  BOOST_TEST(!sodium::compare(keypair1.public_key(),
	  keypair2.public_key()));
  BOOST_TEST(!sodium::compare(keypair1.private_key(),
	  keypair2.private_key()));

  BOOST_TEST((keypair1 != keypair2)); // check also operator!=()
}

BOOST_AUTO_TEST_CASE( sodium_test_keypairsign_seedcompare_extract_seed_bytes )
{
  bytes seed1(ks_seed);
  sodium::randombytes_buf_inplace(seed1);

  keypairsign<> keypair(seed1);

  // reconstruct seed from private key stored in keypair
  bytes seed2 = keypair.seed();

  BOOST_TEST(seed1 == seed2);
}

// 2. sodium::bytes_protected ----------------------------------------

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_size_ctor_default_bytes_protected)
{
	keypairsign<sodium::bytes_protected> keypair;

	BOOST_TEST(keypair.public_key().size() == ks_pub);
	BOOST_TEST(keypair.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_size_ctor_seed_bytes_protected)
{
	bytes seed(ks_seed);
	sodium::randombytes_buf_inplace(seed);

	keypairsign<sodium::bytes_protected> keypair(seed);

	BOOST_TEST(keypair.public_key().size() == ks_pub);
	BOOST_TEST(keypair.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_size_ctor_privkey_bytes_protected)
{
	keypairsign<sodium::bytes_protected> keypair1;
	keypairsign<sodium::bytes_protected> keypair2(keypair1.private_key().data(), keypair1.private_key().size());

	BOOST_TEST(keypair2.public_key().size() == ks_pub);
	BOOST_TEST(keypair2.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_copy_ctor_bytes_protected)
{
	keypairsign<sodium::bytes_protected> keypair;
	keypairsign<sodium::bytes_protected> keypair_copy{ keypair };

	BOOST_TEST((keypair == keypair_copy)); // check also operator==()
	BOOST_TEST((keypair.private_key() == keypair_copy.private_key())); // key::operator==()
	BOOST_TEST(keypair.public_key() == keypair_copy.public_key());  // std::vector::operator==()
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_copy_assignement_bytes_protected)
{
	keypairsign<sodium::bytes_protected> keypair;
	keypairsign<sodium::bytes_protected> keypair_copy = keypair;

	BOOST_TEST((keypair == keypair_copy));
	BOOST_TEST((keypair.private_key() == keypair_copy.private_key()));
	BOOST_TEST(keypair.public_key() == keypair_copy.public_key());
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_nonzero_ctor_default_bytes_protected)
{
	keypairsign<sodium::bytes_protected> keypair;

	BOOST_TEST(!sodium::is_zero(keypair.public_key()));
	BOOST_TEST(!sodium::is_zero(keypair.private_key()));
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_nonzero_ctor_seed_bytes_protected)
{
	bytes seed(ks_seed);
	sodium::randombytes_buf_inplace(seed);

	keypairsign<sodium::bytes_protected> keypair(seed);

	BOOST_TEST(!sodium::is_zero(keypair.public_key()));
	BOOST_TEST(!sodium::is_zero(keypair.private_key()));
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_nonzero_ctor_privkey_bytes_protected)
{
	keypairsign<sodium::bytes_protected> keypair1;
	keypairsign<sodium::bytes_protected> keypair2(keypair1.private_key().data(), keypair1.private_key().size());

	BOOST_TEST(!sodium::is_zero(keypair2.public_key()));
	BOOST_TEST(!sodium::is_zero(keypair2.private_key()));
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_seedcompare_ctor_same_seed_bytes_protected)
{
	bytes seed(ks_seed);
	sodium::randombytes_buf_inplace(seed);

	keypairsign<sodium::bytes_protected> keypair1(seed);
	keypairsign<sodium::bytes_protected> keypair2(seed); // same seed

	BOOST_TEST(sodium::compare(keypair1.public_key(),
		keypair2.public_key()));
	BOOST_TEST(sodium::compare(keypair1.private_key(),
		keypair2.private_key()));

	BOOST_TEST((keypair1 == keypair2)); // check also operator==()
	BOOST_TEST((keypair1.private_key() == keypair2.private_key()));
	BOOST_TEST(keypair1.public_key() == keypair2.public_key());
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_seedcompare_ctor_different_seed_bytes_protected)
{
	bytes seed1(ks_seed);
	sodium::randombytes_buf_inplace(seed1);
	bytes seed2(ks_seed);
	sodium::randombytes_buf_inplace(seed2);

	BOOST_TEST(seed1 != seed2); // very unlikely that they are the same

	keypairsign<sodium::bytes_protected> keypair1(seed1);
	keypairsign<sodium::bytes_protected> keypair2(seed2); // different seed

	BOOST_TEST(!sodium::compare(keypair1.public_key(),
		keypair2.public_key()));
	BOOST_TEST(!sodium::compare(keypair1.private_key(),
		keypair2.private_key()));

	BOOST_TEST((keypair1 != keypair2)); // check also operator!=()
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_seedcompare_extract_seed_bytes_protected)
{
	bytes seed1(ks_seed);
	sodium::randombytes_buf_inplace(seed1);

	keypairsign<sodium::bytes_protected> keypair(seed1);

	// reconstruct seed from private key stored in keypair
	bytes seed2 = keypair.seed();

	BOOST_TEST(seed1 == seed2);
}

// 3. sodium::chars -------------------------------------------------------

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_size_ctor_default_chars)
{
	keypairsign<sodium::chars> keypair;

	BOOST_TEST(keypair.public_key().size() == ks_pub);
	BOOST_TEST(keypair.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_size_ctor_seed_chars)
{
	bytes seed(ks_seed);
	sodium::randombytes_buf_inplace(seed);

	keypairsign<sodium::chars> keypair(seed);

	BOOST_TEST(keypair.public_key().size() == ks_pub);
	BOOST_TEST(keypair.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_size_ctor_privkey_chars)
{
	keypairsign<sodium::chars> keypair1;
	keypairsign<sodium::chars> keypair2(keypair1.private_key().data(), keypair1.private_key().size());

	BOOST_TEST(keypair2.public_key().size() == ks_pub);
	BOOST_TEST(keypair2.private_key().size() == ks_priv);
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_copy_ctor_chars)
{
	keypairsign<sodium::chars> keypair;
	keypairsign<sodium::chars> keypair_copy{ keypair };

	BOOST_TEST((keypair == keypair_copy)); // check also operator==()
	BOOST_TEST((keypair.private_key() == keypair_copy.private_key())); // key::operator==()
	BOOST_TEST(keypair.public_key() == keypair_copy.public_key());  // std::vector::operator==()
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_copy_assignement_chars)
{
	keypairsign<sodium::chars> keypair;
	keypairsign<sodium::chars> keypair_copy = keypair;

	BOOST_TEST((keypair == keypair_copy));
	BOOST_TEST((keypair.private_key() == keypair_copy.private_key()));
	BOOST_TEST(keypair.public_key() == keypair_copy.public_key());
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_nonzero_ctor_default_chars)
{
	keypairsign<sodium::chars> keypair;

	BOOST_TEST(!sodium::is_zero(keypair.public_key()));
	BOOST_TEST(!sodium::is_zero(keypair.private_key()));
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_nonzero_ctor_seed_chars)
{
	bytes seed(ks_seed);
	sodium::randombytes_buf_inplace(seed);

	keypairsign<sodium::chars> keypair(seed);

	BOOST_TEST(!sodium::is_zero(keypair.public_key()));
	BOOST_TEST(!sodium::is_zero(keypair.private_key()));
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_nonzero_ctor_privkey_chars)
{
	keypairsign<sodium::chars> keypair1;
	keypairsign<sodium::chars> keypair2(keypair1.private_key().data(), keypair1.private_key().size());

	BOOST_TEST(!sodium::is_zero(keypair2.public_key()));
	BOOST_TEST(!sodium::is_zero(keypair2.private_key()));
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_seedcompare_ctor_same_seed_chars)
{
	bytes seed(ks_seed);
	sodium::randombytes_buf_inplace(seed);

	keypairsign<sodium::chars> keypair1(seed);
	keypairsign<sodium::chars> keypair2(seed); // same seed

	BOOST_TEST(sodium::compare(keypair1.public_key(),
		keypair2.public_key()));
	BOOST_TEST(sodium::compare(keypair1.private_key(),
		keypair2.private_key()));

	BOOST_TEST((keypair1 == keypair2)); // check also operator==()
	BOOST_TEST((keypair1.private_key() == keypair2.private_key()));
	BOOST_TEST(keypair1.public_key() == keypair2.public_key());
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_seedcompare_ctor_different_seed_chars)
{
	bytes seed1(ks_seed);
	sodium::randombytes_buf_inplace(seed1);
	bytes seed2(ks_seed);
	sodium::randombytes_buf_inplace(seed2);

	BOOST_TEST(seed1 != seed2); // very unlikely that they are the same

	keypairsign<sodium::chars> keypair1(seed1);
	keypairsign<sodium::chars> keypair2(seed2); // different seed

	BOOST_TEST(!sodium::compare(keypair1.public_key(),
		keypair2.public_key()));
	BOOST_TEST(!sodium::compare(keypair1.private_key(),
		keypair2.private_key()));

	BOOST_TEST((keypair1 != keypair2)); // check also operator!=()
}

BOOST_AUTO_TEST_CASE(sodium_test_keypairsign_seedcompare_extract_seed_chars)
{
	bytes seed1(ks_seed);
	sodium::randombytes_buf_inplace(seed1);

	keypairsign<sodium::chars> keypair(seed1);

	// reconstruct seed from private key stored in keypair
	bytes seed2 = keypair.seed();

	BOOST_TEST(seed1 == seed2);
}

BOOST_AUTO_TEST_SUITE_END ()
<|endoftext|>


<commit_before>#include "controlpanel.h"
#include <QVBoxLayout>
#include <QHBoxLayout>

controlPanel::controlPanel(QWidget *parent) :
    QWidget(parent),
    _playPauseButton(new QPushButton("Play/Pause")),
    _nextButton(new QPushButton("Next")),
    _previousButton(new QPushButton("Previous")),
    _volumeSlider(new QSlider(Qt::Horizontal)),
    _currentState(controlPanel::Paused)
{
    _volumeSlider->setRange(0,100);
    _volumeSlider->setValue(50);

    QVBoxLayout * layout = new QVBoxLayout;
    QHBoxLayout * buttonLayout = new QHBoxLayout;
    QHBoxLayout * optionsLayout = new QHBoxLayout;

    buttonLayout->addWidget(_previousButton);
    buttonLayout->addWidget(_playPauseButton);
    buttonLayout->addWidget(_nextButton);

    optionsLayout->addWidget(_volumeSlider);

    layout->addLayout(optionsLayout);
    layout->addLayout(buttonLayout);

    this->setLayout(layout);
}

const QObject * controlPanel::widget(Widget widget)
{
    if(widget == controlPanel::PlayPauseButton)
        return _playPauseButton;
    else if(widget == controlPanel::NextButton)
        return _nextButton;
    else if(widget == controlPanel::PreviousButton)
        return _previousButton;
    else if(widget == controlPanel::VolumeSlider)
        return _volumeSlider;
    else return new QObject;
}

void controlPanel::setPlayButtonIcon(const QIcon &icon)
{
    _playButtonIcon = icon;

    _playPauseButton->text().clear();

    if(_currentState == controlPanel::Paused)
        _playPauseButton->setIcon(icon);

}

void controlPanel::setPauseButtonIcon(const QIcon &icon)
{
    _pauseButtonIcon = icon;

    _playPauseButton->text().clear();

    if(_currentState == controlPanel::Playing)
        _playPauseButton->setIcon(icon);
}

void controlPanel::setNextButtonIcon(const QIcon &icon)
{
    _nextButton->text().clear();
    _nextButton->setIcon(icon);
}

void controlPanel::setPreviousButtonIcon(const QIcon &icon)
{
    _previousButton->text().clear();
    _previousButton->setIcon(icon);
}

void controlPanel::togglePlayPauseState()
{
    if(_currentState == controlPanel::Paused)
    {
        _currentState = controlPanel::Playing;
        if(!_playButtonIcon.isNull())
            _playPauseButton->setIcon(_pauseButtonIcon);
        else
        {
            _playPauseButton->setIcon(QIcon());
            _playPauseButton->setText("Pause");
        }
    }
    else if(_currentState == controlPanel::Playing)
    {
        _currentState = controlPanel::Paused;
        if(!_pauseButtonIcon.isNull())
            _playPauseButton->setIcon(_playButtonIcon);
        else
        {
            _playPauseButton->setIcon(QIcon());
            _playPauseButton->setText("Play");
        }
    }
}
<commit_msg>Got rid of unecessary code in togglePlayPauseState function.<commit_after>#include "controlpanel.h"
#include <QVBoxLayout>
#include <QHBoxLayout>

controlPanel::controlPanel(QWidget *parent) :
    QWidget(parent),
    _playPauseButton(new QPushButton("Play/Pause")),
    _nextButton(new QPushButton("Next")),
    _previousButton(new QPushButton("Previous")),
    _volumeSlider(new QSlider(Qt::Horizontal)),
    _currentState(controlPanel::Paused)
{
    _volumeSlider->setRange(0,100);
    _volumeSlider->setValue(50);

    QVBoxLayout * layout = new QVBoxLayout;
    QHBoxLayout * buttonLayout = new QHBoxLayout;
    QHBoxLayout * optionsLayout = new QHBoxLayout;

    buttonLayout->addWidget(_previousButton);
    buttonLayout->addWidget(_playPauseButton);
    buttonLayout->addWidget(_nextButton);

    optionsLayout->addWidget(_volumeSlider);

    layout->addLayout(optionsLayout);
    layout->addLayout(buttonLayout);

    this->setLayout(layout);
}

const QObject * controlPanel::widget(Widget widget)
{
    if(widget == controlPanel::PlayPauseButton)
        return _playPauseButton;
    else if(widget == controlPanel::NextButton)
        return _nextButton;
    else if(widget == controlPanel::PreviousButton)
        return _previousButton;
    else if(widget == controlPanel::VolumeSlider)
        return _volumeSlider;
    else return new QObject;
}

void controlPanel::setPlayButtonIcon(const QIcon &icon)
{
    _playButtonIcon = icon;

    _playPauseButton->text().clear();

    if(_currentState == controlPanel::Paused)
        _playPauseButton->setIcon(icon);

}

void controlPanel::setPauseButtonIcon(const QIcon &icon)
{
    _pauseButtonIcon = icon;

    _playPauseButton->text().clear();

    if(_currentState == controlPanel::Playing)
        _playPauseButton->setIcon(icon);
}

void controlPanel::setNextButtonIcon(const QIcon &icon)
{
    _nextButton->text().clear();
    _nextButton->setIcon(icon);
}

void controlPanel::setPreviousButtonIcon(const QIcon &icon)
{
    _previousButton->text().clear();
    _previousButton->setIcon(icon);
}

void controlPanel::togglePlayPauseState()
{
    if(_currentState == controlPanel::Paused)
    {
        _currentState = controlPanel::Playing;
        if(!_playButtonIcon.isNull())
            _playPauseButton->setIcon(_pauseButtonIcon);
        else
            _playPauseButton->setIcon(QIcon());
    }
    else if(_currentState == controlPanel::Playing)
    {
        _currentState = controlPanel::Paused;
        if(!_pauseButtonIcon.isNull())
            _playPauseButton->setIcon(_playButtonIcon);
        else
            _playPauseButton->setIcon(QIcon());
    }
}
<|endoftext|>


<commit_before>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Modified by Cloudius Systems.
 * Copyright 2015 Cloudius Systems.
 */

#pragma once

#include "types.hh"
#include "core/sstring.hh"
#include "util/serialization.hh"
#include "gms/gossip_digest.hh"

namespace gms {

/**
 * This is the first message that gets sent out as a start of the Gossip protocol in a
 * round.
 */
class gossip_digest_syn {
private:
    const sstring _cluster_id;
    const sstring _partioner;
    const std::vector<gossip_digest> _digests;
public:
    gossip_digest_syn(sstring id, sstring p, std::vector<gossip_digest> digests)
        : _cluster_id(id)
        , _partioner(p)
        , _digests(digests) {
    }

    std::vector<gossip_digest> get_gossip_digests() {
        return _digests;
    }

    // The following replaces GossipDigestSynSerializer from the Java code
    void serialize(bytes::iterator& out) const {
        serialize_string(out, _cluster_id);
        serialize_string(out, _partioner);
        gossip_digest_serialization_helper::serialize(out, _digests);
    }

    static gossip_digest_syn deserialize(bytes_view& v) {
        sstring cluster_id = read_simple_short_string(v);
        sstring partioner = read_simple_short_string(v);
        std::vector<gossip_digest> digests = gossip_digest_serialization_helper::deserialize(v);
        return gossip_digest_syn(cluster_id, partioner, std::move(digests));
    }

    size_t serialized_size() const {
        return serialize_string_size(_cluster_id) + serialize_string_size(_partioner) +
               gossip_digest_serialization_helper::serialized_size(_digests);
    }
};

}
<commit_msg>gossip: Remove const for gossip_digest_syn<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Modified by Cloudius Systems.
 * Copyright 2015 Cloudius Systems.
 */

#pragma once

#include "types.hh"
#include "core/sstring.hh"
#include "util/serialization.hh"
#include "gms/gossip_digest.hh"

namespace gms {

/**
 * This is the first message that gets sent out as a start of the Gossip protocol in a
 * round.
 */
class gossip_digest_syn {
private:
    sstring _cluster_id;
    sstring _partioner;
    std::vector<gossip_digest> _digests;
public:
    gossip_digest_syn(sstring id, sstring p, std::vector<gossip_digest> digests)
        : _cluster_id(id)
        , _partioner(p)
        , _digests(digests) {
    }

    std::vector<gossip_digest> get_gossip_digests() {
        return _digests;
    }

    // The following replaces GossipDigestSynSerializer from the Java code
    void serialize(bytes::iterator& out) const {
        serialize_string(out, _cluster_id);
        serialize_string(out, _partioner);
        gossip_digest_serialization_helper::serialize(out, _digests);
    }

    static gossip_digest_syn deserialize(bytes_view& v) {
        sstring cluster_id = read_simple_short_string(v);
        sstring partioner = read_simple_short_string(v);
        std::vector<gossip_digest> digests = gossip_digest_serialization_helper::deserialize(v);
        return gossip_digest_syn(cluster_id, partioner, std::move(digests));
    }

    size_t serialized_size() const {
        return serialize_string_size(_cluster_id) + serialize_string_size(_partioner) +
               gossip_digest_serialization_helper::serialized_size(_digests);
    }
};

}
<|endoftext|>