<commit_before>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include <xenia/hid/input_system.h>

#include <xenia/emulator.h>
#include <xenia/cpu/processor.h>
#include <xenia/hid/input_driver.h>

using namespace xe;
using namespace xe::hid;

InputSystem::InputSystem(Emulator* emulator) :
    emulator_(emulator) {
  memory_ = xe_memory_retain(emulator->memory());
}

InputSystem::~InputSystem() {
  for (std::vector<InputDriver*>::iterator it = drivers_.begin();
       it != drivers_.end(); ++it) {
    InputDriver* driver = *it;
    delete driver;
  }
  xe_memory_release(memory_);
}

X_STATUS InputSystem::Setup() {
  processor_ = emulator_->processor();

  return X_STATUS_SUCCESS;
}

void InputSystem::AddDriver(InputDriver* driver) {
  drivers_.push_back(driver);
}

X_RESULT InputSystem::GetCapabilities(
    uint32_t user_index, uint32_t flags, X_INPUT_CAPABILITIES& out_caps) {
  for (std::vector<InputDriver*>::iterator it = drivers_.begin();
       it != drivers_.end(); ++it) {
    InputDriver* driver = *it;
    if (XSUCCEEDED(driver->GetCapabilities(user_index, flags, out_caps))) {
      return X_ERROR_SUCCESS;
    }
  }
  return X_ERROR_DEVICE_NOT_CONNECTED;
}

X_RESULT InputSystem::GetState(uint32_t user_index, X_INPUT_STATE& out_state) {
  for (std::vector<InputDriver*>::iterator it = drivers_.begin();
       it != drivers_.end(); ++it) {
    InputDriver* driver = *it;
    if (XSUCCEEDED(driver->GetState(user_index, out_state))) {
      return X_ERROR_SUCCESS;
    }
  }
  return X_ERROR_DEVICE_NOT_CONNECTED;
}

X_RESULT InputSystem::SetState(
    uint32_t user_index, X_INPUT_VIBRATION& vibration) {
  for (std::vector<InputDriver*>::iterator it = drivers_.begin();
       it != drivers_.end(); ++it) {
    InputDriver* driver = *it;
    if (XSUCCEEDED(driver->SetState(user_index, vibration))) {
      return X_ERROR_SUCCESS;
    }
  }
  return X_ERROR_DEVICE_NOT_CONNECTED;
}
<commit_msg>Fix input error return.<commit_after>/**
 ******************************************************************************
 * Xenia : Xbox 360 Emulator Research Project                                 *
 ******************************************************************************
 * Copyright 2013 Ben Vanik. All rights reserved.                             *
 * Released under the BSD license - see LICENSE in the root for more details. *
 ******************************************************************************
 */

#include <xenia/hid/input_system.h>

#include <xenia/emulator.h>
#include <xenia/cpu/processor.h>
#include <xenia/hid/input_driver.h>

using namespace xe;
using namespace xe::hid;

InputSystem::InputSystem(Emulator* emulator) :
    emulator_(emulator) {
  memory_ = xe_memory_retain(emulator->memory());
}

InputSystem::~InputSystem() {
  for (std::vector<InputDriver*>::iterator it = drivers_.begin();
       it != drivers_.end(); ++it) {
    InputDriver* driver = *it;
    delete driver;
  }
  xe_memory_release(memory_);
}

X_STATUS InputSystem::Setup() {
  processor_ = emulator_->processor();

  return X_STATUS_SUCCESS;
}

void InputSystem::AddDriver(InputDriver* driver) {
  drivers_.push_back(driver);
}

X_RESULT InputSystem::GetCapabilities(
    uint32_t user_index, uint32_t flags, X_INPUT_CAPABILITIES& out_caps) {
  for (std::vector<InputDriver*>::iterator it = drivers_.begin();
       it != drivers_.end(); ++it) {
    InputDriver* driver = *it;
    if (XSUCCEEDED(driver->GetCapabilities(user_index, flags, out_caps))) {
      return X_ERROR_SUCCESS;
    }
  }
  return X_ERROR_DEVICE_NOT_CONNECTED;
}

X_RESULT InputSystem::GetState(uint32_t user_index, X_INPUT_STATE& out_state) {
  for (std::vector<InputDriver*>::iterator it = drivers_.begin();
       it != drivers_.end(); ++it) {
    InputDriver* driver = *it;
    if (driver->GetState(user_index, out_state) == X_ERROR_SUCCESS) {
      return X_ERROR_SUCCESS;
    }
  }
  return X_ERROR_DEVICE_NOT_CONNECTED;
}

X_RESULT InputSystem::SetState(
    uint32_t user_index, X_INPUT_VIBRATION& vibration) {
  for (std::vector<InputDriver*>::iterator it = drivers_.begin();
       it != drivers_.end(); ++it) {
    InputDriver* driver = *it;
    if (XSUCCEEDED(driver->SetState(user_index, vibration))) {
      return X_ERROR_SUCCESS;
    }
  }
  return X_ERROR_DEVICE_NOT_CONNECTED;
}
<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2009      Andrew Manson <g.real.ate@gmail.com>
//

#include "GeoLineStringGraphicsItem.h"

#include "GeoDataLineString.h"
#include "GeoDataLineStyle.h"
#include "GeoPainter.h"
#include "ViewportParams.h"
#include "GeoDataStyle.h"

namespace Marble
{

GeoLineStringGraphicsItem::GeoLineStringGraphicsItem( const GeoDataLineString* lineString )
        : GeoGraphicsItem(),
          m_lineString( lineString )
{
}

void GeoLineStringGraphicsItem::setLineString( const GeoDataLineString* lineString )
{
    m_lineString = lineString;
}

GeoDataCoordinates GeoLineStringGraphicsItem::coordinate() const
{
    return m_lineString->latLonAltBox().center();
}

void GeoLineStringGraphicsItem::coordinate( qreal &longitude, qreal &latitude, qreal &altitude ) const
{
    GeoDataCoordinates coords = m_lineString->latLonAltBox().center();
    longitude = coords.longitude();
    latitude = coords.latitude();
    altitude = coords.altitude();
}

GeoDataLatLonAltBox GeoLineStringGraphicsItem::latLonAltBox() const
{
    return m_lineString->latLonAltBox();
}

void GeoLineStringGraphicsItem::paint( GeoPainter* painter, ViewportParams* viewport,
                                       const QString& renderPos, GeoSceneLayer* layer )
{
    Q_UNUSED( renderPos );
    Q_UNUSED( layer );

    if ( !style() )
    {
        painter->save();
        painter->setPen( QPen() );
        painter->drawPolyline( *m_lineString );
        painter->restore();
        return;
    }

    if(style()->lineStyle().color() == Qt::transparent)
        return;

    painter->save();
    QPen currentPen = painter->pen();

    if ( currentPen.color() != style()->lineStyle().color() )
        currentPen.setColor( style()->lineStyle().color() );

    if ( currentPen.widthF() != style()->lineStyle().width() ||
            style()->lineStyle().physicalWidth() != 0.0 )
    {
        if ( float( viewport->radius() ) / EARTH_RADIUS * style()->lineStyle().physicalWidth() < style()->lineStyle().width() )
            currentPen.setWidthF( style()->lineStyle().width() );
        else
            currentPen.setWidthF( float( viewport->radius() ) / EARTH_RADIUS * style()->lineStyle().physicalWidth() );
    }

    if ( currentPen.capStyle() != style()->lineStyle().capStyle() )
        currentPen.setCapStyle( style()->lineStyle().capStyle() );

    if ( currentPen.style() != style()->lineStyle().penStyle() )
        currentPen.setStyle( style()->lineStyle().penStyle() );

    if ( style()->lineStyle().penStyle() == Qt::CustomDashLine )
        currentPen.setDashPattern( style()->lineStyle().dashPattern() );

    if ( painter->mapQuality() != Marble::HighQuality
            && painter->mapQuality() != Marble::PrintQuality )
    {
        QColor penColor = currentPen.color();
        penColor.setAlpha( 255 );
        currentPen.setColor( penColor );
    }

    if ( painter->pen() != currentPen ) painter->setPen( currentPen );
    if ( style()->lineStyle().background() )
    {
        painter->save();
        QPen bgPen( painter->pen() );
        bgPen.setColor( style()->polyStyle().color() );
        bgPen.setStyle( Qt::SolidLine );
        bgPen.setCapStyle( Qt::RoundCap );
        painter->setPen( bgPen );
        painter->drawPolyline( *m_lineString );
        painter->restore();
    }
    painter->drawPolyline( *m_lineString );
    painter->restore();
}

}
<commit_msg>faster background painting for GeoLineStringGraphicsItems<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2009      Andrew Manson <g.real.ate@gmail.com>
//

#include "GeoLineStringGraphicsItem.h"

#include "GeoDataLineString.h"
#include "GeoDataLineStyle.h"
#include "GeoPainter.h"
#include "ViewportParams.h"
#include "GeoDataStyle.h"

namespace Marble
{

GeoLineStringGraphicsItem::GeoLineStringGraphicsItem( const GeoDataLineString* lineString )
        : GeoGraphicsItem(),
          m_lineString( lineString )
{
}

void GeoLineStringGraphicsItem::setLineString( const GeoDataLineString* lineString )
{
    m_lineString = lineString;
}

GeoDataCoordinates GeoLineStringGraphicsItem::coordinate() const
{
    return m_lineString->latLonAltBox().center();
}

void GeoLineStringGraphicsItem::coordinate( qreal &longitude, qreal &latitude, qreal &altitude ) const
{
    GeoDataCoordinates coords = m_lineString->latLonAltBox().center();
    longitude = coords.longitude();
    latitude = coords.latitude();
    altitude = coords.altitude();
}

GeoDataLatLonAltBox GeoLineStringGraphicsItem::latLonAltBox() const
{
    return m_lineString->latLonAltBox();
}

void GeoLineStringGraphicsItem::paint( GeoPainter* painter, ViewportParams* viewport,
                                       const QString& renderPos, GeoSceneLayer* layer )
{
    Q_UNUSED( renderPos );
    Q_UNUSED( layer );

    if ( !style() )
    {
        painter->save();
        painter->setPen( QPen() );
        painter->drawPolyline( *m_lineString );
        painter->restore();
        return;
    }

    if(style()->lineStyle().color() == Qt::transparent)
        return;

    painter->save();
    QPen currentPen = painter->pen();

    if ( currentPen.color() != style()->lineStyle().color() )
        currentPen.setColor( style()->lineStyle().color() );

    if ( currentPen.widthF() != style()->lineStyle().width() ||
            style()->lineStyle().physicalWidth() != 0.0 )
    {
        if ( float( viewport->radius() ) / EARTH_RADIUS * style()->lineStyle().physicalWidth() < style()->lineStyle().width() )
            currentPen.setWidthF( style()->lineStyle().width() );
        else
            currentPen.setWidthF( float( viewport->radius() ) / EARTH_RADIUS * style()->lineStyle().physicalWidth() );
    }

    if ( currentPen.capStyle() != style()->lineStyle().capStyle() )
        currentPen.setCapStyle( style()->lineStyle().capStyle() );

    if ( currentPen.style() != style()->lineStyle().penStyle() )
        currentPen.setStyle( style()->lineStyle().penStyle() );

    if ( style()->lineStyle().penStyle() == Qt::CustomDashLine )
        currentPen.setDashPattern( style()->lineStyle().dashPattern() );

    if ( painter->mapQuality() != Marble::HighQuality
            && painter->mapQuality() != Marble::PrintQuality )
    {
        QColor penColor = currentPen.color();
        penColor.setAlpha( 255 );
        currentPen.setColor( penColor );
    }

    if ( painter->pen() != currentPen ) painter->setPen( currentPen );
    if ( style()->lineStyle().background() )
    {
        QBrush brush = painter->background();
        brush.setColor( style()->polyStyle().color() );
        painter->setBackground( brush );

        painter->setBackgroundMode( Qt::OpaqueMode );
    }
    painter->drawPolyline( *m_lineString );
    painter->restore();
}

}
<|endoftext|>


