<commit_before>#include "gun_system.h"
#include "game/transcendental/cosmos.h"
#include "game/messages/intent_message.h"
#include "game/messages/damage_message.h"
#include "game/messages/queue_destruction.h"
#include "game/messages/gunshot_response.h"
#include "game/detail/item_slot_transfer_request.h"

#include "game/components/physics_component.h"
#include "game/components/damage_component.h"
#include "game/components/particles_existence_component.h"
#include "game/components/position_copying_component.h"
#include "game/components/container_component.h"
#include "game/components/item_component.h"
#include "game/components/flags_component.h"
#include "game/components/sentience_component.h"

#include "game/systems_temporary/physics_system.h"

#include "game/detail/inventory_utils.h"

#include "game/components/transform_component.h"
#include "game/components/gun_component.h"

#include "augs/misc/randomization.h"
#include "augs/log.h"

#include "game/transcendental/entity_handle.h"
#include "game/transcendental/step.h"
#include "game/detail/position_scripts.h"

using namespace augs;

void gun_system::consume_gun_intents(const logic_step step) {
	auto& cosmos = step.cosm;
	const auto& delta = step.get_delta();
	const auto& events = step.transient.messages.get_queue<messages::intent_message>();

	for (const auto& it : events) {
		auto* const maybe_gun = cosmos[it.subject].find<components::gun>();

		if (maybe_gun == nullptr) {
			continue;
		}

		auto& gun = *maybe_gun;

		if (it.intent == intent_type::PRESS_GUN_TRIGGER) {
			gun.trigger_pressed = it.is_pressed;
		}

		if (it.intent == intent_type::RELOAD && it.is_pressed) {

		}
	}
}

vec2 components::gun::calculate_muzzle_position(const components::transform gun_transform) const {
	return gun_transform.pos + vec2(bullet_spawn_offset).rotate(gun_transform.rotation, vec2());
}

vec2  components::gun::calculate_barrel_center(const components::transform gun_transform) const {
	return gun_transform.pos + vec2(0, bullet_spawn_offset.y).rotate(gun_transform.rotation, vec2());
}

void gun_system::launch_shots_due_to_pressed_triggers(const logic_step step) {
	auto& cosmos = step.cosm;
	const auto& delta = step.get_delta();
	step.transient.messages.get_queue<messages::gunshot_response>().clear();

	auto& physics_sys = cosmos.systems_temporary.get<physics_system>();

	for (const auto& it : cosmos.get(processing_subjects::WITH_GUN)) {
		const auto& gun_transform = it.logic_transform();
		const auto owning_capability = it.get_owning_transfer_capability();

		const auto owning_sentience =
			(owning_capability.alive() && owning_capability.has<components::sentience>()) ? owning_capability : cosmos[entity_id()];

		auto& gun = it.get<components::gun>();

		const auto magic_missile_def = cosmos[gun.magic_missile_definition];
		const auto is_magic_launcher = magic_missile_def.alive();
		const auto mana_needed = is_magic_launcher ? magic_missile_def.get<components::damage>().amount / 4 : 0;

		const bool has_enough_mana =
			(is_magic_launcher
			&& owning_sentience.alive()
			&& owning_sentience.get<components::sentience>().personal_electricity.value >= mana_needed)
			|| !is_magic_launcher;

		if (
			gun.trigger_pressed
			&& has_enough_mana
			&& gun.shot_cooldown.try_to_fire_and_reset(cosmos.get_timestamp(), delta)
		) {
			if (gun.action_mode != components::gun::action_type::AUTOMATIC) {
				gun.trigger_pressed = false;
			}

			const components::transform muzzle_transform = { gun.calculate_muzzle_position(gun_transform), gun_transform.rotation };

			messages::gunshot_response response;

			response.muzzle_transform = muzzle_transform;
			response.subject = it;

			float total_recoil_multiplier = 1.f;

			if (is_magic_launcher) {
				const auto round_entity = cosmos.clone_entity(magic_missile_def); //??

				auto& damage = round_entity.get<components::damage>();
				damage.sender = it;
				total_recoil_multiplier *= damage.recoil_multiplier;

				round_entity.set_logic_transform(muzzle_transform);

				auto rng = cosmos.get_rng_for(round_entity);
				set_velocity(round_entity, vec2().set_from_degrees(muzzle_transform.rotation).set_length(rng.randval(gun.muzzle_velocity)));
				response.spawned_rounds.push_back(round_entity);

				auto& sentience = owning_sentience.get<components::sentience>();
				sentience.personal_electricity.value -= sentience.consciousness.calculate_damage_result(mana_needed).effective;

				round_entity.set_flag(entity_flag::IS_IMMUNE_TO_PAST);
				round_entity.add_standard_components();

				step.transient.messages.post(response);
			}
			else {
				const auto chamber_slot = it[slot_function::GUN_CHAMBER];

				if (chamber_slot.get_mounted_items().size() == 1) {

					const auto item_in_chamber = chamber_slot.get_mounted_items()[0];

					std::vector<entity_handle> bullet_entities;
					bullet_entities.clear();

					const auto pellets_slot = item_in_chamber[slot_function::ITEM_DEPOSIT];

					bool destroy_pellets_container = false;

					if (pellets_slot.alive()) {
						destroy_pellets_container = true;
						bullet_entities = pellets_slot.get_mounted_items();
					}
					else {
						bullet_entities.push_back(item_in_chamber);
					}

					for(const auto catridge_or_pellet_stack : bullet_entities) {
						int charges = catridge_or_pellet_stack.get<components::item>().charges;

						while (charges--) {
							{
								const auto round_entity = cosmos.clone_entity(catridge_or_pellet_stack[sub_entity_name::BULLET_ROUND]); //??

								auto& damage = round_entity.get<components::damage>();
								damage.amount *= gun.damage_multiplier;
								damage.sender = it;
								total_recoil_multiplier *= damage.recoil_multiplier;

								round_entity.set_logic_transform(muzzle_transform);

								auto rng = cosmos.get_rng_for(round_entity);
								set_velocity(round_entity, vec2().set_from_degrees(muzzle_transform.rotation).set_length(rng.randval(gun.muzzle_velocity)));
								response.spawned_rounds.push_back(round_entity);

								round_entity.set_flag(entity_flag::IS_IMMUNE_TO_PAST);
								round_entity.add_standard_components();
							}

							const auto shell_definition = catridge_or_pellet_stack[sub_entity_name::BULLET_SHELL];

							if (shell_definition.alive()) {
								const auto shell_entity = cosmos.clone_entity(shell_definition);

								auto rng = cosmos.get_rng_for(shell_entity);

								const auto spread_component = rng.randval(gun.shell_spread_degrees) + gun.shell_spawn_offset.rotation;

								auto shell_transform = gun_transform;
								shell_transform.pos += vec2(gun.shell_spawn_offset.pos).rotate(gun_transform.rotation, vec2());
								shell_transform.rotation += spread_component;

								shell_entity.set_logic_transform(shell_transform);

								set_velocity(shell_entity, vec2().set_from_degrees(muzzle_transform.rotation + spread_component).set_length(rng.randval(gun.shell_velocity)));
								response.spawned_shells.push_back(shell_entity);

								shell_entity.add_standard_components();
							}
						}

						step.transient.messages.post(response);

						step.transient.messages.post(messages::queue_destruction(catridge_or_pellet_stack));
					}

					if (destroy_pellets_container) {
						step.transient.messages.post(messages::queue_destruction(chamber_slot.get_items_inside()[0]));
					}

					chamber_slot->items_inside.clear();

					if (gun.action_mode >= components::gun::action_type::SEMI_AUTOMATIC) {
						std::vector<entity_handle> source_store_for_chamber;

						const auto chamber_magazine_slot = it[slot_function::GUN_CHAMBER_MAGAZINE];

						if (chamber_magazine_slot.alive()) {
							source_store_for_chamber = chamber_magazine_slot.get_items_inside();
						}
						else {
							const auto detachable_magazine_slot = it[slot_function::GUN_DETACHABLE_MAGAZINE];

							if (detachable_magazine_slot.alive() && detachable_magazine_slot.has_items()) {
								source_store_for_chamber = detachable_magazine_slot.get_items_inside()[0][slot_function::ITEM_DEPOSIT].get_items_inside();
							}
						}

						if (source_store_for_chamber.size() > 0) {
							const item_slot_transfer_request into_chamber_transfer (*source_store_for_chamber.rbegin(), chamber_slot, 1, true);
							perform_transfer(into_chamber_transfer, step);
						}
					}
				}
			}

			if (total_recoil_multiplier > 0.f) {
				const auto owning_capability = it.get_owning_transfer_capability();
				const auto owning_crosshair_recoil = owning_capability[sub_entity_name::CHARACTER_CROSSHAIR][sub_entity_name::CROSSHAIR_RECOIL_BODY];
				gun.recoil.shoot_and_apply_impulse(owning_crosshair_recoil, total_recoil_multiplier / 100.f, true);
			}
		}
		else if (gun.shot_cooldown.is_ready(cosmos.get_timestamp(), delta)) {
			gun.recoil.cooldown(delta.in_milliseconds());
		}
	}
}<commit_msg>bugfix<commit_after>#include "gun_system.h"
#include "game/transcendental/cosmos.h"
#include "game/messages/intent_message.h"
#include "game/messages/damage_message.h"
#include "game/messages/queue_destruction.h"
#include "game/messages/gunshot_response.h"
#include "game/detail/item_slot_transfer_request.h"

#include "game/components/physics_component.h"
#include "game/components/damage_component.h"
#include "game/components/particles_existence_component.h"
#include "game/components/position_copying_component.h"
#include "game/components/container_component.h"
#include "game/components/item_component.h"
#include "game/components/flags_component.h"
#include "game/components/sentience_component.h"

#include "game/systems_temporary/physics_system.h"

#include "game/detail/inventory_utils.h"

#include "game/components/transform_component.h"
#include "game/components/gun_component.h"

#include "augs/misc/randomization.h"
#include "augs/log.h"

#include "game/transcendental/entity_handle.h"
#include "game/transcendental/step.h"
#include "game/detail/position_scripts.h"

using namespace augs;

void gun_system::consume_gun_intents(const logic_step step) {
	auto& cosmos = step.cosm;
	const auto& delta = step.get_delta();
	const auto& events = step.transient.messages.get_queue<messages::intent_message>();

	for (const auto& it : events) {
		auto* const maybe_gun = cosmos[it.subject].find<components::gun>();

		if (maybe_gun == nullptr) {
			continue;
		}

		auto& gun = *maybe_gun;

		if (it.intent == intent_type::PRESS_GUN_TRIGGER) {
			gun.trigger_pressed = it.is_pressed;
		}

		if (it.intent == intent_type::RELOAD && it.is_pressed) {

		}
	}
}

