<commit_before>
#include <Beard/utility.hpp>
#include <Beard/keys.hpp>
#include <Beard/geometry.hpp>
#include <Beard/txt/Defs.hpp>
#include <Beard/tty/Defs.hpp>
#include <Beard/tty/Terminal.hpp>
#include <Beard/ui/Root.hpp>
#include <Beard/ui/Field.hpp>

#include <duct/CharacterSet.hpp>

#include <iostream>

namespace Beard {
namespace ui {

// class Field implementation

namespace {
static ui::Widget::type_info const
s_type_info{
	ui::Widget::Type::Field,
	enum_combine(
		ui::Widget::TypeFlags::focusable
	)
};
} // anonymous namespace

Field::~Field() noexcept = default;

void
Field::update_view() noexcept {
	if (!has_input_control()) {
		m_view.col_extent(txt::Extent::head);
	} else {
		auto const& frame = get_geometry().get_frame();
		auto const inner_width = max_ce(0, frame.size.width - 2 - 1);
		if (
			m_view.col() > m_cursor.col() ||
			m_view.col() + inner_width < m_cursor.col()
		) {
			m_view.col_abs(
				m_cursor.col() - (inner_width * 0.5)
			);
		}
	}
}

// implementation

ui::Widget::type_info const&
Field::get_type_info_impl() const noexcept {
	return s_type_info;
}

void
Field::reflow_impl(
	Rect const& area,
	bool const cache
) noexcept {
	base_type::reflow_impl(area, cache);
	update_view();
}

namespace {
static KeyInputMatch const
s_kim_icontrol[]{
	{KeyMod::none, KeyCode::enter, codepoint_none, false}/*,
	{KeyMod::none, KeyCode::none, ' ', false}*/
};

static duct::CharacterSet const
s_input_blacklist{<commit_msg>ui::Field: changed floating-point op to an integer op (x*0.5 to x/2).<commit_after>
#include <Beard/utility.hpp>
#include <Beard/keys.hpp>
#include <Beard/geometry.hpp>
#include <Beard/txt/Defs.hpp>
#include <Beard/tty/Defs.hpp>
#include <Beard/tty/Terminal.hpp>
#include <Beard/ui/Root.hpp>
#include <Beard/ui/Field.hpp>

#include <duct/CharacterSet.hpp>

#include <iostream>

namespace Beard {
namespace ui {

// class Field implementation

namespace {
static ui::Widget::type_info const
s_type_info{
	ui::Widget::Type::Field,
	enum_combine(
		ui::Widget::TypeFlags::focusable
	)
};
} // anonymous namespace

Field::~Field() noexcept = default;

void
Field::update_view() noexcept {
	if (!has_input_control()) {
		m_view.col_extent(txt::Extent::head);
	} else {
		auto const& frame = get_geometry().get_frame();
		auto const inner_width = max_ce(0, frame.size.width - 2 - 1);
		if (
			m_view.col() > m_cursor.col() ||
			m_view.col() + inner_width < m_cursor.col()
		) {
			m_view.col_abs(
				m_cursor.col() - (inner_width / 2)
			);
		}
	}
}

// implementation

ui::Widget::type_info const&
Field::get_type_info_impl() const noexcept {
	return s_type_info;
}

void
Field::reflow_impl(
	Rect const& area,
	bool const cache
) noexcept {
	base_type::reflow_impl(area, cache);
	update_view();
}

namespace {
static KeyInputMatch const
s_kim_icontrol[]{
	{KeyMod::none, KeyCode::enter, codepoint_none, false}/*,
	{KeyMod::none, KeyCode::none, ' ', false}*/
};

static duct::CharacterSet const
s_input_blacklist{
{'fraction_non_alphanumeric': 0.15869272237196766, 'fraction_numerical': 0.004043126684636119, 'mean_word_length': 4.90258449304175, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2189254', 'n_tokens_mistral': 1172, 'n_tokens_neox': 1127, 'n_words': 219}