<commit_before>#include "HTTPSession.h"
#include "Application/HTTP/UrlParam.h"
#include "Application/HTTP/HTTPRequest.h"
#include "Application/HTTP/HTTPConnection.h"
#include "Application/HTTP/HTTPConsts.h"
#include "Application/HTTP/Mime.h"

#define MSG_FAIL            "Unable to process your request at this time"
#define CONTENT_TYPE_PLAIN  HTTP_HEADER_CONTENT_TYPE ": " MIME_TYPE_TEXT_PLAIN HTTP_CS_CRLF
#define CONTENT_TYPE_HTML   HTTP_HEADER_CONTENT_TYPE ": " MIME_TYPE_TEXT_HTML HTTP_CS_CRLF

HTTPSession::HTTPSession()
{
    headerSent = false;
    conn = NULL;
    type = PLAIN;
}

void HTTPSession::SetConnection(HTTPConnection* conn_)
{
    conn = conn_;

    if (conn != NULL)
        json.Init(conn);
}

bool HTTPSession::ParseRequest(HTTPRequest& request, ReadBuffer& cmd, UrlParam& params)
{
    char*       qmark;
    ReadBuffer  rb;
    ReadBuffer  jsonCallback;
    ReadBuffer  mimeType;
    ReadBuffer  origin;

    // TODO: when adding keep-alive HTTP sessions, move this to an Init() function
    isFlushed = false;

    uri = request.line.uri;
    rb = request.line.uri;
    if (rb.GetCharAt(0) == '/')
        rb.Advance(1);

    mimeType.Reset();
    ParseType(rb);
    cmd = rb;

    qmark = NULL;
    if (rb.GetLength() > 0)
        qmark = FindInBuffer(rb.GetBuffer(), rb.GetLength() - 1, '?');

    if (qmark)
    {
        rb.Advance((unsigned) (qmark - rb.GetBuffer() + 1));
        params.Init(rb.GetBuffer(), rb.GetLength(), '&');
        cmd.SetLength((unsigned) (qmark - cmd.GetBuffer()));

        if (type == JSON)
        {
            HTTP_GET_OPT_PARAM(params, "callback", jsonCallback);
            json.SetCallbackPrefix(jsonCallback);
        }

        // mime type is overridable
        HTTP_GET_OPT_PARAM(params, "mimetype", mimeType);
        if (mimeType.GetLength() != 0)
            conn->SetContentType(mimeType);

        // CORS support
        // http://www.w3.org/TR/cors/
        HTTP_GET_OPT_PARAM(params, "origin", origin);
    }

    return true;
}

void HTTPSession::ParseType(ReadBuffer& rb)
{
    const char  JSON_PREFIX[] = "json/";
    const char  HTML_PREFIX[] = "html/";

    if (HTTP_MATCH_PREFIX(rb, JSON_PREFIX))
    {
        SetType(JSON);
        rb.Advance(sizeof(JSON_PREFIX) - 1);
    }
    else if (HTTP_MATCH_PREFIX(rb, HTML_PREFIX))
    {
        SetType(HTML);
        rb.Advance(sizeof(HTML_PREFIX) - 1);
    }
    else
        SetType(PLAIN);
}

void HTTPSession::ResponseFail()
{
    ASSERT(headerSent == false);
    if (!conn)
        return;

    if (type == JSON)
        json.PrintStatus("error", MSG_FAIL);
    else
        conn->Response(HTTP_STATUS_CODE_OK, MSG_FAIL, sizeof(MSG_FAIL) - 1);
}

void HTTPSession::Redirect(const ReadBuffer& location)
{
    Buffer      extraHeader;

    ASSERT(headerSent == false);
    if (!conn)
        return;

    extraHeader.Writef(HTTP_HEADER_LOCATION ": %R" HTTP_CS_CRLF, &location);
    extraHeader.NullTerminate();
    conn->ResponseHeader(HTTP_STATUS_CODE_TEMPORARY_REDIRECT, true, extraHeader.GetBuffer());
}

void HTTPSession::Print(const ReadBuffer& line)
{
    Buffer      header;
    ReadBuffer  tmp;

    if (!conn)
        return;

    if (!headerSent)
    {
        if (type == JSON)
            json.Start();
        else
            conn->WriteHeader(HTTP_STATUS_CODE_OK);

        headerSent = true;
    }

    if (type == JSON)
    {
        tmp = "response";
        json.PrintString(tmp);
        json.PrintColon();
        json.PrintString(line);
    }
    else
    {
        conn->Write(line.GetBuffer(), line.GetLength());
        conn->Print("\n");
    }
}

void HTTPSession::PrintPair(const ReadBuffer& key, const ReadBuffer& value)
{
    if (!conn)
        return;

    if (!headerSent)
    {
        if (type == JSON)
            json.Start();
        else
            conn->WriteHeader(HTTP_STATUS_CODE_OK);

        headerSent = true;
    }

    if (type == JSON)
        json.PrintPair(key.GetBuffer(), key.GetLength(), value.GetBuffer(), value.GetLength());
    else
    {
        conn->Write(key.GetBuffer(), key.GetLength());
        conn->Print(": ");
        conn->Write(value.GetBuffer(), value.GetLength());
        conn->Print("\n");
    }
}

void HTTPSession::PrintPair(const char* key, const char* value)
{
    PrintPair(ReadBuffer(key), ReadBuffer(value));
}

void HTTPSession::Flush()
{
    if (!conn)
        return;

    if (type == JSON)
        json.End();

    conn->Flush(true);
    isFlushed = true;
}

void HTTPSession::SetType(Type type_)
{
    const char* mime;
    ReadBuffer  mimeType;

    type = type_;

    switch (type)
    {
    case PLAIN:
        mime = MIME_TYPE_TEXT_PLAIN;
        break;
    case HTML:
        mime = MIME_TYPE_TEXT_HTML;
        break;
    case JSON:
        mime = MIME_TYPE_APPLICATION_JSON;
        break;
    default:
        mime = MIME_TYPE_TEXT_PLAIN;
        break;
    }

    if (mimeType.GetLength() == 0)
        mimeType.Wrap(mime);

    conn->SetContentType(mimeType);
}

bool HTTPSession::IsFlushed()
{
    return isFlushed;
}

bool HTTPSession::RedirectLocalhost(HTTPConnection *conn, HTTPRequest &request)
{
#ifdef PLATFORM_WINDOWS

    ReadBuffer  host;

    // fix Windows 7 IPv6 localhost name resolution issue
    host = request.header.GetField(HTTP_HEADER_HOST);
    if (host.BeginsWith("localhost"))
    {
        Buffer      newHost;
        Buffer      ha;
        unsigned    i;

        newHost.Write("127.0.0.1");
        for (i = 0; i < host.GetLength(); i++)
        {
            if (host.GetCharAt(i) == ':')
            {
                host.Advance(i);
                newHost.Append(host);
                break;
            }
        }
        ha.Writef(HTTP_HEADER_LOCATION ": http://%B%R" HTTP_CS_CRLF, &newHost, &request.line.uri);
	    ha.NullTerminate();
		conn->ResponseHeader(HTTP_STATUS_CODE_TEMPORARY_REDIRECT, true, ha.GetBuffer());
        conn->Flush(true);
		return true;
    }

#endif

    return false;
}
<commit_msg>Undo localhost redirection policy.<commit_after>#include "HTTPSession.h"
#include "Application/HTTP/UrlParam.h"
#include "Application/HTTP/HTTPRequest.h"
#include "Application/HTTP/HTTPConnection.h"
#include "Application/HTTP/HTTPConsts.h"
#include "Application/HTTP/Mime.h"

#define MSG_FAIL            "Unable to process your request at this time"
#define CONTENT_TYPE_PLAIN  HTTP_HEADER_CONTENT_TYPE ": " MIME_TYPE_TEXT_PLAIN HTTP_CS_CRLF
#define CONTENT_TYPE_HTML   HTTP_HEADER_CONTENT_TYPE ": " MIME_TYPE_TEXT_HTML HTTP_CS_CRLF

HTTPSession::HTTPSession()
{
    headerSent = false;
    conn = NULL;
    type = PLAIN;
}

void HTTPSession::SetConnection(HTTPConnection* conn_)
{
    conn = conn_;

    if (conn != NULL)
        json.Init(conn);
}

bool HTTPSession::ParseRequest(HTTPRequest& request, ReadBuffer& cmd, UrlParam& params)
{
    char*       qmark;
    ReadBuffer  rb;
    ReadBuffer  jsonCallback;
    ReadBuffer  mimeType;
    ReadBuffer  origin;

    // TODO: when adding keep-alive HTTP sessions, move this to an Init() function
    isFlushed = false;

    uri = request.line.uri;
    rb = request.line.uri;
    if (rb.GetCharAt(0) == '/')
        rb.Advance(1);

    mimeType.Reset();
    ParseType(rb);
    cmd = rb;

    qmark = NULL;
    if (rb.GetLength() > 0)
        qmark = FindInBuffer(rb.GetBuffer(), rb.GetLength() - 1, '?');

    if (qmark)
    {
        rb.Advance((unsigned) (qmark - rb.GetBuffer() + 1));
        params.Init(rb.GetBuffer(), rb.GetLength(), '&');
        cmd.SetLength((unsigned) (qmark - cmd.GetBuffer()));

        if (type == JSON)
        {
            HTTP_GET_OPT_PARAM(params, "callback", jsonCallback);
            json.SetCallbackPrefix(jsonCallback);
        }

        // mime type is overridable
        HTTP_GET_OPT_PARAM(params, "mimetype", mimeType);
        if (mimeType.GetLength() != 0)
            conn->SetContentType(mimeType);

        // CORS support
        // http://www.w3.org/TR/cors/
        HTTP_GET_OPT_PARAM(params, "origin", origin);
    }

    return true;
}

void HTTPSession::ParseType(ReadBuffer& rb)
{
    const char  JSON_PREFIX[] = "json/";
    const char  HTML_PREFIX[] = "html/";

    if (HTTP_MATCH_PREFIX(rb, JSON_PREFIX))
    {
        SetType(JSON);
        rb.Advance(sizeof(JSON_PREFIX) - 1);
    }
    else if (HTTP_MATCH_PREFIX(rb, HTML_PREFIX))
    {
        SetType(HTML);
        rb.Advance(sizeof(HTML_PREFIX) - 1);
    }
    else
        SetType(PLAIN);
}

void HTTPSession::ResponseFail()
{
    ASSERT(headerSent == false);
    if (!conn)
        return;

    if (type == JSON)
        json.PrintStatus("error", MSG_FAIL);
    else
        conn->Response(HTTP_STATUS_CODE_OK, MSG_FAIL, sizeof(MSG_FAIL) - 1);
}

void HTTPSession::Redirect(const ReadBuffer& location)
{
    Buffer      extraHeader;

    ASSERT(headerSent == false);
    if (!conn)
        return;

    extraHeader.Writef(HTTP_HEADER_LOCATION ": %R" HTTP_CS_CRLF, &location);
    extraHeader.NullTerminate();
    conn->ResponseHeader(HTTP_STATUS_CODE_TEMPORARY_REDIRECT, true, extraHeader.GetBuffer());
}