vec2 components::gun::calculate_muzzle_position(const components::transform gun_transform) const {
	return gun_transform.pos + vec2(bullet_spawn_offset).rotate(gun_transform.rotation, vec2());
}

vec2  components::gun::calculate_barrel_center(const components::transform gun_transform) const {
	return gun_transform.pos + vec2(0, bullet_spawn_offset.y).rotate(gun_transform.rotation, vec2());
}

void gun_system::launch_shots_due_to_pressed_triggers(const logic_step step) {
	auto& cosmos = step.cosm;
	const auto& delta = step.get_delta();
	step.transient.messages.get_queue<messages::gunshot_response>().clear();

	auto& physics_sys = cosmos.systems_temporary.get<physics_system>();

	for (const auto& it : cosmos.get(processing_subjects::WITH_GUN)) {
		const auto& gun_transform = it.logic_transform();
		const auto owning_capability = it.get_owning_transfer_capability();

		const auto owning_sentience =
			(owning_capability.alive() && owning_capability.has<components::sentience>()) ? owning_capability : cosmos[entity_id()];

		auto& gun = it.get<components::gun>();

		const auto magic_missile_def = cosmos[gun.magic_missile_definition];
		const auto is_magic_launcher = magic_missile_def.alive();
		const auto mana_needed = is_magic_launcher ? magic_missile_def.get<components::damage>().amount / 4 : 0;

		const bool has_enough_mana =
			(is_magic_launcher
			&& owning_sentience.alive()
			&& owning_sentience.get<components::sentience>().personal_electricity.value >= mana_needed)
			|| !is_magic_launcher;

		if (
			gun.trigger_pressed
			&& has_enough_mana
			&& gun.shot_cooldown.try_to_fire_and_reset(cosmos.get_timestamp(), delta)
		) {
			if (gun.action_mode != components::gun::action_type::AUTOMATIC) {
				gun.trigger_pressed = false;
			}

			const components::transform muzzle_transform = { gun.calculate_muzzle_position(gun_transform), gun_transform.rotation };

			messages::gunshot_response response;

			response.muzzle_transform = muzzle_transform;
			response.subject = it;

			float total_recoil_multiplier = 1.f;

			if (is_magic_launcher) {
				const auto round_entity = cosmos.clone_entity(magic_missile_def); //??

				auto& damage = round_entity.get<components::damage>();
				damage.sender = it;
				total_recoil_multiplier *= damage.recoil_multiplier;

				round_entity.set_logic_transform(muzzle_transform);

				auto rng = cosmos.get_rng_for(round_entity);
				set_velocity(round_entity, vec2().set_from_degrees(muzzle_transform.rotation).set_length(rng.randval(gun.muzzle_velocity)));
				response.spawned_rounds.push_back(round_entity);

				auto& sentience = owning_sentience.get<components::sentience>();
				sentience.personal_electricity.value -= sentience.personal_electricity.calculate_damage_result(mana_needed).effective;

				round_entity.set_flag(entity_flag::IS_IMMUNE_TO_PAST);
				round_entity.add_standard_components();

				step.transient.messages.post(response);
			}
			else {
				const auto chamber_slot = it[slot_function::GUN_CHAMBER];

				if (chamber_slot.get_mounted_items().size() == 1) {

					const auto item_in_chamber = chamber_slot.get_mounted_items()[0];

					std::vector<entity_handle> bullet_entities;
					bullet_entities.clear();

					const auto pellets_slot = item_in_chamber[slot_function::ITEM_DEPOSIT];

					bool destroy_pellets_container = false;

					if (pellets_slot.alive()) {
						destroy_pellets_container = true;
						bullet_entities = pellets_slot.get_mounted_items();
					}
					else {
						bullet_entities.push_back(item_in_chamber);
					}

					for(const auto catridge_or_pellet_stack : bullet_entities) {
						int charges = catridge_or_pellet_stack.get<components::item>().charges;

						while (charges--) {
							{
								const auto round_entity = cosmos.clone_entity(catridge_or_pellet_stack[sub_entity_name::BULLET_ROUND]); //??

								auto& damage = round_entity.get<components::damage>();
								damage.amount *= gun.damage_multiplier;
								damage.sender = it;
								total_recoil_multiplier *= damage.recoil_multiplier;

								round_entity.set_logic_transform(muzzle_transform);

								auto rng = cosmos.get_rng_for(round_entity);
								set_velocity(round_entity, vec2().set_from_degrees(muzzle_transform.rotation).set_length(rng.randval(gun.muzzle_velocity)));
								response.spawned_rounds.push_back(round_entity);

								round_entity.set_flag(entity_flag::IS_IMMUNE_TO_PAST);
								round_entity.add_standard_components();
							}

							const auto shell_definition = catridge_or_pellet_stack[sub_entity_name::BULLET_SHELL];

							if (shell_definition.alive()) {
								const auto shell_entity = cosmos.clone_entity(shell_definition);

								auto rng = cosmos.get_rng_for(shell_entity);

								const auto spread_component = rng.randval(gun.shell_spread_degrees) + gun.shell_spawn_offset.rotation;

								auto shell_transform = gun_transform;
								shell_transform.pos += vec2(gun.shell_spawn_offset.pos).rotate(gun_transform.rotation, vec2());
								shell_transform.rotation += spread_component;

								shell_entity.set_logic_transform(shell_transform);

								set_velocity(shell_entity, vec2().set_from_degrees(muzzle_transform.rotation + spread_component).set_length(rng.randval(gun.shell_velocity)));
								response.spawned_shells.push_back(shell_entity);

								shell_entity.add_standard_components();
							}
						}

						step.transient.messages.post(response);

						step.transient.messages.post(messages::queue_destruction(catridge_or_pellet_stack));
					}

					if (destroy_pellets_container) {
						step.transient.messages.post(messages::queue_destruction(chamber_slot.get_items_inside()[0]));
					}

					chamber_slot->items_inside.clear();

					if (gun.action_mode >= components::gun::action_type::SEMI_AUTOMATIC) {
						std::vector<entity_handle> source_store_for_chamber;

						const auto chamber_magazine_slot = it[slot_function::GUN_CHAMBER_MAGAZINE];

						if (chamber_magazine_slot.alive()) {
							source_store_for_chamber = chamber_magazine_slot.get_items_inside();
						}
						else {
							const auto detachable_magazine_slot = it[slot_function::GUN_DETACHABLE_MAGAZINE];

							if (detachable_magazine_slot.alive() && detachable_magazine_slot.has_items()) {
								source_store_for_chamber = detachable_magazine_slot.get_items_inside()[0][slot_function::ITEM_DEPOSIT].get_items_inside();
							}
						}

						if (source_store_for_chamber.size() > 0) {
							const item_slot_transfer_request into_chamber_transfer (*source_store_for_chamber.rbegin(), chamber_slot, 1, true);
							perform_transfer(into_chamber_transfer, step);
						}
					}
				}
			}

			if (total_recoil_multiplier > 0.f) {
				const auto owning_capability = it.get_owning_transfer_capability();
				const auto owning_crosshair_recoil = owning_capability[sub_entity_name::CHARACTER_CROSSHAIR][sub_entity_name::CROSSHAIR_RECOIL_BODY];
				gun.recoil.shoot_and_apply_impulse(owning_crosshair_recoil, total_recoil_multiplier / 100.f, true);
			}
		}
		else if (gun.shot_cooldown.is_ready(cosmos.get_timestamp(), delta)) {
			gun.recoil.cooldown(delta.in_milliseconds());
		}
	}
}<|endoftext|>


<commit_before>/*
  +----------------------------------------------------------------------+
  | Swoole                                                               |
  +----------------------------------------------------------------------+
  | This source file is subject to version 2.0 of the Apache license,    |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.apache.org/licenses/LICENSE-2.0.html                      |
  | If you did not receive a copy of the Apache2.0 license and are unable|
  | to obtain it through the world-wide-web, please send a note to       |
  | license@swoole.com so we can mail you a copy immediately.            |
  +----------------------------------------------------------------------+
  | Author: Tianfeng Han  <mikan.tenny@gmail.com>                        |
  +----------------------------------------------------------------------+
*/

#include "php_swoole_cxx.h"
#include "swoole_http.h"
#include "websocket.h"

#include "main/rfc1867.h"

#ifdef SW_USE_HTTP2
#include "http2.h"
#endif

using namespace swoole;
using swoole::coroutine::Socket;

swString *swoole_http_buffer;
#ifdef SW_HAVE_COMPRESSION
/* not only be used by zlib but also be used by br */
swString *swoole_zlib_buffer;
#endif
swString *swoole_http_form_data_buffer;

zend_class_entry *swoole_http_server_ce;
zend_object_handlers swoole_http_server_handlers;

static bool http_context_send_data(http_context* ctx, const char *data, size_t length);
static bool http_context_send_file(http_context* ctx, const char *file, uint32_t l_file, off_t offset, size_t length);
static bool http_context_disconnect(http_context* ctx);

int php_swoole_http_onReceive(swServer *serv, swEventData *req)
{
    int fd = req->info.fd;
    int server_fd = req->info.server_fd;

    swConnection *conn = swServer_connection_verify_no_ssl(serv, fd);
    if (!conn)
    {
        swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, "connection[%d] is closed", fd);
        return SW_ERR;
    }

    swListenPort *port = (swListenPort *) serv->connection_list[server_fd].object;
    //other server port
    if (!port->open_http_protocol)
    {
        return php_swoole_onReceive(serv, req);
    }
    //websocket client
    if (conn->websocket_status == WEBSOCKET_STATUS_ACTIVE)
    {
        return swoole_websocket_onMessage(serv, req);
    }
#ifdef SW_USE_HTTP2
    if (conn->http2_stream)
    {
        return swoole_http2_server_onFrame(serv, conn, req);
    }
#endif

    http_context *ctx = swoole_http_context_new(fd);
    swoole_http_server_init_context(serv, ctx);

    zval *zdata = &ctx->request.zdata;
    php_swoole_get_recv_data(serv, zdata, req, NULL, 0);

    swTraceLog(SW_TRACE_SERVER, "http request from %d with %d bytes: <<EOF\n%.*s\nEOF", fd, (int) Z_STRLEN_P(zdata), (int) Z_STRLEN_P(zdata), Z_STRVAL_P(zdata));

    zval args[2], *zrequest_object = &args[0], *zresponse_object = &args[1];
    args[0] = *ctx->request.zobject;
    args[1] = *ctx->response.zobject;

    swoole_http_parser *parser = &ctx->parser;
    parser->data = ctx;
    swoole_http_parser_init(parser, PHP_HTTP_REQUEST);

    size_t parsed_n = swoole_http_requset_parse(ctx, Z_STRVAL_P(zdata), Z_STRLEN_P(zdata));
    if (ctx->parser.state == s_dead)
    {
#ifdef SW_HTTP_BAD_REQUEST_PACKET
        ctx->send(ctx, SW_STRL(SW_HTTP_BAD_REQUEST_PACKET));
#endif
        ctx->close(ctx);
        swNotice("request is illegal and it has been discarded, %ld bytes unprocessed", Z_STRLEN_P(zdata) - parsed_n);
        goto _dtor_and_return;
    }

    do {
        zval *zserver = ctx->request.zserver;
        swConnection *serv_sock = swServer_connection_get(serv, conn->server_fd);
        if (serv_sock)
        {
            add_assoc_long(zserver, "server_port", swSocket_get_port(serv_sock->socket_type, &serv_sock->info));
        }
        add_assoc_long(zserver, "remote_port", swSocket_get_port(conn->socket_type, &conn->info));
        add_assoc_string(zserver, "remote_addr", (char *) swSocket_get_ip(conn->socket_type, &conn->info));
        add_assoc_long(zserver, "master_time", conn->last_time);
    } while (0);

    // begin to check and call registerd callback
    do {
        zend_fcall_info_cache *fci_cache = NULL;

        if (conn->websocket_status == WEBSOCKET_STATUS_CONNECTION)
        {
            fci_cache = php_swoole_server_get_fci_cache(serv, server_fd, SW_SERVER_CB_onHandShake);
            if (fci_cache == NULL)
            {
                swoole_websocket_onHandshake(serv, port, ctx);
                goto _dtor_and_return;
            }
            else
            {
                conn->websocket_status = WEBSOCKET_STATUS_HANDSHAKE;
                ctx->upgrade = 1;
            }
        }
        else
        {
            fci_cache = php_swoole_server_get_fci_cache(serv, server_fd, SW_SERVER_CB_onRequest);
            if (fci_cache == NULL)
            {
                swoole_websocket_onRequest(ctx);
                goto _dtor_and_return;
            }
        }

        if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, NULL, SwooleG.enable_coroutine)))
        {
            php_swoole_error(E_WARNING, "%s->onRequest handler error", ZSTR_VAL(swoole_http_server_ce->name));
    #ifdef SW_HTTP_SERVICE_UNAVAILABLE_PACKET
            ctx->send(ctx, SW_STRL(SW_HTTP_SERVICE_UNAVAILABLE_PACKET));
    #endif
            ctx->close(ctx);
        }
    } while (0);

    _dtor_and_return:
    zval_ptr_dtor(zrequest_object);
    zval_ptr_dtor(zresponse_object);

    return SW_OK;
}

void php_swoole_http_onClose(swServer *serv, swDataHead *ev)
{
    swConnection *conn = swWorker_get_connection(serv, ev->fd);
    if (!conn)
    {
        return;
    }
#ifdef SW_USE_HTTP2
    if (conn->http2_stream)
    {
        swoole_http2_server_session_free(conn);
    }
#endif
    php_swoole_onClose(serv, ev);
}

void php_swoole_http_server_minit(int module_number)
{
    SW_INIT_CLASS_ENTRY_EX(swoole_http_server, "Swoole\\Http\\Server", "swoole_http_server", NULL, NULL, swoole_server);
    SW_SET_CLASS_SERIALIZABLE(swoole_http_server, zend_class_serialize_deny, zend_class_unserialize_deny);
    SW_SET_CLASS_CLONEABLE(swoole_http_server, sw_zend_class_clone_deny);
    SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http_server, sw_zend_class_unset_property_deny);

    zend_declare_property_null(swoole_http_server_ce, ZEND_STRL("onRequest"), ZEND_ACC_PRIVATE);
}

http_context* swoole_http_context_new(int fd)
{
    http_context *ctx = (http_context *) ecalloc(1, sizeof(http_context));

    zval *zrequest_object = &ctx->request._zobject;
    ctx->request.zobject = zrequest_object;
    object_init_ex(zrequest_object, swoole_http_request_ce);
    php_swoole_http_request_set_context(zrequest_object, ctx);

    zval *zresponse_object = &ctx->response._zobject;
    ctx->response.zobject = zresponse_object;
    object_init_ex(zresponse_object, swoole_http_response_ce);
    php_swoole_http_response_set_context(zresponse_object, ctx);

    zend_update_property_long(swoole_http_request_ce, zrequest_object, ZEND_STRL("fd"), fd);
    zend_update_property_long(swoole_http_response_ce, zresponse_object, ZEND_STRL("fd"), fd);

#if PHP_MEMORY_DEBUG
    php_vmstat.new_http_request ++;
#endif

    swoole_http_init_and_read_property(swoole_http_request_ce, zrequest_object, &ctx->request.zserver, ZEND_STRL("server"));
    swoole_http_init_and_read_property(swoole_http_request_ce, zrequest_object, &ctx->request.zheader, ZEND_STRL("header"));
    ctx->fd = fd;

    return ctx;
}

void swoole_http_server_init_context(swServer *serv, http_context *ctx)
{
    ctx->parse_cookie = serv->http_parse_cookie;
    ctx->parse_body = serv->http_parse_post;
    ctx->parse_files = serv->http_parse_files;
#ifdef SW_HAVE_COMPRESSION
    ctx->enable_compression = serv->http_compression;
#endif
    ctx->private_data = serv;
    ctx->upload_tmp_dir = serv->upload_tmp_dir;
    ctx->send = http_context_send_data;
    ctx->sendfile = http_context_send_file;
    ctx->close = http_context_disconnect;
}

void swoole_http_context_copy(http_context *src, http_context *dst)
{
    dst->parse_cookie = src->parse_cookie;
    dst->parse_body = src->parse_body;
    dst->parse_files = src->parse_files;
#ifdef SW_HAVE_COMPRESSION
    dst->enable_compression = src->enable_compression;
#endif
    dst->private_data = src->private_data;
    dst->upload_tmp_dir = src->upload_tmp_dir;
    dst->send = src->send;
    dst->sendfile = src->sendfile;
    dst->close = src->close;
}

void swoole_http_context_free(http_context *ctx)
{
    /* http context can only be free'd after request and response were free'd */
    if (ctx->request.zobject || ctx->response.zobject)
    {
        return;
    }
#ifdef SW_USE_HTTP2
    if (ctx->stream)
    {
        ((http2_stream *) ctx->stream)->ctx = nullptr;
    }
#endif

    http_request *req = &ctx->request;
    http_response *res = &ctx->response;
    if (req->path)
    {
        efree(req->path);
    }
    if (Z_TYPE(req->zdata) == IS_STRING)
    {
        zend_string_release(Z_STR(req->zdata));
    }
    if (req->chunked_body)
    {
        swString_free(req->chunked_body);
    }
#ifdef SW_USE_HTTP2
    if (req->h2_data_buffer)
    {
        swString_free(req->h2_data_buffer);
    }
#endif
    if (res->reason)
    {
        efree(res->reason);
    }
    efree(ctx);
}

void php_swoole_http_server_init_global_variant()
{
    swoole_http_buffer = swString_new(SW_HTTP_RESPONSE_INIT_SIZE);
    if (!swoole_http_buffer)
    {
        php_swoole_fatal_error(E_ERROR, "[swoole_http_buffer] swString_new(%d) failed", SW_HTTP_RESPONSE_INIT_SIZE);
        return;
    }

    swoole_http_form_data_buffer = swString_new(SW_HTTP_RESPONSE_INIT_SIZE);
    if (!swoole_http_form_data_buffer)
    {
        php_swoole_fatal_error(E_ERROR, "[swoole_http_form_data_buffer] swString_new(%d) failed", SW_HTTP_RESPONSE_INIT_SIZE);
        return;
    }

    //for is_uploaded_file and move_uploaded_file
    if (!SG(rfc1867_uploaded_files))
    {
        ALLOC_HASHTABLE(SG(rfc1867_uploaded_files));
        zend_hash_init(SG(rfc1867_uploaded_files), 8, NULL, NULL, 0);
    }
}

http_context* php_swoole_http_request_get_and_check_context(zval *zobject)
{
    http_context *ctx = php_swoole_http_request_get_context(zobject);
    if (!ctx)
    {
        php_swoole_fatal_error(E_WARNING, "http request is unavailable (maybe it has been ended)");
    }
    return ctx;
}

http_context* php_swoole_http_response_get_and_check_context(zval *zobject)
{
    http_context *ctx = php_swoole_http_response_get_context(zobject);
    if (!ctx || (ctx->end || ctx->detached))
    {
        php_swoole_fatal_error(E_WARNING, "http response is unavailable (maybe it has been ended or detached)");
        return NULL;
    }
    return ctx;
}

bool http_context_send_data(http_context* ctx, const char *data, size_t length)
{
    swServer *serv = (swServer *) ctx->private_data;
    zval *return_value = (zval *) ctx->private_data_2;
    ssize_t ret = serv->send(serv, ctx->fd, (void*) data, length);
    if (ret < 0 && SwooleG.error == SW_ERROR_OUTPUT_SEND_YIELD)
    {
        zval _yield_data;
        ZVAL_STRINGL(&_yield_data, swoole_http_buffer->str, swoole_http_buffer->length);
        php_swoole_server_send_yield(serv, ctx->fd, &_yield_data, return_value);
        if (Z_TYPE_P(return_value) == IS_FALSE)
        {
            ctx->send_chunked = 0;
            ctx->send_header = 0;
        }
    }
    return ret == SW_OK;
}

static bool http_context_send_file(http_context* ctx, const char *file, uint32_t l_file, off_t offset, size_t length)
{
    swServer *serv = (swServer *) ctx->private_data;
    return serv->sendfile(serv, ctx->fd, file, l_file, offset, length) == SW_OK;
}