void HTTPSession::Print(const ReadBuffer& line)
{
    Buffer      header;
    ReadBuffer  tmp;

    if (!conn)
        return;

    if (!headerSent)
    {
        if (type == JSON)
            json.Start();
        else
            conn->WriteHeader(HTTP_STATUS_CODE_OK);

        headerSent = true;
    }

    if (type == JSON)
    {
        tmp = "response";
        json.PrintString(tmp);
        json.PrintColon();
        json.PrintString(line);
    }
    else
    {
        conn->Write(line.GetBuffer(), line.GetLength());
        conn->Print("\n");
    }
}

void HTTPSession::PrintPair(const ReadBuffer& key, const ReadBuffer& value)
{
    if (!conn)
        return;

    if (!headerSent)
    {
        if (type == JSON)
            json.Start();
        else
            conn->WriteHeader(HTTP_STATUS_CODE_OK);

        headerSent = true;
    }

    if (type == JSON)
        json.PrintPair(key.GetBuffer(), key.GetLength(), value.GetBuffer(), value.GetLength());
    else
    {
        conn->Write(key.GetBuffer(), key.GetLength());
        conn->Print(": ");
        conn->Write(value.GetBuffer(), value.GetLength());
        conn->Print("\n");
    }
}

void HTTPSession::PrintPair(const char* key, const char* value)
{
    PrintPair(ReadBuffer(key), ReadBuffer(value));
}

void HTTPSession::Flush()
{
    if (!conn)
        return;

    if (type == JSON)
        json.End();

    conn->Flush(true);
    isFlushed = true;
}

void HTTPSession::SetType(Type type_)
{
    const char* mime;
    ReadBuffer  mimeType;

    type = type_;

    switch (type)
    {
    case PLAIN:
        mime = MIME_TYPE_TEXT_PLAIN;
        break;
    case HTML:
        mime = MIME_TYPE_TEXT_HTML;
        break;
    case JSON:
        mime = MIME_TYPE_APPLICATION_JSON;
        break;
    default:
        mime = MIME_TYPE_TEXT_PLAIN;
        break;
    }

    if (mimeType.GetLength() == 0)
        mimeType.Wrap(mime);

    conn->SetContentType(mimeType);
}

bool HTTPSession::IsFlushed()
{
    return isFlushed;
}

bool HTTPSession::RedirectLocalhost(HTTPConnection *conn, HTTPRequest &request)
{
    ReadBuffer  host;

    // fix Windows 7 IPv6 localhost name resolution issue
    host = request.header.GetField(HTTP_HEADER_HOST);
    if (host.BeginsWith("localhost"))
    {
        Buffer      newHost;
        Buffer      ha;
        unsigned    i;

        newHost.Write("127.0.0.1");
        for (i = 0; i < host.GetLength(); i++)
        {
            if (host.GetCharAt(i) == ':')
            {
                host.Advance(i);
                newHost.Append(host);
                break;
            }
        }
        ha.Writef(HTTP_HEADER_LOCATION ": http://%B%R" HTTP_CS_CRLF, &newHost, &request.line.uri);
	    ha.NullTerminate();
		conn->ResponseHeader(HTTP_STATUS_CODE_TEMPORARY_REDIRECT, true, ha.GetBuffer());
        conn->Flush(true);
		return true;
    }

    return false;
}
<|endoftext|>