static bool http_context_disconnect(http_context* ctx)
{
    swServer *serv = (swServer *) ctx->private_data;
    return serv->close(serv, ctx->fd, 0) == SW_OK;
}
<commit_msg>Fix http_context_send_data (#3059)<commit_after>/*
  +----------------------------------------------------------------------+
  | Swoole                                                               |
  +----------------------------------------------------------------------+
  | This source file is subject to version 2.0 of the Apache license,    |
  | that is bundled with this package in the file LICENSE, and is        |
  | available through the world-wide-web at the following url:           |
  | http://www.apache.org/licenses/LICENSE-2.0.html                      |
  | If you did not receive a copy of the Apache2.0 license and are unable|
  | to obtain it through the world-wide-web, please send a note to       |
  | license@swoole.com so we can mail you a copy immediately.            |
  +----------------------------------------------------------------------+
  | Author: Tianfeng Han  <mikan.tenny@gmail.com>                        |
  +----------------------------------------------------------------------+
*/

#include "php_swoole_cxx.h"
#include "swoole_http.h"
#include "websocket.h"

#include "main/rfc1867.h"

#ifdef SW_USE_HTTP2
#include "http2.h"
#endif

using namespace swoole;
using swoole::coroutine::Socket;

swString *swoole_http_buffer;
#ifdef SW_HAVE_COMPRESSION
/* not only be used by zlib but also be used by br */
swString *swoole_zlib_buffer;
#endif
swString *swoole_http_form_data_buffer;

zend_class_entry *swoole_http_server_ce;
zend_object_handlers swoole_http_server_handlers;

static bool http_context_send_data(http_context* ctx, const char *data, size_t length);
static bool http_context_send_file(http_context* ctx, const char *file, uint32_t l_file, off_t offset, size_t length);
static bool http_context_disconnect(http_context* ctx);

int php_swoole_http_onReceive(swServer *serv, swEventData *req)
{
    int fd = req->info.fd;
    int server_fd = req->info.server_fd;

    swConnection *conn = swServer_connection_verify_no_ssl(serv, fd);
    if (!conn)
    {
        swoole_error_log(SW_LOG_NOTICE, SW_ERROR_SESSION_NOT_EXIST, "connection[%d] is closed", fd);
        return SW_ERR;
    }

    swListenPort *port = (swListenPort *) serv->connection_list[server_fd].object;
    //other server port
    if (!port->open_http_protocol)
    {
        return php_swoole_onReceive(serv, req);
    }
    //websocket client
    if (conn->websocket_status == WEBSOCKET_STATUS_ACTIVE)
    {
        return swoole_websocket_onMessage(serv, req);
    }
#ifdef SW_USE_HTTP2
    if (conn->http2_stream)
    {
        return swoole_http2_server_onFrame(serv, conn, req);
    }
#endif

    http_context *ctx = swoole_http_context_new(fd);
    swoole_http_server_init_context(serv, ctx);

    zval *zdata = &ctx->request.zdata;
    php_swoole_get_recv_data(serv, zdata, req, NULL, 0);

    swTraceLog(SW_TRACE_SERVER, "http request from %d with %d bytes: <<EOF\n%.*s\nEOF", fd, (int) Z_STRLEN_P(zdata), (int) Z_STRLEN_P(zdata), Z_STRVAL_P(zdata));

    zval args[2], *zrequest_object = &args[0], *zresponse_object = &args[1];
    args[0] = *ctx->request.zobject;
    args[1] = *ctx->response.zobject;

    swoole_http_parser *parser = &ctx->parser;
    parser->data = ctx;
    swoole_http_parser_init(parser, PHP_HTTP_REQUEST);

    size_t parsed_n = swoole_http_requset_parse(ctx, Z_STRVAL_P(zdata), Z_STRLEN_P(zdata));
    if (ctx->parser.state == s_dead)
    {
#ifdef SW_HTTP_BAD_REQUEST_PACKET
        ctx->send(ctx, SW_STRL(SW_HTTP_BAD_REQUEST_PACKET));
#endif
        ctx->close(ctx);
        swNotice("request is illegal and it has been discarded, %ld bytes unprocessed", Z_STRLEN_P(zdata) - parsed_n);
        goto _dtor_and_return;
    }

    do {
        zval *zserver = ctx->request.zserver;
        swConnection *serv_sock = swServer_connection_get(serv, conn->server_fd);
        if (serv_sock)
        {
            add_assoc_long(zserver, "server_port", swSocket_get_port(serv_sock->socket_type, &serv_sock->info));
        }
        add_assoc_long(zserver, "remote_port", swSocket_get_port(conn->socket_type, &conn->info));
        add_assoc_string(zserver, "remote_addr", (char *) swSocket_get_ip(conn->socket_type, &conn->info));
        add_assoc_long(zserver, "master_time", conn->last_time);
    } while (0);

    // begin to check and call registerd callback
    do {
        zend_fcall_info_cache *fci_cache = NULL;

        if (conn->websocket_status == WEBSOCKET_STATUS_CONNECTION)
        {
            fci_cache = php_swoole_server_get_fci_cache(serv, server_fd, SW_SERVER_CB_onHandShake);
            if (fci_cache == NULL)
            {
                swoole_websocket_onHandshake(serv, port, ctx);
                goto _dtor_and_return;
            }
            else
            {
                conn->websocket_status = WEBSOCKET_STATUS_HANDSHAKE;
                ctx->upgrade = 1;
            }
        }
        else
        {
            fci_cache = php_swoole_server_get_fci_cache(serv, server_fd, SW_SERVER_CB_onRequest);
            if (fci_cache == NULL)
            {
                swoole_websocket_onRequest(ctx);
                goto _dtor_and_return;
            }
        }

        if (UNEXPECTED(!zend::function::call(fci_cache, 2, args, NULL, SwooleG.enable_coroutine)))
        {
            php_swoole_error(E_WARNING, "%s->onRequest handler error", ZSTR_VAL(swoole_http_server_ce->name));
    #ifdef SW_HTTP_SERVICE_UNAVAILABLE_PACKET
            ctx->send(ctx, SW_STRL(SW_HTTP_SERVICE_UNAVAILABLE_PACKET));
    #endif
            ctx->close(ctx);
        }
    } while (0);

    _dtor_and_return:
    zval_ptr_dtor(zrequest_object);
    zval_ptr_dtor(zresponse_object);

    return SW_OK;
}

void php_swoole_http_onClose(swServer *serv, swDataHead *ev)
{
    swConnection *conn = swWorker_get_connection(serv, ev->fd);
    if (!conn)
    {
        return;
    }
#ifdef SW_USE_HTTP2
    if (conn->http2_stream)
    {
        swoole_http2_server_session_free(conn);
    }
#endif
    php_swoole_onClose(serv, ev);
}

void php_swoole_http_server_minit(int module_number)
{
    SW_INIT_CLASS_ENTRY_EX(swoole_http_server, "Swoole\\Http\\Server", "swoole_http_server", NULL, NULL, swoole_server);
    SW_SET_CLASS_SERIALIZABLE(swoole_http_server, zend_class_serialize_deny, zend_class_unserialize_deny);
    SW_SET_CLASS_CLONEABLE(swoole_http_server, sw_zend_class_clone_deny);
    SW_SET_CLASS_UNSET_PROPERTY_HANDLER(swoole_http_server, sw_zend_class_unset_property_deny);

    zend_declare_property_null(swoole_http_server_ce, ZEND_STRL("onRequest"), ZEND_ACC_PRIVATE);
}

http_context* swoole_http_context_new(int fd)
{
    http_context *ctx = (http_context *) ecalloc(1, sizeof(http_context));

    zval *zrequest_object = &ctx->request._zobject;
    ctx->request.zobject = zrequest_object;
    object_init_ex(zrequest_object, swoole_http_request_ce);
    php_swoole_http_request_set_context(zrequest_object, ctx);

    zval *zresponse_object = &ctx->response._zobject;
    ctx->response.zobject = zresponse_object;
    object_init_ex(zresponse_object, swoole_http_response_ce);
    php_swoole_http_response_set_context(zresponse_object, ctx);

    zend_update_property_long(swoole_http_request_ce, zrequest_object, ZEND_STRL("fd"), fd);
    zend_update_property_long(swoole_http_response_ce, zresponse_object, ZEND_STRL("fd"), fd);

#if PHP_MEMORY_DEBUG
    php_vmstat.new_http_request ++;
#endif

    swoole_http_init_and_read_property(swoole_http_request_ce, zrequest_object, &ctx->request.zserver, ZEND_STRL("server"));
    swoole_http_init_and_read_property(swoole_http_request_ce, zrequest_object, &ctx->request.zheader, ZEND_STRL("header"));
    ctx->fd = fd;

    return ctx;
}

void swoole_http_server_init_context(swServer *serv, http_context *ctx)
{
    ctx->parse_cookie = serv->http_parse_cookie;
    ctx->parse_body = serv->http_parse_post;
    ctx->parse_files = serv->http_parse_files;
#ifdef SW_HAVE_COMPRESSION
    ctx->enable_compression = serv->http_compression;
#endif
    ctx->private_data = serv;
    ctx->upload_tmp_dir = serv->upload_tmp_dir;
    ctx->send = http_context_send_data;
    ctx->sendfile = http_context_send_file;
    ctx->close = http_context_disconnect;
}

void swoole_http_context_copy(http_context *src, http_context *dst)
{
    dst->parse_cookie = src->parse_cookie;
    dst->parse_body = src->parse_body;
    dst->parse_files = src->parse_files;
#ifdef SW_HAVE_COMPRESSION
    dst->enable_compression = src->enable_compression;
#endif
    dst->private_data = src->private_data;
    dst->upload_tmp_dir = src->upload_tmp_dir;
    dst->send = src->send;
    dst->sendfile = src->sendfile;
    dst->close = src->close;
}

void swoole_http_context_free(http_context *ctx)
{
    /* http context can only be free'd after request and response were free'd */
    if (ctx->request.zobject || ctx->response.zobject)
    {
        return;
    }
#ifdef SW_USE_HTTP2
    if (ctx->stream)
    {
        ((http2_stream *) ctx->stream)->ctx = nullptr;
    }
#endif

    http_request *req = &ctx->request;
    http_response *res = &ctx->response;
    if (req->path)
    {
        efree(req->path);
    }
    if (Z_TYPE(req->zdata) == IS_STRING)
    {
        zend_string_release(Z_STR(req->zdata));
    }
    if (req->chunked_body)
    {
        swString_free(req->chunked_body);
    }
#ifdef SW_USE_HTTP2
    if (req->h2_data_buffer)
    {
        swString_free(req->h2_data_buffer);
    }
#endif
    if (res->reason)
    {
        efree(res->reason);
    }
    efree(ctx);
}

void php_swoole_http_server_init_global_variant()
{
    swoole_http_buffer = swString_new(SW_HTTP_RESPONSE_INIT_SIZE);
    if (!swoole_http_buffer)
    {
        php_swoole_fatal_error(E_ERROR, "[swoole_http_buffer] swString_new(%d) failed", SW_HTTP_RESPONSE_INIT_SIZE);
        return;
    }

    swoole_http_form_data_buffer = swString_new(SW_HTTP_RESPONSE_INIT_SIZE);
    if (!swoole_http_form_data_buffer)
    {
        php_swoole_fatal_error(E_ERROR, "[swoole_http_form_data_buffer] swString_new(%d) failed", SW_HTTP_RESPONSE_INIT_SIZE);
        return;
    }

    //for is_uploaded_file and move_uploaded_file
    if (!SG(rfc1867_uploaded_files))
    {
        ALLOC_HASHTABLE(SG(rfc1867_uploaded_files));
        zend_hash_init(SG(rfc1867_uploaded_files), 8, NULL, NULL, 0);
    }
}

http_context* php_swoole_http_request_get_and_check_context(zval *zobject)
{
    http_context *ctx = php_swoole_http_request_get_context(zobject);
    if (!ctx)
    {
        php_swoole_fatal_error(E_WARNING, "http request is unavailable (maybe it has been ended)");
    }
    return ctx;
}

http_context* php_swoole_http_response_get_and_check_context(zval *zobject)
{
    http_context *ctx = php_swoole_http_response_get_context(zobject);
    if (!ctx || (ctx->end || ctx->detached))
    {
        php_swoole_fatal_error(E_WARNING, "http response is unavailable (maybe it has been ended or detached)");
        return NULL;
    }
    return ctx;
}

bool http_context_send_data(http_context* ctx, const char *data, size_t length)
{
    swServer *serv = (swServer *) ctx->private_data;
    zval *return_value = (zval *) ctx->private_data_2;
    ssize_t ret = serv->send(serv, ctx->fd, (void*) data, length);
    if (ret < 0 && SwooleG.error == SW_ERROR_OUTPUT_SEND_YIELD)
    {
        zval _yield_data;
        ZVAL_STRINGL(&_yield_data, data, length);
        php_swoole_server_send_yield(serv, ctx->fd, &_yield_data, return_value);
        ret = Z_BVAL_P(return_value) ? SW_OK : SW_ERR;
    }
    return ret == SW_OK;
}

static bool http_context_send_file(http_context* ctx, const char *file, uint32_t l_file, off_t offset, size_t length)
{
    swServer *serv = (swServer *) ctx->private_data;
    return serv->sendfile(serv, ctx->fd, file, l_file, offset, length) == SW_OK;
}

static bool http_context_disconnect(http_context* ctx)
{
    swServer *serv = (swServer *) ctx->private_data;
    return serv->close(serv, ctx->fd, 0) == SW_OK;
}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "SearchWindow.h"
#include "NaiveSearchWindow.h"
#include "DataSource.h"
#include "WinampControl.h"
#include "Settings.h"

class NaiveSearchWindow sealed :
    public vl::presentation::controls::GuiWindow,
    public IPlugin
{
private:
    DataSource * dataSource;
    GuiVirtualTextList* listBox;
    GuiSinglelineTextBox * searchBox;
    bool inputing = false;

    static inline bool IsContorlKeyClean(
        const NativeWindowKeyInfo& info,
        bool altstatus = false,
        bool ctrlstatus = false,
        bool shiftstatus = false)
    {
        return (info.alt == altstatus && info.ctrl == ctrlstatus && info.shift == shiftstatus);
    }

    vl::Ptr<vl::presentation::INativeDelay> lastChangeDelay, refreshPLDelay;
    SearchWindowStartUpParam* p;

    void NaiveHide()
    {
        auto thiswinf = vl::presentation::windows::GetWindowsForm(this->GetNativeWindow());
        ShowWindow(thiswinf->GetWindowHandle(), SW_HIDE);
    }

    void NaiveShow()
    {
        GuiWindow::Show();
        auto thiswinf = vl::presentation::windows::GetWindowsForm(this->GetNativeWindow());
        ShowWindow(thiswinf->GetWindowHandle(), SW_SHOWNORMAL);

        BringWindowToTop(thiswinf->GetWindowHandle());
        SetForegroundWindow(thiswinf->GetWindowHandle());

        this->SetActivated();
        searchBox->SelectAll();
        searchBox->SetFocus();
    }
public:

    void InitializeComponents()
    {
        this->SetTitleBar(false);
        this->SetTopMost(true);

        this->SetBounds(Settings::Default().WindowBounds());

        GuiTableComposition * table = new GuiTableComposition();
        table->SetRowsAndColumns(2, 1);
        table->SetCellPadding(3);
        table->SetAlignmentToParent({ 0, 0, 0, 0 });

        table->SetRowOption(0, GuiCellOption::AbsoluteOption(26));
        table->SetRowOption(1, GuiCellOption::PercentageOption(1.0));

        table->SetColumnOption(0, GuiCellOption::PercentageOption(1.0));

        this->GetContainerComposition()->AddChild(table);

        {
            GuiCellComposition* cell = new GuiCellComposition();
            table->AddChild(cell);
            cell->SetSite(0, 0, 1, 1);

            searchBox = g::NewTextBox();
            searchBox->GetBoundsComposition()->SetAlignmentToParent({ 0, 0, 0, 0 });
            searchBox->TextChanged.AttachMethod(this, &NaiveSearchWindow::searchBox_TextChanged);

            auto fc = searchBox->GetFocusableComposition()->GetEventReceiver();
            fc->gotFocus.AttachMethod(this, &NaiveSearchWindow::searchBox_gotFocus);
            fc->lostFocus.AttachMethod(this, &NaiveSearchWindow::searchBox_lostFocus);

            cell->AddChild(searchBox->GetBoundsComposition());
        }

        {
            GuiCellComposition* cell = new GuiCellComposition();
            table->AddChild(cell);
            cell->SetSite(1, 0, 1, 1);

            dataSource = new DataSource;
            this->OnListRefresh();

            listBox = new GuiVirtualTextList(GetCurrentTheme()->CreateTextListStyle(), GetCurrentTheme()->CreateTextListItemStyle(), dataSource);
            listBox->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0));
            listBox->SetHorizontalAlwaysVisible(false);
            listBox->SetMultiSelect(false);
            listBox->ItemLeftButtonDoubleClick.AttachMethod(this, &NaiveSearchWindow::listBox_ItemLeftButtonDoubleClick);
            listBox->SetVerticalAlwaysVisible(false);

            cell->AddChild(listBox->GetBoundsComposition());
        }

        this->GetNativeWindow()->HideInTaskBar();
        this->SetBorder(false);
        GetApplication()->DelayExecuteInMainThread([this]()
        {
            this->NaiveHide();
            this->Show();
            this->NaiveHide();
        }, 50);
#pragma region Window Events
        this->WindowLostFocus.AttachMethod(this, &NaiveSearchWindow::window_WindowLostFocus);
#pragma endregion End Window Events
    }

    NaiveSearchWindow(SearchWindowStartUpParam * param)
        : vl::presentation::controls::GuiWindow(GetCurrentTheme()->CreateWindowStyle()),
        p(param)
    {
        InitializeComponents();
        p->SearchPlugin = this;
    }