<commit_before>/* Twofold-ChaiScript
 * (C) Copyright 2015 HicknHack Software GmbH
 *
 * The original code can be found at:
 *     https://github.com/arBmind/Twofold-ChaiScript
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "Engine.h"

#include "Twofold/intern/ChaiScriptTargetBuilderApi.h"

#include "Twofold/intern/QStringHelper.h"
#include "Twofold/intern/find_last.h"

#include <chaiscript/chaiscript.hpp>
#include <chaiscript/utility/utility.hpp>

#include <QVector>

#include <vector>

namespace Twofold {
namespace intern {
chaiscript::ModulePtr chaiscript_stdlib();
} // namespace intern

using namespace intern;

namespace {

FileLineColumnPositionList generateExceptionCallerStack(const PreparedTemplate &preparedTemplate, const QStringList &backtrace)
{
    FileLineColumnPositionList callerStack;
    for (const auto& traceLine : backtrace) {
        // traceline format: "<function>() at <line>"
        auto begin = traceLine.begin();
        const auto end = traceLine.end();

        begin = find_last(begin, end, QChar(' '));
        QString lineString = toQString(begin, end);

        bool convertSuccesful = false;
        const int line = lineString.toInt(&convertSuccesful);
        const int column = 1;
        if (convertSuccesful) {
            const auto position = SourceMap::getOriginalPositionFromGenerated(preparedTemplate.sourceMap, {line, column});
            callerStack.push_back(position);
        }
    }
    return callerStack;
}

} // namespace

class Engine::Private
{
public:
    Private(MessageHandlerPtr messageHandler, TextLoaderPtr textLoader)
        : m_messageHandler(messageHandler)
        , m_textLoader(textLoader)
        , m_chai(chaiscript_stdlib())
    {
        defineQVariantCasts();
    }

    Target execPrepared(const PreparedTemplate &preparedTemplate, const Engine::Context &inputs)
    {
        ChaiScriptTargetBuilderApi scriptTargetBuilder(preparedTemplate.originPositions);
        auto old_state = m_chai.get_state();

        defineInputs(inputs);
        defineTemplateApi(scriptTargetBuilder);

        try {
            auto resultValue = m_chai.eval(preparedTemplate.script.toStdString(),
                                           chaiscript::exception_specification<const std::exception &>());
        } catch (const chaiscript::exception::eval_error &error) {
            const int line = error.start_position.line;
            const int column = error.start_position.column;
            FileLineColumnPositionList position {{ SourceMap::getOriginalPositionFromGenerated(preparedTemplate.sourceMap, {line, column}) }};
            const QString text = "Eval Error: " + QString::fromLatin1(error.what());
            m_messageHandler->scriptMessage(MessageType::Error, position, text);
        } catch (const chaiscript::exception::bad_boxed_cast &e) {
            const QString text = "Bad Boxed Cast: " + QString::fromLatin1(e.what());
            m_messageHandler->message(MessageType::Error, text);
        } catch (const std::exception &e) {
            const QString text = "Exception: " + QString::fromLatin1(e.what());
            m_messageHandler->message(MessageType::Error, text);
        }

        m_chai.set_state(old_state);

        const auto sourceMapText = scriptTargetBuilder.build();
        return { sourceMapText.sourceMap, sourceMapText.text };
    }

    //    void showSyntaxError(QScriptSyntaxCheckResult checkResult, const PreparedTemplate &preparedTemplate)
    //    {
    //        const int line = checkResult.errorLineNumber();
    //        const int column = checkResult.errorColumnNumber();
    //        FileLineColumnPositionList position {{ SourceMap::getOriginalPositionFromGenerated(preparedTemplate.sourceMap, {line, column}) }};
    //        const QString text = "Syntax Error: " + checkResult.errorMessage();
    //        m_messageHandler->scriptMessage(MessageType::Error, position, text);
    //    }

    PreparedTemplateBuilder createPreparedBuilder() {
        return { m_messageHandler, m_textLoader };
    }

private:
    //    void showException(QScriptValue resultValue, const PreparedTemplate &preparedTemplate)
    //    {
    //        const QStringList backtrace = m_chai.uncaughtExceptionBacktrace();
    //        auto positionStack = generateExceptionCallerStack(preparedTemplate, backtrace);
    //        const int line = m_chai.uncaughtExceptionLineNumber();
    //        const int column = 1; // TODO: use agent and stack!
    //        positionStack.insert(positionStack.begin(), SourceMap::getOriginalPositionFromGenerated(preparedTemplate.sourceMap, {line, column}));
    //        const QString text = "Uncaught Exception: " + resultValue.toString();
    //        m_messageHandler->scriptMessage(MessageType::Error, positionStack, text);
    //    }

    void defineQVariantCasts()
    {
        m_chai.eval(R"CHAISCRIPT(
def for_each_with_index(container, func) {
  for (var i = 0; i < container.size(); ++i) {
    func(container[i], i);
  }
}
def to_string(void) {
  ""
}
                       )CHAISCRIPT"
                , chaiscript::Exception_Handler(), "twofold prelude");

        m_chai.add(chaiscript::user_type<QVariant>(), "QVariant");
        m_chai.add(chaiscript::type_conversion<QVariant, int>([](const QVariant& v){return v.toInt();}));
        m_chai.add(chaiscript::type_conversion<QVariant, float>([](const QVariant& v){return v.toFloat();}));
        m_chai.add(chaiscript::type_conversion<QVariant, bool>([](const QVariant& v){return v.toBool();}));

        m_chai.add(chaiscript::type_conversion<QVariant, std::vector<QVariant> >([](const QVariant& v){
            std::vector<QVariant> r;
            const auto seq = v.value<QSequentialIterable>();
            r.reserve(1 + seq.size());
            for (const auto &e : seq) r.push_back(e);
            return r;
        }));

        m_chai.add(chaiscript::fun([](const QVariant* v){
            return v->toString().toStdString();
        }), "to_string");
//        m_chai.add(chaiscript::fun< std::string (void) >([](void){
//            return "";
//        }), "to_string");

        m_chai.add(chaiscript::fun([](const QVariant* v, bool x){
            return v->toBool() == x;
        }), "==");
        m_chai.add(chaiscript::fun([](const QVariant* v, const std::string &x){
            return v->toString().toStdString() == x;
        }), "==");

        m_chai.add(chaiscript::fun([](const QVariant* v, const std::string& k){
            if (v->canConvert(QMetaType::QObjectStar)) {
                const auto* o = v->value<QObject*>();
                return o->property( k.c_str() );
            }
            else if (v->canConvert(QMetaType::QVariantHash)) {
                const auto& a = v->value<QAssociativeIterable>();
                return a.value(QString::fromStdString(k));
            }
            throw std::range_error("unknown type");
        }), "method_missing");

        m_chai.add(chaiscript::fun([](const QVariant* v, int index)->QVariant{
            if (v->canConvert(QMetaType::QVariantList)) {
                const auto& s = v->value<QSequentialIterable>();
                if (index >= s.size())
                    throw std::range_error("index out of range");

                return s.at(index);
            }
            throw std::range_error("unknown type");
        }), "[]");

        m_chai.add(chaiscript::user_type<QObject>(), "QObject");
        m_chai.add(chaiscript::fun([](const QObject* o, const std::string& k){
            return o->property( k.c_str() );
        }), "method_missing");

        m_chai.add(chaiscript::user_type<QString>(), "QString");
        m_chai.add(chaiscript::type_conversion<std::string, QString>([](const std::string& v){return QString::fromStdString(v);}));

    }

    void defineTemplateApi(ChaiScriptTargetBuilderApi &templateApi)
    {
        auto module = std::make_shared<chaiscript::Module>();

        chaiscript::utility::add_class<ChaiScriptTargetBuilderApi>(*module,
                                                                   "TwofoldTemplate", {}, {
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::append), "append" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::newLine), "newLine" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::pushIndentation), "pushIndentation" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::popIndentation), "popIndentation" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::indentPart), "indentPart" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::pushPartIndent), "pushPartIndent" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::popPartIndent), "popPartIndent" },
                                                                   }
                                                                   );

        m_chai.add(module);
        m_chai.add_global(chaiscript::var(&templateApi), "_template");
    }

    void defineInputs(const Engine::Context &inputs)
    {
        for (const auto &v : inputs) {
            m_chai.add_global(v.second, v.first);
        }
    }

    MessageHandlerPtr m_messageHandler;
    TextLoaderPtr m_textLoader;
    chaiscript::ChaiScript m_chai;
};

Engine::Engine(MessageHandlerPtr messageHandler, TextLoaderPtr textLoader)
    : m_private(new Private(messageHandler, textLoader))
{
}

Engine::Engine(TextLoaderPtr textLoader, MessageHandlerPtr messageHandler)
    : Engine(messageHandler, textLoader)
{

}

void Engine::showTemplateSyntaxErrors(const PreparedTemplate &) const
{
    //    auto checkResult = QScriptEngine::checkSyntax(preparedTemplate.script);
    //    if (checkResult.state() == QScriptSyntaxCheckResult::Error)
    //        m_private->showSyntaxError(checkResult, preparedTemplate);
}

Target Engine::exec(const PreparedTemplate &preparedTemplate, const Context &inputs)
{
    return m_private->execPrepared(preparedTemplate, inputs);
}

PreparedTemplate Engine::prepare(const QString &templateName) const
{
    auto prepared = m_private->createPreparedBuilder().build(templateName);
    this->showTemplateSyntaxErrors(prepared);
    return prepared;
}

Target Engine::execTemplateName(const QString &templateName, const Context &inputs)
{
    auto prepared = this->prepare(templateName);
    return this->exec(prepared, inputs);
}

void Engine::PrivateDeleter::operator()(Engine::Private *p) const
{
    delete p;
}

} // namespace Twofold
<commit_msg>* commented out unused function<commit_after>/* Twofold-ChaiScript
 * (C) Copyright 2015 HicknHack Software GmbH
 *
 * The original code can be found at:
 *     https://github.com/arBmind/Twofold-ChaiScript
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "Engine.h"

#include "Twofold/intern/ChaiScriptTargetBuilderApi.h"

#include "Twofold/intern/QStringHelper.h"
#include "Twofold/intern/find_last.h"

#include <chaiscript/chaiscript.hpp>
#include <chaiscript/utility/utility.hpp>

#include <QVector>

#include <vector>

namespace Twofold {
namespace intern {
chaiscript::ModulePtr chaiscript_stdlib();
} // namespace intern

using namespace intern;

namespace {

//FileLineColumnPositionList generateExceptionCallerStack(const PreparedTemplate &preparedTemplate, const QStringList &backtrace)
//{
//    FileLineColumnPositionList callerStack;
//    for (const auto& traceLine : backtrace) {
//        // traceline format: "<function>() at <line>"
//        auto begin = traceLine.begin();
//        const auto end = traceLine.end();

//        begin = find_last(begin, end, QChar(' '));
//        QString lineString = toQString(begin, end);

//        bool convertSuccesful = false;
//        const int line = lineString.toInt(&convertSuccesful);
//        const int column = 1;
//        if (convertSuccesful) {
//            const auto position = SourceMap::getOriginalPositionFromGenerated(preparedTemplate.sourceMap, {line, column});
//            callerStack.push_back(position);
//        }
//    }
//    return callerStack;
//}

} // namespace

class Engine::Private
{
public:
    Private(MessageHandlerPtr messageHandler, TextLoaderPtr textLoader)
        : m_messageHandler(messageHandler)
        , m_textLoader(textLoader)
        , m_chai(chaiscript_stdlib())
    {
        defineQVariantCasts();
    }

    Target execPrepared(const PreparedTemplate &preparedTemplate, const Engine::Context &inputs)
    {
        ChaiScriptTargetBuilderApi scriptTargetBuilder(preparedTemplate.originPositions);
        auto old_state = m_chai.get_state();

        defineInputs(inputs);
        defineTemplateApi(scriptTargetBuilder);

        try {
            auto resultValue = m_chai.eval(preparedTemplate.script.toStdString(),
                                           chaiscript::exception_specification<const std::exception &>());
        } catch (const chaiscript::exception::eval_error &error) {
            const int line = error.start_position.line;
            const int column = error.start_position.column;
            FileLineColumnPositionList position {{ SourceMap::getOriginalPositionFromGenerated(preparedTemplate.sourceMap, {line, column}) }};
            const QString text = "Eval Error: " + QString::fromLatin1(error.what());
            m_messageHandler->scriptMessage(MessageType::Error, position, text);
        } catch (const chaiscript::exception::bad_boxed_cast &e) {
            const QString text = "Bad Boxed Cast: " + QString::fromLatin1(e.what());
            m_messageHandler->message(MessageType::Error, text);
        } catch (const std::exception &e) {
            const QString text = "Exception: " + QString::fromLatin1(e.what());
            m_messageHandler->message(MessageType::Error, text);
        }

        m_chai.set_state(old_state);

        const auto sourceMapText = scriptTargetBuilder.build();
        return { sourceMapText.sourceMap, sourceMapText.text };
    }

    //    void showSyntaxError(QScriptSyntaxCheckResult checkResult, const PreparedTemplate &preparedTemplate)
    //    {
    //        const int line = checkResult.errorLineNumber();
    //        const int column = checkResult.errorColumnNumber();
    //        FileLineColumnPositionList position {{ SourceMap::getOriginalPositionFromGenerated(preparedTemplate.sourceMap, {line, column}) }};
    //        const QString text = "Syntax Error: " + checkResult.errorMessage();
    //        m_messageHandler->scriptMessage(MessageType::Error, position, text);
    //    }

    PreparedTemplateBuilder createPreparedBuilder() {
        return { m_messageHandler, m_textLoader };
    }

private:
    //    void showException(QScriptValue resultValue, const PreparedTemplate &preparedTemplate)
    //    {
    //        const QStringList backtrace = m_chai.uncaughtExceptionBacktrace();
    //        auto positionStack = generateExceptionCallerStack(preparedTemplate, backtrace);
    //        const int line = m_chai.uncaughtExceptionLineNumber();
    //        const int column = 1; // TODO: use agent and stack!
    //        positionStack.insert(positionStack.begin(), SourceMap::getOriginalPositionFromGenerated(preparedTemplate.sourceMap, {line, column}));
    //        const QString text = "Uncaught Exception: " + resultValue.toString();
    //        m_messageHandler->scriptMessage(MessageType::Error, positionStack, text);
    //    }

    void defineQVariantCasts()
    {
        m_chai.eval(R"CHAISCRIPT(
def for_each_with_index(container, func) {
  for (var i = 0; i < container.size(); ++i) {
    func(container[i], i);
  }
}
def to_string(void) {
  ""
}
                       )CHAISCRIPT"
                , chaiscript::Exception_Handler(), "twofold prelude");

        m_chai.add(chaiscript::user_type<QVariant>(), "QVariant");
        m_chai.add(chaiscript::type_conversion<QVariant, int>([](const QVariant& v){return v.toInt();}));
        m_chai.add(chaiscript::type_conversion<QVariant, float>([](const QVariant& v){return v.toFloat();}));
        m_chai.add(chaiscript::type_conversion<QVariant, bool>([](const QVariant& v){return v.toBool();}));

        m_chai.add(chaiscript::type_conversion<QVariant, std::vector<QVariant> >([](const QVariant& v){
            std::vector<QVariant> r;
            const auto seq = v.value<QSequentialIterable>();
            r.reserve(1 + seq.size());
            for (const auto &e : seq) r.push_back(e);
            return r;
        }));

        m_chai.add(chaiscript::fun([](const QVariant* v){
            return v->toString().toStdString();
        }), "to_string");
//        m_chai.add(chaiscript::fun< std::string (void) >([](void){
//            return "";
//        }), "to_string");

        m_chai.add(chaiscript::fun([](const QVariant* v, bool x){
            return v->toBool() == x;
        }), "==");
        m_chai.add(chaiscript::fun([](const QVariant* v, const std::string &x){
            return v->toString().toStdString() == x;
        }), "==");

        m_chai.add(chaiscript::fun([](const QVariant* v, const std::string& k){
            if (v->canConvert(QMetaType::QObjectStar)) {
                const auto* o = v->value<QObject*>();
                return o->property( k.c_str() );
            }
            else if (v->canConvert(QMetaType::QVariantHash)) {
                const auto& a = v->value<QAssociativeIterable>();
                return a.value(QString::fromStdString(k));
            }
            throw std::range_error("unknown type");
        }), "method_missing");

        m_chai.add(chaiscript::fun([](const QVariant* v, int index)->QVariant{
            if (v->canConvert(QMetaType::QVariantList)) {
                const auto& s = v->value<QSequentialIterable>();
                if (index >= s.size())
                    throw std::range_error("index out of range");

                return s.at(index);
            }
            throw std::range_error("unknown type");
        }), "[]");

        m_chai.add(chaiscript::user_type<QObject>(), "QObject");
        m_chai.add(chaiscript::fun([](const QObject* o, const std::string& k){
            return o->property( k.c_str() );
        }), "method_missing");

        m_chai.add(chaiscript::user_type<QString>(), "QString");
        m_chai.add(chaiscript::type_conversion<std::string, QString>([](const std::string& v){return QString::fromStdString(v);}));

    }

    void defineTemplateApi(ChaiScriptTargetBuilderApi &templateApi)
    {
        auto module = std::make_shared<chaiscript::Module>();

        chaiscript::utility::add_class<ChaiScriptTargetBuilderApi>(*module,
                                                                   "TwofoldTemplate", {}, {
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::append), "append" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::newLine), "newLine" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::pushIndentation), "pushIndentation" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::popIndentation), "popIndentation" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::indentPart), "indentPart" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::pushPartIndent), "pushPartIndent" },
                                                                       { chaiscript::fun(&ChaiScriptTargetBuilderApi::popPartIndent), "popPartIndent" },
                                                                   }
                                                                   );

        m_chai.add(module);
        m_chai.add_global(chaiscript::var(&templateApi), "_template");
    }

    void defineInputs(const Engine::Context &inputs)
    {
        for (const auto &v : inputs) {
            m_chai.add_global(v.second, v.first);
        }
    }

    MessageHandlerPtr m_messageHandler;
    TextLoaderPtr m_textLoader;
    chaiscript::ChaiScript m_chai;
};

Engine::Engine(MessageHandlerPtr messageHandler, TextLoaderPtr textLoader)
    : m_private(new Private(messageHandler, textLoader))
{
}

Engine::Engine(TextLoaderPtr textLoader, MessageHandlerPtr messageHandler)
    : Engine(messageHandler, textLoader)
{

}

void Engine::showTemplateSyntaxErrors(const PreparedTemplate &) const
{
    //    auto checkResult = QScriptEngine::checkSyntax(preparedTemplate.script);
    //    if (checkResult.state() == QScriptSyntaxCheckResult::Error)
    //        m_private->showSyntaxError(checkResult, preparedTemplate);
}

Target Engine::exec(const PreparedTemplate &preparedTemplate, const Context &inputs)
{
    return m_private->execPrepared(preparedTemplate, inputs);
}

PreparedTemplate Engine::prepare(const QString &templateName) const
{
    auto prepared = m_private->createPreparedBuilder().build(templateName);
    this->showTemplateSyntaxErrors(prepared);
    return prepared;
}

Target Engine::execTemplateName(const QString &templateName, const Context &inputs)
{
    auto prepared = this->prepare(templateName);
    return this->exec(prepared, inputs);
}

void Engine::PrivateDeleter::operator()(Engine::Private *p) const
{
    delete p;
}

} // namespace Twofold
<|endoftext|>


<commit_before>#include "TextInputWidget.hpp"
#include <iostream>

gsf::TextInputWidget::Ptr gsf::TextInputWidget::create(sf::Font &font)
{
    Ptr widget{ std::make_unique<TextInputWidget>(font) };
    return widget;
}

gsf::TextInputWidget::Ptr gsf::TextInputWidget::create(float width, float height,
        sf::Font &font)
{
    Ptr widget{ std::make_unique<TextInputWidget>(width, height, font) };
    return widget;
}

gsf::TextInputWidget::TextInputWidget(sf::Font &font)
: Widget{ }
//, m_text{ "", font, 12, sf::Color::Black }
, m_text{ nullptr }
, m_font{ font }
, m_charSize{ 12 }
, m_isEditable{ true }
, m_cursor{ "|", font, m_charSize }
, m_cursorColor{ sf::Color::Black }
, m_scrollable{ nullptr }
, m_acceptNewLines{ true }
, m_isFocused{ false }
, m_cursorPos{ 0 }
, m_lBreaksBefCur{ 0 }
, m_isCursorShown{ true }
, m_blinkFreq{ 0.8f }
, m_lastBlinkTime{ 0.f }
, m_whiteListChars{ L"" }
, m_blackListChars{ L"" }
, m_minBreakCharCnt{ 0 }
{
    init();
}
gsf::TextInputWidget::TextInputWidget(float width, float height,
        sf::Font &font)
: Widget{ width, height }
//, m_text{ "", font, 12, sf::Color::Black }
, m_text{ nullptr }
, m_font{ font }
, m_charSize{ 12 }
, m_isEditable{ true }
, m_cursor{ "|", font, m_charSize }
, m_cursorColor{ sf::Color::Black }
, m_scrollable{ nullptr }
, m_acceptNewLines{ true }
, m_isFocused{ false }
, m_cursorPos{ 0 }
, m_lBreaksBefCur{ 0 }
, m_isCursorShown{ true }
, m_blinkFreq{ 0.8f }
, m_lastBlinkTime{ 0.f }
, m_whiteListChars{ L"" }
, m_blackListChars{ L"" }
, m_minBreakCharCnt{ 0 }
{
    init();
}

void gsf::TextInputWidget::init()
{
    std::unique_ptr<TextWidget> text{
        std::make_unique<TextWidget>("", m_font, m_charSize, sf::Color::Black) };
    std::unique_ptr<ScrollableWidget> scrollable{
        std::make_unique<ScrollableWidget>(
                getWidth(),
                getHeight()) };
    m_scrollable = scrollable.get();
    m_text = text.get();
    scrollable->setBackgroundColor(sf::Color::Transparent);
    scrollable->attachChild(std::move(text));
    // Change content area so that the scrollbar fits in the TextInputWidget when
    // necassary.
    scrollable->setOnVerticalScrollNeededChangedListener(
            [](Widget* widget, bool isNeeded)
            {
                // Vertical Scrollbar is needed so we reduce the width of the content
                // area, so that the scrollbar fits in the TextInputWidget
                if (isNeeded)
                {
                    widget->setWidth(widget->getWidth()
                            - ScrollableWidget::SCROLLBAR_THICKNESS);
                }
                // Vertical Scrollbar is no longer so we can make the
                // reductoion undone
                else
                {
                    widget->setWidth(widget->getWidth()
                            + ScrollableWidget::SCROLLBAR_THICKNESS);
                }
            });
    attachChild(std::move(scrollable));
    m_cursor.setFillColor(m_cursorColor);
    setOutlineThickness(4.f);
}

void gsf::TextInputWidget::setCursorColor(sf::Color color)
{
    m_cursorColor = color;
    m_cursor.setFillColor(color);
}

sf::Color gsf::TextInputWidget::getCursorColor() const
{
    return m_cursorColor;
}

void gsf::TextInputWidget::setIsEditable(bool isEditable)
{
    m_isEditable = isEditable;
}

bool gsf::TextInputWidget::isEditable() const
{
    return m_isEditable;
}

void gsf::TextInputWidget::setText(const std::wstring &text)
{
    m_currentText = text;
    m_text->setText(m_currentText);
    // Move cursor to end of text
    m_cursorPos = m_currentText.size();
    // Adjust text so that it fits the scrollbar when horizontal scrolling is disabled
    adjustShownText();
    m_scrollable->recalculateScroll();
    m_scrollable->scrollToBottom();
    m_scrollable->scrollToLeft();
}

std::wstring gsf::TextInputWidget::getText() const
{
    //return m_text->getText().toWideString();
    return m_currentText;
}

void gsf::TextInputWidget::setCharacterSize(const unsigned int size)
{
    m_text->setCharacterSize(size);
    m_charSize = size;
    m_cursor.setCharacterSize(size);
}

unsigned int gsf::TextInputWidget::getCharacterSize() const
{
    return m_charSize;
}

void gsf::TextInputWidget::setTextColor(const sf::Color color)
{
    m_text->setTextColor(color);
}

sf::Color gsf::TextInputWidget::getTextColor() const
{
    return m_text->getTextColor();
}

void gsf::TextInputWidget::setIsNewLineAccepted(bool isAccepted)
{
    m_acceptNewLines = isAccepted;
}

bool gsf::TextInputWidget::getIsNewLineAccepted() const
{
    return m_acceptNewLines;
}

bool gsf::TextInputWidget::isFocused() const
{
    return m_isFocused;
}

void gsf::TextInputWidget::setIsVerticalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsVerticalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isVerticalScrollEnabled() const
{
    return m_scrollable->isVerticalScrollEnabled();
}

void gsf::TextInputWidget::setIsHorizontalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsHorizontalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isHorizontalScrollEnabled() const
{
    return m_scrollable->isHorizontalScrollEnabled();
}

void gsf::TextInputWidget::setIsVerticalScrollbarDrawn(bool isDrawn)
{
    m_scrollable->setIsVerticalScrollbarDrawn(isDrawn);
}

void gsf::TextInputWidget::setIsHorizontalScrollbarDrawn(bool isDrawn)
{
    m_scrollable->setIsHorizontalScrollbarDrawn(isDrawn);
}

std::wstring gsf::TextInputWidget::getBlackListChars() const
{
    return m_blackListChars;
}

void gsf::TextInputWidget::setBlackListChars(std::wstring chars)
{
    m_blackListChars = chars;
}

std::wstring gsf::TextInputWidget::getWhiteListChars() const
{
    return m_whiteListChars;
}

void gsf::TextInputWidget::setWhiteListChars(std::wstring chars)
{
    m_whiteListChars = chars;
}

void gsf::TextInputWidget::adjustShownText()
{
    if (!m_scrollable->isHorizontalScrollEnabled() && m_currentText.size() > 0)
    {
        m_lBreaksBefCur = 0;
        m_lBreakIndexes.clear();
        std::wstring shownString{ L"" };
        // The chars which are in the actual line
        unsigned int charCntLine{ 0 };
        // The total width of all chars in the current line
        float lineWidth{ 0.f };
        for (unsigned int i{ 0 }; i < m_currentText.size(); i++)
        {
            wchar_t c{ m_currentText[i] };
            // If we have a new line as char we can set the lineWidth and charCntLine
            // to 0 because there is no need to handle the chars in this line
            // (It is already handled by user width the new line char)
            if (c == '\n')
            {
                lineWidth = 0.f;
                charCntLine = 0;
                shownString += c;
                continue;
            }
            // Width of the current char
            float cWidth{ m_text->getWidthAndHeightOfChar(c).x };
            lineWidth += cWidth;
            // When Text is out of scrollable widget, we have to add a new line
            if (lineWidth > m_scrollable->getWidth())
            {
                if (i < m_cursorPos)
                {
                    // We have to increase the "line breaks befor cursor" counter
                    // so we add the cursor later on the right position
                    m_lBreaksBefCur++;
                }
                //shownString += m_currentText.substr(i - charCntLine, charCntLine);
                // Add new line
                shownString += L"\n";
                // Store the position (of the shown text)
                // where the new line was added
                m_lBreakIndexes.push_back(i + 1);
                // add the char with which the line was to wide in the new line
                shownString += c;
                // We have added the char c in the new line,
                // so we have now 1 char in the current line
                charCntLine = 1;
                lineWidth = cWidth;
            }
            else
            {
                charCntLine++;
                shownString += c;
            }
        }
        m_shownText = shownString;
        m_text->setText(m_shownText);
    }
}

void gsf::TextInputWidget::resetCursorStatus()
{
    m_lastBlinkTime = 0.f;
    m_isCursorShown = true;
}

unsigned int gsf::TextInputWidget::getAddedLineBreaksUpToIndex
    (unsigned int index) const
{
    unsigned int cnt{ 0 };

    for (unsigned int lBreakIndex : m_lBreakIndexes)
    {
        if (lBreakIndex < index)
        {
            cnt++;
        }
        else
        {
            return cnt;
        }
    }
    return cnt;
}

bool gsf::TextInputWidget::handleEventCurrentAfterChildren(sf::Event &event,
        const sf::RenderTarget &target)
{

    bool handled{ Widget::handleEventCurrentAfterChildren(event, target) };
    if (!m_isEditable)
    {
        // Nothing to do
        return handled;
    }

    //bool handled{ ChildWidget::handleEvent(event) };/*||
      //  m_scrollable->handleEventWidget(event) };*/
    // Check if actual Widget is focused
    if (event.type == sf::Event::MouseButtonPressed)
    {
        sf::Vector2f mousePos{ target.mapPixelToCoords({ event.mouseButton.x,
            event.mouseButton.y }) };
        sf::Vector2f localPos{ convertToLocalPoint(mousePos) };

        bool isMouseInShownArea{ getShownArea().contains(mousePos) };
        bool intersecting{ isIntersecting(mousePos) };
        if (isMouseInShownArea && intersecting)
        {
            m_isFocused = true;
            handled = true;
            // Put cursor to clicked postion
            // Get the index of the char where the mouse has clicked
            int clickedCharIndex{ m_text->findIndexOfCharOnPos(localPos) };
            // Clicked on a char?
            if (clickedCharIndex > -1)
            {
                // The index is the index of m_shownText, but we need the index of
                // the char in m_currentText, so we have to remove the automatic
                // added line breaks.
                unsigned int autoAddedLineBreaks{
                    getAddedLineBreaksUpToIndex(clickedCharIndex) };
                m_cursorPos = clickedCharIndex - autoAddedLineBreaks;
                m_lBreaksBefCur = autoAddedLineBreaks;
            }
        }
        else
        {
            m_isFocused = false;
        }
    }
    if (event.type == sf::Event::KeyPressed && m_isFocused)
    {
        switch (event.key.code)
        {
        case sf::Keyboard::Left:
            if (m_cursorPos > 0)
            {
                m_cursorPos--;
            }
            // when cursor is moved it should be drawn so we reset its status
            resetCursorStatus();
            adjustShownText();
            //m_cursor.setPosition(
            //    m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
            return true;
        case sf::Keyboard::Right:
            if (m_cursorPos < m_currentText.length())
            {
                m_cursorPos++;
            }
            resetCursorStatus();
            adjustShownText();
            //m_cursor.setPosition
            //    (m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
            return true;
        default: break;
        }
    }
    // If Widget is focused and Text entered, handle entered text
    if (m_isFocused && event.type == sf::Event::TextEntered)
    {
        // To handle umlauts and other 'exotic' chars we use widestring
        // and wide char
        //std::wstring actualTxt{ m_text.getString().toWideString() };
        wchar_t c{ static_cast<wchar_t>(event.text.unicode) };
        std::cout << "Entered: " << c << std::endl;
        switch (c)
        {
        // Backspace
        case 8:
            if (m_currentText.length() > 0)
            {
                // Remove chars right of cursor when there are chars
                if (m_cursorPos > 0 && m_cursorPos < m_currentText.length())
                {
                    m_currentText.erase(m_cursorPos - 1, 1);
                    m_cursorPos--;
                }
                // When cursos is at the end of the text, p
                // place cursor behind char which we want to delete,
                else if (m_cursorPos == m_currentText.length())
                {
                    // Delete last char
                    m_currentText.pop_back();
                    m_cursorPos--;
                }
            }
            break;
        // Delete Pressed
        case 127:
            if (m_currentText.length() > 0 &&
                    m_cursorPos < m_currentText.length())
            {
                m_currentText.erase(m_cursorPos, 1);
            }
            break;
        // Enter key
        case 13:
            // Dont add new line, when new lines are not accepted
            if (!m_acceptNewLines)
            {
                return false;
            }
            m_currentText.insert(m_cursorPos, L"\n"); m_cursorPos++;
            break;
        // Add char to text
        default:
            // If there are white listed chars specified, check if char is in it.
            // If not return
            if (m_whiteListChars.length() > 0 &&
                    m_whiteListChars.find(c) == std::wstring::npos)
            {
                return false;
            }
            // Check if char is black listed, if so return
            if(m_blackListChars.find(c) != std::wstring::npos)
            {
                return false;
            }
            m_currentText.insert(m_cursorPos, std::wstring() + c);
                 m_cursorPos++;
        }
        resetCursorStatus();
        m_shownText = m_currentText;
        m_text->setText(m_shownText);
        adjustShownText();
        //m_cursor.setPosition
            //(m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
        m_scrollable->recalculateScroll();
        m_scrollable->scrollToRight();
        m_scrollable->scrollToBottom();
        return true;
    }
    return handled;
}