#pragma region IPlugin
    //
    //IPlugin
    //
    void OnConfig() override
    {
        //TODO:Add Config Window
        Show(true);
    }

    void OnExit() override
    {
        Settings::Default().WindowBounds() = this->GetBounds();
        try
        {
            Settings::Default().Save();

        }
        catch (...) {}
        GetApplication()->InvokeLambdaInMainThreadAndWait([=](){ this->Close(); }, 500);
    }

    void OnHotkeyPressed() override
    {
        this->Show();
    }

    void OnListRefresh() override
    {
        if (refreshPLDelay)
        {
            if (refreshPLDelay->GetStatus() == INativeDelay::Pending)
            {
                refreshPLDelay->Cancel();
            }
        }
        refreshPLDelay = GetApplication()->DelayExecute([=]()
        {
            dataSource->UpdatePlaylist(p->Plugin->hwndParent);
        }, 200);
    }
#pragma endregion

#pragma region GuiWindow

    //
    //GuiWindow
    //
    void Show()
    {
        Show(false);
    }

    void Show(bool showSizeBox)
    {
        auto app = GetApplication();
        if (app->IsInMainThread())
        {
            this->NaiveShow();
            this->SetSizeBox(showSizeBox);
        }
        else
        {
            app->InvokeLambdaInMainThread([=](){ this->Show(); });
        }
    }

    void KeyDown(const NativeWindowKeyInfo& info) override
    {
        if (info.code == VKEY_RETURN && IsContorlKeyClean(info)) //Enter
        {
            auto index = listBox->GetSelectedItemIndex();
            if (index == -1)
            {
                index = 0;
            }
            PlayIndex(dataSource->TranslateIndex(index));
            this->NaiveHide();
        }
        else if (info.code == VKEY_TAB && IsContorlKeyClean(info)) //Tab
        {
            auto index = listBox->GetSelectedItemIndex();
            auto count = dataSource->Count();
            if (index != -1)
            {
                listBox->SetSelected(index, false);
            }
            index = (index + 1) % count;
            listBox->SetSelected(index, true);
            listBox->EnsureItemVisible(index);
            listBox->SetFocus();
        }
        else if (info.code == VKEY_Q && IsContorlKeyClean(info)) //Q
        {
            if (p->QueueApi && !inputing)
            {
                auto index = listBox->GetSelectedItemIndex();
                if (index == -1)
                {
                    index = 0;
                }
                QueueIndex(p->QueueApi, dataSource->TranslateIndex(index));
                this->NaiveHide();
            }
        }
        else if (info.code == VKEY_S)
        {
            if (IsContorlKeyClean(info, false, true)) //Ctrl+S
            {
                this->SetSizeBox(!this->GetSizeBox());
            }
#ifdef _DEBUG
            else if (IsContorlKeyClean(info, true,true)) //Ctrl+Alt+S
            {
                OpenFolderAndSelectFile(Settings::Default().SettingFilePath());
            }
#endif
        }
        else if (info.code == VKEY_ESCAPE) //ESC
        {
            this->NaiveHide();
        }
    }

    template <int r>
    static bool IsNear(const int& x1, const int& y1, const int& x2, const int& y2)
    {
        const int dx = x1 - x2;
        const int dy = y1 - y2;
        return dx * dx + dy * dy <= r * r;
    }

    HitTestResult HitTest(Point location) override
    {
        HitTestResult ret = GuiWindow::HitTest(location);
        if (ret == HitTestResult::NoDecision)
        {
            auto bounds = this->GetNativeWindow()->GetClientBoundsInScreen();
            bool isNear =
                IsNear<16>(location.x, location.y, 0, 0) ||
                IsNear<16>(location.x, location.y, bounds.Width(), 0) ||
                IsNear<16>(location.x, location.y, 0, bounds.Height()) ||
                IsNear<16>(location.x, location.y, bounds.Width(), bounds.Height());
            if (isNear)
            {
                ret = HitTestResult::Title;
            }
        }
        else if (ret == HitTestResult::Client)
        {
            ret = HitTestResult::Title;
        }
        return ret;
    }
#pragma endregion