void gsf::TextInputWidget::updateCurrentAfterChildren(float dt)
{
    if (!m_isEditable)
    {
        // Nothing to do
        return;
    }

    // Update cursor stuff
    m_lastBlinkTime += dt;
    if (m_lastBlinkTime >= m_blinkFreq)
    {
        m_isCursorShown = !m_isCursorShown;
        m_lastBlinkTime = 0.f;
    }

    m_cursor.setPosition(
            m_text->findGlobalCharacterPos(m_cursorPos + m_lBreaksBefCur));
    //std::wstring text{ m_currentText };
    //std::wstring text{ m_shownText };
    //m_text->setText(text);
}

void gsf::TextInputWidget::drawCurrentAfterChildren(sf::RenderTarget &target,
                    sf::RenderStates states, sf::View defaultView) const
{
    // Draw cursor after children, so that children are not drawn over cursor
    if (m_isCursorShown && m_isEditable)
    {
        target.draw(m_cursor, states);
    }
}
<commit_msg>Move cursor in TextInputWidget to end f a click was not on a char<commit_after>#include "TextInputWidget.hpp"
#include <iostream>

gsf::TextInputWidget::Ptr gsf::TextInputWidget::create(sf::Font &font)
{
    Ptr widget{ std::make_unique<TextInputWidget>(font) };
    return widget;
}