#pragma region Listeners

    //Listeners

    void listBox_ItemLeftButtonDoubleClick(GuiGraphicsComposition* sender, GuiItemMouseEventArgs& e)
    {
        PlayIndex(dataSource->TranslateIndex(listBox->GetSelectedItemIndex()));
    }

    void searchBox_TextChanged(GuiGraphicsComposition* sender, GuiEventArgs& e)
    {
        const auto & text = searchBox->GetText();
        if (StrStrW(text.Buffer(), L"\t") != NULL)
        {
            WString extab(text);
            for (int i = extab.Length() - 1; i >= 0; --i)
            {
                if (extab[i] == L'\t')
                {
                    extab.Remove(i, 1);
                }
            }
            searchBox->SetText(extab);
        }
        else
        {
            if (lastChangeDelay)
            {
                if (lastChangeDelay->GetStatus() == INativeDelay::Pending)
                {
                    lastChangeDelay->Cancel();
                }
            }
            lastChangeDelay = GetApplication()->DelayExecuteInMainThread([=]()
            {
                dataSource->UpdateFilter(searchBox->GetText());
            }, 700);
        }
    }

    void searchBox_gotFocus(GuiGraphicsComposition* sender, GuiEventArgs& e)
    {
        inputing = true;
    }

    void searchBox_lostFocus(GuiGraphicsComposition* sender, GuiEventArgs& e)
    {
        inputing = false;
    }

    void window_WindowLostFocus(GuiGraphicsComposition* sender, GuiEventArgs& e)
    {
        this->NaiveHide();
    }
#pragma endregion

    ~NaiveSearchWindow()
    {

    }
};

GuiWindow * CreateNaiveSearchWindow(SearchWindowStartUpParam * param)
{
    return new NaiveSearchWindow(param);
}
<commit_msg>拖动-移动逻辑改进<commit_after>#include "stdafx.h"
#include "SearchWindow.h"
#include "NaiveSearchWindow.h"
#include "DataSource.h"
#include "WinampControl.h"
#include "Settings.h"

class NaiveSearchWindow sealed :
    public vl::presentation::controls::GuiWindow,
    public IPlugin
{
private:
    DataSource * dataSource;
    GuiVirtualTextList* listBox;
    GuiSinglelineTextBox * searchBox;
    GuiTableComposition * table;
    bool inputing = false;

    static inline bool IsContorlKeyClean(
        const NativeWindowKeyInfo& info,
        bool altstatus = false,
        bool ctrlstatus = false,
        bool shiftstatus = false)
    {
        return (info.alt == altstatus && info.ctrl == ctrlstatus && info.shift == shiftstatus);
    }

    vl::Ptr<vl::presentation::INativeDelay> lastChangeDelay, refreshPLDelay;
    SearchWindowStartUpParam* p;

    void NaiveHide()
    {
        auto thiswinf = vl::presentation::windows::GetWindowsForm(this->GetNativeWindow());
        ShowWindow(thiswinf->GetWindowHandle(), SW_HIDE);
    }

    void NaiveShow()
    {
        GuiWindow::Show();
        auto thiswinf = vl::presentation::windows::GetWindowsForm(this->GetNativeWindow());
        ShowWindow(thiswinf->GetWindowHandle(), SW_SHOWNORMAL);

        BringWindowToTop(thiswinf->GetWindowHandle());
        SetForegroundWindow(thiswinf->GetWindowHandle());

        this->SetActivated();
        searchBox->SelectAll();
        searchBox->SetFocus();
    }
public:

    void InitializeComponents()
    {
        this->SetTitleBar(false);
        this->SetTopMost(true);

        this->SetBounds(Settings::Default().WindowBounds());

        table = new GuiTableComposition();
        table->SetRowsAndColumns(2, 1);
        table->SetCellPadding(3);
        table->SetAlignmentToParent({ 0, 0, 0, 0 });

        table->SetRowOption(0, GuiCellOption::AbsoluteOption(26));
        table->SetRowOption(1, GuiCellOption::PercentageOption(1.0));

        table->SetColumnOption(0, GuiCellOption::PercentageOption(1.0));

        this->GetContainerComposition()->AddChild(table);

        {
            GuiCellComposition* cell = new GuiCellComposition();
            table->AddChild(cell);
            cell->SetSite(0, 0, 1, 1);

            searchBox = g::NewTextBox();
            searchBox->GetBoundsComposition()->SetAlignmentToParent({ 0, 0, 0, 0 });
            searchBox->TextChanged.AttachMethod(this, &NaiveSearchWindow::searchBox_TextChanged);

            auto fc = searchBox->GetFocusableComposition()->GetEventReceiver();
            fc->gotFocus.AttachMethod(this, &NaiveSearchWindow::searchBox_gotFocus);
            fc->lostFocus.AttachMethod(this, &NaiveSearchWindow::searchBox_lostFocus);

            cell->AddChild(searchBox->GetBoundsComposition());
        }

        {
            GuiCellComposition* cell = new GuiCellComposition();
            table->AddChild(cell);
            cell->SetSite(1, 0, 1, 1);

            dataSource = new DataSource;
            this->OnListRefresh();

            listBox = new GuiVirtualTextList(GetCurrentTheme()->CreateTextListStyle(), GetCurrentTheme()->CreateTextListItemStyle(), dataSource);
            listBox->GetBoundsComposition()->SetAlignmentToParent(Margin(0, 0, 0, 0));
            listBox->SetHorizontalAlwaysVisible(false);
            listBox->SetMultiSelect(false);
            listBox->ItemLeftButtonDoubleClick.AttachMethod(this, &NaiveSearchWindow::listBox_ItemLeftButtonDoubleClick);
            listBox->SetVerticalAlwaysVisible(false);

            cell->AddChild(listBox->GetBoundsComposition());
        }

        this->GetNativeWindow()->HideInTaskBar();
        this->SetBorder(false);
        GetApplication()->DelayExecuteInMainThread([this]()
        {
            this->NaiveHide();
            this->Show();
            this->NaiveHide();
        }, 50);
#pragma region Window Events
        this->WindowLostFocus.AttachMethod(this, &NaiveSearchWindow::window_WindowLostFocus);
#pragma endregion End Window Events
    }

    NaiveSearchWindow(SearchWindowStartUpParam * param)
        : vl::presentation::controls::GuiWindow(GetCurrentTheme()->CreateWindowStyle()),
        p(param)
    {
        InitializeComponents();
        p->SearchPlugin = this;
    }

#pragma region IPlugin
    //
    //IPlugin
    //
    void OnConfig() override
    {
        //TODO:Add Config Window
        Show(true);
    }

    void OnExit() override
    {
        Settings::Default().WindowBounds() = this->GetBounds();
        try
        {
            Settings::Default().Save();

        }
        catch (...) {}
        GetApplication()->InvokeLambdaInMainThreadAndWait([=](){ this->Close(); }, 500);
    }

    void OnHotkeyPressed() override
    {
        this->Show();
    }

    void OnListRefresh() override
    {
        if (refreshPLDelay)
        {
            if (refreshPLDelay->GetStatus() == INativeDelay::Pending)
            {
                refreshPLDelay->Cancel();
            }
        }
        refreshPLDelay = GetApplication()->DelayExecute([=]()
        {
            dataSource->UpdatePlaylist(p->Plugin->hwndParent);
        }, 200);
    }
#pragma endregion

#pragma region GuiWindow

    //
    //GuiWindow
    //
    void Show()
    {
        Show(false);
    }

    void Show(bool showSizeBox)
    {
        auto app = GetApplication();
        if (app->IsInMainThread())
        {
            this->NaiveShow();
            this->SetSizeBox(showSizeBox);
        }
        else
        {
            app->InvokeLambdaInMainThread([=](){ this->Show(); });
        }
    }

    void KeyDown(const NativeWindowKeyInfo& info) override
    {
        if (info.code == VKEY_RETURN && IsContorlKeyClean(info)) //Enter
        {
            auto index = listBox->GetSelectedItemIndex();
            if (index == -1)
            {
                index = 0;
            }
            PlayIndex(dataSource->TranslateIndex(index));
            this->NaiveHide();
        }
        else if (info.code == VKEY_TAB && IsContorlKeyClean(info)) //Tab
        {
            auto index = listBox->GetSelectedItemIndex();
            auto count = dataSource->Count();
            if (index != -1)
            {
                listBox->SetSelected(index, false);
            }
            index = (index + 1) % count;
            listBox->SetSelected(index, true);
            listBox->EnsureItemVisible(index);
            listBox->SetFocus();
        }
        else if (info.code == VKEY_Q && IsContorlKeyClean(info)) //Q
        {
            if (p->QueueApi && !inputing)
            {
                auto index = listBox->GetSelectedItemIndex();
                if (index == -1)
                {
                    index = 0;
                }
                QueueIndex(p->QueueApi, dataSource->TranslateIndex(index));
                this->NaiveHide();
            }
        }
        else if (info.code == VKEY_S)
        {
            if (IsContorlKeyClean(info, false, true)) //Ctrl+S
            {
                this->SetSizeBox(!this->GetSizeBox());
            }
#ifdef _DEBUG
            else if (IsContorlKeyClean(info, true,true)) //Ctrl+Alt+S
            {
                OpenFolderAndSelectFile(Settings::Default().SettingFilePath());
            }
#endif
        }
        else if (info.code == VKEY_ESCAPE) //ESC
        {
            this->NaiveHide();
        }
    }

    template <int r>
    static bool IsNear(const int& x1, const int& y1, const int& x2, const int& y2)
    {
        const int dx = x1 - x2;
        const int dy = y1 - y2;
        return dx * dx + dy * dy <= r * r;
    }

    HitTestResult HitTest(Point location) override
    {
        HitTestResult ret = GuiWindow::HitTest(location);
        if (ret == HitTestResult::NoDecision)
        {
            auto bounds = this->GetNativeWindow()->GetClientBoundsInScreen();
            bool isInChild =
                vl::collections::From(table->Children()).Any([=](GuiGraphicsComposition * c){ return c->GetBounds().Contains(location); });
            if (!isInChild)
            {
                ret = HitTestResult::Title;
            }
        }
        else if (ret == HitTestResult::Client)
        {
            ret = HitTestResult::Title;
        }
        return ret;
    }
#pragma endregion

#pragma region Listeners

    //Listeners

    void listBox_ItemLeftButtonDoubleClick(GuiGraphicsComposition* sender, GuiItemMouseEventArgs& e)
    {
        PlayIndex(dataSource->TranslateIndex(listBox->GetSelectedItemIndex()));
    }

    void searchBox_TextChanged(GuiGraphicsComposition* sender, GuiEventArgs& e)
    {
        const auto & text = searchBox->GetText();
        if (StrStrW(text.Buffer(), L"\t") != NULL)
        {
            WString extab(text);
            for (int i = extab.Length() - 1; i >= 0; --i)
            {
                if (extab[i] == L'\t')
                {
                    extab.Remove(i, 1);
                }
            }
            searchBox->SetText(extab);
        }
        else
        {
            if (lastChangeDelay)
            {
                if (lastChangeDelay->GetStatus() == INativeDelay::Pending)
                {
                    lastChangeDelay->Cancel();
                }
            }
            lastChangeDelay = GetApplication()->DelayExecuteInMainThread([=]()
            {
                dataSource->UpdateFilter(searchBox->GetText());
            }, 700);
        }
    }

    void searchBox_gotFocus(GuiGraphicsComposition* sender, GuiEventArgs& e)
    {
        inputing = true;
    }

    void searchBox_lostFocus(GuiGraphicsComposition* sender, GuiEventArgs& e)
    {
        inputing = false;
    }

    void window_WindowLostFocus(GuiGraphicsComposition* sender, GuiEventArgs& e)
    {
        this->NaiveHide();
    }
#pragma endregion

    ~NaiveSearchWindow()
    {

    }
};