gsf::TextInputWidget::Ptr gsf::TextInputWidget::create(float width, float height,
        sf::Font &font)
{
    Ptr widget{ std::make_unique<TextInputWidget>(width, height, font) };
    return widget;
}

gsf::TextInputWidget::TextInputWidget(sf::Font &font)
: Widget{ }
//, m_text{ "", font, 12, sf::Color::Black }
, m_text{ nullptr }
, m_font{ font }
, m_charSize{ 12 }
, m_isEditable{ true }
, m_cursor{ "|", font, m_charSize }
, m_cursorColor{ sf::Color::Black }
, m_scrollable{ nullptr }
, m_acceptNewLines{ true }
, m_isFocused{ false }
, m_cursorPos{ 0 }
, m_lBreaksBefCur{ 0 }
, m_isCursorShown{ true }
, m_blinkFreq{ 0.8f }
, m_lastBlinkTime{ 0.f }
, m_whiteListChars{ L"" }
, m_blackListChars{ L"" }
, m_minBreakCharCnt{ 0 }
{
    init();
}
gsf::TextInputWidget::TextInputWidget(float width, float height,
        sf::Font &font)
: Widget{ width, height }
//, m_text{ "", font, 12, sf::Color::Black }
, m_text{ nullptr }
, m_font{ font }
, m_charSize{ 12 }
, m_isEditable{ true }
, m_cursor{ "|", font, m_charSize }
, m_cursorColor{ sf::Color::Black }
, m_scrollable{ nullptr }
, m_acceptNewLines{ true }
, m_isFocused{ false }
, m_cursorPos{ 0 }
, m_lBreaksBefCur{ 0 }
, m_isCursorShown{ true }
, m_blinkFreq{ 0.8f }
, m_lastBlinkTime{ 0.f }
, m_whiteListChars{ L"" }
, m_blackListChars{ L"" }
, m_minBreakCharCnt{ 0 }
{
    init();
}

void gsf::TextInputWidget::init()
{
    std::unique_ptr<TextWidget> text{
        std::make_unique<TextWidget>("", m_font, m_charSize, sf::Color::Black) };
    std::unique_ptr<ScrollableWidget> scrollable{
        std::make_unique<ScrollableWidget>(
                getWidth(),
                getHeight()) };
    m_scrollable = scrollable.get();
    m_text = text.get();
    scrollable->setBackgroundColor(sf::Color::Transparent);
    scrollable->attachChild(std::move(text));
    // Change content area so that the scrollbar fits in the TextInputWidget when
    // necassary.
    scrollable->setOnVerticalScrollNeededChangedListener(
            [](Widget* widget, bool isNeeded)
            {
                // Vertical Scrollbar is needed so we reduce the width of the content
                // area, so that the scrollbar fits in the TextInputWidget
                if (isNeeded)
                {
                    widget->setWidth(widget->getWidth()
                            - ScrollableWidget::SCROLLBAR_THICKNESS);
                }
                // Vertical Scrollbar is no longer so we can make the
                // reductoion undone
                else
                {
                    widget->setWidth(widget->getWidth()
                            + ScrollableWidget::SCROLLBAR_THICKNESS);
                }
            });
    attachChild(std::move(scrollable));
    m_cursor.setFillColor(m_cursorColor);
    setOutlineThickness(4.f);
}

void gsf::TextInputWidget::setCursorColor(sf::Color color)
{
    m_cursorColor = color;
    m_cursor.setFillColor(color);
}

sf::Color gsf::TextInputWidget::getCursorColor() const
{
    return m_cursorColor;
}

void gsf::TextInputWidget::setIsEditable(bool isEditable)
{
    m_isEditable = isEditable;
}

bool gsf::TextInputWidget::isEditable() const
{
    return m_isEditable;
}

void gsf::TextInputWidget::setText(const std::wstring &text)
{
    m_currentText = text;
    m_text->setText(m_currentText);
    // Move cursor to end of text
    m_cursorPos = m_currentText.size();
    // Adjust text so that it fits the scrollbar when horizontal scrolling is disabled
    adjustShownText();
    m_scrollable->recalculateScroll();
    m_scrollable->scrollToBottom();
    m_scrollable->scrollToLeft();
}

std::wstring gsf::TextInputWidget::getText() const
{
    //return m_text->getText().toWideString();
    return m_currentText;
}

void gsf::TextInputWidget::setCharacterSize(const unsigned int size)
{
    m_text->setCharacterSize(size);
    m_charSize = size;
    m_cursor.setCharacterSize(size);
}

unsigned int gsf::TextInputWidget::getCharacterSize() const
{
    return m_charSize;
}

void gsf::TextInputWidget::setTextColor(const sf::Color color)
{
    m_text->setTextColor(color);
}

sf::Color gsf::TextInputWidget::getTextColor() const
{
    return m_text->getTextColor();
}

void gsf::TextInputWidget::setIsNewLineAccepted(bool isAccepted)
{
    m_acceptNewLines = isAccepted;
}

bool gsf::TextInputWidget::getIsNewLineAccepted() const
{
    return m_acceptNewLines;
}

bool gsf::TextInputWidget::isFocused() const
{
    return m_isFocused;
}

void gsf::TextInputWidget::setIsVerticalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsVerticalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isVerticalScrollEnabled() const
{
    return m_scrollable->isVerticalScrollEnabled();
}

void gsf::TextInputWidget::setIsHorizontalScrollEnabled(bool isEnabled)
{
    m_scrollable->setIsHorizontalScrollEnabled(isEnabled);
}

bool gsf::TextInputWidget::isHorizontalScrollEnabled() const
{
    return m_scrollable->isHorizontalScrollEnabled();
}

void gsf::TextInputWidget::setIsVerticalScrollbarDrawn(bool isDrawn)
{
    m_scrollable->setIsVerticalScrollbarDrawn(isDrawn);
}

void gsf::TextInputWidget::setIsHorizontalScrollbarDrawn(bool isDrawn)
{
    m_scrollable->setIsHorizontalScrollbarDrawn(isDrawn);
}

std::wstring gsf::TextInputWidget::getBlackListChars() const
{
    return m_blackListChars;
}

void gsf::TextInputWidget::setBlackListChars(std::wstring chars)
{
    m_blackListChars = chars;
}

std::wstring gsf::TextInputWidget::getWhiteListChars() const
{
    return m_whiteListChars;
}

void gsf::TextInputWidget::setWhiteListChars(std::wstring chars)
{
    m_whiteListChars = chars;
}

void gsf::TextInputWidget::adjustShownText()
{
    if (!m_scrollable->isHorizontalScrollEnabled() && m_currentText.size() > 0)
    {
        m_lBreaksBefCur = 0;
        m_lBreakIndexes.clear();
        std::wstring shownString{ L"" };
        // The chars which are in the actual line
        unsigned int charCntLine{ 0 };
        // The total width of all chars in the current line
        float lineWidth{ 0.f };
        for (unsigned int i{ 0 }; i < m_currentText.size(); i++)
        {
            wchar_t c{ m_currentText[i] };
            // If we have a new line as char we can set the lineWidth and charCntLine
            // to 0 because there is no need to handle the chars in this line
            // (It is already handled by user width the new line char)
            if (c == '\n')
            {
                lineWidth = 0.f;
                charCntLine = 0;
                shownString += c;
                continue;
            }
            // Width of the current char
            float cWidth{ m_text->getWidthAndHeightOfChar(c).x };
            lineWidth += cWidth;
            // When Text is out of scrollable widget, we have to add a new line
            if (lineWidth > m_scrollable->getWidth())
            {
                if (i < m_cursorPos)
                {
                    // We have to increase the "line breaks befor cursor" counter
                    // so we add the cursor later on the right position
                    m_lBreaksBefCur++;
                }
                //shownString += m_currentText.substr(i - charCntLine, charCntLine);
                // Add new line
                shownString += L"\n";
                // Store the position (of the shown text)
                // where the new line was added
                m_lBreakIndexes.push_back(i + 1);
                // add the char with which the line was to wide in the new line
                shownString += c;
                // We have added the char c in the new line,
                // so we have now 1 char in the current line
                charCntLine = 1;
                lineWidth = cWidth;
            }
            else
            {
                charCntLine++;
                shownString += c;
            }
        }
        m_shownText = shownString;
        m_text->setText(m_shownText);
    }
}