GuiWindow * CreateNaiveSearchWindow(SearchWindowStartUpParam * param)
{
    return new NaiveSearchWindow(param);
}
<|endoftext|>


<commit_before>#ifndef CPPMATH_AABB_HPP
#define CPPMATH_AABB_HPP

#include "Vector.hpp"
#include "Intersection.hpp"

namespace math
{
    template <class T>
    class AABB
    {
        public:
            AABB();
            AABB(T x, T y, T w, T h);
            AABB(const Vec2<T>& pos_, const Vec2<T>& size_);

        public:
            // TODO: This functions was useful at some point but probably not
            // anymore. Consider removing it.
            void crop(const AABB<T>& rect);

            void center(T x, T y);
            void center(const Point2<T>& p);

            bool contains(const Point2<T>& point) const;
            bool contains(const AABB<T>& rect) const;
            Intersection<T> intersect(const AABB<T>& rect) const;

            bool operator!=(const AABB<T>& r) const;
            bool operator==(const AABB<T>& r) const;

            template <class T2>
            operator AABB<T2>() const;

        public:
            Vec2<T> pos;
            Vec2<T> size;
    };

    typedef AABB<float> AABBf;
    typedef AABB<int> AABBi;
}

#include "AABB.inl"

#endif
<commit_msg>Add more aliases for AABB members<commit_after>#ifndef CPPMATH_AABB_HPP
#define CPPMATH_AABB_HPP

#include "Vector.hpp"
#include "Intersection.hpp"

namespace math
{
    template <class T>
    class AABB
    {
        public:
            AABB();
            AABB(T x, T y, T w, T h);
            AABB(const Vec2<T>& pos_, const Vec2<T>& size_);

        public:
            // TODO: This functions was useful at some point but probably not
            // anymore. Consider removing it.
            void crop(const AABB<T>& rect);

            void center(T x, T y);
            void center(const Point2<T>& p);

            bool contains(const Point2<T>& point) const;
            bool contains(const AABB<T>& rect) const;
            Intersection<T> intersect(const AABB<T>& rect) const;

            bool operator!=(const AABB<T>& r) const;
            bool operator==(const AABB<T>& r) const;

            template <class T2>
            operator AABB<T2>() const;

        public:
            union {
                struct {
                    Vec2<T> pos;
                    Vec2<T> size;
                };
                struct {
                    T x, y, w, h;
                };
            };
    };

    typedef AABB<float> AABBf;
    typedef AABB<int> AABBi;
}

#include "AABB.inl"

#endif
<|endoftext|>


<commit_before>#ifndef _H_OT_ME_SWITCH
#define _H_OT_ME_SWITCH

#ifdef OT_USE_SCRIPT_CHAI
// USE_OLD_CHAISCRIPT == 0   This will use the C++ conversion of the Chaiscript in OT_ME, OT command line, and otapitest unit tests
// USE_OLD_CHAISCRIPT == 1   This will use the original Chaiscript in OT_ME, OT command line, and otapitest unit tests
#define USE_OLD_CHAISCRIPT  1
#else
// DO NOT CHANGE THIS ONE! WHen Chaiscript is not included we always have to use the C++ code
#define USE_OLD_CHAISCRIPT  0
#endif

#endif
<commit_msg>Forgot to set the switch to use the new C++ functions by default<commit_after>#ifndef _H_OT_ME_SWITCH
#define _H_OT_ME_SWITCH

#ifdef OT_USE_SCRIPT_CHAI
// USE_OLD_CHAISCRIPT == 0   This will use the C++ conversion of the Chaiscript in OT_ME, OT command line, and otapitest unit tests
// USE_OLD_CHAISCRIPT == 1   This will use the original Chaiscript in OT_ME, OT command line, and otapitest unit tests
#define USE_OLD_CHAISCRIPT  0
#else
// DO NOT CHANGE THIS ONE! WHen Chaiscript is not included we always have to use the C++ code
#define USE_OLD_CHAISCRIPT  0
#endif

#endif
<|endoftext|>


<commit_before><commit_msg>Portals - force full check on adding moving object<commit_after><|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "behaviorsettingswidget.h"
#include "ui_behaviorsettingswidget.h"

#include <texteditor/tabsettings.h>
#include <texteditor/storagesettings.h>
#include <texteditor/behaviorsettings.h>
#include <texteditor/extraencodingsettings.h>

#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QByteArray>
#include <QtCore/QTextCodec>
#include <QtCore/QTextStream>

#include <algorithm>
#include <functional>

namespace TextEditor {

struct BehaviorSettingsWidgetPrivate
{
    ::Ui::BehaviorSettingsWidget m_ui;
    QList<QTextCodec *> m_codecs;
};

BehaviorSettingsWidget::BehaviorSettingsWidget(QWidget *parent)
    : QWidget(parent)
    , m_d(new BehaviorSettingsWidgetPrivate)
{
    m_d->m_ui.setupUi(this);

    QList<int> mibs = QTextCodec::availableMibs();
    qSort(mibs);
    QList<int>::iterator firstNonNegative =
        std::find_if(mibs.begin(), mibs.end(), std::bind2nd(std::greater_equal<int>(), 0));
    if (firstNonNegative != mibs.end())
        std::rotate(mibs.begin(), firstNonNegative, mibs.end());
    foreach (int mib, mibs) {
        QTextCodec *codec = QTextCodec::codecForMib(mib);
        QString compoundName = codec->name();
        foreach (const QByteArray &alias, codec->aliases()) {
            compoundName += QLatin1String(" / ");
            compoundName += QString::fromLatin1(alias);
        }
        m_d->m_ui.encodingBox->addItem(compoundName);
        m_d->m_codecs.append(codec);
    }

    connect(m_d->m_ui.cleanWhitespace, SIGNAL(clicked(bool)),
            this, SLOT(slotStorageSettingsChanged()));
    connect(m_d->m_ui.inEntireDocument, SIGNAL(clicked(bool)),
            this, SLOT(slotStorageSettingsChanged()));
    connect(m_d->m_ui.addFinalNewLine, SIGNAL(clicked(bool)),
            this, SLOT(slotStorageSettingsChanged()));
    connect(m_d->m_ui.cleanIndentation, SIGNAL(clicked(bool)),
            this, SLOT(slotStorageSettingsChanged()));
    connect(m_d->m_ui.mouseNavigation, SIGNAL(clicked()),
            this, SLOT(slotBehaviorSettingsChanged()));
    connect(m_d->m_ui.scrollWheelZooming, SIGNAL(clicked(bool)),
            this, SLOT(slotBehaviorSettingsChanged()));
    connect(m_d->m_ui.utf8BomBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(slotExtraEncodingChanged()));
    connect(m_d->m_ui.encodingBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(slotEncodingBoxChanged(int)));
}

BehaviorSettingsWidget::~BehaviorSettingsWidget()
{
    delete m_d;
}

void BehaviorSettingsWidget::setActive(bool active)
{
    m_d->m_ui.tabPreferencesWidget->setEnabled(active);
    m_d->m_ui.groupBoxEncodings->setEnabled(active);
    m_d->m_ui.groupBoxMouse->setEnabled(active);
    m_d->m_ui.groupBoxStorageSettings->setEnabled(active);
}

void BehaviorSettingsWidget::setAssignedCodec(QTextCodec *codec)
{
    for (int i = 0; i < m_d->m_codecs.size(); ++i) {
        if (codec == m_d->m_codecs.at(i)) {
            m_d->m_ui.encodingBox->setCurrentIndex(i);
            break;
        }
    }
}

QTextCodec *BehaviorSettingsWidget::assignedCodec() const
{
    return m_d->m_codecs.at(m_d->m_ui.encodingBox->currentIndex());
}

void BehaviorSettingsWidget::setTabPreferences(TabPreferences *tabPreferences)
{
    m_d->m_ui.tabPreferencesWidget->setTabPreferences(tabPreferences);
}

void BehaviorSettingsWidget::setAssignedStorageSettings(const StorageSettings &storageSettings)
{
    m_d->m_ui.cleanWhitespace->setChecked(storageSettings.m_cleanWhitespace);
    m_d->m_ui.inEntireDocument->setChecked(storageSettings.m_inEntireDocument);
    m_d->m_ui.cleanIndentation->setChecked(storageSettings.m_cleanIndentation);
    m_d->m_ui.addFinalNewLine->setChecked(storageSettings.m_addFinalNewLine);
}

void BehaviorSettingsWidget::assignedStorageSettings(StorageSettings *storageSettings) const
{
    storageSettings->m_cleanWhitespace = m_d->m_ui.cleanWhitespace->isChecked();
    storageSettings->m_inEntireDocument = m_d->m_ui.inEntireDocument->isChecked();
    storageSettings->m_cleanIndentation = m_d->m_ui.cleanIndentation->isChecked();
    storageSettings->m_addFinalNewLine = m_d->m_ui.addFinalNewLine->isChecked();
}

void BehaviorSettingsWidget::setAssignedBehaviorSettings(const BehaviorSettings &behaviorSettings)
{
    m_d->m_ui.mouseNavigation->setChecked(behaviorSettings.m_mouseNavigation);
    m_d->m_ui.scrollWheelZooming->setChecked(behaviorSettings.m_scrollWheelZooming);
}

void BehaviorSettingsWidget::assignedBehaviorSettings(BehaviorSettings *behaviorSettings) const
{
    behaviorSettings->m_mouseNavigation = m_d->m_ui.mouseNavigation->isChecked();
    behaviorSettings->m_scrollWheelZooming = m_d->m_ui.scrollWheelZooming->isChecked();
}

void BehaviorSettingsWidget::setAssignedExtraEncodingSettings(
    const ExtraEncodingSettings &encodingSettings)
{
    m_d->m_ui.utf8BomBox->setCurrentIndex(encodingSettings.m_utf8BomSetting);
}

void BehaviorSettingsWidget::assignedExtraEncodingSettings(
    ExtraEncodingSettings *encodingSettings) const
{
    encodingSettings->m_utf8BomSetting =
        (ExtraEncodingSettings::Utf8BomSetting)m_d->m_ui.utf8BomBox->currentIndex();
}

QString BehaviorSettingsWidget::collectUiKeywords() const
{
    static const QLatin1Char sep(' ');
    QString keywords;
    QTextStream(&keywords)
        << sep << m_d->m_ui.tabPreferencesWidget->searchKeywords()
        << sep << m_d->m_ui.cleanWhitespace->text()
        << sep << m_d->m_ui.inEntireDocument->text()
        << sep << m_d->m_ui.cleanIndentation->text()
        << sep << m_d->m_ui.addFinalNewLine->text()
        << sep << m_d->m_ui.encodingLabel->text()
        << sep << m_d->m_ui.utf8BomLabel->text()
        << sep << m_d->m_ui.mouseNavigation->text()
        << sep << m_d->m_ui.scrollWheelZooming->text()
        << sep << m_d->m_ui.groupBoxStorageSettings->title()
        << sep << m_d->m_ui.groupBoxEncodings->title()
        << sep << m_d->m_ui.groupBoxMouse->title();
    keywords.remove(QLatin1Char('&'));
    return keywords;
}

void BehaviorSettingsWidget::setFallbacksVisible(bool on)
{
    m_d->m_ui.tabPreferencesWidget->setFallbacksVisible(on);
}

void BehaviorSettingsWidget::slotStorageSettingsChanged()
{
    StorageSettings settings;
    assignedStorageSettings(&settings);
    emit storageSettingsChanged(settings);
}

void BehaviorSettingsWidget::slotBehaviorSettingsChanged()
{
    StorageSettings settings;
    assignedStorageSettings(&settings);
    emit storageSettingsChanged(settings);
}

void BehaviorSettingsWidget::slotExtraEncodingChanged()
{
    ExtraEncodingSettings settings;
    assignedExtraEncodingSettings(&settings);
    emit extraEncodingSettingsChanged(settings);
}

void BehaviorSettingsWidget::slotEncodingBoxChanged(int index)
{
    emit textCodecChanged(m_d->m_codecs.at(index));
}

} // TextEditor
<commit_msg>Fix behavior settings<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at info@qt.nokia.com.
**
**************************************************************************/