void gsf::TextInputWidget::resetCursorStatus()
{
    m_lastBlinkTime = 0.f;
    m_isCursorShown = true;
}

unsigned int gsf::TextInputWidget::getAddedLineBreaksUpToIndex
    (unsigned int index) const
{
    unsigned int cnt{ 0 };

    for (unsigned int lBreakIndex : m_lBreakIndexes)
    {
        if (lBreakIndex < index)
        {
            cnt++;
        }
        else
        {
            return cnt;
        }
    }
    return cnt;
}

bool gsf::TextInputWidget::handleEventCurrentAfterChildren(sf::Event &event,
        const sf::RenderTarget &target)
{

    bool handled{ Widget::handleEventCurrentAfterChildren(event, target) };
    if (!m_isEditable)
    {
        // Nothing to do
        return handled;
    }

    //bool handled{ ChildWidget::handleEvent(event) };/*||
      //  m_scrollable->handleEventWidget(event) };*/
    // Check if actual Widget is focused
    if (event.type == sf::Event::MouseButtonPressed)
    {
        sf::Vector2f mousePos{ target.mapPixelToCoords({ event.mouseButton.x,
            event.mouseButton.y }) };
        sf::Vector2f localPos{ convertToLocalPoint(mousePos) };

        bool isMouseInShownArea{ getShownArea().contains(mousePos) };
        bool intersecting{ isIntersecting(mousePos) };
        if (isMouseInShownArea && intersecting)
        {
            m_isFocused = true;
            handled = true;
            // Put cursor to clicked postion
            // Get the index of the char where the mouse has clicked
            int clickedCharIndex{ m_text->findIndexOfCharOnPos(localPos) };
            // Clicked on a char?
            if (clickedCharIndex > -1)
            {
                // The index is the index of m_shownText, but we need the index of
                // the char in m_currentText, so we have to remove the automatic
                // added line breaks.
                unsigned int autoAddedLineBreaks{
                    getAddedLineBreaksUpToIndex(clickedCharIndex) };
                m_cursorPos = clickedCharIndex - autoAddedLineBreaks;
                m_lBreaksBefCur = autoAddedLineBreaks;
            }
            // If there was no click on a char, move cursor to end
            else
            {

                m_cursorPos = m_shownText.length();
            }
        }
        else
        {
            m_isFocused = false;
        }
    }
    if (event.type == sf::Event::KeyPressed && m_isFocused)
    {
        switch (event.key.code)
        {
        case sf::Keyboard::Left:
            if (m_cursorPos > 0)
            {
                m_cursorPos--;
            }
            // when cursor is moved it should be drawn so we reset its status
            resetCursorStatus();
            adjustShownText();
            //m_cursor.setPosition(
            //    m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
            return true;
        case sf::Keyboard::Right:
            if (m_cursorPos < m_currentText.length())
            {
                m_cursorPos++;
            }
            resetCursorStatus();
            adjustShownText();
            //m_cursor.setPosition
            //    (m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
            return true;
        default: break;
        }
    }
    // If Widget is focused and Text entered, handle entered text
    if (m_isFocused && event.type == sf::Event::TextEntered)
    {
        // To handle umlauts and other 'exotic' chars we use widestring
        // and wide char
        //std::wstring actualTxt{ m_text.getString().toWideString() };
        wchar_t c{ static_cast<wchar_t>(event.text.unicode) };
        std::cout << "Entered: " << c << std::endl;
        switch (c)
        {
        // Backspace
        case 8:
            if (m_currentText.length() > 0)
            {
                // Remove chars right of cursor when there are chars
                if (m_cursorPos > 0 && m_cursorPos < m_currentText.length())
                {
                    m_currentText.erase(m_cursorPos - 1, 1);
                    m_cursorPos--;
                }
                // When cursos is at the end of the text, p
                // place cursor behind char which we want to delete,
                else if (m_cursorPos == m_currentText.length())
                {
                    // Delete last char
                    m_currentText.pop_back();
                    m_cursorPos--;
                }
            }
            break;
        // Delete Pressed
        case 127:
            if (m_currentText.length() > 0 &&
                    m_cursorPos < m_currentText.length())
            {
                m_currentText.erase(m_cursorPos, 1);
            }
            break;
        // Enter key
        case 13:
            // Dont add new line, when new lines are not accepted
            if (!m_acceptNewLines)
            {
                return false;
            }
            m_currentText.insert(m_cursorPos, L"\n"); m_cursorPos++;
            break;
        // Add char to text
        default:
            // If there are white listed chars specified, check if char is in it.
            // If not return
            if (m_whiteListChars.length() > 0 &&
                    m_whiteListChars.find(c) == std::wstring::npos)
            {
                return false;
            }
            // Check if char is black listed, if so return
            if(m_blackListChars.find(c) != std::wstring::npos)
            {
                return false;
            }
            m_currentText.insert(m_cursorPos, std::wstring() + c);
                 m_cursorPos++;
        }
        resetCursorStatus();
        m_shownText = m_currentText;
        m_text->setText(m_shownText);
        adjustShownText();
        //m_cursor.setPosition
            //(m_text->findCharacterPos(m_cursorPos + m_lBreaksBefCur));
        m_scrollable->recalculateScroll();
        m_scrollable->scrollToRight();
        m_scrollable->scrollToBottom();
        return true;
    }
    return handled;
}

void gsf::TextInputWidget::updateCurrentAfterChildren(float dt)
{
    if (!m_isEditable)
    {
        // Nothing to do
        return;
    }

    // Update cursor stuff
    m_lastBlinkTime += dt;
    if (m_lastBlinkTime >= m_blinkFreq)
    {
        m_isCursorShown = !m_isCursorShown;
        m_lastBlinkTime = 0.f;
    }

    m_cursor.setPosition(
            m_text->findGlobalCharacterPos(m_cursorPos + m_lBreaksBefCur));
    //std::wstring text{ m_currentText };
    //std::wstring text{ m_shownText };
    //m_text->setText(text);
}

void gsf::TextInputWidget::drawCurrentAfterChildren(sf::RenderTarget &target,
                    sf::RenderStates states, sf::View defaultView) const
{
    // Draw cursor after children, so that children are not drawn over cursor
    if (m_isCursorShown && m_isEditable)
    {
        target.draw(m_cursor, states);
    }
}
<|endoftext|>


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

#include "ComputeUserObjectsThread.h"
#include "Problem.h"
#include "SystemBase.h"
#include "ElementUserObject.h"
#include "ShapeElementUserObject.h"
#include "SideUserObject.h"
#include "ShapeSideUserObject.h"
#include "InternalSideUserObject.h"
#include "NodalUserObject.h"
#include "SwapBackSentinel.h"

#include "libmesh/numeric_vector.h"

ComputeUserObjectsThread::ComputeUserObjectsThread(FEProblemBase & problem,
                                                   SystemBase & sys,
                                                   const MooseObjectWarehouse<ElementUserObject> & elemental_user_objects,
                                                   const MooseObjectWarehouse<SideUserObject> & side_user_objects,
                                                   const MooseObjectWarehouse<InternalSideUserObject> & internal_side_user_objects) :
    ThreadedElementLoop<ConstElemRange>(problem),
    _soln(*sys.currentSolution()),
    _elemental_user_objects(elemental_user_objects),
    _side_user_objects(side_user_objects),
    _internal_side_user_objects(internal_side_user_objects)
{
}

// Splitting Constructor
ComputeUserObjectsThread::ComputeUserObjectsThread(ComputeUserObjectsThread & x, Threads::split) :
    ThreadedElementLoop<ConstElemRange>(x._fe_problem),
    _soln(x._soln),
    _elemental_user_objects(x._elemental_user_objects),
    _side_user_objects(x._side_user_objects),
    _internal_side_user_objects(x._internal_side_user_objects)
{
}

ComputeUserObjectsThread::~ComputeUserObjectsThread()
{
}

void
ComputeUserObjectsThread::subdomainChanged()
{
  std::set<MooseVariable *> needed_moose_vars;
  _elemental_user_objects.updateBlockVariableDependency(_subdomain, needed_moose_vars, _tid);
  _side_user_objects.updateBoundaryVariableDependency(needed_moose_vars, _tid);
  _internal_side_user_objects.updateBlockVariableDependency(_subdomain, needed_moose_vars, _tid);

  std::set<unsigned int> needed_mat_props;
  _elemental_user_objects.updateBlockMatPropDependency(_subdomain, needed_mat_props, _tid);
  _side_user_objects.updateBoundaryMatPropDependency(needed_mat_props, _tid);
  _internal_side_user_objects.updateBlockMatPropDependency(_subdomain, needed_mat_props, _tid);

  _elemental_user_objects.subdomainSetup(_subdomain, _tid);
  _side_user_objects.subdomainSetup(_tid);
  _internal_side_user_objects.subdomainSetup(_subdomain, _tid);

  _fe_problem.setActiveElementalMooseVariables(needed_moose_vars, _tid);
  _fe_problem.setActiveMaterialProperties(needed_mat_props, _tid);
  _fe_problem.prepareMaterials(_subdomain, _tid);
}

void
ComputeUserObjectsThread::onElement(const Elem * elem)
{
  _fe_problem.prepare(elem, _tid);
  _fe_problem.reinitElem(elem, _tid);

  // Set up Sentinel class so that, even if reinitMaterials() throws, we
  // still remember to swap back during stack unwinding.
  SwapBackSentinel sentinel(_fe_problem, &FEProblem::swapBackMaterials, _tid);
  _fe_problem.reinitMaterials(_subdomain, _tid);

  if (_elemental_user_objects.hasActiveBlockObjects(_subdomain, _tid))
  {
    const auto & objects = _elemental_user_objects.getActiveBlockObjects(_subdomain, _tid);
    for (const auto & uo : objects)
      uo->execute();
  }

  // UserObject Jacobians
  if (_fe_problem.currentlyComputingJacobian())
    if (_elemental_user_objects.hasActiveBlockObjects(_subdomain, _tid))
    {
      // Prepare shape functions for ShapeElementUserObjects
      std::vector<MooseVariable *> jacobian_moose_vars = _fe_problem.getUserObjectJacobianVariables(_tid);
      for (auto & jvar : jacobian_moose_vars)
      {
        unsigned int jvar_id = jvar->number();
        std::vector<dof_id_type> & dof_indices = jvar->dofIndices();

        _fe_problem.prepareShapes(jvar_id, _tid);

        const auto & e_objects = _elemental_user_objects.getActiveBlockObjects(_subdomain, _tid);
        for (const auto & uo : e_objects)
        {
          std::shared_ptr<ShapeElementUserObject> shape_element_uo = std::dynamic_pointer_cast<ShapeElementUserObject>(uo);
          if (shape_element_uo)
            shape_element_uo->executeJacobianWrapper(jvar_id, dof_indices);
        }
      }
    }
}