#include "behaviorsettingswidget.h"
#include "ui_behaviorsettingswidget.h"

#include <texteditor/tabsettings.h>
#include <texteditor/storagesettings.h>
#include <texteditor/behaviorsettings.h>
#include <texteditor/extraencodingsettings.h>

#include <QtCore/QList>
#include <QtCore/QString>
#include <QtCore/QByteArray>
#include <QtCore/QTextCodec>
#include <QtCore/QTextStream>

#include <algorithm>
#include <functional>

namespace TextEditor {

struct BehaviorSettingsWidgetPrivate
{
    ::Ui::BehaviorSettingsWidget m_ui;
    QList<QTextCodec *> m_codecs;
};

BehaviorSettingsWidget::BehaviorSettingsWidget(QWidget *parent)
    : QWidget(parent)
    , m_d(new BehaviorSettingsWidgetPrivate)
{
    m_d->m_ui.setupUi(this);

    QList<int> mibs = QTextCodec::availableMibs();
    qSort(mibs);
    QList<int>::iterator firstNonNegative =
        std::find_if(mibs.begin(), mibs.end(), std::bind2nd(std::greater_equal<int>(), 0));
    if (firstNonNegative != mibs.end())
        std::rotate(mibs.begin(), firstNonNegative, mibs.end());
    foreach (int mib, mibs) {
        QTextCodec *codec = QTextCodec::codecForMib(mib);
        QString compoundName = codec->name();
        foreach (const QByteArray &alias, codec->aliases()) {
            compoundName += QLatin1String(" / ");
            compoundName += QString::fromLatin1(alias);
        }
        m_d->m_ui.encodingBox->addItem(compoundName);
        m_d->m_codecs.append(codec);
    }

    connect(m_d->m_ui.cleanWhitespace, SIGNAL(clicked(bool)),
            this, SLOT(slotStorageSettingsChanged()));
    connect(m_d->m_ui.inEntireDocument, SIGNAL(clicked(bool)),
            this, SLOT(slotStorageSettingsChanged()));
    connect(m_d->m_ui.addFinalNewLine, SIGNAL(clicked(bool)),
            this, SLOT(slotStorageSettingsChanged()));
    connect(m_d->m_ui.cleanIndentation, SIGNAL(clicked(bool)),
            this, SLOT(slotStorageSettingsChanged()));
    connect(m_d->m_ui.mouseNavigation, SIGNAL(clicked()),
            this, SLOT(slotBehaviorSettingsChanged()));
    connect(m_d->m_ui.scrollWheelZooming, SIGNAL(clicked(bool)),
            this, SLOT(slotBehaviorSettingsChanged()));
    connect(m_d->m_ui.utf8BomBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(slotExtraEncodingChanged()));
    connect(m_d->m_ui.encodingBox, SIGNAL(currentIndexChanged(int)),
            this, SLOT(slotEncodingBoxChanged(int)));
}

BehaviorSettingsWidget::~BehaviorSettingsWidget()
{
    delete m_d;
}

void BehaviorSettingsWidget::setActive(bool active)
{
    m_d->m_ui.tabPreferencesWidget->setEnabled(active);
    m_d->m_ui.groupBoxEncodings->setEnabled(active);
    m_d->m_ui.groupBoxMouse->setEnabled(active);
    m_d->m_ui.groupBoxStorageSettings->setEnabled(active);
}

void BehaviorSettingsWidget::setAssignedCodec(QTextCodec *codec)
{
    for (int i = 0; i < m_d->m_codecs.size(); ++i) {
        if (codec == m_d->m_codecs.at(i)) {
            m_d->m_ui.encodingBox->setCurrentIndex(i);
            break;
        }
    }
}

QTextCodec *BehaviorSettingsWidget::assignedCodec() const
{
    return m_d->m_codecs.at(m_d->m_ui.encodingBox->currentIndex());
}

void BehaviorSettingsWidget::setTabPreferences(TabPreferences *tabPreferences)
{
    m_d->m_ui.tabPreferencesWidget->setTabPreferences(tabPreferences);
}

void BehaviorSettingsWidget::setAssignedStorageSettings(const StorageSettings &storageSettings)
{
    m_d->m_ui.cleanWhitespace->setChecked(storageSettings.m_cleanWhitespace);
    m_d->m_ui.inEntireDocument->setChecked(storageSettings.m_inEntireDocument);
    m_d->m_ui.cleanIndentation->setChecked(storageSettings.m_cleanIndentation);
    m_d->m_ui.addFinalNewLine->setChecked(storageSettings.m_addFinalNewLine);
}

void BehaviorSettingsWidget::assignedStorageSettings(StorageSettings *storageSettings) const
{
    storageSettings->m_cleanWhitespace = m_d->m_ui.cleanWhitespace->isChecked();
    storageSettings->m_inEntireDocument = m_d->m_ui.inEntireDocument->isChecked();
    storageSettings->m_cleanIndentation = m_d->m_ui.cleanIndentation->isChecked();
    storageSettings->m_addFinalNewLine = m_d->m_ui.addFinalNewLine->isChecked();
}

void BehaviorSettingsWidget::setAssignedBehaviorSettings(const BehaviorSettings &behaviorSettings)
{
    m_d->m_ui.mouseNavigation->setChecked(behaviorSettings.m_mouseNavigation);
    m_d->m_ui.scrollWheelZooming->setChecked(behaviorSettings.m_scrollWheelZooming);
}

void BehaviorSettingsWidget::assignedBehaviorSettings(BehaviorSettings *behaviorSettings) const
{
    behaviorSettings->m_mouseNavigation = m_d->m_ui.mouseNavigation->isChecked();
    behaviorSettings->m_scrollWheelZooming = m_d->m_ui.scrollWheelZooming->isChecked();
}

void BehaviorSettingsWidget::setAssignedExtraEncodingSettings(
    const ExtraEncodingSettings &encodingSettings)
{
    m_d->m_ui.utf8BomBox->setCurrentIndex(encodingSettings.m_utf8BomSetting);
}

void BehaviorSettingsWidget::assignedExtraEncodingSettings(
    ExtraEncodingSettings *encodingSettings) const
{
    encodingSettings->m_utf8BomSetting =
        (ExtraEncodingSettings::Utf8BomSetting)m_d->m_ui.utf8BomBox->currentIndex();
}

QString BehaviorSettingsWidget::collectUiKeywords() const
{
    static const QLatin1Char sep(' ');
    QString keywords;
    QTextStream(&keywords)
        << sep << m_d->m_ui.tabPreferencesWidget->searchKeywords()
        << sep << m_d->m_ui.cleanWhitespace->text()
        << sep << m_d->m_ui.inEntireDocument->text()
        << sep << m_d->m_ui.cleanIndentation->text()
        << sep << m_d->m_ui.addFinalNewLine->text()
        << sep << m_d->m_ui.encodingLabel->text()
        << sep << m_d->m_ui.utf8BomLabel->text()
        << sep << m_d->m_ui.mouseNavigation->text()
        << sep << m_d->m_ui.scrollWheelZooming->text()
        << sep << m_d->m_ui.groupBoxStorageSettings->title()
        << sep << m_d->m_ui.groupBoxEncodings->title()
        << sep << m_d->m_ui.groupBoxMouse->title();
    keywords.remove(QLatin1Char('&'));
    return keywords;
}

void BehaviorSettingsWidget::setFallbacksVisible(bool on)
{
    m_d->m_ui.tabPreferencesWidget->setFallbacksVisible(on);
}

void BehaviorSettingsWidget::slotStorageSettingsChanged()
{
    StorageSettings settings;
    assignedStorageSettings(&settings);
    emit storageSettingsChanged(settings);
}

void BehaviorSettingsWidget::slotBehaviorSettingsChanged()
{
    BehaviorSettings settings;
    assignedBehaviorSettings(&settings);
    emit behaviorSettingsChanged(settings);
}

void BehaviorSettingsWidget::slotExtraEncodingChanged()
{
    ExtraEncodingSettings settings;
    assignedExtraEncodingSettings(&settings);
    emit extraEncodingSettingsChanged(settings);
}

void BehaviorSettingsWidget::slotEncodingBoxChanged(int index)
{
    emit textCodecChanged(m_d->m_codecs.at(index));
}

} // TextEditor
<|endoftext|>