void
ComputeUserObjectsThread::onBoundary(const Elem *elem, unsigned int side, BoundaryID bnd_id)
{
  if (_side_user_objects.hasActiveBoundaryObjects(bnd_id, _tid))
  {
    _fe_problem.reinitElemFace(elem, side, bnd_id, _tid);

    // Set up Sentinel class so that, even if reinitMaterialsFace() throws, we
    // still remember to swap back during stack unwinding.
    SwapBackSentinel sentinel(_fe_problem, &FEProblem::swapBackMaterialsFace, _tid);
    _fe_problem.reinitMaterialsFace(_subdomain, _tid);
    _fe_problem.reinitMaterialsBoundary(bnd_id, _tid);

    _fe_problem.setCurrentBoundaryID(bnd_id);

    const auto & objects = _side_user_objects.getActiveBoundaryObjects(bnd_id, _tid);
    for (const auto & uo : objects)
      uo->execute();

    // UserObject Jacobians
    if (_fe_problem.currentlyComputingJacobian())
    {
      // Prepare shape functions for ShapeSideUserObjects
      std::vector<MooseVariable *> jacobian_moose_vars = _fe_problem.getUserObjectJacobianVariables(_tid);
      for (auto & jvar : jacobian_moose_vars)
      {
        unsigned int jvar_id = jvar->number();
        std::vector<dof_id_type> & dof_indices = jvar->dofIndices();

        _fe_problem.prepareFaceShapes(jvar_id, _tid);

        for (const auto & uo : objects)
        {
          std::shared_ptr<ShapeSideUserObject> shape_side_uo = std::dynamic_pointer_cast<ShapeSideUserObject>(uo);
          if (shape_side_uo)
            shape_side_uo->executeJacobianWrapper(jvar_id, dof_indices);
        }
      }
    }

    _fe_problem.setCurrentBoundaryID(Moose::INVALID_BOUNDARY_ID);
  }
}

void
ComputeUserObjectsThread::onInternalSide(const Elem *elem, unsigned int side)
{
  // Pointer to the neighbor we are currently working on.
  const Elem * neighbor = elem->neighbor(side);

  // Get the global id of the element and the neighbor
  const dof_id_type
    elem_id = elem->id(),
    neighbor_id = neighbor->id();

  if (_internal_side_user_objects.hasActiveBlockObjects(_subdomain, _tid))
  {
    if ((neighbor->active() && (neighbor->level() == elem->level()) && (elem_id < neighbor_id)) || (neighbor->level() < elem->level()))
    {
      _fe_problem.prepareFace(elem, _tid);
      _fe_problem.reinitNeighbor(elem, side, _tid);

      // Set up Sentinels so that, even if one of the reinitMaterialsXXX() calls throws, we
      // still remember to swap back during stack unwinding.
      SwapBackSentinel face_sentinel(_fe_problem, &FEProblem::swapBackMaterialsFace, _tid);
      _fe_problem.reinitMaterialsFace(elem->subdomain_id(), _tid);

      SwapBackSentinel neighbor_sentinel(_fe_problem, &FEProblem::swapBackMaterialsNeighbor, _tid);
      _fe_problem.reinitMaterialsNeighbor(neighbor->subdomain_id(), _tid);

      const auto & objects = _internal_side_user_objects.getActiveBlockObjects(_subdomain, _tid);
      for (const auto & uo : objects)
      {
        if (!uo->blockRestricted())
          uo->execute();

        else if (uo->hasBlocks(neighbor->subdomain_id()))
          uo->execute();
      }
    }
  }
}

void
ComputeUserObjectsThread::post()
{
  _fe_problem.clearActiveElementalMooseVariables(_tid);
  _fe_problem.clearActiveMaterialProperties(_tid);
}

void
ComputeUserObjectsThread::join(const ComputeUserObjectsThread & /*y*/)
{
}
<commit_msg>compute thread housekeeping<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "ComputeUserObjectsThread.h"
#include "Problem.h"
#include "SystemBase.h"
#include "ElementUserObject.h"
#include "ShapeElementUserObject.h"
#include "SideUserObject.h"
#include "ShapeSideUserObject.h"
#include "InternalSideUserObject.h"
#include "NodalUserObject.h"
#include "SwapBackSentinel.h"

#include "libmesh/numeric_vector.h"

ComputeUserObjectsThread::ComputeUserObjectsThread(
    FEProblemBase & problem, SystemBase & sys,
    const MooseObjectWarehouse<ElementUserObject> & elemental_user_objects,
    const MooseObjectWarehouse<SideUserObject> & side_user_objects,
    const MooseObjectWarehouse<InternalSideUserObject> & internal_side_user_objects)
  : ThreadedElementLoop<ConstElemRange>(problem),
    _soln(*sys.currentSolution()),
    _elemental_user_objects(elemental_user_objects),
    _side_user_objects(side_user_objects),
    _internal_side_user_objects(internal_side_user_objects)
{
}

// Splitting Constructor
ComputeUserObjectsThread::ComputeUserObjectsThread(ComputeUserObjectsThread & x, Threads::split)
  : ThreadedElementLoop<ConstElemRange>(x._fe_problem),
    _soln(x._soln),
    _elemental_user_objects(x._elemental_user_objects),
    _side_user_objects(x._side_user_objects),
    _internal_side_user_objects(x._internal_side_user_objects)
{
}

ComputeUserObjectsThread::~ComputeUserObjectsThread() {}

void
ComputeUserObjectsThread::subdomainChanged()
{
  std::set<MooseVariable *> needed_moose_vars;
  _elemental_user_objects.updateBlockVariableDependency(_subdomain, needed_moose_vars, _tid);
  _side_user_objects.updateBoundaryVariableDependency(needed_moose_vars, _tid);
  _internal_side_user_objects.updateBlockVariableDependency(_subdomain, needed_moose_vars, _tid);

  std::set<unsigned int> needed_mat_props;
  _elemental_user_objects.updateBlockMatPropDependency(_subdomain, needed_mat_props, _tid);
  _side_user_objects.updateBoundaryMatPropDependency(needed_mat_props, _tid);
  _internal_side_user_objects.updateBlockMatPropDependency(_subdomain, needed_mat_props, _tid);

  _elemental_user_objects.subdomainSetup(_subdomain, _tid);
  _side_user_objects.subdomainSetup(_tid);
  _internal_side_user_objects.subdomainSetup(_subdomain, _tid);

  _fe_problem.setActiveElementalMooseVariables(needed_moose_vars, _tid);
  _fe_problem.setActiveMaterialProperties(needed_mat_props, _tid);
  _fe_problem.prepareMaterials(_subdomain, _tid);
}

void
ComputeUserObjectsThread::onElement(const Elem * elem)
{
  _fe_problem.prepare(elem, _tid);
  _fe_problem.reinitElem(elem, _tid);

  // Set up Sentinel class so that, even if reinitMaterials() throws, we
  // still remember to swap back during stack unwinding.
  SwapBackSentinel sentinel(_fe_problem, &FEProblem::swapBackMaterials, _tid);
  _fe_problem.reinitMaterials(_subdomain, _tid);

  if (_elemental_user_objects.hasActiveBlockObjects(_subdomain, _tid))
  {
    const auto & objects = _elemental_user_objects.getActiveBlockObjects(_subdomain, _tid);
    for (const auto & uo : objects)
      uo->execute();
  }

  // UserObject Jacobians
  if (_fe_problem.currentlyComputingJacobian() &&
      _elemental_user_objects.hasActiveBlockObjects(_subdomain, _tid))
  {
    // Prepare shape functions for ShapeElementUserObjects
    std::vector<MooseVariable *> jacobian_moose_vars =
        _fe_problem.getUserObjectJacobianVariables(_tid);
    for (auto & jvar : jacobian_moose_vars)
    {
      unsigned int jvar_id = jvar->number();
      std::vector<dof_id_type> & dof_indices = jvar->dofIndices();

      _fe_problem.prepareShapes(jvar_id, _tid);

      const auto & e_objects = _elemental_user_objects.getActiveBlockObjects(_subdomain, _tid);
      for (const auto & uo : e_objects)
      {
        auto shape_element_uo = std::dynamic_pointer_cast<ShapeElementUserObject>(uo);
        if (shape_element_uo)
          shape_element_uo->executeJacobianWrapper(jvar_id, dof_indices);
      }
    }
  }
}

void
ComputeUserObjectsThread::onBoundary(const Elem * elem, unsigned int side, BoundaryID bnd_id)
{
  if (!_side_user_objects.hasActiveBoundaryObjects(bnd_id, _tid))
    return;

  _fe_problem.reinitElemFace(elem, side, bnd_id, _tid);

  // Set up Sentinel class so that, even if reinitMaterialsFace() throws, we
  // still remember to swap back during stack unwinding.
  SwapBackSentinel sentinel(_fe_problem, &FEProblem::swapBackMaterialsFace, _tid);
  _fe_problem.reinitMaterialsFace(_subdomain, _tid);
  _fe_problem.reinitMaterialsBoundary(bnd_id, _tid);

  _fe_problem.setCurrentBoundaryID(bnd_id);

  const auto & objects = _side_user_objects.getActiveBoundaryObjects(bnd_id, _tid);
  for (const auto & uo : objects)
    uo->execute();

  // UserObject Jacobians
  if (_fe_problem.currentlyComputingJacobian())
  {
    // Prepare shape functions for ShapeSideUserObjects
    std::vector<MooseVariable *> jacobian_moose_vars =
        _fe_problem.getUserObjectJacobianVariables(_tid);
    for (auto & jvar : jacobian_moose_vars)
    {
      unsigned int jvar_id = jvar->number();
      std::vector<dof_id_type> & dof_indices = jvar->dofIndices();

      _fe_problem.prepareFaceShapes(jvar_id, _tid);

      for (const auto & uo : objects)
      {
        auto shape_side_uo = std::dynamic_pointer_cast<ShapeSideUserObject>(uo);
        if (shape_side_uo)
          shape_side_uo->executeJacobianWrapper(jvar_id, dof_indices);
      }
    }
  }

  _fe_problem.setCurrentBoundaryID(Moose::INVALID_BOUNDARY_ID);
}

void
ComputeUserObjectsThread::onInternalSide(const Elem * elem, unsigned int side)
{
  // Pointer to the neighbor we are currently working on.
  const Elem * neighbor = elem->neighbor(side);

  // Get the global id of the element and the neighbor
  const dof_id_type elem_id = elem->id(), neighbor_id = neighbor->id();

  if (!_internal_side_user_objects.hasActiveBlockObjects(_subdomain, _tid))
    return;
  if (!((neighbor->active() && (neighbor->level() == elem->level()) && (elem_id < neighbor_id)) ||
        (neighbor->level() < elem->level())))
    return;

  _fe_problem.prepareFace(elem, _tid);
  _fe_problem.reinitNeighbor(elem, side, _tid);

  // Set up Sentinels so that, even if one of the reinitMaterialsXXX() calls throws, we
  // still remember to swap back during stack unwinding.
  SwapBackSentinel face_sentinel(_fe_problem, &FEProblem::swapBackMaterialsFace, _tid);
  _fe_problem.reinitMaterialsFace(elem->subdomain_id(), _tid);

  SwapBackSentinel neighbor_sentinel(_fe_problem, &FEProblem::swapBackMaterialsNeighbor, _tid);
  _fe_problem.reinitMaterialsNeighbor(neighbor->subdomain_id(), _tid);

  const auto & objects = _internal_side_user_objects.getActiveBlockObjects(_subdomain, _tid);
  for (const auto & uo : objects)
  {
    if (!uo->blockRestricted())
      uo->execute();
    else if (uo->hasBlocks(neighbor->subdomain_id()))
      uo->execute();
  }
}

void
ComputeUserObjectsThread::post()
{
  _fe_problem.clearActiveElementalMooseVariables(_tid);
  _fe_problem.clearActiveMaterialProperties(_tid);
}

void
ComputeUserObjectsThread::join(const ComputeUserObjectsThread & /*y*/)
{
}
<|endoftext|>